gcc

gcc

GNU編譯器套件
GCC(GNU Compiler Collection,GNU編譯器套件)是由GNU開發的編程語言編譯器。GNU編譯器套件包括C、C++、 Objective-C、 Fortran、Java、Ada和Go語言前端,也包括了這些語言的庫(如libstdc++,libgcj等。)GCC的初衷是為GNU操作系統專門編寫的一款編譯器。GNU系統是徹底的自由軟件。此處,“自由”的含義是它尊重用戶的自由[1]。GCC的外部接口長得像一個标準的Unix編譯器。使用者在命令列下鍵入gcc之程序名,以及一些命令參數,以便決定每個輸入檔案使用的個别語言編譯器,并為輸出程序碼使用适合此硬件平台的組合語言編譯器,并且選擇性地執行連接器以制造可執行的程序。
  • 軟件名稱:GNU Compiler Collection
  • 軟件平台:類Unix操作系統
  • 軟件語言:多國語言
  • 開發商:Free Software Foundation (自由軟件基金會)
  • 軟件授權:GNU通用公共許可證(GNU GPL)
  • 軟件版本:12.2
  • 軟件大小:
  • 編寫語言:C/C++

簡介

GCC是以GPL許可證所發行的自由軟件,也是GNU計劃的關鍵部分。GCC的初衷是為GNU操作系統專門編寫一款編譯器,現已被大多數類Unix操作系統(如Linux、BSD、MacOS X等)采納為标準的編譯器,甚至在微軟的Windows上也可以使用GCC。GCC支持多種計算機體系結構芯片,如x86、ARM、MIPS等,并已被移植到其他多種硬件平台。

GCC原名為GNU C語言編譯器(GNU C Compiler),隻能處理C語言。但其很快擴展,變得可處理C++,後來又擴展為能夠支持更多編程語言,如Fortran、Pascal、Objective -C、Java、Ada、Go以及各類處理器架構上的彙編語言等,所以改名GNU編譯器套件(GNU Compiler Collection)。

結構

GCC的外部接口長得像一個标準的Unix編譯器。使用者在命令列下鍵入gcc之程序名,以及一些命令參數,以便決定每個輸入檔案使用的個别語言編譯器,并為輸出程序碼使用适合此硬件平台的組合語言編譯器,并且選擇性地執行連接器以制造可執行的程序。

每個語言編譯器都是獨立程序,此程序可處理輸入的原始碼,并輸出組合語言碼。全部的語言編譯器都擁有共通的中介架構:一個前端解析符合此語言的原始碼,并産生一抽象語法樹,以及一翻譯此語法樹成為GCC的暫存器轉換語言〈RTL〉的後端。編譯器最佳化與靜态程序碼解析技術(例如FORTIFY_SOURCE,一個試圖發現緩沖區溢位〈buffer overflow〉的編譯器)在此階段應用于程序碼上。最後,适用于此硬件架構的組合語言程序碼以Jack Davidson與Chris Fraser發明的算法産出。

幾乎全部的GCC都由C寫成,除了Ada前端大部分以Ada寫成。

前端接口

前端的功能在于産生一個可讓後端處理之語法樹。此語法解析器是手寫之遞歸語法解析器。

直到2004年,程序的語法樹結構尚無法與欲産出的處理器架構脫鈎。而語法樹的規則有時在不同的語言前端也不一樣,有些前端會提供它們特别的語法樹規則。

在2005年,兩種與語言脫鈎的新型态語法樹納入GCC中。它們稱為GENERIC與GIMPLE。語法解析變成産生與語言相關的暫時語法樹,再将它們轉成GENERIC。之後再使用"gimplifier"技術降低GENERIC的複雜結構,成為一較簡單的靜态唯一形式(Static Single Assignment form,SSA)基礎的GIMPLE形式。此形式是一個與語言和處理器架構脫鈎的全域最佳化通用語言,适用于大多數的現代編程語言。

中介接口

一般編譯器作者會将語法樹的最佳化放在前端,但其實此步驟并不看語言的種類而有不同,且不需要用到語法解析器。因此GCC作者們将此步驟歸入通稱為中介階段的部分裡。此類的最佳化包括消解死碼、消解重複運算與全域數值重編碼等。許多最佳化技巧也正在實作中。

後端接口

GCC後端的行為因不同的前處理器宏和特定架構的功能而不同,例如不同的字符尺寸、呼叫方式與大小尾序等。後端接口的前半部利用這些訊息決定其RTL的生成形式,因此雖然GCC的RTL理論上不受處理器影響,但在此階段其抽象指令已被轉換成目标架構的格式。

