练习 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
$ 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文件,并且尝试理解它做了什么。