目录
1.第二阶段任务
完成编译整个工程的makefile文件
调用模块makefile编译生成静态库文件
链接所有模块的静态文件,最终得到可执行程序
2.关键的实现要点
- 如何自动创建build文件夹以及子文件夹?
- 如何进入每一个模块文件夹进行编译?
- 编译成功后如何链接所有模块静态库?
3.开发中的经验假设
项目中的各个模块字设计阶段就已经基本确定,因此,在之后的开发过程中不会频繁随意的增加或者减少!
4.解决方案设计
1.定义变量保存模块名列表(模块名变量)
2.利用shell中的for循环遍历模块名变量
3.在for循环中进入模块文件夹进行编译
4.循环结束后链接所有的模块静态库文件
5.makefile中嵌入shell的for循环
6.注意事项
makefile中嵌入shell代码时,如果需要使用shell变量的值,必须在变量名前加上$$(例:$$dir)!
先写一个shell脚本测试一下
aston@ubuntu:~/disciple$ ./test.sh
common
module
main
aston@ubuntu:~/disciple$ cat test.sh
MODULES="common module main"
for dir in $MODULES;
do
echo $dir
done
编写makefile
aston@ubuntu:~/disciple$ make test
common
module
main
aston@ubuntu:~/disciple$ cat makefile
#MODULES := common module main
MODULES := common \
module \
main
test :
@set -e; \
for dir in $(MODULES); \
do \
echo $$dir; \
done
7.工程makefile中的关键构成
8.链接时注意事项
- gcc在进行静态链接时必须遵循严格的依赖关系
- 如果不清楚库之间的依赖,可以使用-Xlinker自动确定依赖关系
获取当前工程的绝对路径,同时得到编译存放的相对路径
.PHONY : all compile link
MODULES := common \
module \
main
DIR_PROJECT := $(realpath .)
DIR_BUILD := build
DIR_BUILD_SUB := $(addprefix $(DIR_BUILD)/, $(MODULES))
all :
@echo "$(DIR_PROJECT)"
@echo "$(DIR_BUILD_SUB)"
test :
@set -e; \
for dir in $(MODULES); \
do \
echo $$dir; \
done
测试一下:
/home/aston/disciple
build/common build/module build/main
自动创建对应目录
测试一下
.PHONY : all compile link
MODULES := common \
module \
main
MKDIR := mkdir
RM := rm -rf
DIR_PROJECT := $(realpath .)
DIR_BUILD := build
DIR_BUILD_SUB := $(addprefix $(DIR_BUILD)/, $(MODULES))
all :
@echo "$(DIR_PROJECT)"
@echo "$(DIR_BUILD_SUB)"
compile : $(DIR_BUILD) $(DIR_BUILD_SUB)
@set -e; \
for dir in $(MODULES); \
do \
echo $$dir; \
done
$(DIR_BUILD) $(DIR_BUILD_SUB) :
$(MKDIR) $@
common main makefile module
aston@ubuntu:~/disciple$ make compile
mkdir build
mkdir build/common
mkdir build/module
mkdir build/main
common
module
main
aston@ubuntu:~/disciple$ ls
build common main makefile module
aston@ubuntu:~/disciple$ ls build/
common main module
现在就可以进去每个模块进行编译
compile : $(DIR_BUILD) $(DIR_BUILD_SUB)
@echo "Begin to compile..."
@set -e; \
for dir in $(MODULES); \
do \
cd $$dir && $(MAKE) all DEBUG:=$(DEBUG) && cd ..; \
done
@echo "compile success..."
测试一下:
aston@ubuntu:~/disciple$ make compile
mkdir build
mkdir build/common
mkdir build/module
mkdir build/main
Begin to compile...
make[1]: Entering directory `/home/aston/disciple/common'
makefile:41: /home/aston/disciple/build/common/common.dep: No such file or directory
makefile:41: /home/aston/disciple/build/common/func.dep: No such file or directory
Creating /home/aston/disciple/build/common/func.dep...
Creating /home/aston/disciple/build/common/common.dep...
make[1]: Leaving directory `/home/aston/disciple/common'
make[1]: Entering directory `/home/aston/disciple/common'
ar crs /home/aston/disciple/build/common.a /home/aston/disciple/build/common/common.o /home/aston/disciple/build/common/func.o
Success! Target ==> /home/aston/disciple/build/common.a
make[1]: Leaving directory `/home/aston/disciple/common'
make[1]: Entering directory `/home/aston/disciple/module'
makefile:41: /home/aston/disciple/build/module/module.dep: No such file or directory
Creating /home/aston/disciple/build/module/module.dep...
make[1]: Leaving directory `/home/aston/disciple/module'
make[1]: Entering directory `/home/aston/disciple/module'
ar crs /home/aston/disciple/build/module.a /home/aston/disciple/build/module/module.o
Success! Target ==> /home/aston/disciple/build/module.a
make[1]: Leaving directory `/home/aston/disciple/module'
make[1]: Entering directory `/home/aston/disciple/main'
makefile:41: /home/aston/disciple/build/main/main.dep: No such file or directory
Creating /home/aston/disciple/build/main/main.dep...
make[1]: Leaving directory `/home/aston/disciple/main'
make[1]: Entering directory `/home/aston/disciple/main'
ar crs /home/aston/disciple/build/main.a /home/aston/disciple/build/main/main.o
Success! Target ==> /home/aston/disciple/build/main.a
make[1]: Leaving directory `/home/aston/disciple/main'
compile success...
接下来就是实现link
先将.a文件加上前缀,定义最终生成目标的名和路径
MODULE_LIB := $(addsuffix .a, $(MODULES))
MODULE_LIB := $(addprefix $(DIR_BUILD)/, $(MODULE_LIB))
APP := app.out
APP := $(addprefix $(DIR_BUILD)/, $(APP))
all :
@echo "$(MODULE_LIB)"
测试一下:
make all
build/common.a build/module.a build/main.a
build/app.out
.PHONY : all compile link
MODULES := common \
module \
main
MKDIR := mkdir
RM := rm -rf
CC := gcc
LFALGS :=
DIR_PROJECT := $(realpath .)
DIR_BUILD := build
DIR_BUILD_SUB := $(addprefix $(DIR_BUILD)/, $(MODULES))
MODULE_LIB := $(addsuffix .a, $(MODULES))
MODULE_LIB := $(addprefix $(DIR_BUILD)/, $(MODULE_LIB))
APP := app.out
APP := $(addprefix $(DIR_BUILD)/, $(APP))
all :
@echo "$(MODULE_LIB)"
@echo "$(APP)"
compile : $(DIR_BUILD) $(DIR_BUILD_SUB)
@echo "Begin to compile..."
@set -e; \
for dir in $(MODULES); \
do \
cd $$dir && $(MAKE) all DEBUG:=$(DEBUG) && cd ..; \
done
@echo "compile success..."
link $(APP) : $(MODULE_LIB)
@echo "Begin to link..."
$(CC) -o $(APP) -Xlinker "-(" $^ -Xlinker "-)" $(LFLAGS)
@echo "link success ..."
$(DIR_BUILD) $(DIR_BUILD_SUB) :
$(MKDIR) $@
测试一下:
make link
Begin to link...
gcc -o build/app.out -Xlinker "-(" build/common.a build/module.a build/main.a -Xlinker "-)"
link success ...
aston@ubuntu:~/disciple$ ./build/app.out
Version: 1.0.0
main()::start main ...
void common() ...
module_main()::start module ...
void foo()::Hello, D.T.Software ...
优化一下:
.PHONY : all compile link clean rebuild
MODULES := common \
module \
main
MKDIR := mkdir
RM := rm -rf
CC := gcc
LFALGS :=
DIR_PROJECT := $(realpath .)
DIR_BUILD := build
DIR_BUILD_SUB := $(addprefix $(DIR_BUILD)/, $(MODULES))
MODULE_LIB := $(addsuffix .a, $(MODULES))
MODULE_LIB := $(addprefix $(DIR_BUILD)/, $(MODULE_LIB))
APP := app.out
APP := $(addprefix $(DIR_BUILD)/, $(APP))
all : compile $(APP)
@echo "Target File ==>$(APP)"
compile : $(DIR_BUILD) $(DIR_BUILD_SUB)
@echo "Begin to compile..."
@set -e; \
for dir in $(MODULES); \
do \
cd $$dir && $(MAKE) all DEBUG:=$(DEBUG) && cd ..; \
done
@echo "compile success..."
link $(APP) : $(MODULE_LIB)
@echo "Begin to link..."
$(CC) -o $(APP) -Xlinker "-(" $^ -Xlinker "-)" $(LFLAGS)
@echo "link success ..."
$(DIR_BUILD) $(DIR_BUILD_SUB) :
$(MKDIR) $@
clean :
$(RM) $(DIR_BUILD)
rebuild : clean all
@echo "rebuild success..."
- To be continued…
思考:
当前整个项目的makefile是否存在潜在的问题?是否需要重构?
综合
.PHONY : all compile link clean rebuild
MODULES := common \
module \
main
MKDIR := mkdir
RM := rm -fr
CC := gcc
LFLAGS :=
DIR_PROJECT := $(realpath .)
DIR_BUILD := build
DIR_BUILD_SUB := $(addprefix $(DIR_BUILD)/, $(MODULES))
MODULE_LIB := $(addsuffix .a, $(MODULES))
MODULE_LIB := $(addprefix $(DIR_BUILD)/, $(MODULE_LIB))
APP := app.out
APP := $(addprefix $(DIR_BUILD)/, $(APP))
all : compile $(APP)
@echo "Success! Target ==> $(APP)"
compile : $(DIR_BUILD) $(DIR_BUILD_SUB)
@echo "Begin to compile ..."
@set -e; \
for dir in $(MODULES); \
do \
cd $$dir && $(MAKE) all DEBUG:=$(DEBUG) && cd .. ; \
done
@echo "Compile Success!"
link $(APP) : $(MODULE_LIB)
@echo "Begin to link ..."
$(CC) -o $(APP) -Xlinker "-(" $^ -Xlinker "-)" $(LFLAGS)
@echo "Link Success!"
$(DIR_BUILD) $(DIR_BUILD_SUB) :
$(MKDIR) $@
clean :
@echo "Begin to clean ..."
$(RM) $(DIR_BUILD)
@echo "Clean Success!"
rebuild : clean all