前言
这个是我用xmind转markdown的效果,感觉很差,附上思维导图
思维导图我也上次至CSDN了:makefile知识再整理(超详细)
makefile
编译规则
目标文件
依赖文件
命令行
特性
1.只会执行更新过的程序文件的相关命令,如果都没更新过,make指令将不会执行(提高效率)
2.变量名代替文件名,一般是多个文件名,使用$进行替换
obj = a.o b.o
test : $(obj)
cc -o test $(obj)
a.o:a.c b.h
cc -c a.c
b.o:b.c
cc -c b.c
3.makefile命令尽量成首字母大写,即Makefile
#Makefile1 main:main.c add.c sub.c gcc $^ -o $@ 4.makefile中用#注释 #Makefile1 main:main.c add.c sub.c gcc $^ -o $@ #Makefile2 main:main.o add.o sub.o gcc $^ -o $@ main.o:main.c gcc -c main.c add.o:add.c gcc -c add.c sub.o:sub.c gcc -c sub.c .PHONY:clean clean: rm -f main.o add.o sub.o main
5.在命令前加@,在运行时,可以隐藏所执行命令
hello:hello.o
@gcc hello.o -o hello
hello.o:hello.c
@gcc -c hello
6.echo 命令相当于打印
hello:hello.o
@gcc hello.o -o hello
@echo make done!
hello.o:hello.c
@gcc -c hello
@echo make done!
变量定义
简单赋值 ( := ) 编程语言中常规理解的赋值方式,只对当前语句的变量有效。
递归赋值 ( = ) 赋值语句可能影响多个变量,所有目标变量相关的其他变量都受影响。(相当于C++中的引用)
条件赋值 ( ?= ) 如果变量未定义,则使用符号中的值定义变量。如果该变量已经赋值,则该赋值语句无效。(只能定义未被定义过的变量)
a1 := a.o
a1 ?= b.o
定义无效,因为前面已经定义过了
追加赋值 ( += ) 原变量用空格隔开的方式追加一个新值。(和C语言+=类似)
a1 = a.o;
a1 += b.o;
a1 = a.o b.o
特殊字符
举例说明
TARGET?=demo
OBJS:=main.o add.o sub.o
CC:=gcc
CFLAGS:= -c -o
CFLAGSs:=-o
( T A R G E T ) : (TARGET): (TARGET):(OBJS)
$(CC) $(OBJS) $(CFLAGSs) $(TARGET)
%.o:%.c
$(CC) $< $(CFLAGS) $@
clean:
rm $(OBJS) $(TARGET)
$(CC) $< $(CFLAGS) $@
多用前三个
$@ 表示目标文件名称,包含扩展名
$^ 表示所有的依赖文件,以空格隔开,不重复
$< 表示第一个依赖文件的名称
$+ 表示所有的依赖文件,空格隔开,可以重复
$* 表示目标文件的名称,不包含扩展名
$? 依赖项中,所有比目标文件新的依赖文件
伪指令
存在意义
在Makefile中,.PHONY后面的target表示的也是一个伪造的target, 而不是真实存在的文件target,注意Makefile的target默认是文件。
如果有相同的文件名,如clean,会继续执行伪指令
实际运用
.clean
.PHONY:clean
clean:
rm -rf *.o test
清除文件:make clean
.install
.PHONY: install
install:
mkdir $(test_dir)
cp test $(test_dir)
行命令”make install“后,Make会顺序执行命令”mkdir $(test_dir)“和”cp test $(test_dir)“,把test文件复制到test_dir变量指定的目录中去
.uninstall
.PHONY: uninstall
uninstall:
rm -rf $(test_dir)
把指定的目录以及目录中的文件全部删除
.all
.PHONY: all
all: test $(obj)
Make会把all当成最终的目标。由于伪目标和真实目标一样都有依赖文件
通配符
Makefile中的通配符:*和%
表示所有一类文件
test:*.c
gcc -o $@ $^
#所有的.c文件
%(特殊字符的举例)
test:test.o test1.o
gcc -o $@ $^
%.o:%.c
gcc -o $@ $^
“%.o” 把我们需要的所有的 “.o” 文件组合成为一个列表,从列表中挨个取出的每一个文件,“%” 表示取出来文件的文件名(不包含后缀),然后找到文件中和 "%"名称相同的 “.c” 文件,然后执行下面的命令,直到列表中的文件全部被取出来为止。
条件判断
ifeq
判断参数是否不相等,相等为 true,不相等为 false。
ifneq
判断参数是否不相等,不相等为 true,相等为 false。
ifdef
判断是否有值,有值为 true,没有值为 false。
ifndef
判断是否有值,没有值为 true,有值为 false。
文件查找
VPATH 和 vpath
区别
VPATH 是变使用时需要指定文件的路径;vpath 是关键字,搜索的时候不仅需要加上文件的路径,还需要加上相应限制的条件。
VPATH 是变量,更具体的说是环境变量,Makefile 中的一种特殊变量,使用时需要指定文件的路径;vpath 是关键字,按照模式搜索,也可以说成是选择搜索。搜索的时候不仅需要加上文件的路径,还需要加上相应限制的条件。
VPATH
VPATH = /home/b
obj = a.o b.o
.PHONY : all
all:test ( o b j ) t e s t : (obj) test: (obj)test:(obj)
cc -o test $(obj)
格式:VPATH := /src:/car
先搜索/src,再搜索/car
可以这样理解,把 src 的值赋值给变量 VPATH
注意:无论定义了多少路径,makefile都会首先在当前目录下寻找,找到了,则不会到VPATH继续寻找
vpath
格式:vpath 模式 目录:目录…
vpath test.c /src :/car
其他
vpath test.c
意思是清除符合文件 test.c 的搜索目录
vpath
vpath 单独使的意思是清除所有已被设置的文件搜索路径
常用函数
wildcard
SRC = $(wildcard .c ./foo/.c)
搜索当前目录及./foo/下所有以.c结尾的文件,生成一个以空格间隔的文件名列表,并赋值给SRC.当前目录文件只有文件名,子目录下的文件名包含路径信息,比如./foor/bar.c。
patsubst
Makefile 内容
all:
@echo $(patsubst %.c,%.o,programA.c programB.c)
bash 中执行 make
$ make
programA.o programB.o
$(patsubst ,, )
功能: 查找 中的单词(单词以"空格", “tab”, "换行"来分割) 是否符合 , 符合的话, 用 替代.
notdir
Makefile 内容
all:
@echo $(notdir /home/a.c ./bb.c …/c.c d.c)
bash 中执行 make
$ make
a.c bb.c c.c d.c
$(notdir )
功能: 从文件名序列 中取出非目录部分
返回: 文件名序列 中的非目录部分
XMind: ZEN - Trial Version