慢慢欣赏linux if_changed_xxx的作用

本文详细解析了内核编译过程中生成的以.o.cmd为后缀的临时文件的作用和生成机制。这些文件由scripts/makefile.build中的编译宏创建,用于记录编译步骤和依赖关系。

编译内核会生成很多临时文件,以 o.cmd为后缀。
打开看发现是编译脚本。
这些文件是在scripts/makefile.build文件通过如下编译宏实现:

define rule_cc_o_c
	$(call echo-cmd,checksrc) $(cmd_checksrc)			  \
	$(call echo-cmd,cc_o_c) $(cmd_cc_o_c);				  \
	$(cmd_modversions)						  \
	$(call echo-cmd,record_mcount)					  \
	$(cmd_record_mcount)						  \
	scripts/basic/fixdep $(depfile) $@ '$(call make-cmd,cc_o_c)' >    \
	                                              $(dot-target).tmp;  \
	rm -f $(depfile);						  \
	mv -f $(dot-target).tmp $(dot-target).cmd
endef

调用者也在同一个文件(scripts/makefile.build),编译可执行程序和ko都会生成类似的临时文件

# Built-in and composite module parts
$(obj)/%.o: $(src)/%.c FORCE
	$(call cmd,force_checksrc)
	$(call if_changed_rule,cc_o_c)

# Single-part modules are special since we need to mark them in $(MODVERDIR)

$(single-used-m): $(obj)/%.o: $(src)/%.c FORCE
	$(call cmd,force_checksrc)
	$(call if_changed_rule,cc_o_c)
	@{ echo $(@:.o=.ko); echo $@; } > $(MODVERDIR)/$(@F:.o=.mod)

u-boot-2016.09 make工具之fixdep
https://blog.youkuaiyun.com/guyongqiangx/article/details/52588409

【u-boot-2018.11】make工具之fixdep
https://blog.youkuaiyun.com/linuxweiyh/article/details/100179968

内核编译系统探秘之一 if_changed_rule
http://blog.sina.com.cn/s/blog_61c81f910100phiq.html

Uboot 中make menuconfig 做了什么?
https://www.cnblogs.com/syyxy/p/9350999.html

内核Kbuild 学习
http://blog.chinaunix.net/uid-20778443-id-103963.html
http://www.360doc.com/content/12/0107/15/6828497_177891385.shtml

Linux之Makefile(strip)
https://blog.youkuaiyun.com/zhoudengqing/article/details/41777665

【u-boot】u-boot-2016.09 make编译过程分析(二)
https://blog.youkuaiyun.com/qq_38144425/article/details/73326052

if_changed_rule/cc_o_c/any-prereq/arg-check
https://blog.youkuaiyun.com/lcw_202/article/details/6660957

