標籤:

gcc&arm-linux-gcc編譯過程詳解

gcc&arm-linux-gcc編譯過程詳解

來自專欄 嵌入式Linux那些事兒

arm裸機1期加強版第9課,內容實在太多,如果編輯成一篇文章,估計大家難消化所以我把它拆分為三部分:1.gcc 2.指針,3.Makefile ,今天是第一部分gcc,內容同樣適用於arm-linux-gcc。

老規矩,文字無法完整描述視頻內容,如果覺得這些文章對你有用,想進一步學習更深層次的乾貨,請訪問100ask.taobao.com購買arm裸機1期加強版視頻課程。

第1節_gcc編譯器1_常用選項_編譯過程詳解

gcc的使用方法

gcc [選項] 文件名

gcc常用選項

一個c/c++文件要經過預處理、編譯、彙編和鏈接才能變成可執行文件

? (1)預處理

C/C++源文件中,以#開頭的命令被稱為預處理命令,如"#include"、宏定義命令"#define"、條件編譯命令"#if、#ifdef"等。

預處理是將包含(include)的文件插入原文件中、將宏定義展開、根據條件編譯命令選擇要使用的代碼,最後將這些東西輸出到一個.i文件中並等待進一步處理。

? (2)編譯

編譯就是把C/C++代碼(比如上述的.i文件)翻譯成彙編代碼。

? (3)彙編

彙編就是將第二步輸出的彙編代碼翻譯成符合一定格式的機器代碼,在Linux系統上一般表現為ELF目標文件(OBJ文件)。

反彙編是指將機器代碼轉換為彙編代碼,這在調試程序時常常用到。

? (4)鏈接

鏈接就是將上步生成的OBJ文件和系統庫的OBJ文件、庫文件鏈接起來,最終生成可以在特定平台運行的可執行文件。

hello.c(預處理) -> hello.i(編譯) -> hello.s(彙編) -> hello.o(鏈接) -> hello

詳細的每一步命令如下:

上面一連串命令有點多,gcc會對.c文件默認進行預處理操作,使用-c指明編譯、彙編,從而得到.o文件, 再將.o文件進行鏈接,得到可執行應用程序。

簡化的命令如下:

第2節_gcc編譯器2_深入講解鏈接過程

前面編譯出來的可執行文件比源代碼大了很多,這是什麼原因呢?

執行命令:

gcc -c -o hello.o hello.c

gcc -v -o hello hello.o

可以看到程序的編譯鏈接過程,從鏈接過程分析,鏈接將彙編生成的OBJ文件、系統庫的OBJ文件、庫文件鏈接起來,crt1.o、crti.o、crtbegin.o、crtend.o、crtn.o這些都是gcc加入的系統標準啟動文件,它們的加入使最後出來的可執行文件比原來大了很多。

-lc:鏈接libc庫文件,其中libc庫文件中實現了printf等函數。

比如:

gcc -v -nostdlib -o hello hello.o:

會提示因為沒有鏈接系統標準啟動文件和標準庫文件,而鏈接失敗。

這個-nostdlib選項常用於裸機bootloader、linux內核等程序,因為它們不需要啟動文件、標準庫文件。

一般應用程序才需要系統標準啟動文件和標準庫文件。

裸機/bootloader、linux內核等程序不需要啟動文件、標準庫文件。

動態鏈接和靜態鏈接的區別

? 動態鏈接(默認就是動態鏈接)使用動態鏈接庫進行鏈接,生成的程序在執行的時候需要載入所需的動態庫才能運行。

動態鏈接生成的程序體積較小,但是必須依賴所需的動態庫,否則無法執行。

gcc -c -o hello.o hello.c

gcc -o hello_shared hello.o

? 靜態鏈接使用靜態庫進行鏈接,生成的程序包含程序運行所需要的全部庫,可以直接運行, 不過靜態鏈接生成的程序體積較大。

gcc -c -o hello.o hello.c

gcc -static -o hello_static hello.o

效果演示均見視頻。

想要更多嵌入式Linux乾貨,請關注微信公眾號baiwenkeji

推薦閱讀:

後硬體時代的彷徨與困惑:嵌入式是個大坑?
融合發生之前,嵌入式開發中DSP與FPGA之間的關係
單片機如何入門,先搞清這幾個問題。
嵌入式開發高手
物聯網時代下嵌入式在各個行業的應用

TAG:嵌入式開發 |