GCC的最佳化技巧依其釋出版本而有很大不同,但都包含了标準的最佳化算法,例如循環最佳化、執行緒跳躍、共通程序子句消減、指令排程等等。而RTL的最佳化由于可用的情形較少,且缺乏較高階的資訊,因此相比較起來,增加的GIMPLE語法樹形式,便顯得比較不重要。

後端經由一次重讀取步驟後,利用描述目标處理器的指令集時所取得的信息,将抽象暫存器替換成處理器的真實暫存器。此階段非常複雜,因為它必須關注所有GCC可移植平台的處理器指令集的規格與技術細節。

後端的最後步驟相當公式化,僅僅将前一階段得到的彙編語言代碼藉由簡單的子例程轉換其暫存器與内存位置成相對應的機器碼。

基本用法

在使用GCC編譯器的時候,我們必須給出一系列必要的調用參數和文件名稱。GCC編譯器的調用參數大約有100多個,這裡隻介紹其中最基本、最常用的參數。具體可參考GCC Manual。

GCC最基本的用法是∶gcc [options] [filenames]

其中options就是編譯器所需要的參數,filenames給出相關的文件名稱。

-c,隻編譯,不鍊接成為可執行文件,編譯器隻是由輸入的.c等源代碼文件生成.o為後綴的目标文件,通常用于編譯不包含主程序的子程序文件。

-o output_filename,确定輸出文件的名稱為output_filename,同時這個名稱不能和源文件同名。如果不給出這個選項,gcc就給出預設的可執行文件a.out。

-g,産生符号調試工具(GNU的gdb)所必要的符号資訊,要想對源代碼進行調試,我們就必須加入這個選項。

-O,對程序進行優化編譯、鍊接,采用這個選項,整個源代碼會在編譯、鍊接過程中進行優化處理,這樣産生的可執行文件的執行效率可以提高,但是,編譯、鍊接的速度就相應地要慢一些。

-O2,比-O更好的優化編譯、鍊接,當然整個編譯、鍊接過程會更慢。

-Idirname,将dirname所指出的目錄加入到程序頭文件目錄列表中,是在預編譯過程中使用的參數。C程序中的頭文件包含兩種情況∶

A)#include 

B)#include “myinc.h”

其中,A類使用尖括号(< >),B類使用雙引号(“ ”)。對于A類,預處理程序cpp在系統預設包含文件目錄(如/usr/include)中搜尋相應的文件,而B類,預處理程序在目标文件的文件夾内搜索相應文件。

-v gcc執行時執行的詳細過程,gcc及其相關程序的版本号

原版gcc manual該選項英文解釋

Print (on standard error output) the commands executed to run the stages of compilation. Also print the version number of the compiler driver program and of the preprocessor and the compiler proper.

編譯程序時加上該選項可以看到gcc搜索頭文件/庫文件時使用的搜索路徑!

基本規則

gcc所遵循的部分約定規則:

.c為後綴的文件,C語言源代碼文件;

.a為後綴的文件,是由目标文件構成的檔案庫文件;

.C,.cc或.cxx 為後綴的文件,是C++源代碼文件且必須要經過預處理;

.h為後綴的文件,是程序所包含的頭文件;

.i 為後綴的文件,是C源代碼文件且不應該對其執行預處理;

.ii為後綴的文件,是C++源代碼文件且不應該對其執行預處理;

.m為後綴的文件,是Objective-C源代碼文件;

.mm為後綴的文件,是Objective-C++源代碼文件;

.o為後綴的文件,是編譯後的目标文件;

.s為後綴的文件,是彙編語言源代碼文件;

.S為後綴的文件,是經過預編譯的彙編語言源代碼文件。

語言支持

以2006年5月24日釋出的4.1.1版為準,本編譯器版本可處理下列語言:

Ada 〈GNAT〉

C 〈GCC〉

C++(G++)

Fortran 〈Fortran 77: G77, Fortran 90: GFORTRAN〉

Java 〈編譯器:GCJ;解釋器:GIJ〉

Objective-C 〈GOBJC〉

Objective-C++

先前版本納入的CHILL前端由于缺乏維護而被廢棄。

Fortran前端在4.0版之前是G77,此前端僅支援Fortran 77。在本版本中,G77被廢棄而采用更新的GFortran,因為此前端支援Fortran 95。

下列前端依然存在:

Modula-2

Modula-3

Pascal

PL/I

D語言

Mercury

VHDL

執行過程

雖然我們稱GCC是C語言的編譯器,但使用gcc由C語言源代碼文件生成可執行文件的過程不僅僅是編譯的過程,而是要經曆四個相互關聯的步驟∶預處理(也稱預編譯,Preprocessing)、編譯(Compilation)、彙編(Assembly)和鍊接(Linking)。

