使用make编译一个工程的有点自不必赘言,我也是刚开始试探性的试用一下,以MinGW作为对象,稍作参考。
make中有很多Automatic Variables,可以帮助节省工作量,以下将其逐个写出,参考自The Linux Programmer’s
Toolbox, John Fosco, 第84页(英文版)。
Variable Value
$@ Filename of the target.
$^ The names of all prerequisites with duplicate names removed.
$+ The names of all prerequisites, including duplicates.
$< The name of the first prerequisite in the rule.
$? The names of all prerequisites newer than the target.
$* With a suffix rule, this is the base name (or stem) of the target. If the rule is .c.o:, for example,
and the matching target is foo.o, this value is foo. With some pattern rules, this value may not
be what you expect.
我主要使用了3种:$@、$+和$<。以下以一个例子来解释:
//t.c
#include <stdio.h>
int main()
{
print();
return 0;
}
//t1.c
#include <stdio.h>
int print()
{
printf("Hello, world. It's in t1.c/n");
return 0;
}
要生成Foo为最后的应用程序,那么Makefile为:
ALL : Foo
Foo: t.o /
t1.o
gcc -o $@ $+
.c.o:
gcc -o $@ -c $<
当然第一句不是必要的。我们来看第一个规则,生成Foo,它依赖于t.o和t1.o,那么这两个使用gcc -o Foo t.o t1.o这条语句就行了。但是如果以来的o文件过多,都写上岂不是很麻烦,还容易出错,因此$+就帮助我们了,它代表所有的依赖条件,即所有的o文件, 而$@代表所要生成的Foo,这个倒是没有太大的节省。再看第二个规则,这个规则表示对于遇到的每一个.o文件,都寻找对应的同名的 .c 文件,使用下边的命令编译。注意,一定要是同名的(Windows下大小写不能区分文件名,Linux要区分)。这里由于没有指定具体的要生成的 目标叫什么名字,使用$@就再好不过了;$<则代表使用到的那个.c文件。make有另外一种形式替代第二条规则这种形式“ %.o : %.c ”,其作用与这里使用的形式一致,据说更加清楚,而且不用预先定义就能够识别出GNU本来不认为是C++后缀的cxx(参考82页)。
我在Windows上使用MinGW,所以即使目标位Foo,深沉的仍然是Foo.exe,但是即使任何文件都没有更新,每次运行mingw32- make.exe的时候,仍然会重新生成Foo.exe,“gcc -o Foo t.o t1.o”。我的解决办法是,定义一个宏为".exe"(当然,如果要跨平台的话,这就是Windows下的情况,否则为""),改变后的 Makefile如下:
POSTFIX = .exe
ALL : Foo$(POSTFIX)
Foo$(POSTFIX): t.o /
t1.o
gcc -o $@ $+
%.o: %.c
gcc -o $@ -c $<
这样就不会再没有任何更改的时候再次生成Foo.exe了。
我在Ubuntu8.04上实验时,遇到“遗漏分隔符”的问题,我参考http://hi.baidu.com/hufeifeihu/blog/item/e012131f204e02f0e1fe0b0d.html,做了几次试验,发现作者所言:
targetList: ( dependencyList )------需顶格
(commandList) ------前加tab 键
第一条“须顶格”已经不重要,重要的是第二条,加tab键。实际上Windows上使用MinGW也是这样的问题,只是我习惯了使用Tab去分隔,没有出现这样的错误而已。