[英]Questions about the GCC compiler and linker
假設您的程序由兩個源文件(main.c和auxiliary.c)和兩個頭文件(declarations.h和auxiliary.h)組成。
然后運行編譯器,如下所示:
$gcc main.c auxiliary.c -o myprogram
問題1 :編譯器是否會為我的程序創建一個單獨的目標文件(即,只缺少庫),還是會創建兩個目標文件,每個源文件一個(然后將所有內容鏈接在一起)?
問題2 :是否需要單獨調用鏈接器? 因為如果您使用上面的命令,編譯器會為您處理,對吧?
問題3 :為什么有些庫會自動鏈接(例如,stdio)以及為什么有些庫需要額外的工作(例如,math.h需要在編譯時添加-lm)。 -lm代表什么?
問題4 :假設您有一個源文件,並且您的程序不需要任何外部庫。 這是否意味着您從編譯器獲得的目標代碼已經可執行? (即編譯它像$ gcc -c main.c)。
gcc通常會為每個源文件創建一個對象。 但是有一個-combine
選項可以告訴你不想這樣做。
當你有幾十個源文件時重新編譯所有內容並不是一個好主意(當你有更多時,你將它們分成庫)。
歷史。 曾經有一段時間 - 在共享庫之前 - 當數學庫相對較大並將其放入每個可執行文件中時,即使那些不需要它的人也被認為是浪費的(使用數學庫涉及像printf這樣的函數的替代版本,所以即使不使用你也有成本)
我等着看一個程序,它甚至不使用標准庫的任何部分(邏輯上調用main作為exit(main(argc, argv))
所以至少exit
調用)然后有啟動和完成代碼。
gcc
為每個源文件創建一個目標文件,然后鏈接它們以構建可執行文件。
您的示例證明gcc
能夠鏈接所有需要的步驟
自動鏈接的庫是標准C庫。 其他需要指定。 這允許在不需要atan2()
時構建較小的可執行文件。
-lm
向編譯器指示它應該找到其id為m
的數學庫。 在Unix上,它的文件名是libm.so
或libm.a
具體取決於鏈接是動態的(在運行時執行並導致較小的可執行文件)還是靜態的(在鏈接時執行並導致獨立的可執行文件)。
不可以。無論如何,它必須與標准C庫相關聯。 而且,目標代碼的文件格式與可執行文件不同。
問題1 :使用'-save-temps'執行gcc語句,您將看到編譯器創建了兩個目標文件。
問題2 :對鏈接器的調用是隱含的。 'gcc'命令實際上不是一個編譯器,但是通過根據需要調用預處理器,編譯器,匯編器和鏈接器來驅動編譯過程。 在小程序中,讓'gcc'處理所有事情是個好主意,但對於包含許多源文件的大型程序,這意味着重新編譯所有源文件,即使它們沒有改變。
問題3 :這是一個慣例問題。 (m庫是數學庫。)
問題4 :不,事實並非如此。 總是需要鏈接一些額外的代碼來處理流程啟動/拆卸要求。 在linux上,這些是crt1.o,crti.o,crtbegin.o和crtn.o文件。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.