|
Makefile 对应内核版本:2.6.35.13
if_changed 定义在 scripts/Kbuild.include 中:
[code=Makefile]# Execute command if command has changed or prerequisite(s) are updated.
#
if_changed = $(if $(strip $(any-prereq) $(arg-check)), \
@set -e; \
$(echo-cmd) $(cmd_$(1)); \
echo 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd)
[/mw_shl_code]
if_changed 函数在当发现规则的依赖有更新,或者是对应目标的命令行参数发生改变时($(strip $(any-prereq) $(arg-check)) 语句结果不为空),执行后面的语句。
set -e 表示如果命令执行有错那么命令停止执行并退出。
接着 $(echo-cmd) 用来打印出相关的编译命令,接着执行 $(cmd_$(1) 里的命令。
最后 echo 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd 将上面执行的命令写入一个叫 $(dot-target).cmd 的文件中,该文件为隐藏文件,在编译后的内核源码目录及其子目录下随处可见,比如在 init/ 下可以看到 .initramfs.o.cmd, .version.o.cmd 等等。
比如下面的 if_changed 的用法:
[code=Makefile].tmp_vmlinux2: $(vmlinux-lds) $(vmlinux-all) .tmp_kallsyms1.o FORCE
$(call if_changed,vmlinux__)[/mw_shl_code]
如果目标的依赖或者命令参数已经改变,那么将执行 cmd_vmlinux__ 所代表的新命令。那么这里可能会想到,在新老命令的比较中,老命令是从何而来?正如上面所分析的,老命令正是被写入到 $(dot-target).cmd 文件中的;这样一来,在 Makefile 中肯定有一处是将这些保存了老命令的文件包含进来的语句。在顶层 Makefile 中的 1481-1489 行可以看到:
[code=Makefile]# read all saved command lines
targets := $(wildcard $(sort $(targets)))
cmd_files := $(wildcard .*.cmd $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd))
ifneq ($(cmd_files),)
$(cmd_files): ; # Do not try to update included dependency files
include $(cmd_files)
endif[/mw_shl_code]
在目录 scripts/ 下,像在 Makefile.build、Makefile.headersinst、Makefile.modpost 以 及Makefile.fwinst 等文件中,也可以看到类似的读入语句。但这并不冲突,因为顶层 Makefile 和它们独立运作,变量间互不干扰。 |
|