申明
本着学习交流的原则, 将个人移植u-boot的过程做一个记录. 文章参考了csdn blog里面的很多内容, 有的已经记不得出处了, 只好把当时的摘要直接贴出来. 如果冒犯, 还请见谅. 如有侵权, 请与我邮件联系. 谢谢!
autoconf.mk
uboot的顶层Makefile中有如下的一段代码
[plain] view plain copy print ?
- #
- # Auto-generate the autoconf.mk file (which is included by all makefiles)
- #
- # This target actually generates 2 files; autoconf.mk and autoconf.mk.dep.
- # the dep file is only include in this top level makefile to determine when
- # to regenerate the autoconf.mk file.
- $(obj)include/autoconf.mk.dep: $(obj)include/config.h include/common.h
- @$(XECHO) Generating $@ ; \
- set -e ; \
- : Generate the dependancies ; \
- $(CC) -x c -DDO_DEPS_ONLY -M $(CFLAGS) $(CPPFLAGS) \
- -MQ $(obj)include/autoconf.mk include/common.h > $@
-
- $(obj)include/autoconf.mk: $(obj)include/config.h
- @$(XECHO) Generating $@ ; \
- set -e ; \
- : Extract the config macros ; \
- $(CPP) $(CFLAGS) -DDO_DEPS_ONLY -dM include/common.h | \
- sed -n -f tools/scripts/define2mk.sed > [email protected] && \
- mv [email protected] $@
#
# Auto-generate the autoconf.mk file (which is included by all makefiles)
#
# This target actually generates 2 files; autoconf.mk and autoconf.mk.dep.
# the dep file is only include in this top level makefile to determine when
# to regenerate the autoconf.mk file.
$(obj)include/autoconf.mk.dep: $(obj)include/config.h include/common.h
@$(XECHO) Generating $@ ; \
set -e ; \
: Generate the dependancies ; \
$(CC) -x c -DDO_DEPS_ONLY -M $(CFLAGS) $(CPPFLAGS) \
-MQ $(obj)include/autoconf.mk include/common.h > $@
$(obj)include/autoconf.mk: $(obj)include/config.h
@$(XECHO) Generating $@ ; \
set -e ; \
: Extract the config macros ; \
$(CPP) $(CFLAGS) -DDO_DEPS_ONLY -dM include/common.h | \
sed -n -f tools/scripts/define2mk.sed > [email protected] && \
mv [email protected] $@
先看第一个:
$(obj)include/autoconf.mk.dep: $(obj)include/config.h include/common.h
, 它表示autoconf.mk.dep依赖于config.h和common.h这两个文件.
- @$(XECHO) Generating $@ ; \ 这句话会在编译阶段输出编译信息 Generating include/autoconf.mk.dep
- set -e ; \ 这句话表示, 当下面命令返回值不会0时, 整个脚本立即停止退出
- : Generate the dependancies ; \ 没有明白是啥意思~~
- $(CC) -x c -DDO_DEPS_ONLY -M $(CFLAGS) $(CPPFLAGS) -MQ $(obj)include/autoconf.mk include/common.h > $@
- -DDO_DEPS_ONLY: 设置flag, 具体来说, 我们可以在common.h里面看见#ifdef DO_DEPS_ONLY这样的语句, 这个-D就表示DO_DEPS_ONLY被定义了
- -M : 表示生成依赖关系. 我还专门做了个实验, 如下
- gcc -M main.c 输出结果为 main.o: main.c
- -MQ: 表示指定依赖关系中target的名称, 看下面的实验
- gcc -M -MQ newname.mk main.c 输出结果为 newname.mk: main.c
- 这句话表示: 生成依赖关系 include/autoconf.mk: include/common.h, 结果最终输出到include/autoconf.mk.dep
- 打开编译后生成的include/autoconf.mk.dep, 可以查阅里面的内容. 至于为什么需要生成这个文件, 我现在还不清楚.
再看第二个:
$(obj)include/autoconf.mk: $(obj)include/config.h, 它表示autoconf.mk依赖于include/config.h这个文件
- @$(XECHO) Generating $@ ; \ 这句话会在编译阶段输出编译信息Generating include/autoconf.mk
- set -e; \ 同上
- $(CPP) $(CFLAGS) -DDO_DEPS_ONLY -dM include/common.h | sed -n -f tools/scripts/define2mk.sed > [email protected] && mv [email protected] $@
- -DDO_DEPS_ONLY: 同上
- -dM : 作用是输出include/common.h中定义的所有宏
- | : shell中的管道, 表示将前面的结果传递给后面的命令
- define2mk.sed : 查找和处理以“CONFIG_”开头的宏定义的功能, 将处理的结果输出到include/autoconf.mk.tmp
- mv [email protected] $@ : 重命名为include/autoconf.mk.
- 最终就会生成include/autoconf.mk
- include/common.h文件包含了include/config.h文件,而include/config.h文件又包含了config_defaults.h等uboot下的通用头文件, 还会包含<configs/${CONFIG_NAME}.h>, 这个.h是我们自己创建的, 可以在里面添加自己的"CONFIG_"宏定义. 已决定开启哪些功能.
至此, 我们知道, 系统中所有的"CONFIG_"开头的宏开关, 都被放到了include/autoconf.mk中.
depend
在uboot的顶层Makefile中, 我们经常会看到类似的代码片段
[plain] view plain copy print ?
- $(obj)spl/u-boot-spl.bin: $(SUBDIR_TOOLS) <span style="color: rgb(255, 0, 0);">depend</span>
- $(MAKE) -C spl all
$(obj)spl/u-boot-spl.bin: $(SUBDIR_TOOLS) <span style="color:#ff00;">depend</span>
$(MAKE) -C spl all
这个depend是什么意思呢, Makefile中有如下一段代码
[plain] view plain copy print ?
- # Explicitly make _depend in subdirs containing multiple targets to prevent
- # parallel sub-makes creating .depend files simultaneously.
- depend dep: $(TIMESTAMP_FILE) $(VERSION_FILE) \
- $(obj)include/spl-autoconf.mk \
- $(obj)include/tpl-autoconf.mk \
- $(obj)include/autoconf.mk \
- $(obj)include/generated/generic-asm-offsets.h \
- $(obj)include/generated/asm-offsets.h
- for dir in $(SUBDIRS) $(CPUDIR) $(LDSCRIPT_MAKEFILE_DIR) ; do \
- $(MAKE) -C $$dir _depend ; done
# Explicitly make _depend in subdirs containing multiple targets to prevent
# parallel sub-makes creating .depend files simultaneously.
depend dep: $(TIMESTAMP_FILE) $(VERSION_FILE) \
$(obj)include/spl-autoconf.mk \
$(obj)include/tpl-autoconf.mk \
$(obj)include/autoconf.mk \
$(obj)include/generated/generic-asm-offsets.h \
$(obj)include/generated/asm-offsets.h
for dir in $(SUBDIRS) $(CPUDIR) $(LDSCRIPT_MAKEFILE_DIR) ; do \
$(MAKE) -C $$dir _depend ; done
- depend dep : 它表示这个规则有两个目标. 也就是你自己的目标依赖depend或者dep都会跑到这里来继续.
- $(obj)include/spl-autoconf.mk \ : 表示depend依赖spl-autoconf.mk. 这个mk的生成规则也在Makefile中有定义. 细节方面参考上面的autoconf.mk
- $(obj)include/tpl-autoconf.mk \ : 同上
- $(obj)include/autoconf.mk \ : 同上
- $(obj)include/generated/generic-asm-offsets.h \ : 暂不分析
- $(obj)include/generated/asm-offsets.h : 暂不分析
- for dir in $(SUBDIRS) $(CPUDIR) $(LDSCRIPT_MAKEFILE_DIR) ; do $(MAKE) -C $$dir _depend ; done
- 这句话表示去上面各个目录下执行 make _depend命令.
那我们看看对应子目录下的Makefile, 例如$(CPUDIR) , 会看到如下的代码片段
[plain] view plain copy print ?
- # defines $(obj).depend target
- include $(SRCTREE)/rules.mk
-
- sinclude $(obj).depend
# defines $(obj).depend target
include $(SRCTREE)/rules.mk
sinclude $(obj).depend
并没有看到_depend这个目标, 那make _depend在这个目录下如何执行呢? 来看看它include的rules.mk
[plain] view plain copy print ?
- _depend: $(obj).depend
-
- # Split the source files into two camps: those in the current directory, and
- # those somewhere else. For the first camp we want to support CPPFLAGS_<fname>
- # and for the second we don't / can't.
- PWD_SRCS := $(filter $(notdir $(SRCS)),$(SRCS))
- OTHER_SRCS := $(filter-out $(notdir $(SRCS)),$(SRCS))
-
- # This is a list of dependency files to generate
- DEPS := $(basename $(patsubst %,$(obj).depend.%,$(PWD_SRCS)))
-
- # Join all the dependencies into a single file, in three parts
- # 1 .Concatenate all the generated depend files together
- # 2. Add in the deps from OTHER_SRCS which we couldn't process
- # 3. Add in the HOSTSRCS
- $(obj).depend: $(src)Makefile $(TOPDIR)/config.mk $(DEPS) $(OTHER_SRCS) \
- $(HOSTSRCS)
- cat /dev/null $(DEPS) >$@
- @for f in $(OTHER_SRCS); do \
- g=`basename $$f | sed -e 's/\(.*\)\.[[:alnum:]_]/\1.o/'`; \
- $(CC) -M $(CPPFLAGS) -MQ $(obj)
g
f >> $@ ; \
- done
- @for f in $(HOSTSRCS); do \
- g=`basename $$f | sed -e 's/\(.*\)\.[[:alnum:]_]/\1.o/'`; \
- $(HOSTCC) -M $(HOSTCPPFLAGS) -MQ $(obj)
g
f >> $@ ; \
- done
-
- MAKE_DEPEND = $(CC) -M $(CPPFLAGS) $(EXTRA_CPPFLAGS_DEP) \
- -MQ $(addsuffix .o,$(obj)$(basename $<)) $< >$@
-
-
- $(obj).depend.%: %.c
- $(MAKE_DEPEND)
-
- $(obj).depend.%: %.S
- $(MAKE_DEPEND)
-
- $(HOSTOBJS): $(obj)%.o: %.c
- $(HOSTCC) $(HOSTCFLAGS) $(HOSTCFLAGS_$(@F)) $(HOSTCFLAGS_$(BCURDIR)) -o $@ $< -c
- $(NOPEDOBJS): $(obj)%.o: %.c
- $(HOSTCC) $(HOSTCFLAGS_NOPED) $(HOSTCFLAGS_$(@F)) $(HOSTCFLAGS_$(BCURDIR)) -o $@ $< -c
-
- #########################################################################
_depend: $(obj).depend
# Split the source files into two camps: those in the current directory, and
# those somewhere else. For the first camp we want to support CPPFLAGS_<fname>
# and for the second we don't / can't.
PWD_SRCS := $(filter $(notdir $(SRCS)),$(SRCS))
OTHER_SRCS := $(filter-out $(notdir $(SRCS)),$(SRCS))
# This is a list of dependency files to generate
DEPS := $(basename $(patsubst %,$(obj).depend.%,$(PWD_SRCS)))
# Join all the dependencies into a single file, in three parts
# 1 .Concatenate all the generated depend files together
# 2. Add in the deps from OTHER_SRCS which we couldn't process
# 3. Add in the HOSTSRCS
$(obj).depend: $(src)Makefile $(TOPDIR)/config.mk $(DEPS) $(OTHER_SRCS) \
$(HOSTSRCS)
cat /dev/null $(DEPS) >$@
@for f in $(OTHER_SRCS); do \
g=`basename $$f | sed -e 's/\(.*\)\.[[:alnum:]_]/\1.o/'`; \
$(CC) -M $(CPPFLAGS) -MQ $(obj)$$g $$f >> $@ ; \
done
@for f in $(HOSTSRCS); do \
g=`basename $$f | sed -e 's/\(.*\)\.[[:alnum:]_]/\1.o/'`; \
$(HOSTCC) -M $(HOSTCPPFLAGS) -MQ $(obj)$$g $$f >> $@ ; \
done
MAKE_DEPEND = $(CC) -M $(CPPFLAGS) $(EXTRA_CPPFLAGS_DEP) \
-MQ $(addsuffix .o,$(obj)$(basename $<)) $< >$@
$(obj).depend.%: %.c
$(MAKE_DEPEND)
$(obj).depend.%: %.S
$(MAKE_DEPEND)
$(HOSTOBJS): $(obj)%.o: %.c
$(HOSTCC) $(HOSTCFLAGS) $(HOSTCFLAGS_$(@F)) $(HOSTCFLAGS_$(BCURDIR)) -o $@ $< -c
$(NOPEDOBJS): $(obj)%.o: %.c
$(HOSTCC) $(HOSTCFLAGS_NOPED) $(HOSTCFLAGS_$(@F)) $(HOSTCFLAGS_$(BCURDIR)) -o $@ $< -c
#########################################################################
这里有_depend目标, make _depend的时候, 执行的其实就是这里的_depend. 这个里面的细节不分析了, 大体来说有几点
- $(obj).depend: obj一般为空, 所以这里会在当前目录下生成一个.depend文件
- .depend里面的内容就是类似于 : main.o : main.c main.h .
- 想深究的话可以参考这里 : http://blog.csdn.net/panfengsoftware/article/details/7877864
最后在Makefile里面引用了当前目录下的这个.depend