洞察探索如何通过一套代码实现跨平台小程序开发与高效管理,助力企业数字化转型
644
2022-08-26
makefile学习 (1)
学习自《跟我一起写Makefile》,《linux网络编程》 生成可执行文件的过程分为编译,汇编,链接等阶段,make工程管理器可以根据文件的时间戳发现更新后的文件有选择的编译,通过读入规则文件来执行编译工作。在整个过程中,make工程管理器调用了gcc编译器。
编译和链接
target ... : prerequisites ... command ... ...
prerequisites(依赖文件)中如果有一个以上的文件比target文件要新的话,command所定义的命令就会被执行。make会比较targets文件和prerequisites文件的修改日期,如果prerequisites文件的日期要比targets文件的日期要新,或者target不存在的话,那么,make就会执行后续定义的命令。 clean不是一个文件,它只不过是一个动作名字。要执行其后的命令(不仅用于clean,其他lable同样适用),就要在make命令后明显得指出这个lable的名字。我们可以在一个makefile中定义程序的打包,程序的备份,等等。 注意:第一行的target是总的目标,后面的都是进行依赖处理。
gcc的-c和-o
gcc -c test.c #编译test.c文件得到test.ogcc -c test.c -o test.o #同上gcc -o test test.o #链接test.o可执行文件gcc -o test test.c #将test.c编译并连接成可执行文件gcc test.c -o test #同上
make工作方式
输入make命令后: 1. make会在当前目录下找名字叫“Makefile”或“makefile”的文件。 2. 如果找到,它会找文件中的第一个目标文件(target),并把这个文件作为最终的目标文件。 3. 如果target文件不存在,或是所依赖的后面的 .o 文件的文件修改时间要比target文件新,那么,他就会执行后面所定义的命令来生成target文件。 4. 如果target所依赖的.o文件也不存在,那么make会在当前文件中找目标为.o文件的依赖性,如果找到则再根据那一个规则生成.o文件。(这有点像一个堆栈的过程)
make只管文件的依赖性, 如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错
make变量
3 个预定义变量介绍:
1. $@ 表示要生成的目标 2. $^ 表示全部的依赖文件 3. $<
4个参数:
1. -o 指定目标文件gcc sources/main.c -o bin/main2. -c 编译的时候只生产目标文件不链接gcc -c sources/main.c -o obj/main.o3. -I 主要指定头文件的搜索路径gcc -I headers -c main.c -o main.o4. -l 指定静态库gcc -lpthread
使用$(var)来代替变量var的值,用“$$”来表示$。 变量可以嵌套$($(x)) 可以使用“+=”操作符给变量追加值。 更多变量说明,
makefile的注释:
单行: 行首# 多行: 行首# 行尾\ 比如:
#PWD := $(shell pwd)#INC := $(PWD)/inc\DEBUG := -g\MAIN_OBJ := $(PWD)/*.o\ADD_OBJ := $(PWD)/add/*.o\SUB_OBJ := $(PWD)/sub/*.o\OBJ := $(SUB_OBJ) $(ADD_OBJ) $(MAIN_OBJ)\\main: $(OBJ)\ cc -o main $(OBJ) \\$(MAIN_OBJ) : $(PWD)/*.c $(INC)/*.h\$(ADD_OBJ) : $(PWD)/add/*.c\$SUB_OBJ) : $(PWD)/sub/*.c\
make自动推导
make的“隐晦规则”: 只要make看到一个[.o]文件,它就会自动的把[.c]文件加在依赖关系中,并推导出相关的命令。
关于tab缩进
在编写makefile的过程中,某一行出现红色那就要小心了,因为出现了错误。 编写makefile相关的vimrc配置:
set noexpandtabset softtabstop=4
来自《linux网络编程》的一个加法、减法的工程例子:
文件目录稍作改动。
相关代码:
add_float.c
float add_float(float a, float b){ return
add_int.c
int add_int(int a, int b){ return
sub_float.c
float sub_float(float a, float b){ return
sub_int.c:
int sub_int(int a, int b){ return
add.h
#ifndef __ADD_H__#defineextern int add_int(int a, int b);extern float add_float(float a, float b);#endif
sub.h
#ifndef __SUB_H__#defineextern float sub_float(float a, float b);extern int sub_int(int a, int b);#endif
main.c
#include
现在,写一个简单的makefile,使得产生的.o文件都在mkfl下,然后链接即可。
PWD := $(shell pwd)INC := $(PWD)/incADD := $(PWD)/addSUB := $(PWD)/subDEBUG := -gOBJ := $(PWD)/*.o.PHONY: allall: lib gcc -o main $(OBJ).PHONY: liblib: cc -c $(ADD)/*.c cc -c $(SUB)/*.c cc -c $(PWD)/main.c $(INC)/*.h.PHONY:cleanclean:#make clean -C $(PWD)
清洁文件
删除命令: -rm -f main *.o 在rm命令前面加了一个小减号的意思就是,也许某些文件出现问题,但不要管,继续做后面的事。clean从来都是放在文件的最后
makefile的规则
显式规则:各种依赖关系和命令 隐式规则:利用make的自动推导
特定的makefile文件
例如写了一个makefile_special 那么可以提示make寻找并解释它 make -f makefile_special
makefile的嵌套
include
通配符的展开和替换
如果想要通配符在变量中展开,那么我们需要关键字 wildcard(拓展通配符). 确定所有的.o文件 object := $(wildcard *.o) 如果想要进行通配集合的替换,那么需要关键字patsubst 确定所有.c文件对应的.o文件 object := $(pubsubst %.c, %.o, $(wildcard *.c)) [%为makefile的规则通配符]
文件搜索
vpath
vpath %.c dir1vpath %.c dir2vpath %.c
那么make将会先搜索dir1, 让然后是dir2, 最后是dir3
伪目标
使用.PHONY来指定伪目标,它不是文件,仅仅是一个标签。我们可以显示的指定来进行make。 比如上面加减例子中的makefile,如果使用命令make lib,那么我们将生成所有的.o文件,但是可执行文件main是不会产生的。 利用伪目标生成多个可执行文件:
all : enjoy hello love.PHONY: allenjoy: enjoy.o cc enjoy.c -o enjoyhello: hello.o cc hello.c -o hello love: love.o cc love.c -o love.PHONY: cleanclean: rm -f *.o
第一行指明终极目标,后面又指出这个all是个伪目标,所以不会产生all文件。但是其依赖的三个文件被创建出来了。 当然,你也可以写一个shell脚本,来几行gcc -o ...,这样也行。
自动搜索依赖头文件
gcc -M main.c #这会将库文件也打出来 gcc -MM main.c #仅输出include的头文件 还是以上面的加减例子做说明
cc -MM main.cmain.o: main.c inc/add.h inc/sub.h
[.d]文件中就存放对应[.c]文件的依赖关系
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~