Makefile构建工程设计——工程组织Makefile的嵌套

来源:互联网 发布:为什么黑客都用python 编辑:程序博客网 时间:2024/05/16 15:49

  • Makefile的架构分布
    • 顶层Makefile
    • 库文件层Makefile
    • 源码集合层Makefile
    • 模块层Makefile
  • 整个工程的编译与运行

工程由树形分布,如下所示,里面有源码和库文件源码。

ghost@ghost-machine:~/workspace/testMakefile$ tree.├── inc│   ├── module_func.h│   └── module_system_inc│       └── module_system.h├── Makefile(顶层)├── open_source│   ├── inc│   │   ├── open_module1.h│   │   └── open_module2.h│   ├── Makefile(库文件层)│   ├── open_module1.c│   └── open_module2.c├── prj└── src    ├── main.c    ├── Makefile(源码集合层)    └── module        ├── Makefile(模块层)        ├── module_func.c        └── module_system.c

Makefile的架构分布

Makefile的框架分布决定着如何组织编译整个工程代码。

顶层Makefile

顶层Makefile的作用是将工程调度,先编译哪个模块,后编译哪个模块,这里的顶层Makefile先编译的是库文件的源码。

export CC = gccexport LIB = STATICall:    @echo "this is all project."    @echo "CC=$(CC)"    @echo "LIB=$(LIB)"    @$(MAKE) -C ./open_source LIB=$(LIB) CC=$(CC)    @$(MAKE) -C ./src LIB=$(LIB) CC=$(CC)clean:    rm -rf ./prj/*.o    $(MAKE) -C ./open_source clean    $(MAKE) -C ./src clean

这里定义两个外部变量,通过顶层Makefile传参给其他层的Makefile
export CC = gcc
export LIB = STATIC

LIB的参数有两个:STATIC、DYNAMIC,代表分别编译静态库和动态库。

库文件层Makefile

库文件层的Makefile负责将所管理的源码编译成库文件调度形式给工程用,通过顶层传递的Makefile参数来决定编译动态库还是静态库。

STATICLIB = open_lib.aDYNAMICLIB = open_lib.soINC = -I ./inc -fPICSRC = $(wildcard *.c )OBJ = $(patsubst %c,%o,$(SRC))FLAGE = -g -Wall $(INC)SHARE = -shared -oAR_CONFIG = ar crvRANLIB = ranliball:$(OBJ)ifeq ($(LIB),STATIC)    $(AR_CONFIG) $(STATICLIB) $^    $(RANLIB) $(STATICLIB)else ifeq ($(LIB),DYNAMIC)    $(CC) $(FLAGE) $(SHARE) $(DYNAMICLIB) $^endif.c.o:    $(CC) $(FLAGE) -c $<clean:    rm -f *.o    rm -f ./$(STATICLIB)    rm -f ./$(DYNAMICLIB)

通过ifeq和else ifeq来判断传递的参数来决定编译静态库还是动态库。

源码集合层Makefile

该Makefile具有顶层的部分功能,将不同模块目标文件以及库文件编译整合成project.o文件,对不同模块进行管理。

DIR_INC = -I../inc \          -I../inc/module_system_inc \          -I../open_source/incSRC = $(wildcard ./*.c)OBJ = $(patsubst %.c,%.o,$(SRC))DIR = $(shell pwd)DIR_BIN = project.oMOD_SRC = $(wildcard ./module/*.c)MOD_OBJ = $(patsubst %.c,%.o,$(MOD_SRC))STATICLIB = $(wildcard $(DIR)/../open_source/*.a)DYNAMICLIB = $(wildcard $(DIR)/../open_source/*.so)CFLAGS = -g -Wall $(DIR_INC)all:$(MOD_OBJ) $(DIR_BIN)$(MOD_OBJ):$(MOD_SRC)    @$(MAKE) -C module$(DIR_BIN):$(OBJ)ifeq ($(LIB),STATIC)    $(CC) $(CFLAGS) -o ../prj/$@ $^ $(MOD_OBJ) $(STATICLIB)else ifeq ($(LIB),DYNAMIC)    $(CC) $(CFLAGS) -o ../prj/$@ $^ $(MOD_OBJ) $(DYNAMICLIB)endif$(OBJ):$(SRC)    $(CC) $(CFLAGS) -c $^clean:    rm -f *.o    $(MAKE) -C module clean

模块层Makefile

这是模块代码功能实现的部分,整个工程分布着不同的模块,各个模块都需要进行编译。

DIR_INC = -I../../inc\          -I../../inc/module_system_incDIR_SRC = $(wildcard ./*.c)DIR_TAR = $(patsubst %c,%o,$(DIR_SRC))CFLAGS = -g -Wall $(DIR_INC)all:$(DIR_TAR).c.o:    $(CC) $(CFLAGS) -c $<clean:    rm -rf *.o

整个工程的编译与运行

顶层Makefile已经为传入的参数给定了默认值,也可以通过make来修改。

默认下编译整个工程。

ghost@ghost-machine:~/workspace/testMakefile$ makethis is all project.CC=gccLIB=STATICmake[1]: Entering directory '/home/ghost/workspace/testMakefile/open_source'gcc -g -Wall -I ./inc -fPIC -c open_module1.cgcc -g -Wall -I ./inc -fPIC -c open_module2.car crv open_lib.a open_module1.o open_module2.oa - open_module1.oa - open_module2.oranlib open_lib.amake[1]: Leaving directory '/home/ghost/workspace/testMakefile/open_source'make[1]: Entering directory '/home/ghost/workspace/testMakefile/src'make[2]: Entering directory '/home/ghost/workspace/testMakefile/src/module'gcc -g -Wall -I../../inc -I../../inc/module_system_inc -c module_func.cgcc -g -Wall -I../../inc -I../../inc/module_system_inc -c module_system.cmake[2]: Leaving directory '/home/ghost/workspace/testMakefile/src/module'gcc -g -Wall -I../inc -I../inc/module_system_inc -I../open_source/inc -c main.cgcc -g -Wall -I../inc -I../inc/module_system_inc -I../open_source/inc -o ../prj/project.o main.o ./module/module_func.o ./module/module_system.o /home/ghost/workspace/testMakefile/src/../open_source/open_lib.amake[1]: Leaving directory '/home/ghost/workspace/testMakefile/src'

执行结果

ghost@ghost-machine:~/workspace/testMakefile$ ./prj/project.o test Makefilefile=module_func.c,func=test_func1 is called.file=module_system.c,func=system_func is called.open_module1_func is called

参数传递下编译整个工程。

ghost@ghost-machine:~/workspace/testMakefile$ make CC=g++ LIB=DYNAMICthis is all project.CC=g++LIB=DYNAMICmake[1]: Entering directory '/home/ghost/workspace/testMakefile/open_source'g++ -g -Wall -I ./inc -fPIC -c open_module1.cg++ -g -Wall -I ./inc -fPIC -c open_module2.cg++ -g -Wall -I ./inc -fPIC -shared -o open_lib.so open_module1.o open_module2.omake[1]: Leaving directory '/home/ghost/workspace/testMakefile/open_source'make[1]: Entering directory '/home/ghost/workspace/testMakefile/src'make[2]: Entering directory '/home/ghost/workspace/testMakefile/src/module'g++ -g -Wall -I../../inc -I../../inc/module_system_inc -c module_func.cg++ -g -Wall -I../../inc -I../../inc/module_system_inc -c module_system.cmake[2]: Leaving directory '/home/ghost/workspace/testMakefile/src/module'g++ -g -Wall -I../inc -I../inc/module_system_inc -I../open_source/inc -c main.cg++ -g -Wall -I../inc -I../inc/module_system_inc -I../open_source/inc -o ../prj/project.o main.o ./module/module_func.o ./module/module_system.o /home/ghost/workspace/testMakefile/src/../open_source/open_lib.somake[1]: Leaving directory '/home/ghost/workspace/testMakefile/src'

执行结果

ghost@ghost-machine:~/workspace/testMakefile$ ./prj/project.o test Makefilefile=module_func.c,func=test_func1 is called.file=module_system.c,func=system_func is called.open_module1_func is called