Makefile 笔记
一、简单的 Makefile 例子
- 文档目录结构
- 文档目录结构是用户目录HOME下有src incl bin lib
src:源码 incl:头文件 bin:执行码 lib:静态/动态库 这是大家最常见的Linux编程目录结构,以下代码编译都是依据这个结构。
- 文档目录结构是用户目录HOME下有src incl bin lib
- Makefile 代码
hello:hello.c gcc -I${HOME}/incl -c hello.c // 预处理+编译+汇编命令 不汇编 gcc -o hello hello.o rm -f hell.o mv hello ${HOME}/bin
- 简单的Makefile确实可以当shell脚本执行,但是只学会简单的Makefile并看不懂大神的Makefile啊
二、Makefile 结构说明
- Makefile里主要包含了五个东西:变量定义、显式规则、隐晦规则、文件指示和注释。
- 变量定义。在Makefile中我们要定义一系列的变量,变量一般都是字符串,这个有点像C语言中的宏,当Makefile被执行时,其中的变量都会被扩展到相应的引用位置上。
- 显式规则。显式规则说明了,如何生成一个或多的的目标文件。这是由Makefile的书写者明显指出,要生成的文件,文件的依赖文件,生成的命令。 刚才写的疑似shell脚本的Makefile全部都是显示规则。
- 隐晦规则。由于我们的 make 有自动推导的功能,所以隐晦的规则可以让我们比较粗糙地简略地书写 Makefile,这是由make所支持的。
4.文件指示。其包括了三个部分,一个是在一个Makefile中引用另一个Makefile,就像C语言中的include一样。 - 注释。Makefile中只有行注释,和UNIX的Shell脚本一样,其注释是用“#”字符,这个就像C/C++中的“//”一样。
三、略复杂的 Makefile 例子
- Makefile 代码
# 隐含规则:这个隐晦规则其实就是告诉大家,后缀为cpp的文件怎么编译成.o,后缀为c的文件怎么编译成.o。 INCL=-I${HOME}/incl # 变量定义 .SUFFIXES: .cpp .c .cpp.o: g++ ${INCl} -c $< # ${INCl} 进行了变量使用 .c.o: gcc ${INCL} -c %< # %< 是预定义变量 # C++编译 hellocpp:hellocpp.o echo "开始编译" g++ -o hellocpp hellocpp.o rm -f hellocoo.o mv hellocpp ${HOME}/bin echo "编译结束" # C编译 hello:hello.o echo "开始编译" gcc -o hello hello.o rm -f hello.o mv hello ${HOME}/bin echo "编译结束"
- 预定义变量
$* 不包含扩展名的目标文件名称。 $+ 所有的依赖文件,以空格分开,并以出现的先后为序,可能包含重复的依赖文件。 $< 第一个依赖文件的名称。 $? 所有的依赖文件,以空格分开,这些依赖文件的修改日期比目标的创建日期晚。 $@ 目标的完整名称。 $^ 所有的依赖文件,以空格分开,不包含重复的依赖文件。 $% 如果目标是归档成员,则该变量表示目标的归档成员名称。
- 进一步理解预定义变量
- Makefile文件
all: first second third @echo "\$$@ => $@" @echo "$$^ => $^" # "$"对于makefile有特殊含义输出时需要加上一个"$"进行转义 @echo "$$< => $<" # "$@"对于Bash Shell有特殊含义输出时需要加上"\"进行转义
- 执行后
$@ => all $^ => first second third $< => first
- Makefile文件
四、整理下三中 Makefile 例子
- 最后形成的 Makefile 例子
#最后形成的Makefile INCL=-I${HOME}/incl BIN=$(HOME)/bin OBJ1=hellocpp.o OBJ2=hello.o .SUFFIXES: .cpp .c .cpp.o: g++ ${INCL} -c $< .c.o: gcc ${INCL} -c $< all: hellocpp hello #C++编译 hellocpp:${OBJ1} @echo "============开始编译============" g++ -o $@ $? @rm -f ${OBJ1} @mv $@ ${BIN} @echo "============编译结束============" @echo "" #C编译 hello:${OBJ2} @echo "============开始编译============" gcc -o $@ $? @rm -f ${OBJ2} @mv $@ ${BIN} @echo "============编译结束============" @echo ""
- 命令前加@,表示当前命令不显示