浅析Linux开发工具之gcc/g++
在windows開發平臺,我們用慣了vc、vs等IDE(集成開發環境),在編譯好源代碼之后,按下相應按鈕,IDE就會為我們完成編譯,鏈接的過程。然而在Linux平臺下,卻沒有這么方便的開發環境,很多事情都需要我們親力親為,為此我們要了解兩款編譯器:gcc/g++,它們分別是GNU的c/c++編譯器。
下面,來具體了解一下這兩款編譯器:
1、gcc/g++的安裝
在終端輸入兩條命令即可:
(1)安裝gcc
Debian系列:sudo apt-get install gcc
RedHat系列:sudo yum install gcc
(2)安裝g++
Debian系列:sudo apt-get install g++
RedHat系列:sudo yum install gcc-c++
PS:Debian系列的系統可以用一條命令:sudo apt-get install build-essential來安裝gcc、g++、make這一套工具。
2、gcc/g++的編譯過程
我們都知道,編寫好的源代碼在生成可執行程序的過程中需要以下四步:預處理、匯編、編譯、鏈接,同樣的,我們的工具gcc/g++在為我們生成可執行程序的過程中也經歷了上述四步,下面我們來具體看看這四個執行步驟。
下文圖片中出現的Makefile文件是我為了方便我的編譯創建的一個文件,不用理會。
這里以gcc舉例,g++與之類似,首先編寫源文件:
先用touch命令創建我們要編寫的源文件:
接著編輯源文件的內容:
然后來看看文件編譯后的狀態(這兒只看test.c的,tran.c的與之相似,頭文件無法編譯)
(1)預處理,生成.i的文件
預處理:這個步驟為我們完成的工作是宏替換、頭文件展開、條件編譯、特殊符號的處理。使用的命令是:
gcc -E x.c -o x.i //這里的x指的是依賴的文件的文件名和要生成的文件名
-E:該選項的作用用是讓 gcc 在預處理結束后停止止編譯過程。
-o:指定生成的文件名。
例如:
可以看到這里已經生成了一個名字為test.i的文件:
用cat命令看一下文件test.i的內容:
可以看到,頭文件tran.h已經被替換為上面那些亂七八槽的東西了,宏NUM也被替換為它對應的數字1234。
(2)編譯,生成匯編文件.s
編譯程序,所要作的工作就是通過詞法分析、語義分析、符號匯總和語法分析,在確認所有的指令都符合語法規則之后,將其翻譯成等價的中間代碼表示或匯編代碼。使用的命令是:
gcc -S x.i -o x.s //這里的x指的是依賴的文件的文件名和要生成的文件名
-S:該選項只進行編譯而不進行匯編,生成匯編代碼。
-o:指定生成的文件名
例如:
可以看到已經生成了名為test.s的文件
用cat命令看一下test.s的內容:
可以看到確實是生成了匯編代碼
(3)匯編,生成目標文件 .o文件
匯編過程實際上指把匯編語言代碼翻譯成目標機器指令的過程,也就是說把匯編代碼轉換為二進制文件(即目標文件),目標文件中所存放的是與源程序等效的目標的機器語言代碼。
目標文件由段組成:一個目標文件中至少有兩個段:
代碼段:主要包含的是程序的指令。該段一般是可讀、可執行、不可寫。
數據段:主要存放程序中的全局變量或靜態的數據。一般數據段都是可讀、可執行、可寫 。
這兒使用的命令是:
gcc -c x.s -o x.o
-c:將匯編代碼生成二進制的目標文件
-o:指定生成的文件名
例如:
可以看到已經生成了文件tets.o
(4)鏈接,生成可執行程序
由匯編程序生成的目標文件并不能立即就被執行,其中可能還有許多沒有解決的問題。例如,某個源文件中的函數可能引用了另一個源文件中定義的某個符號(如變量或者函數調用等);在程序中可能調用了某個庫文件中的函數,等等。所有的這些問題,都需要經鏈接程序的處理方能得以解決。
鏈接程序的主要工作就是將有關的目標文件彼此相連接,也即將在一個文件中引用的符號同該符號在另外一個文件中的定義連接起來,使得所有的這些目標文件成為一個能夠誒操作系統裝入執行的統一整體。
根據開發人員指定的同庫函數的鏈接方式的不同,鏈接處理可分為兩種:
(1)靜態鏈接:在這種鏈接方式下,函數的代碼將從其所在地靜態鏈接庫中被拷貝到最終的可執行程序中。這樣該程序在被執行時這些代碼將被裝入到該進程的虛擬地址空間中。靜態鏈接庫實際上是一個目標文件的集合,其中的每個文件含有庫中的一個或者一組相關函數的代碼。(個人備注:靜態鏈接將鏈接庫的代碼復制到可執行程序中,使得可執行程序體積變大)
(2)動態鏈接:在此種方式下,函數的代碼被放到稱作是動態鏈接庫或共享對象的某個目標文件中。鏈接程序此時所作的只是在最終的可執行程序中記錄下共享對象的名字以及其它少量的登記信息。在此可執行文件被執行時,動態鏈接庫的全部內容將被映射到運行時相應進程的虛地址空間。動態鏈接程序將根據可執行程序中記錄的信息找到相應的函數代碼。(個人備注:動態鏈接指的是需要鏈接的代碼放到一個共享對象中,共享對象映射到進程虛地址空間,鏈接程序記錄可執行程序將來需要用的代碼信息,根據這些信息迅速定位相應的代碼片段。可移植性差)
這兒使用的命令是:
gcc -o x x1.o x2.o ……
這兒的-o后面的x是生成的可執行程序的名稱,x1.o,x2.o……是所有需要被鏈接到一起的.o文件。
例如:
這兒省略了tran.o的生成過程
可以看到已經生成了可執行文件test
3、gcc/g++的選項擴展
當然,我們平時不用這么麻煩的一步步執行下來,上面是為了展示一下gcc的編譯過程,平時我們在編譯.c文件時,直接使用命令:
gcc -o file file1.c file2.c ……
file是生成的可執行程序的名字,file1.c,file2.c是要用到的源文件。
下面列出一些常見的gcc選項:
1、-O0 -O1 -O2 -O3 譯器的優化選項的4個級別,-O0表示示沒有優化,-O1為缺省值,-O3優化級別最高高
2、-w 不生生成任何警告信息
3、-Wall 生成所有警告信息。
4、-g 生成調試信息。GNU 調試器可利用用該信息。
5、-static 此選項將禁止使用動態庫,所以,編譯出來的東西,一般都很大。
6、-share 此選項將盡量使用動態庫,所以生成文件比較小,但是需要系統由動態庫。
總結
以上是生活随笔為你收集整理的浅析Linux开发工具之gcc/g++的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: @bean注解和@component注解
- 下一篇: apache启服务命令_Linux系统重