Linux:編譯,鏈接,自動(dòng)化構(gòu)建工具

c語(yǔ)言源代碼編譯成可執(zhí)行程序的過(guò)程包括以下幾個(gè)步驟,每一步都對(duì)源代碼進(jìn)行了不同的處理:

  1. 預(yù)處理(.c文件 -> .i文件)

    目的:將頭文件和宏進(jìn)行替換,取消注釋。文件從 code.c 變?yōu)?code.i。

    Linux:編譯,鏈接,自動(dòng)化構(gòu)建工具

    現(xiàn)在我使用指令對(duì) .c 文件進(jìn)行預(yù)處理,讓我們來(lái)看一下預(yù)處理后的代碼:

    gcc -E code.c -o code.i

    可以看到頭文件確實(shí)被庫(kù) 中的代碼替換了;而其他代碼保持不變。

    Linux:編譯,鏈接,自動(dòng)化構(gòu)建工具

    注意:替換后的代碼仍然是c語(yǔ)言代碼,只是變得更加簡(jiǎn)潔(沒(méi)有注釋?zhuān)?/p>

  2. 編譯(.i文件 -> .s文件)

    目的:將C語(yǔ)言代碼處理為匯編代碼。

    這次我們直接使用預(yù)處理過(guò)的文件進(jìn)行下一步的匯編:

    gcc -S code.i -o code.s

    Linux:編譯,鏈接,自動(dòng)化構(gòu)建工具

    我們發(fā)現(xiàn)這次處理后的代碼已經(jīng)變成我們看不懂的了,這就是已經(jīng)從C代碼轉(zhuǎn)換為了匯編代碼。

  3. 匯編(.s文件 -> .o文件)

    目的:進(jìn)一步處理匯編代碼,形成機(jī)器可識(shí)別的代碼(可重定向目標(biāo)文件)。

    這次我們使用上一次的 code.s 文件繼續(xù)編譯,會(huì)報(bào)錯(cuò);所以我們這次使用 code.c 來(lái)進(jìn)行處理:

    gcc -c code.c -o code.o

    Linux:編譯,鏈接,自動(dòng)化構(gòu)建工具

    這次的代碼和上次的有變化,但還是看不懂。我們記住是從匯編代碼處理為了機(jī)器可識(shí)別的代碼,變成了可重定向目標(biāo)文件。

  4. 鏈接(.o文件 -> exe文件)

    目的:產(chǎn)生可執(zhí)行文件。

    這次使用 .o 文件鏈接為 exe 文件:

    gcc code.o -o code

    Linux:編譯,鏈接,自動(dòng)化構(gòu)建工具

    E、S、c選項(xiàng)先有語(yǔ)言還是先有編譯器?答案是先有語(yǔ)言,但并不是先有當(dāng)前編譯器的語(yǔ)言。在最早的時(shí)期,人們都是使用二進(jìn)制語(yǔ)言來(lái)編寫(xiě)程序的;然而,為了更加方便地編寫(xiě)代碼,人們使用二進(jìn)制編寫(xiě)了匯編代碼,因此匯編語(yǔ)言產(chǎn)生了。然后,人們又使用匯編代碼開(kāi)發(fā)出了匯編代碼編譯器,這個(gè)過(guò)程就叫做語(yǔ)言自舉。

    動(dòng)態(tài)連接和靜態(tài)連接庫(kù)的位置,我們平時(shí)使用的頭文件都是聲明,實(shí)現(xiàn)都在庫(kù)文件中,庫(kù)一般都在 /usr/include 目錄下。

    Linux:編譯,鏈接,自動(dòng)化構(gòu)建工具

    連接方式分為動(dòng)態(tài)鏈接和靜態(tài)連接。

    查看文件使用的哪種庫(kù)?

    Linux:編譯,鏈接,自動(dòng)化構(gòu)建工具

    根據(jù)紅色的部分判斷是什么庫(kù)?

    云服務(wù)器默認(rèn)沒(méi)有安裝C/c++靜態(tài)標(biāo)準(zhǔn)庫(kù),我們可以使用 yum 按照下面的指令安裝:

    sudo yum install libstdc++-static

    Makefile自動(dòng)構(gòu)建工具

    我們可以把 Makefile 理解為指令的集合;Makefile 文件里有我們寫(xiě)好的很多指令,然后我們對(duì) Makefile 進(jìn)行操作就可以更加便捷地調(diào)用其內(nèi)部的指令。

    舉個(gè)例子,比如有一份 proc.c 的C語(yǔ)言文件,在使用的過(guò)程中需要多次對(duì)文件編譯,通常情況下每次編譯都要使用 gcc proc.c -o proc 生成可執(zhí)行文件 proc;這樣操作是很麻煩的。Makefile 工具可以很好地解決這種頻繁調(diào)用編譯的問(wèn)題。

    Makefile 的使用:

    Linux:編譯,鏈接,自動(dòng)化構(gòu)建工具

    第一行:proc 是生成的文件,proc.c 是依賴(lài)文件;冒號(hào)代表的是依賴(lài)關(guān)系。第二行需要空一個(gè) Tab 鍵的長(zhǎng)度(不能使用空格),然后輸入要執(zhí)行的命令。

    Linux:編譯,鏈接,自動(dòng)化構(gòu)建工具

    我們直接使用指令 make 就可以調(diào)用 gcc proc.c -o proc 指令了,這樣使用起來(lái)是不是會(huì)很方便?

    那是不是也可以這樣方便地清理文件呢?

    答案是可以的:

    Linux:編譯,鏈接,自動(dòng)化構(gòu)建工具

    不同的是刪除代碼不需要依賴(lài)任何文件,所以沒(méi)有依賴(lài)文件。我們需要使用 make clean 來(lái)調(diào)用清除可執(zhí)行程序的指令。

    為什么 gcc proc.c -o proc 直接使用 make 就可以呢?

    這是因?yàn)榇a的執(zhí)行順序是從上到下的,make 默認(rèn)調(diào)用第一個(gè)依賴(lài)關(guān)系命令,這里實(shí)際上 make 的完整指令應(yīng)該是 make proc。

    目標(biāo)的調(diào)用順序

    現(xiàn)在來(lái)寫(xiě)一下C語(yǔ)言編譯的完整過(guò)程:

    Linux:編譯,鏈接,自動(dòng)化構(gòu)建工具

    程序執(zhí)行的順序是從上往下執(zhí)行的,當(dāng)執(zhí)行 gcc proc.o -o proc 時(shí),這時(shí)候還沒(méi)有 proc.o 文件,所以就會(huì)先把這一行的指令放入中,依次類(lèi)推,直到最后 gcc -E proc.c -o proc.i 產(chǎn)生了 proc.i 文件,緊接著指令依次出棧;最后執(zhí)行完畢。

    .PHONY偽目標(biāo)

    在沒(méi)有使用 .PHONY 的情況下,proc.c 文件在最新版本時(shí),只能 make 一次。這樣做的目的是提高效率。

    Linux:編譯,鏈接,自動(dòng)化構(gòu)建工具

    在此編譯會(huì)給出“proc is up to date”,proc 可執(zhí)行程序是最新的,不需要再次編譯。

    如何查看文件是否是最新的?

    Linux:編譯,鏈接,自動(dòng)化構(gòu)建工具

    stat 文件名:查看文件的最近一次的更改時(shí)間相關(guān)的信息。正常情況下,proc.c 文件的時(shí)間應(yīng)該是在 proc 之前的,因?yàn)橄扔?proc.c 再有 proc;這是我剛才更新了一下 proc.c 文件,這時(shí)候 proc.c 比 proc 還要新,所以這個(gè)時(shí)候是可以重新編譯的。

    使用偽目標(biāo)忽略時(shí)間:

    Linux:編譯,鏈接,自動(dòng)化構(gòu)建工具

    如果我們對(duì) make proc 設(shè)置偽目標(biāo),那樣就可以無(wú)限次地編譯了。

    Linux:編譯,鏈接,自動(dòng)化構(gòu)建工具

    總結(jié)

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點(diǎn)贊15 分享