GCC編譯和連結多個檔案(包括原始檔、目標檔案、組合檔案等)

2020-07-16 10:04:43
編譯多個原始碼檔案會生成多個目標檔案,每個目標檔案都包含一個原始檔的機器碼和相關資料的符號表。除非使用-c選項指示 GCC 只編譯不連結,否則 GCC 會使用臨時檔案作為目標檔案輸出:

$ gcc -c main.c
$ gcc -c func.c

這些命令會在當前目錄中生成兩個目標檔案,分別是 main.o 和 func.o。把兩個原始檔名放在同一個 GCC 命令中,也可以獲得同樣的結果:

$ gcc -c main.c func.c

然而,實際上編譯器通常每次只會被呼叫來完成一件小型任務。大的程式包含許多原始檔,在開發期間必須被編譯、測試、編輯,然後再編譯,很少會有在建立中的修改行為會影響所有的原始檔。為了節省時間,可以使用 make 控制建立過程,由它呼叫編譯器重新編譯,而且只編譯比對應的最新原始檔舊的那些目標檔案。

一旦所有當前原始檔都被編譯為目標檔案,就可以使用 GCC 來連結它們:

$ gcc main.o func.o -o app.out -lm

GCC 假設擴充套件名為.o的檔案是要被連結的目標檔案。

檔案型別

編譯器支援許多和C語言程式相關的擴充套件名,對它們的說明如下:
擴充套件名(字尾) 說明
.c C程式原始碼,在編譯之前要先進行預處理。
.i C程式預處理輸出,可以被編譯。
.h C程式標頭檔案。(為了節省時間,許多原始檔會包含相同的標頭檔案,GCC 允許事先編譯好標頭檔案,稱為“預編譯標頭檔案”,它合適情況下自動被用於編譯。)
.s 組合語言。
.S 有C命令的組合語言,在組合之前必須先進行預處理。

GCC 也支援以下擴充套件名:.ii、.cc、.cp、.cxx、.cpp、.CPP、.c++、.C、.hh、.H、.m、.mi、.f、.for、.FOR、.F、.fpp、.FPP、.r、.ads 和 .adb。這些檔案型別涉及 C++、Objective-C、Fortran 或 Ada 等程式的編譯。使用其他擴充套件名的檔案會被視為物件檔案,以作為連結之用。

如果使用其他命名慣例為輸入檔案命名,可以使用-x file_type選項來指示 GCC 應該如何對待這些檔案。file_type 必須是下面其中之一:c、c-header、cpp-output、assembler(表示該檔案包含組合語言)、assembler-with-cpp 或 none。

在命令列中,-x後面所列的所有檔案都會被視為所指定的型別。如果想改變型別,可以再次使用-x。如下例所示:

$ gcc -o bigprg mainpart.c -x assembler trickypart.asm -x c otherpart.c

可以在同一個命令列中多次使用-x選項,以指示不同型別的檔案。-x none選項會全部取消這些指示,後續檔案會按照 GCC 預設規則解釋它們的擴充套件名。

混合輸入型別

可以在 GCC 命令列中混合使用其他輸入檔案型別。如果編譯器不能按照請求處理指定的檔案,那麼它會忽略它們。如下例所示:

$ gcc main.c func.o -o app.out -lm

借助於這個命令,假設指定的檔案都存在,GCC 會編譯和組合 main.c,組合 func.o,並且連結庫檔案 libm.a。