当一个大的项目由很多子程序组成,而每一个子程序包都有自己独立的Makefile,这时候就需要一个总控Makefile来一次性完成所有的编译工作。以下给出了一个例子,以说明如何构建总控Makefile。
文件结构
项目PRJ包含了三个子程序包。每个子程序包都拥有自己的Makefile,从而可以在各目录下使用Make完成编译。但是这样很麻烦。通过构建总控Makefile(PRJ/Makefile),可以一次性编译prj_sub1,prj_sub2,prj_sub3三个子程序包。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17PRJ/
├── prj_sub1/
│ ├── a.c
│ ├── b.c
│ ├── c.c
│ └── Makefile
|
├── prj_sub2/
│ ├── d.c
│ ├── e.c
│ └── Makefile
├── prj_sub3/
│ ├── f.c
│ ├── g.c
│ └── Makefile
├── ...
└── Makefile
子程序包Makfile
子程序包中的Makefile包含了编译,install,clean操作。以下例子中,有关函数foreach,自动化变量$@ $<,以及静态模式的内容可以参见X。
需要注意的是变量BIN并没有在Makefile中声明赋值,而是通过总控Makefile中的export来传递。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#Makefile for prj_sub1/
CC = gcc
EXEC = a b c
OBJ = $(foreach exe, ${EXEC}, ${exe}.o)
all: ${OBJ} ${EXEC}
${EXEC}:%:%.o
${CC} -o $@ $<
${OBJ}:%.o:%.c
${CC} -c -o $@ $<
install:
cp ${EXEC} ${BIN}
clean:
rm ${EXEC} ${OBJ}
总控Makefile
1 | export BIN=../bin |
总控Makefile一次性编译了prj_sub1,prj_sub2,prj_sub3三个子程序包。
首先对变量SUBS_make赋值,为prj_sub1.make prj_sub2.make prj_sub3.make。类似的,完成变量SUBS_clean,SUBS_install的赋值。
随后,在编译中,${SUBS_make}:%.make:%声明从变量SUBS_make中逐次提取以.make结尾的字段作为编译目标,去掉.make之后的内容作为编译依赖项目,进而利用make -C $<完成编译。第10,11行等价于:
1 | prj_sub1.make: prj_sub1 |
make -C prj_sub1等价于cd prj_sub1; make。其相当于先进入目录prj_sub1,然后执行make命令。
与编译类似,install与clean操作一次性完成所有子程序包的安装及清理操作。
需要注意的是,利用export BIN=../bin,将变量BIN传递至被调用Makefile。