Linux 内核 Makefile.build 构建外部模块时的奇怪行为

Linux Kernel Makefile.build strange behavior when building external modules

我需要一些与构建外部模块相关的KBuild实现细节建议。

Linux Kernel 5.0.0-32

这是我的 LKM Makefile:

obj-m += pfsw.o
pfsw-objs := src/init.o

all:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

查看 scripts/Makefile.build and printing the debug output with -d option I found that the target of this makefile being executed is __build 的实现:

__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
     $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \
     $(subdir-ym) $(always)
    @:

因为我正在构建外部 LKM,所以唯一的先决条件是 $(obj-m)$(modorder-target)。我从数据库中获取了它们的值:

obj-m := /home/memyself/lkm/procfs_write_perm/pfsw.o
modorder-target := /home/memyself/lkm/procfs_write_perm/modules.order

所以要执行 __build 必须首先构建先决条件 /home/memyself/lkm/procfs_write_perm/pfsw.o。在 Makefile.build 中定义了以下 $(obj)/%.o: 模式规则:

$(obj)/%.o: $(src)/%.c $(recordmcount_source) $(objtool_dep) FORCE
    $(call cmd,force_checksrc)
    $(call if_changed_rule,cc_o_c)

我添加了调试输出来打印目标自动变量的名称:

$(obj)/%.o: $(src)/%.c $(recordmcount_source) $(objtool_dep) FORCE
    @echo "$@"
    $(call cmd,force_checksrc)
    $(call cmd,force_check_kmsg)
    $(call if_changed_rule,cc_o_c)

并期望打印 /home/memyself/lkm/procfs_write_perm/pfsw.o,但实际上打印了 /home/memyself/lkm/procfs_write_perm/src/init.o。 这看起来有点神奇......

问题: 为什么构建目标 /home/memyself/lkm/procfs_write_perm/pfsw.o 导致构建 /home/memyself/lkm/procfs_write_perm/src/init.o?代码中哪里指定的?

我知道 real-obj-m 变量包含准确的值,但是 grep 在代码库中我没有找到它取决于某些东西...

正如@Tsyvarev 在评论中暗示的那样,有一条规则可以从 -objs.

构建 obj-m

在分析行为时,我错误地认为构建 obj-m 的隐式模式规则在我的例子中被扩展为 /home/memyself/lkm/procfs_write_perm/pfsw.o。 运行 使用 make -p 的构建可以在输出中注意到以下条目:

/home/memyself/lkm/procfs_write_perm/pfsw.o: FORCE /home/memyself/lkm/procfs_write_perm/src/init.o
#  Implicit rule search has not been done.
#  Implicit/static pattern stem: ''
#  File is an intermediate prerequisite.
#  Last modified 2019-12-18 21:13:48.337755924
#  File has been updated.
#  Successfully updated.
# automatic
# @ := /home/memyself/lkm/procfs_write_perm/pfsw.o
# automatic
# % := 
# automatic
# * := 
# automatic
# + := FORCE /home/memyself/lkm/procfs_write_perm/src/init.o
# automatic
# | := 
# automatic
# < := FORCE
# automatic
# ^ := FORCE /home/memyself/lkm/procfs_write_perm/src/init.o
# automatic
# ? := FORCE /home/memyself/lkm/procfs_write_perm/src/init.o
# variable set hash-table stats:
# Load=8/32=25%, Rehash=0, Collisions=13/382=3%
#  recipe to execute (from 'scripts/Makefile.build', line 474):
    $(call if_changed,link_multi-m)
    @{ echo $(@:.o=.ko); echo $(filter %.o,$^); \
       $(cmd_undef_syms); } > $(MODVERDIR)/$(@F:.o=.mod)

因此有一个非隐式规则指定要构建的配方 /home/memyself/lkm/procfs_write_perm/pfsw.o 暗示对于该特定情况不应考虑隐式规则 $(obj)/%.o:

上面指定的 make 数据库条目还包含要执行的配方的行号和它来自的文件。在这种情况下是

recipe to execute (from 'scripts/Makefile.build', line 474):

指向 scripts/Makefile.build 条目,在我的例子中是

$(multi-used-m): FORCE
    $(call if_changed,link_multi-m) # <------ This is the line the database points to
    @{ echo $(@:.o=.ko); echo $(filter %.o,$^); \
       $(cmd_undef_syms); } > $(MODVERDIR)/$(@F:.o=.mod)
$(call multi_depend, $(multi-used-m), .o, -objs -y -m)