GNU make命令是用来控制从源文件生成可执行文件或非可执行文件的方式。那么make命令又是通过makefile文件来控制了。所以了解makefile文件就显得很有必要了。
makefile文件由许多规则组成,这些规则的形式一般是这样的:
目标 ... : 先决条件 ...
命令
目标:它一般是一个由程序产生的文件的名字,比如说目标文件的名字或可执行文件的名字。它也可以是一些动作的名字,比如“clean”
先决条件是用来了创建目标文件的文件,一个目标文件通过依赖几个文件。
命令是make执行的动作,可能包含多个命令。它们写在同一行或者各自一行。在每个命令前,我们要按一下tab键。命令就是用先决条件中的文件来创建,如果先决条件的文件有改变,命令就会被重新执行生成新的目标文件。
也有些规则的形式也不一定需要有先决条件,比如说“clean”目标,它包含删除的命令,它就不需要有什么先决条件,如下面:
执行make就会默认执行makefile第一条规则,第一条规则的先决条件中依赖的文件会被生成出来。如果只想生main.o,那么make命令可以这么写make main.o
,对于log.o同理。
执行make clean
:
OK,小结一下。一条makefile规则包含三部:
- 目标文件
- 先决条件,即生成目标的先决条件,一般都是文件
- 命令,make会使用这些命令去利用先决条件去生成目标文件。这些命令只知道如何去更新目标文件
有一些目标不一定有先决条件,如上面的clean目标,它不会依赖任何先决条件,它是一个动作,我们可以告诉它要干什么。比如上面的clean,我们让它删除掉所有生成的文件。
make程序是如何处理makefile文件的?
默认情况下,make以第一个目标开始。所以makefile的第一个目标也叫默认目标。下面的makefile,main就是第一个目标。如果希望改变这个行为,让它默认在某个目标上可以使用.DEFAULT_GOAL
重新指定。如:
看看效果:
当make命令执行时,它会在读取当前目录中的makefile文件,然后从第一个目标开始行(默认),在完成第一个目标前,它必须把目标所依赖的先决条件的文件都生成了,先决条件里的文件又是一些目标,所以必须在它们各自的规则里生成。
makefile中的变量,如前面cxx变量,引用时,只需要$(变量名)
make的推断能力
在真实生产中,更多使用make的推断能力。因为它有条隐藏式的规则去更新*.o
目标文件,根据相应的*.cpp
(对于c语言就是*.c
),所以上面的makefile就可以用下面的写法:
在执行make时,就可以看到那些隐藏的规则了:
此处顺便附上GNU make的一个例子:
上面这个例子还可以下面的来表达。
Makefiles 包括五样东西:
- 显式的规则:告诉make什么时候和怎样生成一个或多个文件,这些文件叫做目标。它的先决条件中会列出目标所依赖的文件,然后会有用于创建或更新目标的命令
- 隐藏式的规则 : 这条规则不用我们写,它会基于它们的目标文件找到它们依赖的文件,并用那些文件来生成目标文件。如现在需要main.o目标文件,那么就会用main.cpp来生成。
- 变量定义,给一个变量赋一些文本字符值,在makefile文件里就可以使用它的值。
- 命令,让make做一些操作,如读取其他makefile文件,决定是使用还是忽略makefile的部分内容等等,
读取取他makefile文件的命令:include filenames...
,如果想让make忽略某个makefile文件,命令则是-include filenames...
- 注释,以#字符开头。
在makefile中如果一行太长,可以换行,但是要在行尾加上\。这样make才会认为下一行与上一行是一起的,要一起使用的。如:
.INCLUDE_DIRS
可以用来指定make的搜索路径。
关于makefile还有很多内容,可以留意我后续的文章。