include/config.h、 include/autoconf.mk、include/autoconf.mk.dep、u-boot.cfg
- 1. 前言
- 2. 概述
- 3 陳述句 $ (Q) $(MAKE) -f $(srctree)/scripts/Makefile.autoconf
- 3.1 依賴include/autoconf.mk
- 3.1.1 include/config.h的規則
- 3.1.1.1 FORCE
- 3.1.1.2 create_symlink
- 3.1.1.3 scripts/Makefile.autoconf
- 3.1.1.4 規則 $(call filechk,config_h)
- 3.1.2 u-boot.cfg的規則 $(call cmd,u_boot_cfg)
- 3.1.3 include/autoconf.mk的規則 $(call cmd,autoconf)
- 3.2 include/autoconf.mk.dep
- 3.3 spl/u-boot.cfg
- 3.4 spl/include/autoconf.mk
- 4. 總結(包含上一篇文章)
- 5. 參考
1. 前言
UBOOT版本:uboot2018.03,開發板myimx8mmek240,
2. 概述
本節主要接上一節決議 :include/config.h、 include/autoconf.mk、include/autoconf.mk.dep、spl/include/autoconf.mk、u-boot.cfg、spl/u-boot.cfg,
3 陳述句 $ (Q) $(MAKE) -f $(srctree)/scripts/Makefile.autoconf
由于未指定目標,采用默認目標__all
#note:scripts/Makefile.autoconf __all: include/autoconf.mk include/autoconf.mk.depifeq ($(shell grep -q '^CONFIG_SPL=y' include/config/auto.conf 2>/dev/null && echo y),y) //本人單板該條件成立
__all: spl/include/autoconf.mkendif
include/autoconf.mk.dep: include/config.h FORCE
$(call cmd,autoconf_dep)spl/include/autoconf.mk: spl/u-boot.cfg
$(Q)mkdir -p $(dir $@)
$(call cmd,autoconf)u-boot.cfg: include/config.h FORCE
$(call cmd,u_boot_cfg)spl/u-boot.cfg: include/config.h FORCE
$(Q)mkdir -p $(dir $@)
$(call cmd,u_boot_cfg,-DCONFIG_SPL_BUILD)
include/config.h: scripts/Makefile.autoconf create_symlink FORCE
$(call filechk,config_h)
3.1 依賴include/autoconf.mk
include/autoconf.mk: u-boot.cfg
$(call cmd,autoconf)
u-boot.cfg: include/config.h FORCE
$(call cmd,u_boot_cfg)
3.1.1 include/config.h的規則
include/config.h: scripts/Makefile.autoconf create_symlink FORCE
$(call filechk,config_h)
3.1.1.1 FORCE
參見UBOOT編譯— make xxx_deconfig程序詳解(一)4.3小節,
3.1.1.2 create_symlink
為mach相關的頭檔案在arch/arm/include/asm/arch創建軟連接,
#note:scripts/Makefile.autoconf
# symbolic links
# If arch/$(ARCH)/mach-$(SOC)/include/mach exists,
# make a symbolic link to that directory.
# Otherwise, create a symbolic link to arch/$(ARCH)/include/asm/arch-$(SOC).
PHONY += create_symlink
create_symlink:
ifdef CONFIG_CREATE_ARCH_SYMLINK
ifneq ($(KBUILD_SRC),)
$(Q)mkdir -p include/asm
$(Q)if [ -d $(KBUILD_SRC)/arch/$(ARCH)/mach-$(SOC)/include/mach ]; then \
dest=arch/$(ARCH)/mach-$(SOC)/include/mach; \
else \
dest=arch/$(ARCH)/include/asm/arch-$(if $(SOC),$(SOC),$(CPU)); \
fi; \
ln -fsn $(KBUILD_SRC)/$$dest include/asm/arch
else
$(Q)if [ -d arch/$(ARCH)/mach-$(SOC)/include/mach ]; then \
dest=../../mach-$(SOC)/include/mach; \
else \
dest=arch-$(if $(SOC),$(SOC),$(CPU)); \
fi; \
ln -fsn $$dest arch/$(ARCH)/include/asm/arch
endif
endif
如果采用直接在源目錄編譯的方式時KBUILD_SRC為空,走else分支,對于我除錯的單板ARCH=arm,SOC=imx8m,因此執行else陳述句展開為:
if [ -d arch/arm/mach-imx8m/include/mach ]; then \
dest=../../mach-imx8m/include/mach; \
else \
dest=arch-imx8m; \
fi; \
ln -fsn $dest arch/arm/include/asm/arch
由于我使用的單板設備商提供的原始碼中沒有arch/arm/mach-imx8m/include/mach 和arch-imx8m目錄(而是直接在arch/arm/include/asm/arch目錄下提供必要的頭檔案,當然一般不建議這么做),執行該句相當于未執行,
3.1.1.3 scripts/Makefile.autoconf
指定的依賴檔案,
3.1.1.4 規則 $(call filechk,config_h)
#note:scripts/Kbuild.include
###
# filechk is used to check if the content of a generated file is updated.
# Sample usage:
# define filechk_sample
# echo $KERNELRELEASE
# endef
# version.h : Makefile
# $(call filechk,sample)
# The rule defined shall write to stdout the content of the new file.
# The existing file will be compared with the new one.
# - If no file exist it is created
# - If the content differ the new file is used
# - If they are equal no change, and no timestamp update
# - stdin is piped in from the first prerequisite ($<) so one has
# to specify a valid file as first prerequisite (often the kbuild file)
define filechk
$(Q)set -e; \
$(kecho) ' CHK $@'; \
mkdir -p $(dir $@); \
$(filechk_$(1)) < $< > $@.tmp; \
if [ -r $@ ] && cmp -s $@ $@.tmp; then \
rm -f $@.tmp; \
else \
$(kecho) ' UPD $@'; \
mv -f $@.tmp $@; \
fi
endef
上述代碼中$@為3.2.1小節的目標:‘include/config.h’,‘ $ (1)’為第一個引數config_h,‘$<’ 為第一個依賴scripts/Makefile.autoconf展開為:
$(Q)set -e; \
$(kecho) ' CHK include/config.h'; \
mkdir -p $(dir $@); \
$(filechk_config_h) < scripts/Makefile.autoconf > include/config.h.tmp; \
if [ -r include/config.h ] && cmp -s include/config.h include/config.h.tmp; then \
rm -f include/config.h.tmp; \
else \
$(kecho) ' UPD include/config.h'; \
mv -f include/config.h.tmp include/config.h; \
fi
filechk_config_h定義在scripts/Makefile.autoconf中
#note:scripts/Makefile.autoconf
# Prior to Kconfig, it was generated by mkconfig. Now it is created here.
define filechk_config_h
(echo "/* Automatically generated - do not edit */"; \
for i in $$(echo $(CONFIG_SYS_EXTRA_OPTIONS) | sed 's/,/ /g'); do \
echo \#define CONFIG_$$i \
| sed '/=/ {s/=/ /;q; } ; { s/$$/ 1/; }'; \
done; \
echo \#define CONFIG_BOARDDIR board/$(if $(VENDOR),$(VENDOR)/)$(BOARD);\
echo \#include \<config_defaults.h\>; \
echo \#include \<config_uncmd_spl.h\>; \
echo \#include \<configs/$(CONFIG_SYS_CONFIG_NAME).h\>; \
echo \#include \<asm/config.h\>; \
echo \#include \<linux/kconfig.h\>; \
echo \#include \<config_fallbacks.h\>;)
endef
其中CONFIG_SYS_EXTRA_OPTIONS為xxx_deconfig中定義:CONFIG_SYS_EXTRA_OPTIONS=“IMX_CONFIG=arch/arm/mach-imx/spl_sd.cfg,SPL_TEXT_BASE=0x7E1000”,具體編譯命令如下:
set -e; : ' CHK include/config.h'; mkdir -p include/; (echo "/* Automatically generated - do not edit */"; for i in $(echo "IMX_CONFIG=arch/arm/mach-imx/spl_sd.cfg,SPL_TEXT_BASE=0x7E1000" | sed 's/,/ /g'); do echo \#define CONFIG_$i | sed '/=/ {s/=/ /;q; } ; { s/$/ 1/; }'; done; echo \#define CONFIG_BOARDDIR board/myzr/myimx8mm; echo \#include \<config_defaults.h\>; echo \#include \<config_uncmd_spl.h\>; echo \#include \<configs/"myimx8mmek240".h\>; echo \#include \<asm/config.h\>; echo \#include \<linux/kconfig.h\>; echo \#include \<config_fallbacks.h\>;) < scripts/Makefile.autoconf > include/config.h.tmp; if [ -r include/config.h ] && cmp -s include/config.h include/config.h.tmp; then rm -f include/config.h.tmp; else : ' UPD include/config.h'; mv -f include/config.h.tmp include/config.h; fi
include/config.h內容如下:

3.1.2 u-boot.cfg的規則 $(call cmd,u_boot_cfg)
#note:scripts/Makefile.autoconf # echo command. # Short version is used, if $(quiet) equals `quiet_', otherwise full one. echo-cmd = $(if $($(quiet)cmd_$(1)),\ echo ' $(call escsq,$($(quiet)cmd_$(1)))$(echo-why)';)
# printing commands
cmd = @$(echo-cmd) $(cmd_$(1))
quiet定義在頂層Makefile,默認值(空),escsq的作用是轉義在回顯陳述句中使用的單引號,為了方便理解,這里把靜默編譯功能關掉,即quiet=quiet_,
quiet_cmd_u_boot_cfg = CFG $@ //編譯時經常看的就是這句列印
cmd_u_boot_cfg = \
$(CPP) $(c_flags) $2 -DDO_DEPS_ONLY -dM $(srctree)/include/common.h > $@.tmp && { \
grep 'define CONFIG_' $@.tmp > $@; \
rm $@.tmp; \
} || { \
rm $@.tmp; false; \
}
上訴命展開如下:
/home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc -E -Wall -Wstrict-prototypes -Wno-format-security -fno-builtin -ffreestanding -fshort-wchar -O2 -fno-stack-protector -fno-delete-null-pointer-checks -g -fstack-usage -Wno-format-nonliteral -Werror=date-time -D__KERNEL__ -D__UBOOT__ -D__ARM__ -fno-pic -mstrict-align -ffunction-sections -fdata-sections -fno-common -ffixed-r9 -fno-common -ffixed-x18 -pipe -Iinclude -I./arch/arm/include -include ./include/linux/kconfig.h -nostdinc -isystem /home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/../lib/gcc/aarch64-linux-gnu/7.3.1/include -DDO_DEPS_ONLY -dM ./include/common.h > u-boot.cfg.tmp && { grep 'define CONFIG_' u-boot.cfg.tmp > u-boot.cfg; rm u-boot.cfg.tmp; } || { rm u-boot.cfg.tmp; false; }
$2為空,編譯選項“-dM”的作用是輸出include/common.h中定義的所有宏,根據上面的規則,編譯器提取include/common.h中(include/common.h檔案包含了include/config.h檔案,而include/config.h檔案又包含了其它頭檔案,這里面的內容都會得到決議, )定義的宏,然后輸出給u-boot.cfg.tmp,然后查找和處理以“CONFIG_”開頭的宏定義的功能并輸出給u-boot.cfg,
3.1.3 include/autoconf.mk的規則 $(call cmd,autoconf)
# We are migrating from board headers to Kconfig little by little.
# In the interim, we use both of
# - include/config/auto.conf (generated by Kconfig)
# - include/autoconf.mk (used in the U-Boot conventional configuration)
# The following rule creates autoconf.mk
# include/config/auto.conf is grepped in order to avoid duplication of the
# same CONFIG macros
quiet_cmd_autoconf = GEN $@ //編譯時經常看的就是這句列印
cmd_autoconf = \
sed -n -f $(srctree)/tools/scripts/define2mk.sed $< | \
while read line; do \
if [ -n "${KCONFIG_IGNORE_DUPLICATES}" ] || \
! grep -q "$${line%=*}=" include/config/auto.conf; then \
echo "$$line"; \
fi \
done > $@
上訴命展開如下:
sed -n -f ./tools/scripts/define2mk.sed u-boot.cfg | while read line; do if [ -n "" ] || ! grep -q "${line%=*}=" include/config/auto.conf; then echo "$line"; fi done > include/autoconf.mk
上面陳述句就是尋找u-boot.cfg 中有但是include/config/auto.conf沒有的行,并把摘到的內容輸出到include/autoconf.mk中 ,
3.2 include/autoconf.mk.dep
include/autoconf.mk.dep: include/config.h FORCE
$(call cmd,autoconf_dep)
#note:scripts/Makefile.autoconf # echo command. # Short version is used, if $(quiet) equals `quiet_', otherwise full one. echo-cmd = $(if $($(quiet)cmd_$(1)),\ echo ' $(call escsq,$($(quiet)cmd_$(1)))$(echo-why)';)
# printing commands
cmd = @$(echo-cmd) $(cmd_$(1))
quiet定義在頂層Makefile,默認值(空),escsq的作用是轉義在回顯陳述句中使用的單引號,為了方便理解,這里把靜默編譯功能關掉,即quiet=quiet_,
quiet_cmd_autoconf_dep = GEN $@
cmd_autoconf_dep = $(CC) -x c -DDO_DEPS_ONLY -M -MP $(c_flags) \
-MQ include/config/auto.conf $(srctree)/include/common.h > $@ || { \
rm $@; false; \
}
上訴命展開如下:
/home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc -x c -DDO_DEPS_ONLY -M -MP -Wall -Wstrict-prototypes -Wno-format-security -fno-builtin -ffreestanding -fshort-wchar -O2 -fno-stack-protector -fno-delete-null-pointer-checks -g -fstack-usage -Wno-format-nonliteral -Werror=date-time -D__KERNEL__ -D__UBOOT__ -D__ARM__ -fno-pic -mstrict-align -ffunction-sections -fdata-sections -fno-common -ffixed-r9 -fno-common -ffixed-x18 -pipe -Iinclude -I./arch/arm/include -include ./include/linux/kconfig.h -nostdinc -isystem /home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/../lib/gcc/aarch64-linux-gnu/7.3.1/include -MQ include/config/auto.conf ./include/common.h > include/autoconf.mk.dep || { rm include/autoconf.mk.dep; false; }
分析:include/autoconf.mk.dep依賴 include/config.h,其中include/config.h為動態創建,
(1)-M 生成目標依賴關系,其中目標的格式為源檔案去路徑檔案名+.o后綴,生成檔案的依賴關系,同時也把一些標準庫的頭檔案包含了進來,本質是告訴前處理器輸出一個適合 make 的規則,用于描述各目標檔案的依賴關系,對于每個源檔案,前處理器輸出 一個 make 規則,該規則的目標項 (target) 是源檔案對應的目標檔案名,依賴項 (dependency) 是源檔案中 “#include” 參考的所有檔案,生成的規則可以是單行,但如果太長,就用’'換行符續成多行,規則顯示在標準輸出,不產生預處理過的 C 程式,
-M 處理后的格式如下:

(2)-MP生成的依賴檔案里面,依賴規則中的所有 .h 依賴項都會在該檔案中生成一個偽目標,其不依賴任何其他依賴項,該偽規則將避免洗掉了對應的頭檔案而沒有更新 “Makefile” 去匹配新的依賴關系而導致 make 出錯的情況出現,
-MP 處理后的格式如下:

(3)-MQ相當于-MT,覆寫默認的源檔案去路徑檔案名+.o后綴的目標生成格式,采用指定的字串,這里對應include/config/auto.conf;
-MQ 處理后的格式如下:

(4)$@為自動變數,代表依賴關系中的目標,這里對應include/autoconf.mk.dep;
(5)-x c,指定源檔案使用C語言語法;
總體來說:該依賴關系用來生成include/autoconf.mk.dep,生成的方法是生成 include/common.h的依賴關系,
3.3 spl/u-boot.cfg
spl/u-boot.cfg: include/config.h FORCE
$(Q)mkdir -p $(dir $@)
$(call cmd,u_boot_cfg,-DCONFIG_SPL_BUILD)
cmd的定義在本篇前面已經講過,這里略過,直接展開$(call cmd,u_boot_cfg,-DCONFIG_SPL_BUILD):
```c
quiet_cmd_u_boot_cfg = CFG $@ //編譯時經常看的就是這句列印
cmd_u_boot_cfg = \
$(CPP) $(c_flags) $2 -DDO_DEPS_ONLY -dM $(srctree)/include/common.h > $@.tmp && { \
grep 'define CONFIG_' $@.tmp > $@; \
rm $@.tmp; \
} || { \
rm $@.tmp; false; \
}
上訴命展開如下:
/home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc -E -Wall -Wstrict-prototypes -Wno-format-security -fno-builtin -ffreestanding -fshort-wchar -O2 -fno-stack-protector -fno-delete-null-pointer-checks -g -fstack-usage -Wno-format-nonliteral -Werror=date-time -D__KERNEL__ -D__UBOOT__ -D__ARM__ -fno-pic -mstrict-align -ffunction-sections -fdata-sections -fno-common -ffixed-r9 -fno-common -ffixed-x18 -pipe -Iinclude -I./arch/arm/include -include ./include/linux/kconfig.h -nostdinc -isystem /home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/../lib/gcc/aarch64-linux-gnu/7.3.1/include -DCONFIG_SPL_BUILD -DDO_DEPS_ONLY -dM ./include/common.h > spl/u-boot.cfg.tmp && { grep 'define CONFIG_' spl/u-boot.cfg.tmp > spl/u-boot.cfg; rm spl/u-boot.cfg.tmp; } || { rm spl/u-boot.cfg.tmp; false; }
$2為-DCONFIG_SPL_BUILD(新增宏定義CONFIG_SPL_BUILD ),編譯選項“-dM”的作用是輸出include/common.h中定義的所有宏,根據上面的規則,編譯器提取include/common.h中(include/common.h檔案包含了include/config.h檔案,而include/config.h檔案又包含了其它頭檔案,這里面的內容都會得到決議, )定義的宏,然后輸出給spl/u-boot.cfg.tmp,然后查找和處理以“CONFIG_”開頭的宏定義的功能并輸出給spl/u-boot.cfg,
spl/u-boot.cfg和u-boot.cfg的區別主要是根據是否定義CONFIG_SPL_BUILD宏,代碼會有不同的分支,
3.4 spl/include/autoconf.mk
spl/include/autoconf.mk: spl/u-boot.cfg
$(Q)mkdir -p $(dir $@)
$(call cmd,autoconf)
# We are migrating from board headers to Kconfig little by little.
# In the interim, we use both of
# - include/config/auto.conf (generated by Kconfig)
# - include/autoconf.mk (used in the U-Boot conventional configuration)
# The following rule creates autoconf.mk
# include/config/auto.conf is grepped in order to avoid duplication of the
# same CONFIG macros
quiet_cmd_autoconf = GEN $@ //編譯時經常看的就是這句列印
cmd_autoconf = \
sed -n -f $(srctree)/tools/scripts/define2mk.sed $< | \
while read line; do \
if [ -n "${KCONFIG_IGNORE_DUPLICATES}" ] || \
! grep -q "$${line%=*}=" include/config/auto.conf; then \
echo "$$line"; \
fi \
done > $@
上訴命展開如下:
sed -n -f ./tools/scripts/define2mk.sed spl/u-boot.cfg | while read line; do if [ -n "" ] || ! grep -q "${line%=*}=" include/config/auto.conf; then echo "$line"; fi done > spl/include/autoconf.mk
上面陳述句就是尋找spl/u-boot.cfg中有但是include/config/auto.conf沒有的行,并把摘到的內容輸出到spl/include/autoconf.mk中 ,
4. 總結(包含上一篇文章)
#頂層Makefile |--- include/config/%.conf: $(KCONFIG_CONFIG) include/config/auto.conf.cmd //KCONFIG_CONFIG = .config | |--- $(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig | |--- #頂層Makefile | |--- %config: scripts_basic outputmakefile FORCE | |--- $(Q)$(MAKE) $(build)=scripts/kconfig $@ | | |--- #scripts/kconfig/Makefile | | |--- silentoldconfig: $(obj)/conf | |--- $(Q)mkdir -p include/config include/generated | |--- $(Q)test -e include/generated/autoksyms.h || touch include/generated/autoksyms.h | |--- $< $(silent) --$@ $(Kconfig) //等價于 scripts/kconfig/conf -s --myimx8mmek240-8mm-2g_defconfig .config | |--- $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.autoconf //未指定目標,采用默認目標__all | |--- #scripts/Makefile.autoconf | |--- __all: include/autoconf.mk include/autoconf.mk.dep | | |--- include/autoconf.mk: u-boot.cfg | | | |--- $(call cmd,autoconf_dep)//通過編譯選項"-M"、"-MP"、"-MQ"生成 include/common.h的依賴關系 | | | |---__all: spl/include/autoconf.mk | |--- spl/include/autoconf.mk: spl/u-boot.cfg | | | |--- $(Q)mkdir -p $(dir $@) | | | |--- $(call cmd,autoconf)//尋找spl/u-boot.cfg中有但是include/config/auto.conf沒有的行,并把摘到的內容輸出到spl/include/autoconf.mk中include/config.h: scripts/Makefile.autoconf create_symlink FORCE
$(call filechk,config_h) //生成include/config.h檔案u-boot.cfg: include/config.h FORCE
$(call cmd,u_boot_cfg) //通過編譯選項"-dM"輸出include/common.h中定義的所有宏
spl/u-boot.cfg: include/config.h FORCE
$(Q)mkdir -p $(dir $@)
$(call cmd,u_boot_cfg,-DCONFIG_SPL_BUILD)//通過宏 CONFIG_SPL_BUILD 和編譯選項"-dM"輸出include/common.h中定義的所有宏_SPL_BUILD)//通過宏 CONFIG_SPL_BUILD 和編譯選項"-dM"輸出include/common.h中定義的所有宏
5. 參考
(1)Linux Makefile 生成 *.d 依賴檔案以及 gcc -M -MF -MP 等相關選項說明
(2)gcc -M -MM -MQ -MF -MT -MD(示例代碼)
(3)gcc 選項 -M -MQ
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/531779.html
標籤:嵌入式
