4.3.7 项目管理器make
熟悉了gcc、gdb,就基本了解了Linux下使用编辑器编写代码,会用gcc把代码编译成可执行程序,也会使用gdb等调试程序对编译后的程序进行调试了,接下来我们就要讲到了开发流程中非常重要的另外一步。尽管它不是必须的,但在大的复杂程序的开发中非常重要。这就是make项目管理器。
1. make作用
当写一个简单的程序,只有一到两个源文件的时候,输入:
- gcc file1.c file2.c
此时只有两个文件需要编译,工作量似乎不是很大,但是如果有多个文件需要编译呢?一种方法就是使用目标文件,只在源文件有改变的情况下才重新编译源文件,因此可以采用这种方法:
- gcc file1.o file2.o ... file40.c ...
上次编译后,file40.c发生了改变,但其他文件没有。这样做可以让编译过程快很多,但是也不能解决繁杂的输入问题。或者我们可以使用一个shell script来解决输入问题,但是也需要重新编译所有文件。其实可以把以上两种方法结合,写一种像shell script一样的东西。这种文件应该包含某种技巧可以决定什么时候该对源文件进行编译。make就能实现这样的功能:它读入一个文件,叫makefile,这个文件不仅决定了源文件之间的依赖关系,而且还决定了源文件什么时候该编译,什么时候不应该编译。
makefile通常和相关的源文件保存在同一个目录下,可以叫做makefile、Makefile或者MAKEFILE。大多数程序员会使用Makefile这个名字,因为这样可以让这个文件被放在目录列表的顶端,可以很容易地看见。
2. makefile使用
工具程序make是GNU提供的非常重要的软件开发工具之一,它的本质思想为:检查源代码和目标文件,以确定哪个源文件需要重新编译以创建新的目标文件。make假设所有改动过的源文件都比已经存在的目标文件新,目标文件的生成依赖于源文件,而它们之间的依赖关系通常都写入一个脚本文件中,这个脚本文件决定着目标文件如何被产生。
下面以一个例子来简单描述如何编写脚本文件以及如何使用make工具。
make从makefile(默认是当前目录下的名为"Makefile"的文件)中读取项目的描述。makefile指定了一系列目标(比如可执行文件)和依赖(比如对象文件和源文件)的编译规则,其格式如下:
- target ... :prerequisites...
- command
- ...
对每一个目标,make检查其对应的依赖文件修改时间来确定该目标是否需要利用对应的命令重新建立。注意到,makefile中命令行必须以单个的TAB字符进行缩进,不能是空格。
GNU make包含许多默认的规则(参考隐含规则)来简化makefile的构建。比如说,它们指定".o"文件可以通过编译".c"文件得到,可执行文件可以通过将".o"链接到一起获得。隐含规则通过被叫做make变量的东西指定,比如CC(C 语言编译器)和 CFLAGS(C程序的编译选项)。对C++,其等价的变量是CXX和CXXFLAGS,而变量CPPFLAGS则是编译预处理选项。
现在我们为上一节gcc中的项目写一个简单的makefile文件。
- CC=gcc
- CFLAGS=-Wall
- hello: hello.o hello_fn.o
- clean:
- rm -f hello hello.o hello_fn.o
该文件可以这样来读:使用C语言编译器gcc和编译选项"-Wall",从对象文件"hello.o"和"hello_fn.o"生成目标可执行文件hello(文件"hello.o"和"hello_fn.o"通过隐含规则分别由"hello.c"和"hello_fn.c"生成)。目标clean没有依赖文件,它只是简单地移除所有编译生成的文件。rm命令的选项"-f"(force) 抑制文件不存在时产生的错误消息。
要使用该makefile文件,输入make。不加参数调用make时,makefile文件中的第一个目标被建立,从而生成可执行文件"hello",输入make命令:
- $ make
将输出编译过程:
- gcc -Wall -c -o hello.o hello.c
- gcc -Wall -c -o hello_fn.o hello_fn.c
- gcc hello.o hello_fn.o -o hello
最后我们执行编译生成的可执行文件,输入命令:
- $ ./hello
- Hello,Embedded Linux!
一个源文件被修改要重新生成可执行文件,简单地再次输入make即可。通过检查目标文件和依赖文件的时间戳,程序make可识别哪些文件已经修改并依据对应的规则更新其对应的目标文件,例如先修改hello.c文件,输入命令:
- $ vim hello.c (打开编辑器修改一下文件,也可以直接在gedit中修改)
然后执行make命令:
- $ make
屏幕将输出:
- gcc -Wall -c -o hello.o hello.c
- gcc hello.o hello_fn.o -o hello
最后我们再次执行:
- $ ./hello
- Hello,Embedded Linux!
最后,我们移除make生成的文件,输入make clean:
- $ make clean
- rm -f hello hello.o hello_fn.o
一个专业的makefile文件通常可以用于实现安装(make install)和测试(make check)等额外的目标。
本例中涉及的程序非常简单,以至于可以完全不需要makefile,但是大些的程序使用make则很有必要。