linux-gcc簡要知識點 **
- 2020 年 11 月 9 日
- 筆記
- /label/gcc, /label/linux, /label/lzm, linux, 教程集合
交叉編譯
使用不同的交叉編譯工具鏈編譯源碼,能在不同框架的處理器上運行。
如:
- X86
gcc -o hello hello.c
上述命令編譯出來的文件能在 X86 上運行,因為 gcc 編譯工具鏈是給PC編譯的。
- ARM
arm-linux-gnueabihf-gcc -o hello hello.c
上述命令編譯出來的文件能在 ARM 上運行。
簡要知識點 **
- 頭文件的作用:
- 聲明(declare)
- c文件的作用
- 定義、實現(define)
- 頭文件尋址
- 默認路徑:編譯器中的 include 目錄
- 可指定:
#include "xx/xx.h"
:由當前文件路徑算起- 編譯時用 “-I” 選項指定
- c文件內的外部函數在哪裡,如 printf 函數:
- 庫:
- 默認路徑:編譯器中的 lib 目錄
- 可指定:
- 編譯時用 “-I” 指定庫文件
- 編譯時用 “-L”指定庫目錄
- 庫:
- 怎麼確定交叉編譯器中頭文件的默認路徑?
- 進入交叉編譯器的目錄,使用find命令直接查找,如
- 執行”find -name “stdio.h”“
- 進入交叉編譯器的目錄,使用find命令直接查找,如
- 怎麼確定交叉編譯器中庫的默認路徑?
- 進入交叉編譯器的目錄,執行”find -name lib“,進去看看, 有很多 .so 文件的裏面就是要找的路徑。
一些概念
- 交叉編譯工具鏈中的 include 目錄和lib 目錄:
- include 存放頭文件
- 這些頭文件一般是函數聲明,還有一些變量聲明,名字空間,宏定義,typedef 等等
- lib 存放obj文件的(對gcc來說為.o)
- 也就是說,一些庫文件,人家不想讓你看見源代碼,只是給了你中間生成的obj文件
- include 存放頭文件
GCC編譯器
PC機上的編譯工具鏈有 gcc、ld、objcopy、objdump等等,他們編譯出來的程序能在 X86 平台上運行。
要使編譯出來的的程序能在 ARM 上運行,就必須使用交叉編譯工具鏈 xxx-gcc、xxx-ld等(不同版本的編譯器的前綴不一樣,如 arm-linux-gcc)。
GCC簡要使用
GCC編譯過程 **
一個C/C++文件要經過預處理、編譯、彙編、鏈接等4個步驟才能變成一個可執行文件。(日常交流中用 編譯 統稱以上四大步驟)
- 預處理,在預處理過程中,對源代碼文件中的文件包含(include)、 預編譯語句(如宏定義define等)進行展開,生成.i文件。 可理解為把頭文件的代碼、宏之類的內容轉換成更純粹的C代碼,不過生成的文件以.i為後綴。
- 編譯,把預處理後的.i文件通過編譯成為彙編語言,生成.s文件,即把代碼從C語言轉換成彙編語言,這是GCC編譯器完成的工作。
- 彙編,將彙編語言文件經過彙編,生成目標文件.o文件,每一個源文件都對應一個目標文件。即把彙編語言的代碼轉換成機器碼,這是as彙編器完成的工作。
- 鏈接,最後將每個源文件對應的.o文件鏈接起來,就生成一個可執行程序文件,這是鏈接器ld完成的工作。
- 鏈接分為兩種
- 動態鏈接
- GCC編譯時的默認選項。
- 指應用程序運行時才去加載外部的代碼庫。
- 靜態鏈接
- 鏈接時使用選項
–static
- 它在編譯階段就會把所有用到的庫打包到自己的可執行程序中。
- 鏈接時使用選項
- 動態鏈接
- 鏈接分為兩種
常用的編譯選項
選項 | 描述 |
---|---|
-E | 預處理,開發過程中想快速確定某個宏可以使用 「-E -dM」 |
-c | 做了預處理、編譯、彙編,但是沒做鏈接 |
-o | 指定輸出文件 |
-I | 指定頭文件目錄(大寫 i) |
-l | 指定鏈接到哪一個庫文件(小寫 L) |
-L | 指定鏈接時庫文件目錄 |
編譯多個文件
- 一起編譯、鏈接:
如:
gcc -o hello main.c hello.c
- 分開編譯,統一鏈接:
如:
gcc -c -o main.o main.c
gcc -c -o hello.o hello.c
gcc -o hello main.o hello.o
製作、使用動態庫
- 製作、編譯:
gcc -c -o main.o main.c
gcc -c -o hello.o hello.c
gcc -shared -o libhello.so hello.o hello1.o // (*可以使用多個 .o 生成一個動態庫*)
gcc -o hello main.o -lhello -L <目錄路徑> // (*該路徑為 libhello.so 文件所在目錄*)
- 運行
- 把 libhello.so 放到PC或板子的/lib目錄下,然後運行test程序。
- 如果不想把 libhello.so 放到/lib, 也可以放到自己新建的某個目錄,如 /mylib,然後執行:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/a
./hello
(其實就是修改 庫的環境變量。)
製作、使用靜態庫
gcc -c -o main.o main.c
gcc -c -o hello.o hello.c
ar crs libhello.a hello.o hello1.o // (*可以使用多個 .o 生成一個靜態庫*)
gcc -o hello main.o libhello.a // (*如果 .a 不在當前目錄下,需要指定它的絕對路徑或相對路徑*)
注意:不需要把 hello.a 靜態庫文件拉到板子上
很有用的選項
gcc -E main.c // 查看預處理結果,比如頭文件是哪個
gcc -E -dM main.c > h.txt // 把所有的宏展開,保存到 h.txt 文件里
gcc -Wp,-MD,yl.dep -c -c -o main.o main.c // 生成依賴文件 yl.dep,後面 Makefile 會用到
參考
- 韋東山
- 野火
- gcc-gun
- 建議:想看庫文件源碼時,如printf、malloc之類的,可以進入glibc的官網地址學習