练习1:理解通过make生成执行文件的过程
操作系统镜像文件ucore.img是如何一步一步生成的,ucore 中MakeFile 解析
内核代码编译过程分析:
1.内核代码的编译过程
- 工具函数的详细解释 tools/function.mk
BJPREFIX := __objs_
.SECONDEXPANSION:
# -------------------- function begin --------------------
# list all files in some directories: (#directories, #types)
#返回相应directories目录下所有 类型为(types)的文件
#example 输入为listf(libs, c s),输出为libs/a.c libs/a.s
listf = $(filter $(if $(2),$(addprefix %.,$(2)),%),\
$(wildcard $(addsuffix $(SLASH)*,$(1))))
# get .o obj files: (#files[, packet])
# 给出文件名列表files,和软件包名称packet,返回相应文件的目标文件名称
#example $(call toobj,libs/a.c libs/b.c,__obj_),生成相应的输出makefile代码为 obj/__obj_/libs/a.o obj/__obj_/libs/b.o
toobj = $(addprefix $(OBJDIR)$(SLASH)$(if $(2),$(2)$(SLASH)),$(addsuffix .o,$(basename $(1))))
# get .d dependency files: (#files[, packet])
#输入为文件名列表,输出为相应代码文件的依赖文件名列表
#example $(call todep,libs/a.c libs/b.c,__obj__),对应相应的makefile代码为 __obj_/libs/a.d __obj_/libs/b.d
todep = $(patsubst %.o,%.d,$(call toobj,$(1),$(2)))
#输出最总的目标文件完整路径名,
#example $(call totarget,kernel),则对应于makefile代码为输出的最总内核目标文件为bin/kernel
totarget = $(addprefix $(BINDIR)$(SLASH),$(1))
# change $(name) to $(OBJPREFIX)$(name): (#names)
#给定名字加上前缀$(OBJPREFIX)
packetname = $(if $(1),$(addprefix $(OBJPREFIX),$(1)),$(OBJPREFIX))
# cc compile template, generate rule for dep, obj: (file, cc[, flags, dir])
#内核各个模块编译的C代码模板,迎来为每一个.c活着.s文件生成编译后的目标文件
define cc_template
#生成依目标文件的依赖文件。4个$$$$符号是因为该代码要被eval两次,并且最终生成的makefile文件继续保留对规则目标文件名的引用
$$(call todep,$(1),$(4)): $(1) | $$$$(dir