練習2:用Make來代替Python
原文:Exercise 2: Make Is Your Python Now
譯者:飛龍
在Python中,你僅僅需要輸入python
,就可以執行你想要執行的程式碼。Python的直譯器會執行它們,並且在執行中匯入它所需的庫和其它東西。C是完全不同的東西,你需要事先編譯你的原始檔,並且手動將它們整合為一個可以自己執行的二進位制檔案。手動來做這些事情很痛苦,在上一個練習中只需要執行make
就能完成。
這個練習是GNU make 的速成課,由於你在學C語言,所以你就必須掌握它。Make 將貫穿剩下的課程,等效於Python(命令)。它會構建原始碼,執行測試,設定一些選項以及為你做所有Python通常會做的事情。
有所不同的是,我會向你展示一些更智慧化的Makefile魔法,你不需要指出你的C程式的每一個愚蠢的細節來構建它。我不會在練習中那樣做,但是你需要先用一段時間的“低階 make”,我才能向你演示“大師級的make”。
使用 Make
使用make的第一階段就是用它已知的方式來構建程式。Make預置了一些知識,來從其它檔案構建多種檔案。上一個練習中,你已經使用像下面的命令來這樣做了:
$ make ex1
# or this one too
$ CFLAGS="-Wall" make ex1
第一個命令中你告訴make,“我想建立名為ex1的檔案”。於是Make執行下面的動作:
-
檔案
ex1
存在嗎? -
沒有。好的,有沒有其他檔案以
ex1
開頭? -
有,叫做
ex1.c
。我知道如何構建.c
檔案嗎? -
是的,我會執行命令
cc ex1.c -o ex1
來構建它。 -
我將使用
cc
從ex1.c
檔案來為你構建ex1
。
上面列出的第二條命令是一種向make命令傳遞“修改器”的途徑。如果你不熟悉Unix shell如何工作,你可以建立這些“環境變數”,它們會在程式執行時生效。有時你會用一條類似於export CFLAGS="-Wall"
的命令來執行相同的事情,取決於你所用的shell。然而你可以僅僅把它們放到你想執行的命令前面,於是環境變數只會在程式執行時有效。
在這個例子中我執行了CFLAGS="-Wall" make ex1
,所以它會給make通常使用的cc
命令新增-Wall
選項。這行命令告訴cc
編譯器要報告所有的警告(然而實際上不可能報告所有警告)。
實際上你可以深入探索使用make的上述方法,但是先讓我們來看看Makefile
,以便讓你對make瞭解得更多一點。首先,建立檔案並寫入以下內容:
CFLAGS=-Wall -g
clean:
rm -f ex1
將檔案在你的當前資料夾上儲存為Makefile
。Make會自動假設當前資料夾中有一個叫做Makefile
的檔案,並且會執行它。此外,一定要注意:確保你只輸入了 TAB 字元,而不是空格和 TAB 的混合。
譯者注:上述程式碼中第四行
rm
前面是一個 TAB ,而不是多個等量的空格。
Makefile
向你展示了make的一些新功能。首先我們在檔案中設定CFLAGS
,所以之後就不用再設定了。並且,我們新增了-g
標識來獲取除錯資訊。接著我們寫了一個叫做clean
的部分,它告訴make如何清理我們的小專案。
確保它和你的ex1.c
檔案在相同的目錄中,之後執行以下命令:
$ make clean
$ make ex1
你會看到什麼
如果程式碼能正常工作,你應該看到這些:
$ 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`
$
你可以看出來我執行了make clean
,它告訴make執行我們的clean
目標。再去看一眼Makefile,之後你會看到在它的下面,我縮排並且輸入了一些想要make為我執行的shell命令。你可以在此處輸入任意多的命令,所以它是一個非常棒的自動化工具。
注
如果你修改了
ex1.c
,新增了#include<stdio>
,輸出中的關於puts
的警告就會消失(這其實應該算作一個錯誤)。我這裡有警告是因為我並沒有去掉它。
同時也要注意,即使我們在Makefile
中並沒有提到ex1
,make
仍然會知道如何構建它,以及使用我們指定的設定。
如何使它崩潰
上面那些已經足夠讓你起步了,但是讓我們以一種特定的方式來破壞make檔案,以便你可以看到發生了什麼。找到rm -f ex1
的那一行並去掉縮排(讓它左移),之後你可以看到發生了什麼。再次執行make clean
,你就會得到下面的資訊:
$ make clean
Makefile:4: *** missing separator. Stop.
永遠記住要縮排,以及如果你得到了像這種奇奇怪怪的錯誤,應該複查你是否都使用了 TAB 字元,由於一些make的變種十分挑剔。
附加題
-
建立目標
all:ex1
,可以以單個命令make
構建ex1
。 -
閱讀
man make
來了解關於如何執行它的更多資訊。 -
閱讀
man cc
來了解關於-Wall
和-g
行為的更多資訊。 -
在網際網路上搜尋Makefile檔案,看看你是否能改進你的檔案。
-
在另一個C語言專案中找到
Makefile
檔案,並且嘗試理解它做了什麼。