在Python中,你僅僅需要輸入python
,就可以運(yùn)行你想要運(yùn)行的代碼。Python的解釋器會(huì)運(yùn)行它們,并且在運(yùn)行中導(dǎo)入它所需的庫(kù)和其它東西。C是完全不同的東西,你需要事先編譯你的源文件,并且手動(dòng)將它們整合為一個(gè)可以自己運(yùn)行的二進(jìn)制文件。手動(dòng)來(lái)做這些事情很痛苦,在上一個(gè)練習(xí)中只需要運(yùn)行make
就能完成。
這個(gè)練習(xí)是GNU make 的速成課,由于你在學(xué)C語(yǔ)言,所以你就必須掌握它。Make 將貫穿剩下的課程,等效于Python(命令)。它會(huì)構(gòu)建源碼,執(zhí)行測(cè)試,設(shè)置一些選項(xiàng)以及為你做所有Python通常會(huì)做的事情。
有所不同的是,我會(huì)向你展示一些更智能化的Makefile魔法,你不需要指出你的C程序的每一個(gè)愚蠢的細(xì)節(jié)來(lái)構(gòu)建它。我不會(huì)在練習(xí)中那樣做,但是你需要先用一段時(shí)間的“低級(jí) make”,我才能向你演示“大師級(jí)的make”。
使用make的第一階段就是用它已知的方式來(lái)構(gòu)建程序。Make預(yù)置了一些知識(shí),來(lái)從其它文件構(gòu)建多種文件。上一個(gè)練習(xí)中,你已經(jīng)使用像下面的命令來(lái)這樣做了:
$ make ex1
# or this one too
$ CFLAGS="-Wall" make ex1
第一個(gè)命令中你告訴make,“我想創(chuàng)建名為ex1的文件”。于是Make執(zhí)行下面的動(dòng)作:
ex1
存在嗎?ex1
開(kāi)頭?ex1.c
。我知道如何構(gòu)建.c
文件嗎?cc ex1.c -o ex1
來(lái)構(gòu)建它。cc
從ex1.c
文件來(lái)為你構(gòu)建ex1
。上面列出的第二條命令是一種向make命令傳遞“修改器”的途徑。如果你不熟悉Unix shell如何工作,你可以創(chuàng)建這些“環(huán)境變量”,它們會(huì)在程序運(yùn)行時(shí)生效。有時(shí)你會(huì)用一條類(lèi)似于export CFLAGS="-Wall"
的命令來(lái)執(zhí)行相同的事情,取決于你所用的shell。然而你可以僅僅把它們放到你想執(zhí)行的命令前面,于是環(huán)境變量只會(huì)在程序運(yùn)行時(shí)有效。
在這個(gè)例子中我執(zhí)行了CFLAGS="-Wall" make ex1
,所以它會(huì)給make通常使用的cc
命令添加-Wall
選項(xiàng)。這行命令告訴cc
編譯器要報(bào)告所有的警告(然而實(shí)際上不可能報(bào)告所有警告)。
實(shí)際上你可以深入探索使用make的上述方法,但是先讓我們來(lái)看看Makefile
,以便讓你對(duì)make了解得更多一點(diǎn)。首先,創(chuàng)建文件并寫(xiě)入以下內(nèi)容:
CFLAGS=-Wall -g
clean:
rm -f ex1
將文件在你的當(dāng)前文件夾上保存為Makefile
。Make會(huì)自動(dòng)假設(shè)當(dāng)前文件夾中有一個(gè)叫做Makefile
的文件,并且會(huì)執(zhí)行它。此外,一定要注意:確保你只輸入了 TAB 字符,而不是空格和 TAB 的混合。
譯者注:上述代碼中第四行
rm
前面是一個(gè) TAB ,而不是多個(gè)等量的空格。
Makefile
向你展示了make的一些新功能。首先我們?cè)谖募性O(shè)置CFLAGS
,所以之后就不用再設(shè)置了。并且,我們添加了-g
標(biāo)識(shí)來(lái)獲取調(diào)試信息。接著我們寫(xiě)了一個(gè)叫做clean
的部分,它告訴make如何清理我們的小項(xiàng)目。
確保它和你的ex1.c
文件在相同的目錄中,之后運(yùn)行以下命令:
$ make clean
$ make ex1
如果代碼能正常工作,你應(yīng)該看到這些:
$ make clean
rm -f ex1
$ make ex1
cc -Wall -g ex1.c -o ex1
ex1.c: In function 'main':
ex1.c:3: warning: implicit declaration of function 'puts'
$
你可以看出來(lái)我執(zhí)行了make clean
,它告訴make執(zhí)行我們的clean
目標(biāo)。再去看一眼Makefile,之后你會(huì)看到在它的下面,我縮進(jìn)并且輸入了一些想要make為我運(yùn)行的shell命令。你可以在此處輸入任意多的命令,所以它是一個(gè)非常棒的自動(dòng)化工具。
注
如果你修改了
ex1.c
,添加了#include<stdio>
,輸出中的關(guān)于puts
的警告就會(huì)消失(這其實(shí)應(yīng)該算作一個(gè)錯(cuò)誤)。我這里有警告是因?yàn)槲也](méi)有去掉它。
同時(shí)也要注意,即使我們?cè)?code>Makefile中并沒(méi)有提到ex1
,make
仍然會(huì)知道如何構(gòu)建它,以及使用我們指定的設(shè)置。
上面那些已經(jīng)足夠讓你起步了,但是讓我們以一種特定的方式來(lái)破壞make文件,以便你可以看到發(fā)生了什么。找到rm -f ex1
的那一行并去掉縮進(jìn)(讓它左移),之后你可以看到發(fā)生了什么。再次運(yùn)行make clean
,你就會(huì)得到下面的信息:
$ make clean
Makefile:4: *** missing separator. Stop.
永遠(yuǎn)記住要縮進(jìn),以及如果你得到了像這種奇奇怪怪的錯(cuò)誤,應(yīng)該復(fù)查你是否都使用了 TAB 字符,由于一些make的變種十分挑剔。
all:ex1
,可以以單個(gè)命令make
構(gòu)建ex1
。man make
來(lái)了解關(guān)于如何執(zhí)行它的更多信息。man cc
來(lái)了解關(guān)于-Wall
和-g
行為的更多信息。Makefile
文件,并且嘗試?yán)斫馑隽耸裁础?/li>