1、通用部分做头文件
首先举个例子看看为什么需要这个东西,例如在一个文件夹下有两个项目,两个项目都需要编写makefile编译,此时可以使用公共头文件
目录结构如下:
1.1、项目(一)
- 有a.cpp、b.cpp、c.cpp、d.cpp四个文件,对应的makefile长这个样子
src = $(wildcard ./*.cpp)
obj = $(patsubst ./%.cpp, ./%.o, $(src));
tar = d
$(tar): $(obj)
${CXX} $^ -o $@
clean:
${RM} $(tar) *.o
.PHONY: clean $(tar)
1.2、项目(二)
- 有x.c、y.c、z.c四个文件,代码如下对应的makefile
src = $(wildcard ./*.c)
obj = $(patsubst ./%.c, ./%.o, $(src));
tar = z
$(tar): $(obj)
${CXX} $^ -o $@
clean:
${RM} $(tar) *.o
.PHONY: clean $(tar)
1.3、对比两个makefile
-
对比上面两个makefile,其主要的不同就是一个项目下是.cpp文件,一个是.c文件,而下面编译的代码几乎相同
-
因此可以通过makefile的手段来进行公共部分的提取
-
项目一makefile
tar = d include ../Makefile
-
项目二makefile
tar = z include ../Makefile
-
新生成的makefile
src = $(wildcard ./*.cpp ./*.c) obj = $(patsubst ./%.cpp,./%.o,$(src)) obj:= $(patsubst ./%.c,./%.o,$(obj)) $(tar):$(obj) ${CXX} $^ -o $@ clean: ${RM} $(tar) *.o .PHONY: clean d
-
2、makefile中=与:=
-
首先makefile在执行过程中会先对变量全部展开,最后在调用指令
-
在makefile中存在=和:=这两种“赋值”操作,但是这二者是存在一定的差异的
-
=
:可以理解为引用,可以在makefile中写一个a=$(a)的指令就会报出自身引用自身的错误 -
:=
:可以理解为赋值,这个值只与当前行之前的变量值有关,先把值拿出来赋值好,后面在修改与其无关。
-
2.1、情况(一)
a=123
b=$(a)asd
show:
@echo $(a)
@echo $(b)
a=456
实际上这个makefile会变成下面这个情况
a=123
b=$(a)asd
a=456
show:
@echo $(a)
@echo $(b)
# 输出
# 456
# 456asd
而=被认为是引用,因此只有最后才知道值,a一旦修改b引用a的值也会被修改
2.2、情况(二)
a=123
b:=$(a)asd
show:
@echo $(a)
@echo $(b)
a=456
这种情况会被转化为下面这个情况
a=123
b:=$(a)asd
a=456
show:
@echo $(a)
@echo $(b)
# 输出
# 456
# 123asd
:=被认为是强制取值进行覆盖,所以赋值完毕之后的修改对b无效
2.3、练习
a=123
a:=$(a)
b=$(a)asd
show:
@echo $(a)
@echo $(b)
a=456
# 输出
首先a = 123,然后a:=$(a)表示强行赋值,a=123;然后b=$(a)asd这里是引用a,最后a修改成456,所以最后输出
456
456asd
3、条件判断
- ifndef:if not definite的缩写
- ifdef:if definite的缩写
- else:否则
- endif:结束if判断
tar=z
ifdef tar
tar:=main
else
tar:=main.o
endif
show:
@echo $(tar)
# 输出 main
# 注释tar=z 输出 main.o
tar=z
ifndef tar
tar=main
endif
show:
@echo $(tar)
# 输出:z
# 注释tar=z,输出:main