编译Linux内核时,像CC、LD和CC[M]这样的代码是什么意思?

19

在从头开始编译Linux时,我意识到在编译过程中会出现编译代码。

例如:CC文件名,LD文件名,CC[M]文件名。

这些代码是什么意思?


1
http://unix.stackexchange.com/questions/199060/what-do-the-terms-cc-ld-and-shipped-refer-to-during-the-kernel-source-compilati - Ciro Santilli OurBigBook.com
3个回答

26

不同的标记指定了以下内容:

  • [CC] - 将C文件编译成一个指定的目标文件。目标文件包含该.c文件的体系结构汇编代码。由于可能引用其范围之外的部分,例如在另一个.c文件中调用另一个函数,因此函数调用在目标文件中保持开放状态,并由链接器在后期进行包含。因此
  • [LD] 是将编译的对象链接在一起,并连接编译器留下的开放式函数调用的过程。然而,许多部分作为内核的核心部分被链接在一起,而有些部分则被省略。因此您会看到
  • [CC (M)] 用于那些被编译为在运行时加载到内核中的点,但它们在内核的完整部分中没有链接在一起。相反,在内核启动时可以插入它们。

1
换句话说,在CC [M]中,M代表“模块”,因为源文件最终编译成可加载的内核模块,即扩展名为.ko的目标文件。 - kaiwan
这个有文档记录吗?因为我也看到像 AR 这样的代码没有列在这里。 - aggregate1166877

10

让我们来举一个具体的例子,看看它在内核4.1中做了什么,例如IHEX

找出代码的作用

只需运行:

make SHELL='sh -x'

如何操作:https://dev59.com/dG025IYBdhLWcg3wvIu2#32010960

如果我们在输出结果中使用grep查找IHEX,我们会找到以下行:

+ echo   IHEX    firmware/e100/d101s_ucode.bin
  IHEX    firmware/e100/d101s_ucode.bin
+ objcopy -Iihex -Obinary /home/ciro/git/kernel/src/firmware/e100/d101s_ucode.bin.ihex firmware/e100/d101s_ucode.bin

因此我们可以得出结论,IHEX 执行的是 objcopy -Iihex

查找代码定义位置

每个内核命令都必须用类似以下的方式进行定义:

quiet_cmd_ihex  = IHEX    $@
      cmd_ihex  = $(OBJCOPY) -Iihex -Obinary $< $@

$(obj)/%: $(obj)/%.ihex
        $(call cmd,ihex)

为了使冗长设置 (例如 V=1make -s) 生效。

因此,总的来说,你只需要

git grep 'cmd.* = CODE'

寻找代码

我已经在https://dev59.com/p3_aa4cB1Zd3GeqP8-CF#32023861详细解释了这个系统的工作原理。

获取所有代码的列表

make | grep -E '^  ' | sort -uk1,1

CC 和 CC [M]

定义于 scripts/Makefile.build 文件中:

quiet_cmd_cc_o_c = CC $(quiet_modtag)  $@
      cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<

[M]来自于目标特定变量

$(real-objs-m)        : quiet_modtag := [M]
$(real-objs-m:.o=.i)  : quiet_modtag := [M]
$(real-objs-m:.o=.s)  : quiet_modtag := [M]
$(real-objs-m:.o=.lst): quiet_modtag := [M]
$(obj-m)              : quiet_modtag := [M]

然后通过以下方式调用:

$(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE
    [...]
    $(call if_changed_rule,cc_o_c)

define rule_cc_o_c
    [...]
    $(call echo-cmd,cc_o_c) $(cmd_cc_o_c);                \

如果您定义了if_changed_rule,它将在scripts/Kbuild.include中被定义为:

if_changed_rule = $(if $(strip $(any-prereq) $(arg-check) ),                 \
    @set -e;                                                             \
    $(rule_$(1)))

并且在顶层Makefile中包含了Kbuild.include

LD

有几个版本,但最简单的似乎是:

quiet_cmd_link_o_target = LD      $@
cmd_link_o_target = $(if $(strip $(obj-y)),\
              $(LD) $(ld_flags) -r -o $@ $(filter $(obj-y), $^) \
              $(cmd_secanalysis),\
              rm -f $@; $(AR) rcs$(KBUILD_ARFLAGS) $@)

$(builtin-target): $(obj-y) FORCE
    $(call if_changed,link_o_target)

并且在 scripts/Kbuild.include 文件中:

# 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));                                             \
    printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd)

4

它应该显示:

  • 在编译内核的核心部分时,显示CC
  • 在编译模块时,显示CC [M]
  • 在链接时显示LD

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接