命令gcc首先調用cpp進行預處理,在預處理過程中,對源代碼文件中的文件包含(include)、預編譯語句(如宏定義define等)進行分析。接着調用cc1進行編譯,這個階段根據輸入文件生成以.i為後綴的目标文件。彙編過程是針對彙編語言的步驟,調用as進行工作,一般來講,.S為後綴的彙編語言源代碼文件和彙編、.s為後綴的彙編語言文件經過預編譯和彙編之後都生成以.o為後綴的目标文件。當所有的目标文件都生成之後,gcc就調用ld來完成最後的關鍵性工作,這個階段就是連接。在連接階段,所有的目标文件被安排在可執行程序中的恰當的位置,同時,該程序所調用到的庫函數也從各自所在的檔案庫中連到合适的地方。

執行過程示例

示例代碼 #include     int main(void) {        printf("hellon");      return 0;    }預編譯過程

這個過程處理宏定義和include,去除注釋,不會對語法進行檢查。

可以看到預編譯後,代碼從6行擴展到了910行。

gcc -E a.c -o a.icat a.c|wc -l5cat a.i|wc -l910編譯過程

這個階段,檢查語法,生成彙編代碼。

gcc -S a.i -o a.scat a.s|wc-l59彙編過程

這個階段,生成目标代碼。

此過程生成ELF格式的目标代碼。

gcc -c a.s -o a.ofile a.oo:ELF64-bitLSBrelocatable,AMDx86-64,version1(SYSV),notstripped鍊接過程

鍊接過程。生成可執行代碼。鍊接分為兩種,一種是靜态鍊接,另外一種是動态鍊接。使用靜态鍊接的好處是,依賴的動态鍊接庫較少,對動态鍊接庫的版本不會很敏感,具有較好的兼容性;缺點是生成的程序比較大。使用動态鍊接的好處是,生成的程序比較小,占用較少的内存。

gcc a.o -o a

程序運行:

./ahello

處理器架構

GCC4.1支持下列處理器架構:

Alpha

ARM

Atmel AVR

Blackfin

H8/300

IA-32〈x86〉 與x86-64

IA-64例如:Itanium

MorphoSys 家族

Motorola 68000

Motorola 88000

MIPS

PA-RISC

PDP-11

PowerPC

System/370,System/390

SuperH

HC12

SPARC

VAX

Renesas R8C/M16C/M32C家族

較不知名的處理器架構也在官方釋出版本中支援:

A29K

ARC

C4x

CRIS

D30V

DSP16xx

FR-30

FR-V

Intel i960

IP2000

M32R

68HC11

MCORE

MMIX

MN10200

MN10300

NS32K

ROMP

Stormy16

V850

Xtensa

由FSF個别維護的GCC處理器架構:

D10V

MicroBlaze

PDP-10

MSP430

Z8000

當GCC需要移植到一個新平台上,通常使用此平台固有的語言來撰寫其初始階段。

程序除錯

為 GCC 除錯的首選工具當然是 GNU 除錯器。其他特殊用途的除錯工具是 Valgrind, 用以發現内存漏失 (Memory leak)。而 GNU 測量器 (gprof) 可以得知程序中某些函式花費多少時間,以及其呼叫頻率;此功能需要使用者在編譯時選定測量〈profiling〉選項。

使用技巧

首先檢查是否在你的機器上安裝了GCC,使用命令:

可用rpm -q gcc 檢查。

如果沒有安裝,請依序檢查并安裝下面各RPM

libbinutils

binutils

make

glibc-devel

gcc-cpp

gcc

看下面的例子:test.c

#include int main(){    char *str="I like Linux!I advice you to join in the Linux World";    printf("%s",str);    return 0;}

使用gcc編譯。輸入gcc -c test.c得到目标文件test.o.-c命令表示對文件進行編譯和彙編。但并不連接。如果再鍵入gcc -o ../bin/test test.o,那麼将得到名為test的可執行文件。其實這兩步可以一氣呵成,gcc ../bin/test test.c.如果程序沒有錯誤就生成了可執行文件。也許你會覺得基于命令行的編譯器比不上如VC之類的集成開發環境,的确gcc的界面要改進,但是你一旦熟練了就會感到。gcc的效率如此之高。可以告訴大家的是Linux底下強大的C/C++集成開發環境Kdevelop和Vc一樣強大,使用了Gcc編譯器。

GNU C編譯器 即gcc是一個功能強大的ANSI C兼容編譯器,你會操作其他操作系統下的一種C編譯器,能很快掌握GCC.

1、使用Gcc,Gcc是基于命令行的,使用時通常後跟一些選項和文件名。Gcc的基本用法如下: gcc [options] [filenames] 命令行選項制定操作将對命令行上的每個給出的文件執行。

2、GCC的常用選項

編譯選項:gcc有超過100個的編譯選項可用。具體的可以使用命令man gcc察看

