这是针对makefile的一次实验,主要针对于makefile如何管理子路径以及头文件依赖。
1.工程目录组织
工程目录下包含一个子目录sub以及main.c文件,sub包含文件add.c、add.h。该工程编译后产生一个可执行main文件,该文件实现加法功能,在执行时需要将做加法的参数传入程序。
|-->root
|--------->main.c
|--------->sub
| --------->add.c
| ---------->add.h
2.编写makefile
编译过程都是先生成.o文件,再使用.o文件生成可执行文件。编译过程需要指定需要编译的源文件、头文件路径以及源文件与头文件的依赖关系。
2.1 指定源文件
obj-c =
obj-c += $(wildcard *.c) #将根目录下所有c文件添加到源文件列表中,obj-c本身为一个字符串。
obj-c += $(wildcard sub/*.c) #将子目录sub下所有c文件添加到源文件列表中。每个文件带相对更文件的路径
obj-o =
obj-o += $(patsubst %.c, %.o, $(obj-c)) #根据c列表生成o列表
2.2 指定头文件路径
INCLUDES = -Isub # 将根目录下头文件路径添加到路径列表中
2.3 源文件与头文件依赖
如果没有此项操作,会出现头文件变更但是依赖于该头文件的c文件不会被编译的问题。
a. DEPENDENCY_LIST = $(patsubst %.o,%.d,$(obj-o)) # 依赖文件加入到依赖文件列表中,依赖文件后缀为.d
b. @gcc $(INCLUDES) -w -c $< -MMD -MT $@ -o $@ # -MMD 生成依赖文件 -MT $@ 指定当前依赖文件中目标名称 -o $@ .o文件生成到源文件目录下
c. -include $(DEPENDENCY_LIST) #将所有依赖文件包含到当前makefile中
3.编译过程步骤
1、读入所有的 Makefile。
2、读入被 include 的其它 Makefile。
3、初始化文件中的变量。
4、推导隐晦规则,并分析所有规则。
5、为所有的目标文件创建依赖关系链。
6、根据依赖关系,决定哪些目标要重新生成。
7、执行生成命令。
4.源文件
4.1 main.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include "add.h"
int main(int argc, void *argv[])
{
printf("%s + %s = %d\r\n", argv[1], argv[2], add(atoi(argv[1]), atoi(argv[2])));
return 0;
}
4.2 add.c
#include <stdio.h>
#include <stdlib.h>
int add(int a, int b)
{
return a + b;
}
4.3 add.h
int add(int a, int b);
4.4 Makefile
#1.带1级子目录的工程,makefile规则先生成.o文件然后使用所有.o文件生成可执行文件。
#2.自动生成源文件对应.o文件的依赖
#3.使用静态模式生成.o文件
#4.最后链接所有第3步生成文件
#5.将.o .d文件放在out路径下
obj-c =
obj-c += $(wildcard *.c)
obj-c += $(wildcard sub/*.c)
obj-o =
obj-o += $(patsubst %.c, %.o, $(obj-c))
INCLUDES = -Isub
out-dir = out
obj-list = $(addprefix $(out-dir)/,$(obj-o))
DEPENDENCY_LIST = $(patsubst %.o,%.d,$(obj-o))
all: path $(obj-o)
@gcc -o main $(obj-o)
#后缀静态模式
.SUFFIXES: .c .o
.c.o:
@echo "building file "$@
@mkdir -p $(out-dir)/$(subst $(notdir $@),,$@)
@gcc $(INCLUDES) -w -c $< -MMD -MT $@ -o $@
@cp $@ $(out-dir)/$@
-include $(DEPENDENCY_LIST)
path:
@mkdir -p $(out-dir)
clean:
rm *.o *.d
rm sub/*.o sub/*.d main
rm -rf $(out-dir)
#静态模式
#$(obj-o): %.o:%.c
# echo $0
# gcc $(INCLUDES) -c -w $< -MMD -MT $@ -o $@
#-include $(dependency_list)
.PHONY: all path clean