imx6ull:uboot顶层Makefile分析
生活随笔
收集整理的這篇文章主要介紹了
imx6ull:uboot顶层Makefile分析
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
版本號
MAKEFLAGES變量
20 MAKEFLAGS += -rR --include-dir=$(CURDIR)- Makefile有兩個特殊的變量:“SHELL”和“MAKEFLAGS”,這兩個變量除非使用“unexport”聲明,否則的話在整個make的執行過程中,它們的值始終自動的傳遞給子make。
- 在 Makefile 中使用“make”命令來執行其他的 Makefile文件
- 上述代碼使用“+=”來給變量 MAKEFLAGS 追加了一些值,“-rR”表示禁止使用內置的隱含規則和變量定義,“--include-dir”指明搜索路徑,”$(CURDIR)”表示當前目錄。
命令輸出
- uboot 默認編譯是不會在終端中顯示完整的命令,都是短命令。例如CC xxx.o和SYM u-boot.sym
- 可以通過設置變量“V=1“來實現完整的命令輸出
實現源碼?
73 ifeq ("$(origin V)", "command line") 74 KBUILD_VERBOSE = $(V) 75 endif 76 ifndef KBUILD_VERBOSE 77 KBUILD_VERBOSE = 0 78 endif 79 80 ifeq ($(KBUILD_VERBOSE),1) 81 quiet = 82 Q = 83 else 84 quiet=quiet_ 85 Q = @ 86 endif- 代碼中先使用 ifeq 來判斷"$(origin V)"和"command line"是否相等
- 函數origin 用于告訴你變量是哪來的。語法為:
$(origin <variable>)
variable 是變量名,o 函數的返回值就是變量來源,因此$(origin V)就是變量 V 的來源 - 當這兩個相等的時候變量 KBUILD_VERBOSE 就等于 V 的值,比如在命令行中輸 入 “ V=1 “ 的 話 那 么 KBUILD_VERBOSE=1 。如果沒有在命令行輸入V的話KBUILD_VERBOSE=0
- 第 80 行判斷 KBUILD_VERBOSE 是否為 1,如果 KBUILD_VERBOSE 為 1 的話變量 quiet和 Q 都為空,如果 KBUILD_VERBOSE=0 的話變量 quiet 為“quiet_“,變量 Q 為“@”
- Makefile 中會用到變量 quiet 和 Q 來控制編譯的時候是否在終端輸出完整的命令
- Q的作用。在頂層Makefile 中有很多如下所示的命令:$(Q)$(MAKE) $(build)=tools
當 V=0 的話上述命令展開就是“@ make $(build)=tools”,make 在執行的時候默認會在終端輸出命令,但是在命令前面加上“@”就不會在終端輸出命令了。
當 V=1 的時候 Q 就為空,上述命令就是“make $(build)=tools”,因此在 make 執行的過程,命令會被完整的輸出在終端上 - quiet的作用。有些命令會有兩個版本,比如:
quiet_cmd_sym ?= SYM $@
cmd_sym ?= $(OBJDUMP) -t $< > $@
sym 命令分為“quiet_cmd_sym”和“cmd_sym”兩個版本,這兩個命令的功能都是一樣的,區別在于 make 執行的時候輸出的命令不同。quiet_cmd_xxx 命令輸出信息少,也就是短命令,而 cmd_xxx 命令輸出信息多,也就是完整的命令。那么Makefile中就會使用變量quiet來指向這兩個版本中的其中一個,進而控制命令的輸出形式 - 如果變量 quiet 為空的話,整個命令都會輸出。
如果變量 quiet 為“quiet_”的話,僅輸出短版本。
如果變量 quiet 為“silent_”的話,整個命令都不會輸出
靜默輸出
- 編譯的時候使用“make -s”即可實現靜默輸出
實現源碼
88 # If the user is running make -s (silent mode), suppress echoing of 89 # commands 90 91 ifneq ($(filter 4.%,$(MAKE_VERSION)),) # make-4 92 ifneq ($(filter %s ,$(firstword x$(MAKEFLAGS))),) 93 quiet=silent_ 94 endif 95 else # make-3.8x 96 ifneq ($(filter s% -s%,$(MAKEFLAGS)),) 97 quiet=silent_ 98 endif 99 endif 100 101 export quiet Q KBUILD_VERBOSE- 第91行判斷當前正在使用的編譯器版本號是否為4.x
- ?filter 函數是個過濾函數,函數格式如下:
$(filter <pattern...>,<text>)
filter 函數表示以 pattern 模式過濾 text 字符串中的單詞,僅保留符合模式 pattern 的單詞,可以有多個模式。函數返回值就是符合 pattern 的字符串。 - $(filter 4.%,$(MAKE_VERSION))的含義就是在字符串“MAKE_VERSION”中找出符合“4.%”的字符(%為通配符),MAKE_VERSION 是編譯器的版本號,我們當前使用的交叉編譯器版本號為 4.9.4,所以肯定可以找出“4.%”。因此$(filter 4.%,$(MAKE_VERSION))不為空,條件成立
- 第 92 行判斷MAKEFLAGS的第一個單詞中是否包含s
- 函數 firstword 是獲取首單詞,函數格式如下:
$(firstword <text>)
firstword 函數用于取出 text 字符串中的第一個單詞,函數的返回值就是獲取到的單詞 - 當使用“make -s”編譯的時候,“-s”會作為 MAKEFLAGS 變量的一部分傳遞給 Makefile
- 第 101 行 ?使用 export 導出變量 quiet、Q 和 KBUILD_VERBOSE
設置編譯結果輸出目錄
- uboot 可以將編譯出來的目標文件輸出到單獨的目錄中,在 make 的時候使用“O”來指定輸出目錄,比如“make O=out”就是設置目標文件輸出到 out 目錄中
- 這么做是為了將源文件和編譯產生的文件分開,當然也可以不指定 O 參數,不指定的話源文件和編譯產生的文件都在同一個目錄內
實現源碼?
103 # kbuild supports saving output files in a separate directory. 104 # To locate output files in a separate directory two syntaxes are supported. 105 # In both cases the working directory must be the root of the kernel src. 106 # 1) O= 107 # Use "make O=dir/to/store/output/files/" 108 # 109 # 2) Set KBUILD_OUTPUT 110 # Set the environment variable KBUILD_OUTPUT to point to the directory 111 # where the output files shall be placed. 112 # export KBUILD_OUTPUT=dir/to/store/output/files/ 113 # make 114 # 115 # The O= assignment takes precedence over the KBUILD_OUTPUT environment 116 # variable. 117 118 # KBUILD_SRC is set on invocation of make in OBJ directory 119 # KBUILD_SRC is not intended to be used by the regular user (for now) 120 ifeq ($(KBUILD_SRC),) 121 122 # OK, Make called in directory where kernel src resides 123 # Do we want to locate output files in a separate directory? 124 ifeq ("$(origin O)", "command line") 125 KBUILD_OUTPUT := $(O) 126 endif 127 128 # That's our default target when none is given on the command line 129 PHONY := _all 130 _all: 131 132 # Cancel implicit rules on top Makefile 133 $(CURDIR)/Makefile Makefile: ; 134 135 ifneq ($(KBUILD_OUTPUT),) 136 # Invoke a second make in the output directory, passing relevant variables 137 # check that the output directory actually exists 138 saved-output := $(KBUILD_OUTPUT) 139 KBUILD_OUTPUT := $(shell mkdir -p $(KBUILD_OUTPUT) && cd $(KBUILD_OUTPUT) \ 140 && /bin/pwd) ...... 155 endif # ifneq ($(KBUILD_OUTPUT),) 156 endif # ifeq ($(KBUILD_SRC),)- 第 124 行判斷“O”是否來自于命令行,如果來自命令行的話條件成立,KBUILD_OUTPUT就為$(O),因此變量 KBUILD_OUTPUT 就是輸出目錄
- 第 135 行判斷 KBUILD_OUTPUT 是否為空
- 第 139 行調用 mkdir 命令,創建 KBUILD_OUTPUT 目錄,并且將創建成功以后的絕對路徑賦值給 KBUILD_OUTPUT。至此,通過 O 指定的輸出目錄就存在了
代碼檢查
- uboot 支持代碼檢查,使用命令“make C=1”使能代碼檢查,檢查那些需要重新編譯的文件?!癿ake C=2”用于檢查所有的源碼文件
實現源碼?
166 # Call a source code checker (by default, "sparse") as part of the 167 # C compilation. 168 # 169 # Use 'make C=1' to enable checking of only re-compiled files. 170 # Use 'make C=2' to enable checking of *all* source files, regardless 171 # of whether they are re-compiled or not. 172 # 173 # See the file "Documentation/sparse.txt" for more details, including 174 # where to get the "sparse" utility. 175 176 ifeq ("$(origin C)", "command line") 177 KBUILD_CHECKSRC = $(C) 178 endif 179 ifndef KBUILD_CHECKSRC 180 KBUILD_CHECKSRC = 0 181 endif- 第 176 行判斷 C 是否來源于命令行,如果 C 來源于命令行,那就將 C 賦值給變量KBUILD_CHECKSRC,如果命令行沒有 C 的話 KBUILD_CHECKSRC 就為 0
模塊編譯
- 在 uboot 中允許單獨編譯某個模塊,使用命令“make M=dir”即可,舊語法“make SUBDIRS=dir”也是支持的
實現源碼?
183 # Use make M=dir to specify directory of external module to build 184 # Old syntax make ... SUBDIRS=$PWD is still supported 185 # Setting the environment variable KBUILD_EXTMOD take precedence 186 ifdef SUBDIRS 187 KBUILD_EXTMOD ?= $(SUBDIRS) 188 endif 189 190 ifeq ("$(origin M)", "command line") 191 KBUILD_EXTMOD := $(M) 192 endif 193 194 # If building an external module we do not care about the all: rule 195 # but instead _all depend on modules 196 PHONY += all 197 ifeq ($(KBUILD_EXTMOD),) 198 _all: all 199 else 200 _all: modules 201 endif 202 203 ifeq ($(KBUILD_SRC),) 204 # building in the source tree 205 srctree := . 206 else 207 ifeq ($(KBUILD_SRC)/,$(dir $(CURDIR))) 208 # building in a subdirectory of the source tree 209 srctree := .. 210 else 211 srctree := $(KBUILD_SRC) 212 endif 213 endif 214 objtree := . 215 src := $(srctree) 216 obj := $(objtree) 217 218 VPATH := $(srctree)$(if $(KBUILD_EXTMOD),:$(KBUILD_EXTMOD)) 219 220 export srctree objtree VPATH- 第 186 行 判 斷 是 否 定 義 了 SUBDIRS , 如 果 定 義 了 SUBDIRS , 變 量KBUILD_EXTMOD=SUBDIRS,這里是為了支持老語法“make SUBIDRS=dir”
- 第 190 行判斷是否在命令行定義了 M,如果定義了的話 KBUILD_EXTMOD=$(M)
- 第 197 行判斷 KBUILD_EXTMOD 是否為空,如果為空的話目標_all 依賴 all,因此要先編譯出 all。否則的話默認目標_all 依賴 modules,要先編譯出 modules,也就是編譯模塊。一般情況下我們不會在 uboot 中編譯模塊,所以此處會編譯 all 這個目標
- 第 203 行判斷 KBUILD_SRC 是否為空,如果為空的話就設置變量 srctree 為當前目錄,即srctree 為“.”,一般不設置 KBUILD_SRC
- 第 214 行設置變量 objtree 為當前目錄
- 第 215 和 216 行分別設置變量 src 和 obj,都為當前目錄
- 第 218 行設置 VPATH
- 第 220 行導出變量 scrtree、objtree 和 VPATH
獲取主機架構和系統
實現源碼?
227 HOSTARCH := $(shell uname -m | \ 228 sed -e s/i.86/x86/ \ 229 -e s/sun4u/sparc64/ \ 230 -e s/arm.*/arm/ \ 231 -e s/sa110/arm/ \ 232 -e s/ppc64/powerpc/ \ 233 -e s/ppc/powerpc/ \ 234 -e s/macppc/powerpc/\ 235 -e s/sh.*/sh/) 236 237 HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \ 238 sed -e 's/\(cygwin\).*/cygwin/') 239 240 export HOSTARCH HOSTOS設置目標架構、交叉編譯器和配置文件
- 編 譯 uboot 的 時 候 需 要 設 置 目 標 板 架 構 和 交 叉 編 譯 器 ,“ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-”就是用于設置 ARCH 和 CROSS_COMPILE
實現源碼?
244 # set default to nothing for native builds 245 ifeq ($(HOSTARCH),$(ARCH)) 246 CROSS_COMPILE ?= 247 endif 248 249 KCONFIG_CONFIG ?= .config 250 export KCONFIG_CONFIG- 第 245 行判斷 HOSTARCH 和 ARCH 這兩個變量是否相等,主機架構(變量 HOSTARCH)是x86_64,而我們編譯的是 ARM 版本 uboot,肯定不相等,所以 CROS_COMPILE= arm-linux-gnueabihf-
- 第 249 行定義變量 KCONFIG_CONFIG,uboot 是可以配置的,這里設置配置文件為.config,.config 默認是沒有的,需要使用命令“make xxx_defconfig”對 uboot 進行配置,配
置完成以后就會在 uboot 根目錄下生成.config。默認情況下.config 和 xxx_defconfig 內容是一樣的,因為.config 就是從 xxx_defconfig 復制過來的。如果后續自行調整了 uboot 的一些配置參數,那么這些新的配置參數就添加到了.config 中,而不是 xxx_defconfig。相當于 xxx_defconfig 只是一些初始配置,而.config 里面的才是實時有效的配置
調用scripts/Kbuild.include
- 主 Makefile 會調用文件 scripts/Kbuild.include 這個文件
實現源碼?
327 # We need some generic definitions (do not try to remake the file). 328 scripts/Kbuild.include: ; 329 include scripts/Kbuild.include- 使用“include”包含了文件 scripts/Kbuild.include,此文件里面定義了很多變量
- 在 uboot 的編譯過程中會用到 scripts/Kbuild.include 中的這些變量
交叉編譯工具變量設置
實現源碼?
331 # Make variables (CC, etc...) 332 333 AS = $(CROSS_COMPILE)as 334 # Always use GNU ld 335 ifneq ($(shell $(CROSS_COMPILE)ld.bfd -v 2> /dev/null),) 336 LD = $(CROSS_COMPILE)ld.bfd 337 else 338 LD = $(CROSS_COMPILE)ld 339 endif 340 CC = $(CROSS_COMPILE)gcc 341 CPP = $(CC) -E 342 AR = $(CROSS_COMPILE)ar 343 NM = $(CROSS_COMPILE)nm 344 LDR = $(CROSS_COMPILE)ldr 345 STRIP = $(CROSS_COMPILE)strip 346 OBJCOPY = $(CROSS_COMPILE)objcopy 347 OBJDUMP = $(CROSS_COMPILE)objdump?
導出其它變量
實現源碼?
368 export VERSION PATCHLEVEL SUBLEVEL UBOOTRELEASE UBOOTVERSION 369 export ARCH CPU BOARD VENDOR SOC CPUDIR BOARDDIR 370 export CONFIG_SHELL HOSTCC HOSTCFLAGS HOSTLDFLAGS CROSS_COMPILE AS LD CC 371 export CPP AR NM LDR STRIP OBJCOPY OBJDUMP 372 export MAKE AWK PERL PYTHON 373 export HOSTCXX HOSTCXXFLAGS DTC CHECK CHECKFLAGS 374 375 export KBUILD_CPPFLAGS NOSTDINC_FLAGS UBOOTINCLUDE OBJCOPYFLAGS LDFLAGS 376 export KBUILD_CFLAGS KBUILD_AFLAGS- 這些變量中大部分都已經在前面定義了
- ARCH CPU BOARD VENDOR SOC CPUDIR BOARDDIR這 7 個變量在頂層 Makefile 是找不到的,這 7 個變量就是在?uboot 根目錄下的 config.mk 里面定義的,具體的值參考imx6ull:uboot根目錄config.mk分析
- 根據分析可知:
ARCH = arm
CPU = armv7
BOARD = mx6ullevk
VENDOR = freescale
SOC = mx6
CPUDIR = arch/arm/cpu/armv7
BOARDDIR = freescale/mx6ullevk
imx6ull:uboot的make xxx_defconfig 過程分析
總結:一通分析下來,繞來繞去,除了上圖中的調用關系外,感覺沒有得到什么有用的內容。這里需要明白的是make xxx_defconfig的執行過程中從頂層makefile開始,中間用到了許多./scripts目錄下的文件以及有該目錄下的某些文件得到的主機程序,最終我們看到的效果就是在uboot根目錄下生成了一個.config文件,該文件中的部分內容就來自于xxx_defconfig
imx6ull:uboot的make過程分析?
總結(待完善)
執行的操作
變量的含義
總結
以上是生活随笔為你收集整理的imx6ull:uboot顶层Makefile分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 泰凌微8258入门教程——导读
- 下一篇: 阿里云下如何巧加web防火墙?