笨辦法學C 練習2:用Make來代替Python

飛龍發表於2019-05-11

練習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來構建它。

  • 我將使用ccex1.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中並沒有提到ex1make仍然會知道如何構建它,以及使用我們指定的設定。

如何使它崩潰

上面那些已經足夠讓你起步了,但是讓我們以一種特定的方式來破壞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檔案,並且嘗試理解它做了什麼。

相關文章