参考韦老师的教学记录
程序编译的过程:
- 预处理
- 编译
- 汇编
- 链接
通常的写法(有a.c b.c两个文件)
gcc -o test a.c b.c
直接编译为test的可执行文件
Makefile核心
- 目标文件不存在
- 某个依赖比目标文件新
变量
- := 简单变量(及时变量) A := 1
- = 延时变量 (用时确认) B = 2
- ?= 延时变量,第一次定义才起效,若在前已定义则忽略
- += 附加;及时变量或延时变量,取决于前面的定义
函数
foreach
$(foreach var, list, text)
对于list中的每一个变量,执行text操作
A = a b c
B = $(foreach f, $(A), $(f).o)
结果 B= a.o b.o c.o
filter
$(filter pattern..., text)
在text中取出符合pattern格式的值
$(filter-out pattern..., text)
在text中取出符合不符合pattern格式的值
C = a b c d/
D = $(filter %/, $(C))
E = $(filter-out %/, $(C))
结果 D = d/ E = a b c
wildcard
$(wildcard pattern)
pattern定义了文件名的格式 wildcard取出其中存在的文件
同级目录下有a.c b.c c.c
files = $(wildcard *.c)
files= a.c b.c c.c
取出真实存在的文件
同级目录下有a.c b.c c.c
files2 = a.c b.c c.c d.c e.c abc
files3 = $(wildcard $(files2))
files3= a.c b.c c.c
patsubst
$(patsubst parttern, replacement, text)
将text中符合parttern格式的替换为replacement。
files2 = a.c b.c c.c d.c e.c abc
dep_files = $(patsubst %.c,%.d,$(files2))
dep_files= a.d b.d c.d d.d e.d abc
缺陷
a.c
#include <stdio.h>
void func_b();
void func_c();
int main()
{
func_b();
func_c();
return 0;
}
b.c
#include <stdio.h>
void func_b()
{
printf("This is B\n");
}
c.c
#include <stdio.h>
#include <c.h>
void func_c()
{
printf("This is C = %d\n", C);
}
c.h
#define C 1
空文件clean
makefile
test:a.o b.o
gcc -o test a.o b.o
%.o : %.c
gcc -c -o $@ $<
clean:
rm *.o test
.PHONY : clean
如果修改c.h,执行Makefile不会重新更新程序
修改Makefile
test:a.o b.o
gcc -o test a.o b.o
c.o : c.c c.h
%.o : %.c
gcc -c -o $@ $<
clean:
rm *.o test
.PHONY : clean
修改头文件c.h后,make可用
对于一个c文件存在很多的头文件,手动的写出各个依赖显然不可行,需要自动的生成规则。
gcc使用 -M 命令可以查看依赖
gcc -M c.c
将依赖写入文件c.d文件
gcc -M -MF c.d c.c
生成依赖文件的同时编译c文件
gcc -c -o c.o c.c -MD -MF c.d
建立Include文件夹,将c.h放入改文件夹中
修改Makefile
objs = a.o b.o c.o
dep_files := $(patsubst %,.%.d, $(objs))
dep_files := $(wildcard $(dep_files))
CFLAGS = -Werror -Iinclude
test: $(objs)
gcc -o test $^
ifneq ($(dep_files),)
include $(dep_files)
endif
%.o : %.c
gcc $(CFLAGS) -c -o $@ $< -MD -MF .$@.d
clean:
rm *.o test
distclean:
rm $(dep_files)
.PHONY: clean
完美