说到Makefile它在嵌入式软件开发中的低位非常重要。
一个完整的Makefile有许多规则组建而成。规则——Makefile中的细胞
目标(target):先决条件(prerequisite)
(一Tab的位置处)命令
上述内容构成了一个规则。
一个Makefile中可以有多个规则,也即可以有多个目标,多个先决条件,多个命令
target1 :prerequisite1
command
target2 :prerequisite2
command1
command2
....
......
还有另外一种
target1 target2 target3 ... :prerequisite1 prerequisite2 prerequisite3 ...
command
targetn ... :prerequisiten ...
command
......
当我们调用make命令时,我们需要告诉它我们要构建哪一个目标(targetn),如我们要构建target2时,我们就要用make target2来创建target2这个目标。当我们用make不指明具体创建哪个目标时,则make将以Makefile文件中的第一个目标作为这次运行的目标。
当一个规则中出现多个目标时,且该规则处于Makefile中第一个时,如果运行make命令不带任何目标,那么规则中的第一个目标被视为默认目标。(这里要注意,一般Makefile中第一个规则中的目标一般只会有一个)
目标与先决条件之间的关系叫做依赖关系(dependency),这种依赖关系指明,在构建目标之前,必须保证先决条件已经存在或先于目标构建好。
举个例子
simple/foo.c(simple目录下有foo.c文件和main.c文件,Makefile)
#include
void foo
{
printf("This is foo()!\n");
}
simple/main.c
extern void foo();
int main()
{
foo();
return 0;
}
simple/Makefile
all : main.c foo.c
gcc -c main.c foo.c
gcc -o simple main.o foo.o
clean :
rm -f simple *.o
上面例子中只用了一个规则,但里面有两个命令,第一个命令是生成main.o foo.o文件,第二个命令是生成simple文件。gcc -o simple -c main.c foo.c是不对的,gcc不允许用-c命令编译多个.c文件时使用-o参数,所以要分开写,且生成的.o文件命名是以.c文件名命名的。
上面的例子中target与prerequisite的依赖关系不是很明显。可以改写成如下语句:
all : main.o foo.o
gcc -o simple main.o foo.o
main.o : main.c
gcc -o main.o -c main.c
foo.o : foo.c
gcc -o foo.o -c foo.c
clean :
rm -f simple *.o
从上面的例子中可以明确的看出目标target与prerequisite的依赖关系。
目标all需要有main.o和foo.o完成,而开始时只有main.c和foo.c文件,所以要构建main.o和foo.o文件,即main.o文件依赖于main.c,foo.o依赖于foo.c,当main.o和foo.o创建好后就可以创建all。
当文件中有了main.o和foo.o文件时,make会检测这些文件是新文件(里面的内容被更新过)还是旧文件(里面的内容没有更新过),若是新文件说明main.o和foo.o的内容被修改过这时使用make时需要重新构建all目标,反之旧文件就不用重新构建all目标。
当文件中没有main.o、foo.o、simple时make命令的输出显示:
#make
gcc -o main.o -c main.c
gcc -o foo.o -c foo.c
gcc -o simple main.o foo.o
当文件中有main.o、foo.o、simple(这些文件是没更新过是原来旧的文件)时make命令的输出显示:
#make
gcc -o simple main.o foo.o
按前面所述simple、main.o、foo.o已经存在且内容没更新过,第二次make时应该不会显示gcc -o simple main.o foo.o,导致它重新编译的原因是该规则中的目标all在编译时没有生成名字叫all的文件第二次make时由于找不到all文件所以重新构建。可以把all改为simple,运行结果如下:
#make
make:“simple”是最新的
在上面的例子中如果在Makefile所在文件目录下存在一个clean文件。如果此时运行make clean,我们会发现make总是提示clean文件是最新的,而不是像我们想的那样进行清除操作。原理和前面的all改为simple差不多,因为它总是把clean当做一个名为clean的文件来处理,而此时Makefile所在文件目录下已经存在名为clean的文件,且每次的内容都不会被修改过,所以会认为clean是最新的。
解决上面问题可以使用伪目标
定义伪目标可以用大写的.PHONY关键字来定义clean
.PHONY clean all
all : main.o foo.o
gcc -o simple main.o foo.o
main.o : main.c
gcc -o main.o -c main.c
foo.o : foo.c
gcc -o foo.o -c foo.c
clean :
rm -f simple *.o
阅读(1686) | 评论(0) | 转发(0) |