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

使用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

相关内容

热门资讯

国庆黄金周景区情况:大同古城半... 文| 芙昕 编辑 | 芙昕 国庆长假,很多人都计划着出门走走,可一到了那些热门景点,看到的往往不是山...
来大东北一共分两步:先“冷藏”... 还在被“东北=冰窖”的刻板印象吓退? 南方的“小土豆”们 别急着裹紧小棉袄 这个冬天 让“气候缓冲带...
第三届“长城之约”活动在河北涞... 11月15日,第三届"长城之约"全球推广活动暨世界文化遗产对话15日在河北省保定市涞源县启幕。 本次...
巴厘岛:时光在此停驻 (自由行... 曾几何时,世人只知巴厘岛而不知印尼。巴厘岛的美太过耀眼,以至于人们常常忘记——它只是印尼万千岛屿中最...