make是什么
gcc :编译器
make:linux自带的构建器
- 构建的具体规则写在makefile中
makefile文件的命名
- makefile
- Makefile
makefile中的规则
三部分:目标,依赖,命令
- 123# (注释#)具体格式:# 目标:依赖# (tab缩进,只能是tab)命令
- 123# 举例:编译语句:gcc a.c b.c c.c -o app 写成makefileapp:a.c b.c c.cgcc a.c b.c c.c -o app
makefile中由一条或多条规则组成
makefile编写
第一个版本:
- 12app:a.c b.c c.cgcc a.c b.c c.c -o app
缺点:效率太低,修改一个文件,全部文件都需要重新编译
第二个版本:
makefile工作原理
检测依赖是否存在:
- 向下搜索下面的规则,如果有规则是用来生成查找的依赖的,执行规则中的命令
依赖存在,判断是否需要更新
原则:目标时间 > 依赖的时间
- 反之,则更新
- 1234567891011121314app:main.o add.o sub.o mul.ogcc main.o add.o sub.o mul.o -o appmain.o:main.cgcc main.c -cadd.o:add.cgcc add.c -csub.o:sub.cgcc sub.c -cmul.o:mul.cgcc mul.c -c
缺点:冗余(很多重复的命令,写法一样重复在写)
第三个版本
自定义变量:
1obj=a.o b.o c.o变量取值:aa=$(obj)
makefile自带的变量:大写
- CPPFLAGES
- CC
自动变量
- $@:规则中的目标
- $<:规则中的第一个依赖
- $^:规则中的所有依赖
- 只能在规则的命令中使用
例:
1234567obj = main.o add.o sub.o mul.otarget = app$(target):$(obj)gcc $(obj) -o $(target)%.o:%.cgcc -c $< -o $@模式匹配:
%.o:%.c
第一次:main.o没有,向下找匹配规则,自动变量会自动生成规则
main.o:main.c
gcc -c main.c -o main.o
第二次:add.o
add.o:add.c
gcc -c add.c -o add.o
缺点:可移植性比较差
第四个版本
- makefile所有的函数都有返回值
- 查找指定目录下指定类型的文件
- src = $(wildcard ./*.c) #搜索当前目录下所有.c文件
- 匹配替换
- patsubst进行替换,有三个参数
- obj = \$(patsubst %.c,%.o,$(src))
12SOURCES = $(wildcard *.cpp)OBJS=$(patsubst %.cpp,%.o, $(SOURCES))第二种匹配替换方法:
- 12SRC=$(wildcard *.cpp)OBJ=$(SRC:.cpp=.o)
用这种方法比patsubst要容易记忆
第五个版本
让make生成不是终极目标的目标
- make 目标名 :来执行
编写一个清理项目的规则
clean:
-rm -f *.o app
声明伪目标:
- .PHONY:clean
- 这样把目标声明成伪目标之后,就不会去进行文件存在检查和文件更新时间检查
补充知识:
- rm:-f, –force 忽略不存在的文件,从不给出提示。
- makefile 命令加一个减号 - 代表当前命令执行失败了不会停止,继续执行下面的命令,即忽略失败
最终版本示例:
|
|
补充
@
make执行到每一句命令的时候,不仅会执行那个命令,同时还会将命令完整的打印输出到屏幕上,但是作为执行命令的符号,我们有时候不希望打印在屏幕上,不好看,也显得乱,例如:
|
|
最终输出为:
|
|
不是我们希望的:
|
|
这时候就需要使用到@符号。
- @
- 在命令前加上@符号后就可以使make不显示这个命令本身和相关参数
例1:
|
|
输出为
|
|
例二:(不仅不显示命令本身,相关的参数也会被自动去掉)
|
|
输出:
|
|