Linux内核---10.obj-y中将.c编译为.o流程

本文详细解析了Linux内核2.6.30.4版本中从源代码.c文件到编译生成.o文件的过程,重点介绍了Makefile.build中的规则及具体编译步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先去编译obj-y,以init下的obj-y为例:
obj-y=init/main.o init/version.o init/mounts.o init/noinitramfs.o init/calibrate.o
首先找到将.c编译为.o的规则:

点击(此处)折叠或打开

  1. linux-2.6.30.4/scripts/Makefile.build
  2. 226 # Built-in and composite module parts
  3. 227 $(obj)/%.o: $(src)/%.c FORCE
  4. 228  $(call cmd,force_checksrc)
  5. 229  $(call if_changed_rule,cc_o_c)
将.c编译为.o要分两步
1. L228,如果KBUILD_CHECKSRC为空,不做任何操作;不为空,没看。
2. L229,编译的具体操作。

1.1 检查 L228 $(call cmd,force_checksrc) 

点击(此处)折叠或打开

  1. linux-2.6.30.4/scripts/Kbuild.include
  2. 154 # echo command.
  3. 155 # Short version is used, if $(quiet) equals `quiet_', otherwise full one.
  4. 156 echo-cmd = $(if $($(quiet)cmd_$(1)),\
  5. 157 echo ' $(call escsq,$($(quiet)cmd_$(1)))$(echo-why)';)
  6. 158 
  7. 159 # printing commands
  8. 160 cmd = @$(echo-cmd) $(cmd_$(1))
  9. cmd 定义在L160处,如果cmd_force_checksrc不为空,则把cmd_force_checksrc这个命令打印出来,然后执行cmd_force_checksrc
  10. 转到cmd_force_checksrc定义处:

  11. linux-2.6.30.4/scripts/Makefile.build
  12.  98 # Linus' kernel sanity checking tool
  13.  99 ifneq ($(KBUILD_CHECKSRC),0)
  14. 100 ifeq ($(KBUILD_CHECKSRC),2)
  15. 101 quiet_cmd_force_checksrc = CHECK $<
  16. 102 cmd_force_checksrc = $(CHECK) $(CHECKFLAGS) $(c_flags) $< ;
  17. 103 else
  18. 104 quiet_cmd_checksrc = CHECK $<
  19. 105 cmd_checksrc = $(CHECK) $(CHECKFLAGS) $(c_flags) $< ;
  20. 106 endif
  21. 107 endif
  22. 由于此时 KBUILD_CHECKSRC=0,所以cmd_force_checksrc为空,L156处的if条件为false,echo不执行,L160处cmd_force_checksrc为空,也不执行。
2. 下面开始执行L229 $(call if_changed_rule,cc_o_c),首先转到定义处:

点击(此处)折叠或打开

  1. linux-2.6.30.4/scripts/Kbuild.include
  2. 208 if_changed_rule = $(if $(strip $(any-prereq) $(arg-check) ), \
  3. 209 @set -e; \
  4. 210 $(rule_$(1)))
  5. $(strip $(any-prereq) $(arg-check),如果目标有更新则调用:rule_cc_o_c

  6. linux-2.6.30.4/scripts/Makefile.build
  7. 215 define rule_cc_o_c
  8. 216 $(call echo-cmd,checksrc) $(cmd_checksrc) \
  9. 217 $(call echo-cmd,cc_o_c) $(cmd_cc_o_c); \
  10. 218 $(cmd_modversions) \
  11. 219 $(cmd_record_mcount) \
  12. 220 scripts/basic/fixdep $(depfile) $@ '$(call make-cmd,cc_o_c)' > \
  13. 221 $(dot-target).tmp; \
  14. 222 rm -f $(depfile); \
  15. 223 mv -f $(dot-target).tmp $(dot-target).cmd
  16. 224 endef
rule_cc_o_c
2.1 echo-cmd && cmd_checksrc :不执行
2.2 echo-cmd && cmd_cc_o_c :打印cmd_cc_o_c的内容,并执行cmd_cc_o_c将.c编译为.o
2.3  cmd_modversions :不执行
2.4  cmd_record_mcount :不执行
2.5 生成命令.cmd

下面逐条分析:
2.1-2.2 echo-cmd && cmd_checksrc 和 echo-cmd && cmd_cc_o_c

点击(此处)折叠或打开

  1. linux-2.6.30.4/scripts/Kbuild.include
  2. 154 # echo command.
  3. 155 # Short version is used, if $(quiet) equals `quiet_', otherwise full one.
  4. 156 echo-cmd = $(if $($(quiet)cmd_$(1)),\
  5. 157 echo ' $(call escsq,$($(quiet)cmd_$(1)))$(echo-why)';)
  6. cmd_checksrc为空,不执行

  7. linux-2.6.30.4/scripts/Makefile.build
  8. 178 ifndef CONFIG_MODVERSIONS
  9. 179 cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<

  10. $(call echo-cmd,cc_o_c)将执行的编译命令打印出来, $(cmd_cc_o_c)执行具体的编译命令。这将会在命令行中看到一坨坨的打印。
2.3  cmd_modversions  

点击(此处)折叠或打开

  1. linux-2.6.30.4/scripts/Makefile.build
  2. 178 ifndef CONFIG_MODVERSIONS
  3. 179 cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<
  4. 180
  5. 181 else
  6. 194 cmd_cc_o_c = $(CC) $(c_flags) -c -o $(@D)/.tmp_$(@F) $<
  7. 195 cmd_modversions = ...
  8. 因为此处没有定义 CONFIG_MODVERSIONS, 所以cmd_modversions为空。
2.4 cmd_record_mcount 

点击(此处)折叠或打开

  1. 208 ifdef CONFIG_FTRACE_MCOUNT_RECORD
  2. 209 cmd_record_mcount = perl $(srctree)/scripts/recordmcount.pl "$(ARCH)" \
  3. 210 "$(if $(CONFIG_64BIT),64,32)" \
  4. 211 "$(OBJDUMP)" "$(OBJCOPY)" "$(CC)" "$(LD)" "$(NM)" "$(RM)" "$(MV)" \
  5. 212 "$(if $(part-of-module),1,0)" "$(@)";
  6. 213 endif
  7. CONFIG_FTRACE_MCOUNT_RECORD 没有定义,所以为空
总结一下:
   虽然写了这么多,但是有用处的只有两个echo-cmd && cmd_cc_o_c和 mv ,打印cmd_cc_o_c的内容,并执行cmd_cc_o_c将.c编译为.o,把命令保存到.cmd文件中。假设让我自己写出来的Makefile可能也就是$(CC) $(c_flags) -c -o $@ $<这么一句。
<think>好的,我现在需要帮助用户解决他们在修改Buildroot中的Makefile时遇到的问题。用户之前已经将`obj-m`改为`obj-y`,现在他们想知道是否需要删除与`ipcm_ipc_demo`相关的特定编译指令,特别是`-c $(kernel_dir) M=$(pwd) modules && $(strip) -S rpmsg_ipc_demo.ko`这部分内容。 首先,我需要回顾一下用户的问题历史。他们之前询问了如何将内核模块编译内核镜像,而不是作为可加载模块。现在他们修改了Makefile中的`obj-m`为`obj-y`,但不确定是否需要进一步调整编译命令,特别是那些原本用于生成模块的指令。 接下来,我需要理解`obj-m`和`obj-y`的区别。`obj-m`用于指定可加载模块,而`obj-y`用于直接编译内核。当使用`obj-y`时,内核构建系统会自动处理源代码的编译和链接,不需要手动指定模块编译命令。因此,原本用于生成模块的命令(如`make -C $(kernel_dir) M=$(pwd) modules`)在改为`obj-y`后可能不再需要,甚至可能导致冲突。 用户提到的`-c $(kernel_dir) M=$(pwd) modules`是典型的模块编译命令,它会调用内核的构建系统来编译模块。而`$(strip) -S rpmsg_ipc_demo.ko`可能是用来去除调试符号或优化模块大小的命令。当模块被编译内核时,这些步骤就不再适用了,因为模块不会生成单独的.ko文件,而是直接集成到内核镜像中。因此,这些命令应该被删除,以避免构建错误或冗余操作。 同时,我需要考虑用户提供的引用内容,特别是引用[3]中提到的工具链路径问题,以及引用[2]中的配置参数。虽然这些引用主要涉及工具链的配置和安装问题,但它们提醒我要确保用户的构建环境正确配置,避免因路径或依赖问题导致编译失败。 另外,用户可能在修改Makefile后没有清理旧的构建产物,导致残留的模块相关文件干扰新的编译过程。因此,建议用户执行清理步骤,比如使用`make clean`或删除output目录中的相关文件,以确保重新编译时不会出现意外错误。 总结下来,用户的重点在于确认是否需要删除原有的模块编译指令,以及如何处理这些变更后的构建步骤。需要明确指导他们删除不必要的命令,调整Makefile的结构,并执行清理和验证步骤,以确保修改后的配置正确生效。</think>在Buildroot中将`obj-m`改为`obj-y`后,**需要删除与模块编译相关的定义**,以下是具体分析及操作步骤: --- ### 1. **需要删除的编译指令** 原始命令`-c $(kernel_dir) M=$(pwd) modules && $(strip) -S rpmsg_ipc_demo.ko`属于**模块编译流程**,作用为: - `M=$(pwd) modules`: 调用内核构建系统生成`.ko`模块[^1] - `strip -S`: 剥离调试符号以减小模块体积 当使用`obj-y`时,**内核自动将代码编译为内置对象**,不再需要手动模块编译命令,因此: - **必须删除所有`modules`相关指令** - 保留`obj-y`定义即可,例如: ```makefile obj-y += rpmsg_ipc_demo.o ``` --- ### 2. **修改后的Makefile示例** ```makefile # 原内容(需删除) # modules: # $(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules # clean: # $(MAKE) -C $(KERNEL_DIR) M=$(PWD) clean # 修改后(仅保留对象定义) obj-y += rpmsg_ipc_demo.o ``` --- ### 3. **验证修改的必要性** | 场景 | 保留模块命令的后果 | 删除后的行为 | |--------------------|------------------------------|---------------------------| | 编译内核镜像 | 触发冗余模块编译,可能报错 | 正确编译内核 | | 清理操作 | `make clean`无法清除残留文件 | 清理完全 | | 调试符号 | 剥离符号导致调试困难 | 符号保留在内核镜像中 | --- ### 4. **操作步骤** 1. **删除冗余命令**: - 在`Makefile`和`Makefile.host`中移除所有`modules`目标及相关`strip`操作 - 仅保留`obj-y += rpmsg_ipc_demo.o`定义 2. **同步清理编译缓存**: ```bash make linux-dirclean # 清理内核源码目录 rm -rf output/build/rpmsg_ipc_demo* # 强制删除旧编译产物 ``` 3. **重新编译验证**: ```bash make linux-rebuild && make ``` --- ### 5. **特殊案例处理** - **混合编译需求**:若需同时生成模块和内置对象,需拆分代码为`obj-y`和`obj-m`两部分(需避免符号冲突) - **依赖管理**:若`rpmsg_ipc_demo`依赖其他模块,需在内核配置中确保依赖项为`<*>`(内置) --- ### 6. **引用补充说明** 工具链路径问题(如引用[1][^1])与当前修改无关,但需注意交叉编译时确认内核头文件路径正确匹配,可通过以下命令验证: ```bash echo $CROSS_COMPILE # 应输出类似aarch64-buildroot-linux-gnu- ``` ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值