1 基本规则
目标文件 :生成目标所需要的文件或者目标
具体操作
注:目标文件入口是all,可以是obj,也可以是执行文件;
all和clean一般是标配;
eg:
all:bin
……
bin:bin.cpp test.o
g++ ……
test.o:
g++ ......
clean:
rm *
注:这里边隐含的表达的编译顺序,all需要bin,bin需要test.o,所以要先编译test.o
2 常用的指令和符号
2.1 通配符
wildcard : 扩展通配符
notdir : 去除路径
patsubst :替换通配符
eg:假设src目录下有a.cc b.cc
SRCFILES = $(wildcard src/*.cc) # 输出src/a.cc src/b.cc,wildcard英文是百搭排的意思,这里就是src下所有以cc结尾的文件;
OBJFILES = $(patsubst %.cc,%.o,$(SRCFILES)) #输出 src/a.o src/b.o 将src/a.cc src/b.cc映射到src/a.o src/b.o
DIRFILES = $(notdir $(SRCFILES))#输出a.cc b.cc,就是去掉路径的意思;
另一种办法:
SRCSRCS = $(wildcard src/*.cpp)
SRCOBJS = $(SRCSRCS:.cpp=.o) #将cpp变成o
2.2 xlinker选项:
xlinker选项是提供多个.a时候,未知他们的依赖顺序时,自动查找依赖顺序;
用法:g++ -c a.cc -o a.o -I./include/ -Xlinker "-(" b.o c.a-Xlinker "-)"
2.3 其他命令:
$@ ——目标文件的名称;
$^ ——所有的依赖文件,以空格分开,不包含重复的依赖文件;
$< ——第一个依赖文件的名称。
示例:
main:main.c sort.o
gcc main.c sort.o -o main
表示为简洁的就是:
main:main.c sort.o
gcc $^ -o $@
3 最简单的makefile,就一行代码,省着我们每次都敲g++命令了;
all:
g++ -o hello_tf -c main.cpp -ltensorflow -L./lib -I./ -I./tensorflow/c/
4 关于-c -o和-g的解释:
示例命令行如下:
说明 标注1的地方,export PS1="----",是为了将命令行前缀改成“----”,主要是看的舒服点,另外可以隐层用户名这类信息;
标注2的地方,最简单,直接g++ 代码文件,默认生成a.out,可以正常执行;
标注3的地方,加入了-c,表示只编译,不链接,所以生成了main.o;
标注4和3一样,都是生成.o文件,只是他用-o指定了生成中间文件的名字,main2.o;
标注5,将.o文件生成可执行文件,生成的r1,r2均可正确执行;;
5 -L -rpath和-rpath-link
-L 依赖的位置;
-rpath_link (或者 -rpath-link):这个也是用于“链接”的时候的,例如你显示指定的需要 a.so,但是 a.so 本身是需要 b.so 的,后者你并没有指定,而是 a.so 引用到它,这个时候,会先从 -rpath-link 给的路径里找;
-rpath: “运行”的时候,去找的目录。运行的时候,要找 .so 文件,会从这个选项里指定的地方去找;
注意:有些高版本的gcc,是可以自己去寻找依赖的;但是某些低版本的却不行,这时候要用 -Wl,-rpath 依赖库地址,去显式依赖;
用法示例:-Wl,--rpath-link ./dep/torch/lib/ 原因,libtorch中,GOMP_critical_end相关的东西是没有的,因为在torch文件夹中,没有显式的用-l去引用,需要用这个来手动引用;
6 如果有找不到的库,或者定义怎么办?
可以通过grep,来寻找缺失的函数名,进而确定该函数在哪个库中,把链接加进来;
如果在工程中grep不到,那可能是系统库,查看系统以来路径,看是不是没有这个库,一般是/lib64/文件夹,另外,可以ldd依赖库,看是哪些是缺少的,对应的寻找;
不定期更新,欢迎拍砖;