第一个很容易理解,但第二个和第三个呢? 内核开发人员经常会看到如下代码:
#ifdef CONFIG_SMP __boot_cpu_id = cpu; #endif
当 CONFIG_SMP 改变时,这段代码应该重新编译。编译源文件的命令行也很重要,因为不同的命令行可能会导致不同的目标文件。
当 .c 文件通过 #include 指令使用头文件时,你需要编写如下规则:
main.o: defs.h recipe...
管理大型项目时,需要大量的这些规则;把它们全部写下来会很乏味无聊。幸运的是,大多数现代 C 编译器都可以通过查看源文件中的 #include 行来为你编写这些规则。对于 GNU 编译器集合(GCC),只需添加一个命令行参数:-MD depfile
# In scripts/Makefile.lib c_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \ -include $(srctree)/include/linux/compiler_types.h \ $(__c_flags) $(modkern_cflags) \ $(basename_flags) $(modname_flags)
这将生成一个 .d 文件,内容如下:
init_task.o: init/init_task.c include/linux/kconfig.h \ include/generated/autoconf.h include/linux/init_task.h \ include/linux/rcupdate.h include/linux/types.h \ ...
然后主程序 fixdep 通过将 depfile 文件和命令行作为输入来处理其他两个依赖项,然后以 makefile 格式输出一个 .<target>.cmd 文件,它记录命令行和目标的所有先决条件(包括配置)。 它看起来像这样:
# The command line used to compile the target cmd_init/init_task.o := gcc -Wp,-MD,init/.init_task.o.d -nostdinc ... ... # The dependency files deps_init/init_task.o := \ $(wildcard include/config/posix/timers.h) \ $(wildcard include/config/arch/task/struct/on/stack.h) \ $(wildcard include/config/thread/info/in/task.h) \ ... include/uapi/linux/types.h \ arch/x86/include/uapi/asm/types.h \ include/uapi/asm-generic/types.h \ ...
在递归 make 中,.<target>.cmd 文件将被包含,以提供所有依赖关系信息并帮助决定是否重建目标。
这背后的秘密是 fixdep 将解析 depfile(.d 文件),然后解析里面的所有依赖文件,搜索所有 CONFIG_ 字符串的文本,将它们转换为相应的空的头文件,并将它们添加到目标的先决条件。每次配置更改时,相应的空的头文件也将更新,因此 kbuild 可以检测到该更改并重建依赖于它的目标。因为还记录了命令行,所以很容易比较最后和当前的编译参数。
展望未来
Kconfig/kbuild 在很长一段时间内没有什么变化,直到新的维护者 Masahiro Yamada 于 2017 年初加入,现在 kbuild 正在再次积极开发中。如果你不久后看到与本文中的内容不同的内容,请不要感到惊讶。
【编辑推荐】
- 如何在Linux上安装应用程序
- 详解Linux Shell脚本编写技巧,附实例说明
- 如何在Linux上安装Elasticsearch和Kibana
- Linux性能实时监测工具之NetData搭建
- 如何在Linux命令行操作PDF
【责任编辑:庞桂玉 TEL:(010)68476606】
点赞 0
(编辑:ASP站长网)
|