嵌套makefile小型范例
这张图片左图和右图分别是make前后的文件夹目录变化,make之后生成了3个.o文件位于obj目录下,还生成了一个bin目录,其下生成了可执行文件test。下面是几个.cpp文件和.h文件的代码,很简单的代码,主要是为了演示嵌套makefile。
#pragma once
void print();
#include "../include/test.h"
#include <iostream>
void print()
{std::cout << "print()..." << std::endl;}
#pragma once
void eat();
#include "eat.h"
#include <iostream>
void eat()
{std::cout << "eat()..." << std::endl;}
#include "../include/test.h"
#include "../src/eat/eat.h"
int main()
{
eat();
print();
return 0;
}
下面是最顶层的Makefile文件内容
1 OBJ := main.o test.o eat.o
2 TOP_DIR := $(PWD)
3 OBJ_DIR := $(TOP_DIR)/obj
4 BIN_DIR := $(TOP_DIR)/bin
5 BIN:= test
6 SUB_DIR := main \
7 src \
8 src/eat \
9 obj
10 export OBJ TOP_DIR OBJ_DIR BIN_DIR BIN
11
12 all: CHECKDIR $(SUB_DIR)
13
14 CHECKDIR:
15 mkdir -p $(SUB_DIR) $(BIN_DIR)
16 $(SUB_DIR):ECHO
17 make -C $@
18 ECHO:
19 @echo $(SUB_DIR)
20 @echo begin compile
21
22 clean:
23 rm -rf $(OBJ_DIR)/*.o $(BIN_DIR)
24
25 .PHONY = all CHECKDIR ECHO clean
分行进行解析:(数字代表行数) 1.设置所有生成的.o文件 2.获取当前工作目录,PWD是makefile自带变量,PWD=$(shell pwd) 3.存放将要生成的.o文件目录 4.可执行文件目录 5.目标文件(在这里就是可执行文件test)名称 6.所有工程需要子目录名称 10.export设置全局变量,代表这些变量在下层的makefile中都可以直接使用,且值不变 25. .PHONY设置all CHECKDIR ECHO clean四个伪目标,伪目标的意思就是不会生成该文件,也可以没有依赖,在这里.PHONY其实也可以不设置,make能自行判断伪目标 12.第一个伪目标,依赖于CHECKDIR和(SUB_DIR) 14-17.生成对应的文件夹并向下执行Makefile 18-20.仅仅是打印一些信息 22、23.删除make生成的所有.o文件和可执行文件
Note:上述语句中需要注意的就是12-17几行,由于makefile中的目标与依赖文件关系,有点类似于栈的性质,拿这里举例,make发现all依赖于CHECKDIR和(SUBDIR),但是这两依赖文件都还没有,继续往下找,先找CHECKDIR怎么生成,发现了14行有目标CHENKDIR,没有依赖就执行15行的命令(如果CHECKDIR还有依赖,继续往下找);all目标的第一个依赖被解决了,继续找第二个依赖(SUB_DIR),发现其还有依赖ECHO,ECHO在18行作为目标没有依赖,所以总是先执行ECHO的打印信息,然后再执行下层的makefile,如下图所示(第一行是创建目录,第二行和第三行就是ECHO打印的信息) 再来简单的看下其他的下层Makefile
$(OBJ_DIR)/main.o:main.cpp
$(CXX) -c $^ -o $@
$(OBJ_DIR)/test.o: test.cpp
$(CXX) -c $^ -o $@
$(OBJ_DIR)/eat.o: eat.cpp
$(CXX) -c $^ -o $@
$(BIN_DIR)/$(BIN):$(OBJ)
$(CXX) $^ -o $@
|