ucore的makefile学习-以实际例子来展示
admin
2024-03-26 16:51:27
0

使用lab1_result目录
执行的命令为

make mytest

代码均添加在

listf

include tools/function.mk

后面一行。

mytest:echo $(call listf,./libs,c)

结果
./libs/string.c ./libs/printfmt.c

toobj

mytest:@echo $(call toobj,a.c,hello)

输出
obj/hello/a.o

todep

跟toobj相似,只是借用了toobj来实现取了下巧

mytest:@echo $(call todep,a.c,hello)

输出
obj/hello/a.d

totarget

mytest:@echo $(call totarget,a.c)

结果
bin/a.c

packetname

mytest:@echo $(call packetname,hello)

输出
__objs_hello

总结

listf用来获取c文件,
toobj指定obj/boot/*.o obj/kern/*.o等
todep指定的东西与.o在同一目录下
totargetbin/下面
以前函数均是返回一个字符串,.d文件指明其依赖的其它文件。

SLASH	:= /
OBJDIR	:= obj
BINDIR	:= bin
listf = $(filter $(if $(2),$(addprefix %.,$(2)),%),\$(wildcard $(addsuffix $(SLASH)*,$(1))))# get .o obj files: (#files[, packet])
toobj = $(addprefix $(OBJDIR)$(SLASH)$(if $(2),$(2)$(SLASH)),\$(addsuffix .o,$(basename $(1))))# get .d dependency files: (#files[, packet])
todep = $(patsubst %.o,%.d,$(call toobj,$(1),$(2)))totarget = $(addprefix $(BINDIR)$(SLASH),$(1))# change $(name) to $(OBJPREFIX)$(name): (#names)
packetname = $(if $(1),$(addprefix $(OBJPREFIX),$(1)),$(OBJPREFIX))# cc compile template, generate rule for dep, obj: (file, cc[, flags, dir])
define cc_template
$$(call todep,$(1),$(4)): $(1) | $$$$(dir $$$$@)@$(2) -I$$(dir $(1)) $(3) -MM $$< -MT "$$(patsubst %.d,%.o,$$@) $$@"> $$@
$$(call toobj,$(1),$(4)): $(1) | $$$$(dir $$$$@)@echo + cc $$<$(V)$(2) -I$$(dir $(1)) $(3) -c $$< -o $$@
ALLOBJS += $$(call toobj,$(1),$(4))
endef$(info  $(call cc_template,a.c ,gcc ,-g,))
test:echo hello
OBJDIR	:= obj
BINDIR	:= bin
SLASH	:= /
.SECONDEXPANSION:
# -------------------- function begin --------------------# list all files in some directories: (#directories, #types)
listf = $(filter $(if $(2),$(addprefix %.,$(2)),%),\$(wildcard $(addsuffix $(SLASH)*,$(1))))# get .o obj files: (#files[, packet])
toobj = $(addprefix $(OBJDIR)$(SLASH)$(if $(2),$(2)$(SLASH)),\$(addsuffix .o,$(basename $(1))))# get .d dependency files: (#files[, packet])
todep = $(patsubst %.o,%.d,$(call toobj,$(1),$(2)))totarget = $(addprefix $(BINDIR)$(SLASH),$(1))# change $(name) to $(OBJPREFIX)$(name): (#names)
packetname = $(if $(1),$(addprefix $(OBJPREFIX),$(1)),$(OBJPREFIX))# cc compile template, generate rule for dep, obj: (file, cc[, flags, dir])
define cc_template
$$(call toobj,$(1),$(4)): $(1) | $$$$(dir $$$$@)@echo + cc $$<$(V)$(2) -I$$(dir $(1)) $(3) -c $$< -o $$@
$$(call todep,$(1),$(4)): $(1) | $$$$(dir $$$$@)@$(2) -I$$(dir $(1)) $(3) -MM $$< -MT "$$(patsubst %.d,%.o,$$@) $$@"> $$@
ALLOBJS += $$(call toobj,$(1),$(4))
endefall: obj/test.o obj/test.d$(eval $(call cc_template,test.c,gcc,-g,))

其中,第一行
@gcc -I$(dir a.c ) -g -MM $< -MT "$(patsubst %.d,%.o,$@) $@"> $@
-I$(dir a.c),用于取.c所有的目录为include的查找目录,即include<...>的文件的查找目录被显示申明,不会再去查找系统默认库目录。
随便写一个test.c,可以对比如下两个的输出,这个gcc指令用来生成.d文件的。
gcc -MM test.c -MT "test.d",
gcc -MM test.c
下面一个gcc命令用于生成.o文件
注意到$$$$(dir $$$$@)行为比较怪异,这是二次展开,用法特殊
当eval执行完后
代码大概如下,

all: obj/test.d obj/test.oobj/test.d: test.c | objgcc -I. -g -MM test.c -MT "test.o test.d" > obj/test.d
obj/test.o: test.c | obj@echo + cc test.c@gcc -I . -g -c test.c -o obj/test.o
ALLOBJS+=obj/test.o

OBJDIR	:= obj
BINDIR	:= bin
SLASH	:= /
OBJPREFIX	:= __objs_
.SECONDEXPANSION:
# -------------------- function begin --------------------# list all files in some directories: (#directories, #types)
listf = $(filter $(if $(2),$(addprefix %.,$(2)),%),\$(wildcard $(addsuffix $(SLASH)*,$(1))))# get .o obj files: (#files[, packet])
toobj = $(addprefix $(OBJDIR)$(SLASH)$(if $(2),$(2)$(SLASH)),\$(addsuffix .o,$(basename $(1))))# get .d dependency files: (#files[, packet])
todep = $(patsubst %.o,%.d,$(call toobj,$(1),$(2)))totarget = $(addprefix $(BINDIR)$(SLASH),$(1))# change $(name) to $(OBJPREFIX)$(name): (#names)
packetname = $(if $(1),$(addprefix $(OBJPREFIX),$(1)),$(OBJPREFIX))# cc compile template, generate rule for dep, obj: (file, cc[, flags, dir])
define cc_template
$$(call todep,$(1),$(4)): $(1) | $$$$(dir $$$$@)@$(2) -I$$(dir $(1)) $(3) -MM $$< -MT "$$(patsubst %.d,%.o,$$@) $$@"> $$@
$$(call toobj,$(1),$(4)): $(1) | $$$$(dir $$$$@)@echo + cc $$<$(V)$(2) -I$$(dir $(1)) $(3) -c $$< -o $$@
ALLOBJS += $$(call toobj,$(1),$(4))
endef
# add files to packet: (#files, cc[, flags, packet, dir])
define do_add_files_to_packet
__temp_packet__ := $(call packetname,$(4))
ifeq ($$(origin $$(__temp_packet__)),undefined)
$$(__temp_packet__) :=
endif
__temp_objs__ := $(call toobj,$(1),$(5))
$$(foreach f,$(1),$$(eval $$(call cc_template,$$(f),$(2),$(3),$(5))))
$$(__temp_packet__) += $$(__temp_objs__)
endef$(eval $(call do_add_files_to_packet,test.c,gcc,-g,hello,))
$(info $(call do_add_files_to_packet,test.c,gcc,-g,hello,))
all:obj/test.o obj/test.decho ${__objs_hello}

关于do_add_files_to_packet干了什么,生成target obj/.o,obj/.d,并且将所有的.o文件收集到变量packet里面带上一个__objs_前缀。

将一些.o文件收集到变量__objs_packet中。

# add objs to packet: (#objs, packet)
define do_add_objs_to_packet
__temp_packet__ := $(call packetname,$(2))
ifeq ($$(origin $$(__temp_packet__)),undefined)
$$(__temp_packet__) :=
endif
$$(__temp_packet__) += $(1)
endef

__temp_target__存放你要生成的可执行目标,
__temp_target__将__objs_packt里的.o文件和objs里的.o文件接在一起
TARGETS加上当前目标
编译当前目标

# add packets and objs to target (target, #packes, #objs[, cc, flags])
define do_create_target
__temp_target__ = $(call totarget,$(1))
__temp_objs__ = $$(foreach p,$(call packetname,$(2)),$$($$(p))) $(3)
TARGETS += $$(__temp_target__)
ifneq ($(4),)
$$(__temp_target__): $$(__temp_objs__) | $$$$(dir $$$$@)$(V)$(4) $(5) $$^ -o $$@
else
$$(__temp_target__): $$(__temp_objs__) | $$$$(dir $$$$@)
endif
endef

之个finish是帮助生成文件夹的


# finish all
define do_finish_all
ALLDEPS = $$(ALLOBJS:.o=.d)
$$(sort $$(dir $$(ALLOBJS)) $(BINDIR)$(SLASH) $(OBJDIR)$(SLASH)):@$(MKDIR) $$@
endef

总结:
do_add_files_to_packet:调用了cc_template,需要一个obj目录并生成.o和.d文件
do_add_objs_to_packet:在__objs_(2)变量里加上2)变量里加上2)变量里加上(1)变量里的.o文件
do_create_target:产生相应的target,形如bin/boot,将packes是一堆变量,每个变量里面的.o文件取出,并加上objs,得到一大堆.o文件,利用.o生成当前目标,并将目标存于TARGETS

相关内容

热门资讯

在哈利波特与混血王子中,为什么... 在哈利波特与混血王子中,为什么罗恩在吃饭时自己头上会下雪才不是,才不是因为巴不得分手高兴所以挥舞魔杖...
八月第二周(8.6~8.12日... 八月第二周(8.6~8.12日)会得到月老牵线,桃花运降临的星座究竟是谁?八月第二周桃花运很好的星座...
足球1x2是什么意思出款多快? 足球1x2是什么意思出款多快?功能介绍: 游戏趣味变声,在游戏语音时,对您输入的声音进行处理,进行...
虚度半生事无为,轮回一世多悲忧... 虚度半生事无为,轮回一世多悲忧,不怨世人笑我痴,只恨自苦三钱命,啥意思虚度半生事无为,轮回一世多悲忧...
写人作文的方法和技巧 写人作文的方法和技巧写人作文的方法和技巧如下:1、肖像描写(外貌描写)通过对容貌、神情、姿态、服饰、...
保安人员培训记录有什么内容? 保安人员培训记录有什么内容?您好,玖玖泰丰验厂网可免费为您提供验厂咨询,十年验厂老品牌,百分百通过验...
有什么好看级数多的动漫 有什么好看级数多的动漫驱魔少年106家庭教师203挺好妖精的尾巴。灼眼的夏娜三季共75集 旋风管家(...
男人如果能够给你什么样的感受就... 男人如果能够给你什么样的感受就说明他是真心爱你的?一个男人如果能够给你非常幸福,而且非常快乐的感受,...
这个动漫人物是谁了。叫什么? 这个动漫人物是谁了。叫什么?舒克和贝塔里的贝塔贝塔~~~~~舒克和贝塔里的贝塔最早的动画,舒克与贝塔...
他还能回到我身边吗?好痛…… 他还能回到我身边吗?好痛……男人的心一旦不在你身上了,那么你哭是错,闹是错,连呼吸活着都是一种错,这...
pda、草木良品、抚柔的薰衣草... pda、草木良品、抚柔的薰衣草纯露哪种比较好前两个找不到。。。最后个品质不确定,但看了各种介绍写上保...
佳人伊憔悴~来个接下一句的 佳人伊憔悴~来个接下一句的雄霸其兴隆。
我的模拟人生:漂流物语安装完以... 我的模拟人生:漂流物语安装完以后运行的时候说找不到与DirectX9.0c兼容的图形适配器怎么办啊~...
求一首非常另类的中文歌曲,在K... 求一首非常另类的中文歌曲,在KTV一唱就能带动全场气氛的,最好是搞笑的!来来~ 小猪我向阁下推荐几首...
家风是什么班会 家风是什么班会传统习俗 家规 家训 礼仪 等等 具有很强的约束力
家乡的变化手抄报。 家乡的变化手抄报。 资料:在一个美丽的星期六,我会到我非常想念的老家。我的老家是一个,春天阳光明...
好看穿越电视剧 好看穿越电视剧除了神话 寻秦记 穿越时空的爱恋 最好是现穿古你可以期待一下有部新剧《宫...
求网游小说推荐。谢谢! 求网游小说推荐。谢谢!失落叶――――《 网游之纵横天下》 游戏生涯 作者将诸多元素完美的融合到一部大...
百变机兽之洛洛历险记 百变机兽之洛洛历险记洛洛的死敌,也就是猛兽族的机战王,他(她)叫什么?最早出现在第几集?晶晶,40集...
“势不可挡”是什么意思? “势不可挡”是什么意思?一个人是谁吗……不够的问题……不可抵挡的意思势不可挡的意思是来势迅猛,不可抵...