21.打造专业的编译器环境(中)

目录

 

1.第二阶段任务

2.关键的实现要点

3.开发中的经验假设

4.解决方案设计

5.makefile中嵌入shell的for循环

6.注意事项

7.工程makefile中的关键构成

8.链接时注意事项

综合


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

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值