c - Linux Kernel Makefile.build 构建外部模块时的奇怪行为

标签 c linux makefile linux-kernel kbuild

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

Linux 内核 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 的实现并使用 -d 选项打印调试输出我发现正在执行的此 makefile 的目标是 __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。有以下$(obj)/%.o: Makefile.build 中定义的模式规则:

$(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)

关于c - Linux Kernel Makefile.build 构建外部模块时的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59396154/

相关文章:

客户端不创建文件

c++ - 如何在 16 位显示器上缩小原始 rgb 数据数组

linux - 使用 9 位序列号对文件进行排序和重命名

linux - 未链接的文件和 posix_fadvise(POSIX_FADV_NOREUSE)

c++ - 如何使用 cmake 使用不同的编译器构建多个可执行文件?

c - 如何调试这个基本的 IF-ELSE 程序?

c - 如何在不使用 LD_LIBRARY_PATH 的情况下链接 makefile 中共享库的特定版本?

c++ - 如何在 C++ 代码中获取终端维度?

c - Valgrind 不显示行号

c++ - gtest - 对 `testing::InitGoogleTest(int*, char**)' 的 undefined reference