1.目的
主要是介绍一种多Makefile编译,即多个目录中含有Makefile,其好处是各自Makefile管理其对应目录的文件
2.组件
2.1 原始结构
├── include
│ ├── test1.h
│ └── test2.h
├── lib
├── main
│ ├── main.cpp
│ └── Makefile
├── Makefile
├── obj
│ └── Makefile
└── src
├── Makefile
├── test1.cpp
└── test2.cpp
2.2 Makefile
2.2.1顶层Makefile
1 ##top makefile
2
3 ##directory
4 PWD_DIR=$(shell pwd)
5 SRC_DIR=$(PWD_DIR)/src
6 OBJ_DIR=$(PWD_DIR)/obj
7 MAIN_DIR=$(PWD_DIR)/main
8 LIB_DIR=$(PWD_DIR)/lib
9 INC_DIR=$(PWD_DIR)/include
10 BIN_DIR=$(PWD_DIR)/bin
11
12 ##compiler
13 CXX=g++ ##CC=gcc
14 CFLAG=-Wall -g -I$(INC_DIR)
15
16 ##target
17 TARGET=app0_makefile
18
19 ##gloable variable
20 export PWD_DIR SRC_DIR OBJ_DIR MAIN_DIR LIB_DIR INC_DIR BIN_DIR TARGET CXX CFLAG
21
22 ##cmd
23 MKDIR=-mkdir -p
24 RM=-rm -rf
25
26 ##make rule
27 all:create_dir do_make cp_target
28
29 create_dir:
30 $(MKDIR) $(BIN_DIR)
31
32 do_make:
33 make -C $(SRC_DIR)
34 make -C $(MAIN_DIR)
35 make -C $(OBJ_DIR)
36
37 cp_target:
38 cp $(BIN_DIR)/$(TARGET) ~/workspace_sycong/
39
40 ##clean
41 clean:
42 $(RM) $(OBJ_DIR)/*.o
43 $(RM) $(BIN_DIR)
line4~10:指定一些目录
line13:指定编译器 g++ for .cpp, gcc for .c
line14:-I包含头文件,-g 包含debug信息,可gdb调试
line17:指定可执行程序名
line20:导出变量,使得在其他Makefile文件中可使用该变量
line27:all命令,执行其后面的命令
line29~30:创建目录
line32~35:使用src,main,obj目录的Makefile进程编译和链接
line37:可执行程序从./bin/目录拷贝至~/workspace_sycong/ (bin在非Linux分区,则chmod修改不成功)
line41~43:删除.o文件和bin目录
2.2.2 src层Makefile
1 #ALL_FILES=$(wildcard *.cpp)
2 #ALL_OBJS=$(patsubst %.cpp, %.o, $(ALL_FILES))
3
4 ##cpp file in src dir
5 FILE_1=test1.cpp
6 FILE_2=test2.cpp
7 #FILE_3=...
8
9 ##relpace .cpp to $(OBJ_DIR)/.o
10 OBJ_1=$(patsubst %.cpp, $(OBJ_DIR)/%.o, $(FILE_1))
11 OBJ_2=$(patsubst %.cpp, $(OBJ_DIR)/%.o, $(FILE_2))
12 #OBJ_3=$(patsubst %.cpp, $(OBJ_DIR)/%.o, $(FILE_3))
13
14 ##make rule
15 all:ECHO $(OBJ_DIR)/$(OBJ_1) $(OBJ_DIR)/$(OBJ_2)
16
17 ECHO:
18 @echo $(FILE_1) $(OBJ_1)
19 @echo $(FILE_2) $(OBJ_2)
20 @echo "echo end"
21
22 $(OBJ_DIR)/$(OBJ_1):$(FILE_1)
23 $(CXX) -c $^ -o $@ $(CFLAG)
24
25 $(OBJ_DIR)/$(OBJ_2):$(FILE_2)
26 $(CXX) -c $^ -o $@ $(CFLAG)
27
line4~7:指定src下的.cpp文件
line9~12:制定obj下的.o文件
line14~15:all命令
line17~20:echo输出信息
line22~26:编译出.o文件
2.2.3 main层Makefile
1 $(OBJ_DIR)/main.o:main.cpp
2 $(CXX) -c $^ -o $@ $(CFLAG)
2.2.4 obj层Makefile
1 ALL_OBJS=$(wildcard *.o)
2
3 $(BIN_DIR)/$(TARGET):$(ALL_OBJS)
4 $(CXX) -o $@ $^ $(CFLAG)
line3~4:链接生成可执行程序
3.make
make之后结构如下:
.
├── bin
│ └── app0_makefile
├── include
│ ├── test1.h
│ └── test2.h
├── lib
├── main
│ ├── main.cpp
│ └── Makefile
├── Makefile
├── obj
│ ├── main.o
│ ├── Makefile
│ ├── test1.o
│ └── test2.o
└── src
├── Makefile
├── test1.cpp
└── test2.cpp
在obj目录中生成了2个.o目标文件,且在bin中生成了可执行程序
4.other
wildcard 这是扩展通配符函数,功能是展开成一列所有符合由其参数描述的文 件名,文件间以空格间隔;比如:罗列出src下的所有.c文件:$(wildcard ${SRC}/*.c)
patsubst 这是匹配替换函数, patsubst(需要匹配的文件样式,匹配替换成什么文件,需要匹配的源文件)函数。比如:用src下的*.c替换成对应的 *.o文件存放到obj中:$(patsubst %.c, ${OBJ}/%.o, $(notdir $(SOURCE)))
notdir 这是去除路径函数,在上面patsubst函数中已经使用过,去除SOURCE中文件的所有目录,只留下文件名;
$@:表示目标文件
$^:表示所有依赖文件