優化選項:用GCC編譯C/C++代碼時,它會試着用最少的時間完成編譯并且編譯後的代碼易于調試。易于調試意味着編譯後的代碼與源代碼有同樣的執行順序,編譯後的代碼沒有經過優化。有很多的選項可以告訴GCC在耗費更多編譯時間和犧牲易調試性的基礎上産生更小更快的可執行文件。這些選項中最典型的就是-O和-O2。-O選項告訴gcc對源代碼進行基本優化。-O2選項告訴GCC産生盡可能小的和盡可能快的代碼。還有一些很特殊的選項可以通過man gcc察看。

調試和剖析選項:GCC支持數種調試剖析選項。在這些選項中最常用的是-g和-pg.-g選項告訴gcc産生能被GNU調試器(如gdb)使用的調試信息,以便調試用戶的程序。-pg選項告訴gcc在用戶的程序中加入額外的代碼,執行時,産生gprof用的剖析信息以顯示程序的耗時情況。

3、使用gdb

使用方法:在命令行中鍵入gdb并按回車就可以運行gdb了,啟動gdb後,能在命令行上制定很多的選項,也可以下面的方式來運行gdb: gdb filename 用這種方式運行gdb時,能直接指定想要調試的程序。在命令行上健入gdb -h得到一個有關gdb的選項的說明簡單列表。

編譯代碼以供調試,為了使gdb工作,必須使程序在編譯時包含調試信息,調試信息包含程序裡的每個變量的類型,在可執行文件裡的地址映射以及源代碼的行号。gdb利用這些信息使源代碼和機器碼相關聯。

關于gcc的大體就寫這麼多吧,更多的信息可以查找幫助,記得學習Linux的一大武器man或者info命令,下次在介紹一下使用C/C++編寫大型程序的makefile文件和make命令。

版本發布

2012年03月23日,GCC 首個公開發布版本是在 1987 年由 Richard Stallman 發布的,到今天已經整整 25 年了。為了慶祝 25 周年,GCC 也相應發布了 GCC 4.7.0 版本,這是 GCC 一個全新的重要版本。

GCC 4.7.0 帶來了一組關于鍊接時優化 (LTO) 框架可提升伸縮性和降低内存使用,據開發者稱,在 64 位系統上需要 8G 内存來對 Firefox 進行優化,然而用了 LTO 後隻需 3G。

此外就是體驗的支持軟件事務内存,支持更多 C++11 标準,包括原子性、C++11 内存模型,用戶定義文字、别名聲明、構造器委派和可擴展的語法等。

GCC 4.7.0 還改進對 Fortran 的支持,支持 Google Go 1 等等多項改進。

2012年06月14日,GCC 4.7.1 發布了,這是一個 bug 修複版本,主要是 4.7.0 中的一些回歸測試發現的問題修複。

2013年04月11日,GCC 4.7.3 發布。

2013年03月22日,GCC 4.8.0發布,進一步加強了對已C++11的支持。并且G++開始支持-std=c++1y選項,用來支持計劃于2014年發布的C++11修訂版标準(C++14)。

2013年10月16日,GCC 4.8.2發布。提供了對于OpenMP 4.0的支持。

2014年04月22日,GCC發布了4.9.0版本,提供了對C11标準的Generic Selection語法特性(_Generic)的支持以及對多線程方面特性的支持。

安裝方法

linux中

RedHat中安裝

用which gcc命令查看,假如有顯示” /usr/bin/gcc”的話說明已經安裝了,否則就是沒有安裝。

這裡以redhat 64位 linux為例。首先将redhat的iso系統鏡像挂在到/mnt/cdrom目錄下:

mount -o loop /data/rhel-server-5.4-x86_64-dvd.iso /mnt/cdrom

進入/mnt/cdrom目錄,就可以訪問iso鏡像中的内容了。

cd /mnt/cdrom

cd Server/

安裝gcc的依賴包以及gcc,按以下命令依次執行:

rpm -ivh binutils-2.17.50.0.6-12.el5.x86_64.rpm

rpm -ivh cpp-4.1.2-46.el5.x86_64.rpm

rpm -ivh kernel-headers-2.6.18-164.el5.x86_64.rpm

rpm -ivh glibc-devel-2.5-42.x86_64.rpm

rpm -ivh glibc-headers-2.5-42.x86_64.rpm

rpm -ivh libgomp-4.4.0-6.el5.x86_64.rpm

rpm -ivh gcc-4.1.2-46.el5.x86_64.rpm

大家在安裝rpm包時,由于依賴關系,在安裝時會提示“此包依賴其他包xx”,讓你先安裝其他包,總之大家按照提示來,提示你先安裝哪個包就安裝哪個包。

Ubuntu中安裝

安裝4.8版為例:

sudo apt-get install gcc-4.8

相關詞條

相關搜索

其它詞條