1.格式
目标:依赖
tab键 命令
目标:一般是要编译的目标,也可以是一个动作
依赖:执行当前目标所依赖的先项目,可以是其他目标,具体文件或库等一个,可以 多个
命令:可以多个命令,一个一行
2.常用选项
make [-f file] [options] [target]
默认会在目录查找makefile或Makefile,也可以-f指定文件,options可以使用make -h查看,target没有指定默认是第一个,指定就用指定的
3.可以将不同单元分开,能够实现修改只编译部分,比如:
将g++ a.cpp b.cpp c.cpp abc.cpp -o abc变成
abc:a.o b.o c.o abc.cpp
g++ a.o b.o c.o abc.cpp -o abc
a.o:a.cpp
g++ a.cpp -o a.o
b.o:b.cpp
g++ b.cpp -o b.o
c.o:c.cpp
g++ c.cpp -o c.o
4.编译过程
g++ main.cpp -o xxx 直接从源码到可执行文件
预处理:g++ -E main.cpp > main.ii
编译:g++ -S main.ii 得到main.s的汇编
汇编:g++ -c main.s 得到main.o的二进制文件
链接:g++ -lstdc++ main.o 得到a.out
5.变量
系统变量
$* 不包括扩展名的目标文件名称
$+ 所有依赖的文件,以空格分隔
$< 表示规则中第一个条件
$? 所有时间戳比目标文件晚的依赖文件,空格分隔
$@ 目标文件完整名称
$^ 所有不重复的依赖文件,空格分隔
$% 如果目标是归档成员,则该变量表示目标的归档成员名称
系统常量(可以使用make -p查看)
AS 汇编程序名称 默认as
CC C编译器名称 默认cc
CPP c预编译器名称 默认cc -E
CXX c++编译器名称 默认g++
RM 文件删除程序别名 默认rm -f
自定义变量
定义:变量名=变量值(赋值,用终值,不管终值在定义前还是后)
使用:
(
变量名)
/
(变量名)/
(变量名)/{变量名}
修改值使用 := (也是赋值,只受当前行或前面的影响)
6.伪目标和模式匹配
伪目标:.PHONY:clean
声明为伪目标后不会判断目标是否存在或目标是否更新,就像上面执行clean就不会找clean文件,伪目标可以多个,空格分隔
模式匹配:目标和依赖相同部分可以使用%,可以将
abc:a.o b.o c.o abc.cpp
g++ a.o b.o c.o abc.cpp -o abc
a.o:a.cpp
g++ a.cpp -o a.o
b.o:b.cpp
g++ b.cpp -o b.o
c.o:c.cpp
g++ c.cpp -o c.o
改为
abc:a.o b.o c.o abc.cpp
g++ a.o b.o c.o abc.cpp -o abc
%.o:%.cpp
g++ $^ -o $@
wildcard $(wildcard ./.cpp) 获取当前目录下所有.cpp文件
patsubst $(patsubst %.cpp,%.o,./.cpp)将对应的cpp文件名替换成.o文件名
7.运行流程
8.编译动态链接库
动态链接库:运行时加载的库,只需要维护地址
-fPIC 产生位置无关代码
-shared 共享
-l(小L) 指定动态库
-I(大i)指定头文件目录,默认当前目录
-L 手动指定库文件搜索目录,默认只链接共享目录
Linux默认动态库路径配置文件:
/etc/ld.so.conf /etc/ld.so.conf.d/*.conf
9.编译静态链接库
静态链接库:会加入到可执行的二进制文件中,程序编译完成后,该库文件可以删除,静态库不需要加载运行时速达更快,但体积更大,不能独立更新
g++ -c test.cpp -o test.o
ar -r libtest.a test.o
10.通用部分做公共头文件
可以直接使用include xxx 包含
Makefile都是先展开变量然后调用指令
11.Makefile中调用shell命令
变量:A:=$(shell ls)
直接在命令调用也可以
12.嵌套调用
比如在外面新建一个Makefile,里面使用make -C(指定工作目录)如:
all:
make -C ./hello/world
13.Makefile条件判断
ifeq 是否相等
ifneq 是否不等
ifdef 变量是否存在
ifndef 变量是否不存在
最后要有endif
14.循环
foreach
for do end
15.自定义函数的实现和调用
本质为多行命令,放在外面
define func1
endef
define func2
echo $(1) $(2)
endef
all:
$(call func1)
$(call func2,abc,def) #带参数的
16. make install
make 将源文件编译成二进制可执行文件(包含各种库文件)
make install 创建目录然后将可执行文件拷贝到指定目录,加全局可执行目录
make clean 重置编译环境,删除无关文件
install 例子
install:$(TARGET)
if [-d $(PATH)];then echo $(PATH);else mkdir $(PATH);cp $(TARGET) $(PATH); fi;