交叉編譯必知--gcc/g++詳細講解

了解c/c++編譯器的基本使用昧互,能夠在后續(xù)移植第三方框架進行交叉編譯時(編譯android可用的庫),清楚的了解應(yīng)該傳遞什么參數(shù)。android的Android.mk就是一段段Makefile單元,很多第三方庫直接提供makefile,需要能夠大致的讀懂makefile文件谅年。

gcc/g++

gcc

GNU C編譯器。原本只能處理C語言肮韧,很快擴展融蹂,變得可處理C++。

g++

gcc和g++都能夠編譯c/c++弄企,但是編譯時候行為不同超燃。

對于gcc與g++:

  • 后綴為.c的源文件,gcc把它當作是C程序拘领,而g++當作是C++程序意乓;后綴為.cpp的,兩者都會認為是c++程序约素。
  • g++會自動鏈接c++標準庫stl届良,gcc不會笆凌。
  • gcc不會定義__cplusplus宏,而g++會士葫。

編譯器過程

一個C/C++文件要經(jīng)過預(yù)處理(preprocessing)乞而、編譯(compilation)、匯編(assembly)为障、和鏈接(linking)才能變成可執(zhí)行文件晦闰。

1、預(yù)處理

?gcc -E main.c -o main.i

?-E的作用是讓gcc在預(yù)處理結(jié)束后停止編譯鳍怨。
?預(yù)處理階段主要處理include和define等。它把#include包含進來的.h 文件插入到#include所在的位置跪妥,把源程序中使用到的用#define定義的宏用實際的字符串代替

2鞋喇、編譯階段

gcc -S main.i -o main.s

-S的作用是編譯后結(jié)束,編譯生成了匯編文件眉撵。
?在這個階段中侦香,gcc首先要檢查代碼的規(guī)范性、是否有語法錯誤等纽疟,以確定代碼的實際要做的工作罐韩,在檢查無誤后,gcc把代碼翻譯成匯編語言污朽。

3散吵、匯編階段

gcc -c main.s -o main.o

匯編階段把 .s文件翻譯成二進制機器指令文件.o,這個階段接收.c, .i, .s的文件都沒有問題。

4蟆肆、鏈接階段

?gcc -o main main.s

鏈接階段矾睦,鏈接的是函數(shù)庫。在main.c中并沒有定義”printf”的函數(shù)實現(xiàn)炎功,且在預(yù)編譯中包含進的”stdio.h”中也只有該函數(shù)的聲明枚冗。系統(tǒng)把這些函數(shù)實現(xiàn)都被做到名為libc.so的動態(tài)庫。

/etc/ld.so.conf
在沒有特別指定時蛇损,gcc會到系統(tǒng)編譯器只會使用/lib和/usr/lib這兩個目錄下的庫文件赁温。如果存在一個so不在這兩個目錄,在編譯時候就會出現(xiàn)找不到的情況淤齐。
/etc/ld.so.conf文件中可以指定而外的編譯鏈接庫路徑股囊。
輸入:cat /etc/ld.so.conf:

include /etc/ld.so.conf.d/*.conf #引入其他的conf文件
/usr/local/lib  #增加庫搜索目錄

#編輯完成后 使用 ldconfig 更新

靜態(tài)庫和動態(tài)庫

庫通常以前綴“ lib”命名。對于所有C標準庫都是如此床玻。鏈接時毁涉,對庫的命令行引用將不包含庫前綴或后綴。
比如liblog.so這個庫锈死,引用的使用去掉前綴lib和后綴.so即可引用該庫贫堰。

.a 為靜態(tài)庫穆壕,可以是一個或多個.o合在一起,用于靜態(tài)連接;多個.o文件可以鏈接生成一個.exe的可執(zhí)行文件其屏。靜態(tài)庫在程序編譯時會被鏈接到目標代碼中喇勋,相當于將你使用庫里的函數(shù)加載到程序里,在編譯的時候直接編譯進去偎行,這樣川背,在編譯之后執(zhí)行程序時將不再需要該靜態(tài)庫。編譯之后程序文件大蛤袒,但加載快熄云,隔離性也好。所以它的優(yōu)點就顯而易見了妙真,即編譯后的執(zhí)行程序不需要外部的函數(shù)庫支持缴允,因為所有使用的函數(shù)都已經(jīng)被編譯進去了。當然這也會成為它的缺點珍德,因為如果靜態(tài)函數(shù)庫改變了练般,那么你的程序必須重新編譯。

.so 為動態(tài)庫(共享庫)锈候,類似windows平臺的.dll文件薄料。動態(tài)庫在程序編譯時并不會被鏈接到目標代碼中,而是在編譯時僅引用泵琳,體積小摄职,在程序運行到相關(guān)函數(shù)時才調(diào)用函數(shù)庫里的相應(yīng)函數(shù),才被載入虑稼,因此在程序運行時還需要動態(tài)庫存在琳钉。多個應(yīng)用程序可以使用同一個動態(tài)庫,啟動多個應(yīng)用程序的時候蛛倦,只需要將動態(tài)庫加載到內(nèi)存一次即可歌懒。

簡而言之:
靜態(tài)庫節(jié)省時間,靜態(tài)庫在程序編譯時會被連接到目標代碼中溯壶,程序運行時將不再需要該靜態(tài)庫及皂。
動態(tài)庫節(jié)省空間,動態(tài)庫在程序編譯時并不會被連接到目標代碼中且改,而是在程序運行是才被載入验烧,因此在程序運行時還需要動態(tài)庫存在。
Java中在不經(jīng)過封裝的情況下只能直接使用動態(tài)庫又跛。

生成靜態(tài)庫

gcc -fPIC -c  Test.c -o Test.o
ar r libTest.a Test.o 

-fPIC 產(chǎn)生與位置無關(guān)代碼 
可能會被不同的進程加載到不同的位置上碍拆,如果共享對象中的指令使用了絕對地址。
那么在共享對象被加載時就必須根據(jù)相關(guān)模塊的加載位置對這個地址做調(diào)整,也就是修改這些地址感混,
讓它在對應(yīng)進程中能正確訪問端幼,那么就不能實現(xiàn)多進程共享一份物理內(nèi)存(無法動態(tài)共享)

這里有一個例子,詳細介紹了靜態(tài)庫的生成和如何鏈接靜態(tài)庫弧满。

生成動態(tài)庫

gcc -fPIC -shared Test.c -o libTest.so
#或者
gcc -fPIC -c Test.c  #生成.o
gcc -shared Test.o -o libTest.so

-fPIC:編譯器指令婆跑,用于輸出位置無關(guān)的代碼,這是共享庫所需的特征庭呜。
-shared:生成一個共享對象滑进,然后可以將其與其他對象鏈接以形成可執(zhí)行文件。
-Wl 選項:將選項傳遞給鏈接器募谎。 
-o:操作輸出扶关。

這里有一個例子,詳細介紹了靜態(tài)庫的生成和如何鏈接靜態(tài)庫近哟。

使用庫

默認優(yōu)先使用動態(tài)庫
gcc main.c -L. -lTest -o main

強制使用靜態(tài)庫
-Wl 表示傳遞給 ld 鏈接器的參數(shù)
最后的 -Bdynamic 表示 默認仍然使用動態(tài)庫 
gcc main.c -L. -Wl,-Bstatic  -lTest -Wl,-Bdynamic -o main

使用動態(tài)庫鏈接的程序驮审,linux運行需要將動態(tài)庫路徑加入/etc/ld.so.conf。

查看可執(zhí)行文件符號
nm main

打包 .a 到so
--whole-archive: 將未使用的靜態(tài)庫符號(函數(shù)實現(xiàn))也鏈接進動態(tài)庫 
--no-whole-archive : 默認吉执,未使用不鏈接進入動態(tài)庫
gcc -shared -o libMain.so -Wl,--whole-archive libMain.a -Wl,--no-whole-archive

頭文件與庫文件的指定

--sysroot=XX
使用xx作為這一次編譯的頭文件與庫文件的查找目錄,查找下面的 usr/include usr/lib目錄地来。
-isysroot XX
頭文件查找目錄,覆蓋--sysroot 戳玫,查找 XX/usr/include
-isystem XX
指定頭文件查找路徑(直接查找根目錄)
-IXX
頭文件查找目錄
優(yōu)先級: -I > -isystem > sysroot
-L:XX
指定庫文件查找目錄
-lxx.so
指定需要鏈接的庫名

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市未斑,隨后出現(xiàn)的幾起案子咕宿,更是在濱河造成了極大的恐慌,老刑警劉巖蜡秽,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件府阀,死亡現(xiàn)場離奇詭異,居然都是意外死亡芽突,警方通過查閱死者的電腦和手機试浙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來寞蚌,“玉大人田巴,你說我怎么就攤上這事⌒樱” “怎么了壹哺?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長艘刚。 經(jīng)常有香客問我管宵,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任箩朴,我火速辦了婚禮岗喉,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘隧饼。我一直安慰自己沈堡,他們只是感情好,可當我...
    茶點故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布燕雁。 她就那樣靜靜地躺著诞丽,像睡著了一般。 火紅的嫁衣襯著肌膚如雪拐格。 梳的紋絲不亂的頭發(fā)上僧免,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天,我揣著相機與錄音捏浊,去河邊找鬼懂衩。 笑死,一個胖子當著我的面吹牛金踪,可吹牛的內(nèi)容都是我干的浊洞。 我是一名探鬼主播,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼胡岔,長吁一口氣:“原來是場噩夢啊……” “哼法希!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起靶瘸,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤苫亦,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后怨咪,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體屋剑,經(jīng)...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年诗眨,在試婚紗的時候發(fā)現(xiàn)自己被綠了唉匾。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,680評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡辽话,死狀恐怖肄鸽,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情油啤,我是刑警寧澤典徘,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站益咬,受9級特大地震影響逮诲,放射性物質(zhì)發(fā)生泄漏帜平。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一梅鹦、第九天 我趴在偏房一處隱蔽的房頂上張望裆甩。 院中可真熱鬧,春花似錦齐唆、人聲如沸嗤栓。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽茉帅。三九已至,卻和暖如春锭弊,著一層夾襖步出監(jiān)牢的瞬間堪澎,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工味滞, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留樱蛤,地道東北人。 一個月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓剑鞍,卻偏偏與公主長得像昨凡,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子蚁署,可洞房花燭夜當晚...
    茶點故事閱讀 45,691評論 2 361

推薦閱讀更多精彩內(nèi)容