Make和Makefile编写(详见GCC手册)
Makefile和Make Rules
多模块软件、依赖树和Make
默认规则
Make使用程序对简单变量的支持
内建变量
虚目标
特殊目标
一般性语法错误及其纠正措施
命令行的使用和调试
Makefile中常用规则总结
make常用选项
-d 显示调试信息
-f 指定从哪个文件中读取依赖关系信息。默认文件是“Makefile”或“makefile” ,"-"表示从标准输入
-h 显示所有的Makefile的help信息
-n 打印所有Makefile执行命令,但不执行这些命令
-s 运行时不显示任何信息
注释
#
连接符
\
关联列表和命令列表中使用shell通配符
?
*
默认模式规则
%.o:%.c:
$(CC) $(CFLAGS) -c $<
%.o:%.s:
$(AS) $(ASFLAGS) -o $@ $<
简单变量
定义:变量名:=文本
添加:变量名+=文本
变量引用
$(变量名)
${变量名}
$单字符变量
C := gcc $C
CC := gcc OPTIONS := -O3 OBJECTS :=main.o OBJECTS := input.o compute.o SOURCE :=main.c input.c compute.c HEADERS := main.h input.h compute.h power: $(OBJECTS) $(CC) $(OPTIONS) $(OBJECTS) -o power -lm main.o: main.h input.h compute.h #包含隐含规则 input.o: input.h compute.o: compute.h tar: Makefile $(HEADERS) $(SOURCES) #伪目标tar用于打包Makefile和源文件头文件 tar -cvf power.tar Makefile $(HEADERS) $(SOURCES) clean: rm *.o
内置变量
$@ 当前目标的名称
$? 比当前目标更加新的已修改的依赖性列表
$< 比当前目标更新的已修改的当前依赖性名称
$^ 用空格分开的所有依赖性列表
@echo "Build complete" power: $(OBJECTS) $(CC) $(OPTIONS) -O $@ $^ -lm @echo "The executable is in the power file." main.o: main.h input.h compute.h compute.o: compute.h input.o: input.h power.tar: Makefile $(HEADERS) $(SOURCES) tar -cvf $@ $^ .PHONY:clean clean: rm -f *.o power
虚目标
允许强制执行某些在正常规则中不会发生的事件。
比如:可以通过设置一个虚目标生成多个可执行文件,若不使用虚目标,make就只能建立第一个目标。
.PHONY: rebuild-all rebuild-all:prog1 prog2 prog3 prog1: prog1.o utils.o cc -o prog1 prog1.o utils.o prog2: prog2.o cc -o $@ $^ prog3: prog3.o sort.o utils.o cc -o $@ $^
常见虚目标列表
all 生成工程中所有可以执行者,通常是Makefile的第一个生成目标
$make all #使目标全部被执行
clean 删除make all生成的所有文件
install 在系统目录中安装工程项目生成的可执行文件和文档
uninstall 删除make install 安装的所有文件
$cat Makefile
INSTALLDIR=/home/embedclub/bin install: client server cp -f $^ $(INSTALLDIR) rm -f *.o $^ cd $(INSTALLDIR); chmod 755 $^ uninstall: cd $(INSTALLDIR); rm client server client: client.o miscc.o rcopyc.o gcc client.o miscc.o rcopyc.o -lnsl -o client \ client.o: client.c netc.h rcopy.h rcopy.h gcc -c client.c
$make install
$make uninstall
一般性语法错误
1 缺少Tab键,可使用cat -t Makefile查看tab键位置
2 在连接符和换行符之间插入了空格,可使用cat -e Makefile查看换行符位置
显示Makefile中不正确的行 grep '\\[]$' Makefile
使用非标准的Makefile名称文件
$make -f prog1.makefile
从标准输入读取
$make -f -
显示Makefile中所执行命令的顺序
$make -n
制作工程文件的Makefile
一般的工程文件proc组成:
src:main.c fun1.c fun2.c
include:fun1.h fun2.h
Makefile
$cat Makefile
VPATH = src:include all:test4 tar .PHONY:all test4:main.o fun1.o fun2.o gcc main.o fun1.o fun2.o -o test4 main.o:main.c gcc -c -linclude -o $@ $^ fun1.o: fun2.o: tar: tar cvf test4.tar src include Makefile .PHONY:clean clean: rm *.o test4
Makefile编写规则详解
Make命令与Makefile
Makefile文件内容
显示规则:说明了如何生成一个或多个目标文件(包括要生成的文件/文件的依赖文件/生成的命令)。
隐式规则
变量定义:一般是字符串,Makefile被执行时,其中变量都会拓展到相应的引用位。
文件指示: 1 在一个Makefile文件中引用另一个Makefile文件 (类似include)
2 根据某些情况指定makefile文件中的有效部分 (类似预编译#if)
3 定义一个多行的命令
注释: 注释符#(Makefile文件中需要用到#,可以使用\#转义)
注意:
makefile文件的文件名可以是其他名称,但要使用-f或--file指定
make工作执行步骤
1 读入所有makefile文件
2 读入被include包括的其他makefile文件
3 初始化文件中的变量
4 推导隐式规则,并分析所有规则
5 为所有目标文件创建依赖关系链
6 根据依赖关系,决定哪些目标要重新生成
7 执行生成命令
make参数 例子 作用
-f --file make -f makelinux 指定特定的makefile文件
-I --include-dir 在指定目录下寻找makefile文件
-n --just-print 只是显示->命令不执行命令
-s --silent 禁止命令的输出显示
makefile关键子 例子 作用
include include ../Make.defines 将别的makefile文件包含进来
include foo.make *.mk $(bar)
-include 不理会无法找到的文件
wildcard objects:= $(wildcard *.o) 让通配符在变量中展开,即让objects的值成为所有.o的文件名的集合
vpath <pattern> <directory> vpath %.h ../headers 为符合模式<pattern>的文件指定搜素目录
vpath %.c foo:bar
vpath blish 这两句一起用的话,表示.c结尾的文件先在foo,然后在bar,最后在blish中寻找
vpath <patterh> 清除符合模式<pattern>的文件的搜索目录
vpath 清除所有已设置好的文件搜索目录
定义环境变量 例子 作用
MAKEFILES 把此变量的值(其他makefile,多个文件用空格分隔)作为一个类似于include的动作
VPATH VPATH = src:../headers 让make根据路径寻找目标依赖文件,多个路径用:隔开
自动变量
$@ 目标集
$< 所有的依赖目标集
Makefile书写规则(里面的命令其实是shell命令)
通配符(定义一系列比较类似的文件)
* objects=*.o 所有的.o文件的集合
?
[]
~ ~/test 表示宿主主目录下test文件
文件搜寻
VPATH
vpath 关键字
伪目标
.PHONY .PHONY: clean 伪目标可以直接放在make后面像操作文件一样操作
make clean
多目标
静态模式
目标集合 目标集模式 目标集的二次定义
<targets ...>: <target-pattern>: <prereq-pattern>
<commands>
...
makefile文件的函数
filter
自动生成依赖关系
gcc -MM main.c //查找main.c文件包含的头文件,并生成依赖关系
.d文件的应用
使用命令
显示命令 @ehco (@避免输出命令,只输出命令执行结果)
执行命令
exec:
cd /home/hchen; pwd 第二条命令执行建立在第一条命令结果上
#伪目标同样可以存在依赖关系 .PHONY: cleanall cleanobj cleandiff cleanall: cleanobj cleandiff rm program cleanobj: rm *.o cleaniff: rm *.diff
#静态模式 objects=foo.o bar.o all: $(objects) $(objects): %.o: %.c $(gcc) -c $(CFLAGS) $< -o $@ #展开后等价于 foo.o:foo.c $(gcc) -c $(CFLAGS) foo.c -o foo.o bar.o: bar.c $(gcc) -c $(CFLAGS) bar.c -o bar.o
学习积累
源文件:ChessBoard.h ChessBoard.cpp Player.h Player.cpp main.cpp
依赖关系:
ChessBoard.cpp 包含ChessBoard.h
Player.cpp 包含 Player.h
main.cpp 包含ChessBoard.h 和 Player.h
Makefile:
1 gomoku: ChessBoard.o Player.o main.o 2 g++ -o gomoku ChessBoard.o Player.o main.o 3 #main.o: main.cpp Player.h ChessBoard.h 4 # g++ -c $^ 5 #ChessBoard.o: ChessBoard.cpp ChessBoard.h 6 # g++ -c $^ 7 #Player.o: Player.cpp Player.h 8 # g++ -c $^ 9 10 #通过下面方法编译器可以自动推导 11 main.o: Player.h ChessBoard.h 12 ChessBoard.o: ChessBoard.h 13 Player.o: Player.h 14 15 .PHONY: clean allclean 16 clean: 17 rm *.o *.gch 18 allclean: 19 rm *.o *.gch gomoku