版本号
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 指定的输出目录就存在了
代码检查
模块编译