您的位置:首页 > 运维架构 > 网站架构

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

2017-10-09 22:42 501 查看
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 = gcc
export LIB = STATIC

all:
@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.a
DYNAMICLIB = open_lib.so

INC = -I ./inc -fPIC
SRC = $(wildcard *.c )
OBJ = $(patsubst %c,%o,$(SRC))

FLAGE = -g -Wall $(INC)
SHARE = -shared -o
AR_CONFIG = ar crv
RANLIB = ranlib

all:$(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/inc
SRC = $(wildcard ./*.c)
OBJ = $(patsubst %.c,%.o,$(SRC))
DIR = $(shell pwd)

DIR_BIN = project.o

MOD_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_inc
DIR_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$ make
this is all project.
CC=gcc
LIB=STATIC
make[1]: Entering directory '/home/ghost/workspace/testMakefile/open_source'
gcc -g -Wall -I ./inc -fPIC -c open_module1.c
gcc -g -Wall -I ./inc -fPIC -c open_module2.c
ar crv open_lib.a open_module1.o open_module2.o
a - open_module1.o
a - open_module2.o
ranlib open_lib.a
make[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.c
gcc -g -Wall -I../../inc -I../../inc/module_system_inc -c module_system.c
make[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.c
gcc -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.a
make[1]: Leaving directory '/home/ghost/workspace/testMakefile/src'


执行结果

ghost@ghost-machine:~/workspace/testMakefile$ ./prj/project.o
test Makefile
file=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=DYNAMIC
this is all project.
CC=g++
LIB=DYNAMIC
make[1]: Entering directory '/home/ghost/workspace/testMakefile/open_source'
g++ -g -Wall -I ./inc -fPIC -c open_module1.c
g++ -g -Wall -I ./inc -fPIC -c open_module2.c
g++ -g -Wall -I ./inc -fPIC -shared -o open_lib.so open_module1.o open_module2.o
make[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.c
g++ -g -Wall -I../../inc -I../../inc/module_system_inc -c module_system.c
make[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.c
g++ -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.so
make[1]: Leaving directory '/home/ghost/workspace/testMakefile/src'


执行结果

ghost@ghost-machine:~/workspace/testMakefile$ ./prj/project.o
test Makefile
file=module_func.c,func=test_func1 is called.
file=module_system.c,func=system_func is called.
open_module1_func is called
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  makefile 设计 架构