记录一下Makefile的学习过程
目录
1.普通代码编译顺序
假设有3个文件:main.cpp test1.cpp test2.cpp test1.h test2.h,编译为可执行文件test
一般步骤:g++ main.o test1.o test2.o -o test
g++ main.cpp -o main.o;g++ test1.cpp -o test1.o;g++ test2.cpp -o test2.o
所以一般Makefile可写为:
Object := main.o test1.o test2.o
//定义变量
test : $(object)
//test为生成目标,右侧为依赖项。即右边为输入参数,左边为输出,下一行为命令,即代码行(一定要以tab开头)
g++ main.o test1.o test2.o -o test
main.o : main.cpp test1.h test2.h
g++ main.cpp -o main.o
test1.o : test1.cpp test1.h
g++ test1.cpp -o test1.o
test2.o : test2.cpp test2.h
g++ test2.cpp -o test2.o
2.Makefile 自动推导
Makefile见到.o文件会自动推导出相应的h和c文件以及g++步骤,所以上述可简化为:
Object := main.o test1.o test2.o
test : $(object)
g++ main.o test1.o test2.o -o test
main.o : main.cpp
test1.o : test1.cpp
test2.o : test2.cpp
//可合并以上三行
$(object):main.cpp test1.cpp test2.cpp
g++ -c $^ -o $@
Makefile有相应的clean操作;
Clean:
rm ...
更标准的写法为:
.PHONY : clean
Clean:
Rm ....
.PHONY表示clean为伪目标
3.命名规则
一般命名为Makefile或小写,若为其他名称需指定文件名,命令为:make -f name或make --file name
4.目标和依赖
一般规则为:
A:B,即A为生成项,B为依赖项
若有多条这样的关系,第一条里的A为最终生成目标
5.指定搜索目录
一般大工程中会区分很多文件夹,如果不指定搜索目录,make只会在当前目录下搜索
可以用make中的关键字:vpath指定搜索路径,用法如下:
vpath 文件格式 搜索路径,如:vpath %.h ../header,即在上一级目录header中查找所有h结尾的文件
6.调试
Make -n 或make --just-print 只显示命令不执行操作
7.Makefile中的变量
$@:所有目标
$^:所有依赖项
$<:第一个依赖项
$?:所有比目标更新的依赖文件
8.条件判断
ifeq(a,b)//判断相等
else
endif
ifneq(a,b)//判断不相等
else
Endif
Ifdef a//判断是否定义
else
Endif
9.静态库和动态库
动态库编译过程:
g++ -c test.cpp -o test.o -I./include -g -fPIC
g++ -shared test.o -o libtest.so
Makefile实现:
编译动态库:
libtest.so:test.o
g++ -shared $^ -o $@
链接动态库:
Target:main.o
g++ $^ -o $@ -l libtest.so -L./lib -I./include
10.常用函数
(1)Subst
$(subst<from>,<to>,<str>)
把字符串str中from替换为to,返回被替换的字符串
Eg:subst(ee,EE,feed on the street)
Return:fEEd on the strEEt
(2)Patsubst
$(patsubst(pattern,replace,str))
把字符串str中满足pattern的替换为replace
$(patsubst(%.c,%o,a.c b.c))
Return:a.o b.o
类似于变量替换规则:
$(var:<pattern>=<replace>)
$(a.c b.c:%.c=%.o)
(3)Strip
去空格函数,去掉开头和结尾的空格
(4)Findstring
查找字串
$(findstring <find>,<in>)
在字串in中查找find,查找到返回find,否则返回空
(5)Filter
$(filter <pattern>,text)
text中保留符合模式pattern的字串,过滤掉其他的
$(filter %.o,a.c b.c a.o b.o)
输出为:a.o,b.o
(6)Filter-out
$(filter-out <pattern>,text)
除去符合模式pattern的字串
(7)Sort
对list中的单词排序(升序)
$(sort <list>)
(8)Word
$(word n,text)
取出text中第n个字串
(9)Dir
取目录,最后一个‘/’之前的目录,没有的话返回‘./’
Dir(path)
Dir(src/test.c test.c)返回src/ ./