一、make 是啥?
make 是软件构造工具,通过读取 Makefile文件自动化完成构建。
二、make 核心?
target ... : prerequisites ...
(TAB)command
1. target 名为目标文件,实际是Object File,或执行文件,以及标签(Label)。
2. prerequisites 是target所依赖的文件或是目标。
如果 prerequisites 的修改时间比 target 更新,或者 target 文件不存在,command 被执行。首次执行 make 创建了 target 文件是因为 target 文件不存在,之后执行 make 会根据修改时间的属性进行判断,如更新了源码内容,那么 command 还会再次执行。
这就是 Makefile 的规则和核心。
三、make 实例
标准的编译过程:源文件先被编译成目标文件,然后再由目标文件连接成可执行文件。
cc = gcc
prom = calc
deps = calc.h
obj = main.o getch.o getop.o stack.o$(prom): $(obj)
$(cc) -o $(prom) $(obj)main.o: main.c $(deps)
$(cc) -c main.cgetch.o: getch.c $(deps)
$(cc) -c getch.cgetop.o: getop.c $(deps)
$(cc) -c getop.cstack.o: stack.c $(deps)
$(cc) -c stack.c
我们发现所有.c都会被编译成相同名称的.o文件,可以根据该特点再对其做进一步的简化:
cc = gcc
prom = calc
deps = calc.h
obj = main.o getch.o getop.o stack.o$(prom): $(obj)
$(cc) -o $(prom) $(obj)%.o: %.c $(deps)
$(cc) -c $< -o $@
1. %.o:%.c,这是一个模式规则,表示所有的.o目标都依赖于与它同名的.c文件(当然还有deps中列出的头文件)。
2. $< 是依赖关系表中的第一项(如果我们想引用的是整个关系表,那么就应该使用$^),具体到我们这里就是%.c。
3. $@ 是当前语句的目标,即%.o。这样一来,make命令就会自动将所有的.c源文件编译成同名的.o文件。不用我们一项一项去指定了。整个代码自然简洁了许多。
如果我们需要往工程中添加一个.c或.h,可能同时就要再手动为obj常量再添加一个.o文件,如果这列表很长,代码会非常难看,为此,我们需要用到Makefile中的函数,再次简化:
cc = gcc
prom = calc
deps = $(shell find ./ -name"*.h")
src = $(shell find ./ -name"*.c")
obj = $(src:%.c=%.o)$(prom): $(obj)
$(cc) -o $(prom) $(obj)%.o: %.c $(deps)
$(cc) -c $< -o $@clean:
rm -rf $(obj) $(prom)
shell函数主要用于执行shell命令,具体到这里就是找出当前目录下所有的.c和.h文件。而$(src:%.c=%.o)则是一个字符替换函数,它会将src所有的.c字串替换成.o,实际上就等于列出了所有.c文件要编译的结果。
四、make 执行过程
man make:
... ...
-d Print debugging information in addition to normal processing. The debugging information says which files are being considered for remaking, which file-times are being compared and with what results, which files actually need to be remade, which implicit rules are considered and which are applied---everything interesting about how make decides what to do.
基本信息输出:make --debug=b
详细信息输出:make -d