linux-gcc簡要知識點 **


交叉編譯

使用不同的交叉編譯工具鏈編譯源碼,能在不同框架的處理器上運行。
如:

  • X86
gcc -o hello hello.c

上述命令編譯出來的文件能在 X86 上運行,因為 gcc 編譯工具鏈是給PC編譯的。

  • ARM
arm-linux-gnueabihf-gcc -o hello hello.c

上述命令編譯出來的文件能在 ARM 上運行。

簡要知識點 **

  1. 頭文件的作用:
    1. 聲明(declare)
  2. c文件的作用
    1. 定義、實現(define)
  3. 頭文件尋址
    1. 默認路徑:編譯器中的 include 目錄
    2. 可指定:
      1. #include "xx/xx.h" :由當前文件路徑算起
      2. 編譯時用 “-I” 選項指定
  4. c文件內的外部函數在哪裡,如 printf 函數:
    1. 庫:
      1. 默認路徑:編譯器中的 lib 目錄
      2. 可指定:
        1. 編譯時用 “-I” 指定庫文件
        2. 編譯時用 “-L”指定庫目錄
  5. 怎麼確定交叉編譯器中頭文件的默認路徑?
    1. 進入交叉編譯器的目錄,使用find命令直接查找,如
      • 執行”find -name “stdio.h”
  6. 怎麼確定交叉編譯器中庫的默認路徑?
    1. 進入交叉編譯器的目錄,執行”find -name lib“,進去看看, 有很多 .so 文件的裏面就是要找的路徑。

一些概念

  1. 交叉編譯工具鏈中的 include 目錄和lib 目錄:
    1. include 存放頭文件
      1. 這些頭文件一般是函數聲明,還有一些變量聲明,名字空間,宏定義,typedef 等等
    2. lib 存放obj文件的(對gcc來說為.o)
      1. 也就是說,一些庫文件,人家不想讓你看見源代碼,只是給了你中間生成的obj文件

GCC編譯器

 PC機上的編譯工具鏈有 gcc、ld、objcopy、objdump等等,他們編譯出來的程序能在 X86 平台上運行。
 要使編譯出來的的程序能在 ARM 上運行,就必須使用交叉編譯工具鏈 xxx-gcc、xxx-ld等(不同版本的編譯器的前綴不一樣,如 arm-linux-gcc)。

GCC簡要使用

GCC編譯過程 **

 一個C/C++文件要經過預處理、編譯、彙編、鏈接等4個步驟才能變成一個可執行文件。(日常交流中用 編譯 統稱以上四大步驟

  1. 預處理,在預處理過程中,對源代碼文件中的文件包含(include)、 預編譯語句(如宏定義define等)進行展開,生成.i文件。 可理解為把頭文件的代碼、宏之類的內容轉換成更純粹的C代碼,不過生成的文件以.i為後綴。
  2. 編譯,把預處理後的.i文件通過編譯成為彙編語言,生成.s文件,即把代碼從C語言轉換成彙編語言,這是GCC編譯器完成的工作。
  3. 彙編,將彙編語言文件經過彙編,生成目標文件.o文件,每一個源文件都對應一個目標文件。即把彙編語言的代碼轉換成機器碼,這是as彙編器完成的工作。
  4. 鏈接,最後將每個源文件對應的.o文件鏈接起來,就生成一個可執行程序文件,這是鏈接器ld完成的工作。
    • 鏈接分為兩種
      • 動態鏈接
        • GCC編譯時的默認選項。
        • 指應用程序運行時才去加載外部的代碼庫。
      • 靜態鏈接
        • 鏈接時使用選項 –static
        • 它在編譯階段就會把所有用到的庫打包到自己的可執行程序中。

常用的編譯選項

選項 描述
-E 預處理,開發過程中想快速確定某個宏可以使用 「-E -dM」
-c 做了預處理、編譯、彙編,但是沒做鏈接
-o 指定輸出文件
-I 指定頭文件目錄(大寫 i)
-l 指定鏈接到哪一個庫文件(小寫 L)
-L 指定鏈接時庫文件目錄

編譯多個文件

  1. 一起編譯、鏈接:
    如:
gcc -o hello main.c hello.c
  1. 分開編譯,統一鏈接:
    如:
gcc -c -o main.o main.c
gcc -c -o hello.o hello.c
gcc -o hello main.o hello.o

製作、使用動態庫

  1. 製作、編譯:
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 文件所在目錄*)
  1. 運行
    1. libhello.so 放到PC或板子的/lib目錄下,然後運行test程序。
    2. 如果不想把 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 會用到

參考