1. 多目录递归makefile简介
1.1 前言
通过演示一个多目录makefile递归编译示例,解释其执行过程,帮助理解linux内核的编译框架原理。示例的子目录是可以很方便进行扩展的,其makefile自动识别当前目录下的.c文件,你也可以改成或增加识别.cpp等文件。
1.2 文件结构
根目录mk_exam下顶层Makefile(上图红框)使用了大写,其余子目录下的makefile(上图篮筐)用了小写。根目录mk_exam下有a目录、b目录、Makefile和一个m.c
根目录mk_exam下执行make以后
产生了几个.o和bi.a文件和可执行文件test。bi.a,这里使用linux内核的中间文件名称buit-in.a的缩写,是一个部分链接的静态库文件的中间文件。
它们之间的关系可以简单理解如下:
- c1.c -> c1.o
- c1.o + c.o -> a/c/bi.a
- a.o + a/c/bi.a -> a/bi.a
- b.o -> b/bi.a
- m.o + a/bi.a + b/bi.a -> test
2. makefile执行流程
开始时在编译根目录mk_exam下,具体执行命令、路径变化和生成对象:
- 绿色标号①:执行make -C b/ -f makefile
- 绿色标号②:进入b目录
- 绿色标号③:执行cc -c -o b.o b.c,生成b/b.o
- 绿色标号④:执行ld -r b.o -o bi.a,生成b/bi.a
- 绿色标号⑤:离开b目录,回到了编译根目录mk_exam
- 绿色标号⑥:执行make -C a/ -f makefile
- 绿色标号⑦:进入a目录
- 绿色标号⑧:执行cc -c -o a.o a.c,生成a/a.o
- 绿色标号⑨:执行make -C c/ -f makefile
- 绿色标号⑩:进入c目录
- 绿色标号⑪:执行cc -c -o c.o c.c,生成c/c.o
- 绿色标号⑫:执行cc -c -o c1.o c1.c,生成c/c1.o
- 绿色标号⑬:执行ld -r c.o c1.o -o bi.a,生成c/bi.a
- 绿色标号⑭:离开c目录,实际上就回到a目录
- 绿色标号⑮:执行ld -r a.o c/bi.a -o bi.a,生成a/bi.a
- 绿色标号⑯:离开a目录,实际上就回到编译根目录mk_exam
- 绿色标号⑰:执行cc -c -o m.o m.c,生成m.o
- 绿色标号⑱:执行gcc -o test b/bi.a a/bi.a m.o,生成test
编译执行目录路径总结如下:
- 进入编译根目录mk_exam下
- 红色标号①:进入b目录,后退出b目录
- 红色标号②:进入a目录
- 红色标号③:进入c目录
- 红色标号④:后退到a目录
- 红色标号⑤:后退到编译根目录mk_exam,结束编译
3. 示例源码及运行结果
示例代码a.c、m.c如下:
make生成test执行如下:
xx@xx-vb:~/Pictures/mk_exam$ ./test
hello m=3 from a
4. 建议
不熟悉makefile基本用法的朋友们,建议先熟悉makefile的基本用法具体可参考跟我一起写 Makefile 熟悉目标依赖的关系,比如一些自动化变量的用法:
- $@ 表示目标文件
- $^ 表示所有的依赖文件
- $< 表示第一个依赖文件
- $? 表示比目标还要新的依赖文件列表