<think> 我们分析Linux内核源码中Makefile、Kconfig、.config文件的作用。根据引用资料,这三个文件在内核配置和编译过程中扮演着核心角色,彼此之间紧密关联。 ### 1. **Makefile的作用** - **定义编译规则**:Makefile文件(分布在每个源代码目录中)指定了如何编译源代码、链接目标文件以及生成最终的内核镜像或模块。它定义了哪些文件需要编译,以及它们的依赖关系。 - **条件编译控制**:通过读取`.config`文件中的配置变量(如`CONFIG_XXX=y`或`CONFIG_XXX=m`),Makefile决定将哪些文件编译内核(`obj-y`)、编译为模块(`obj-m`)或不编译(`obj-n`)。例如: ```makefile obj-$(CONFIG_LEDS_CTL) += itop4412_leds.o # 若CONFIG_LEDS_CTL为y或m,则编译该文件[^5] ``` - **递归构建**:顶层Makefile通过调用子目录的Makefile实现对整个源代码树的编译管理[^4]。 ### 2. **Kconfig的作用** - **提供配置选项**:Kconfig文件(同样分布在每个子目录)定义了用户可配置的选项。这些选项通过图形化界面(如`make menuconfig`)展示,允许开发者启用或禁用内核功能。 - **结构化层级**:Kconfig采用树形结构。顶层Kconfig包含架构相关的配置,并通过`source`指令引入子目录的Kconfig文件[^4]: ```kconfig source "drivers/pcmcia/Kconfig" # 包含子目录的配置[^4] ``` - **配置依赖与约束**:Kconfig可以定义选项之间的依赖关系(`depends on`)、互斥关系(`select`)以及默认值(`default`),确保配置的合理性[^1]。 ### 3. **.config文件的作用** - **存储配置结果**:`.config`文件位于内核根目录,是用户通过配置界面(如`make menuconfig`)选择后生成的最终配置集合。它记录了所有配置选项的取值(例如`CONFIG_SMP=y`)。 - **驱动编译过程**:Makefile通过包含`.config`文件获取配置信息,决定哪些代码需要编译[^3]。 - **条件更新**:当修改配置时,`.config`会更新,并触发Makefile重新评估依赖关系。 ### 三者的协同工作流程 ```mermaid graph TD A[用户执行 make menuconfig] -->|读取Kconfig| B[生成/更新 .config] B --> C[make 命令] C -->|包含.config| D[Makefile] D -->|根据CONFIG_*变量| E[编译对应文件] ``` ### 关键机制解析 1. **配置界面生成**: - 当执行`make menuconfig`时,配置系统(如`conf`工具)解析所有Kconfig文件,生成菜单树并允许用户交互[^2]。 - 用户的选择被保存到`.config`文件中。 2. **条件编译实现**: - Makefile通过条件判断将`.config`中的符号(如`CONFIG_XXX`)转换为编译指令。例如: ```makefile ifeq ($(CONFIG_SMP), y) CFLAGS += -DUSE_SMP endif ``` 3. **递归构建机制**: - 顶层Makefile通过`include`指令聚合子目录的Makefile,形成全局依赖树[^5]。 ### 示例:文件交互过程 以`drivers/char/`目录为例: - **Kconfig**:定义字符设备驱动的配置选项(如`config ITOP4412_LEDS`)[^5]。 - **Makefile**:根据`.config`中的`CONFIG_ITOP4412_LEDS`值决定是否编译`itop4412_leds.c`。 - **.config**:包含用户设定的`CONFIG_ITOP4412_LEDS=y`。 > **总结**: > Kconfig提供**配置接口**,`.config`保存**配置结果**,Makefile执行**编译动作**。三者共同构成Linux内核模块化、可配置的编译系统[^1][^3]。 §§相关问题§§ 1. 如何在内核中添加一个新的驱动模块并使其可通过menuconfig配置? 2. 为什么修改.config后需要执行`make oldconfig`? 3. 内核编译时如何处理模块间的依赖关系? </think> ### Linux内核源码中Makefile、Kconfig、.config文件作用分析 在Linux内核编译体系中,**Makefile**、**Kconfig**和**.config**三个文件构成核心配置框架,其作用与关系如下: #### 1. **Kconfig:配置选项定义** - **作用**: - 定义可配置选项(如驱动、功能开关),形成树形结构 - 提供配置依赖关系(如`depends on`、`select`) - 描述配置项的帮助文档 - **示例结构**: ```kconfig config USB_SUPPORT bool "USB support" depends on PCI help Enable USB host controller support ``` - **层级调用**: - 顶层Kconfig通过`source`指令包含子目录配置(如`source "drivers/usb/Kconfig"`)[^4] - 支持`make menuconfig`等交互界面生成[^3] #### 2. **.config:配置结果存储** - **作用**: - 保存用户选择的配置项(如`CONFIG_USB_SUPPORT=y`) - 作为Makefile编译的条件输入 - **生成方式**: - 通过`make menuconfig`等命令交互生成 - 修改后需执行`make oldconfig`同步变更[^1] - **典型内容**: ``` CONFIG_SMP=y CONFIG_USB=m # m表示编译为模块 ``` #### 3. **Makefile:编译规则引擎** - **作用**: - 定义文件编译规则和依赖关系 - 根据`.config`决定编译对象: ```makefile obj-$(CONFIG_USB) += usb-core.o # 若CONFIG_USB=y则编译 obj-m += usb-storage.o # 编译为可加载模块 ``` - 实现递归编译(顶层Makefile调用子目录)[^4][^5] - **关键特性**: - `obj-y`强制编译内核 - `obj-m`编译为可加载模块 - 条件编译(如`ifeq ($(CONFIG_SMP),y)`)[^5] ```mermaid graph TD A[Kconfig] -->|定义选项| B[menuconfig] B -->|用户选择| C[.config] C -->|输入| D[Makefile] D -->|条件判断| E[编译对象] E --> F[内核镜像/模块] ``` #### 三文件协同流程 1. **配置阶段**: Kconfig定义选项 → 用户通过`menuconfig`选择 → 生成`.config` 2. **编译阶段**: Makefile读取`.config` → 根据`CONFIG_*`变量决定编译内容 → 递归构建子目录 3. **维护机制**: - 修改Kconfig后需重新生成菜单 - 直接修改`.config`后需运行`make oldconfig`同步 - Makefile通过`if_changed`检测文件变更[^5] > **本质关系**: > Kconfig是**选项定义器**,.config是**配置存储器**,Makefile是**编译执行器**。三者共同实现Linux内核超过2000万行代码的可配置编译[^1][^2]。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值