I need some KBuild
implementation details advice related to building of external modules.
Linux Kernel 5.0.0-32
Here is my LKM
Makefile:
obj-m += pfsw.o
pfsw-objs := src/init.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
Looking at the implementation of 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)
@:
Since I'm building External LKM the only prerequisites are $(obj-m)
and $(modorder-target)
. I got their values from the database:
obj-m := /home/memyself/lkm/procfs_write_perm/pfsw.o
modorder-target := /home/memyself/lkm/procfs_write_perm/modules.order
So to execute __build
the prerequisite /home/memyself/lkm/procfs_write_perm/pfsw.o
have to be built first. There is the following $(obj)/%.o:
pattern rule defined in Makefile.build
:
$(obj)/%.o: $(src)/%.c $(recordmcount_source) $(objtool_dep) FORCE
$(call cmd,force_checksrc)
$(call if_changed_rule,cc_o_c)
I added debug output to print the name of the target automatic variable:
$(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)
and expected /home/memyself/lkm/procfs_write_perm/pfsw.o
to be printed, but actually /home/memyself/lkm/procfs_write_perm/src/init.o
was printed.
This looks like some magic...
QUESTION: Why is building the target /home/memyself/lkm/procfs_write_perm/pfsw.o
causes building /home/memyself/lkm/procfs_write_perm/src/init.o
? Where does it specified in the code?
I understand that there is the real-obj-m
variable containing exactly the value, but grep
ing the code base I did not find it depending on something...
As @Tsyvarev hinted in the comments there is a rule to build obj-m
from its -objs
.
When analyzing the behavior I mistakenly considered an implicit pattern rule to build the obj-m
which in my case is expanded to /home/memyself/lkm/procfs_write_perm/pfsw.o
. Running the build with make -p
it is possible to notice the following entry in the output:
/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)
So there is a not-implicit rule specifying a recipe to build /home/memyself/lkm/procfs_write_perm/pfsw.o
implying that the implicit rule $(obj)/%.o:
should not be considered for that specific case.
The make
database entry specified above also contains a line number of the recipe to execute and a file it came from. In this case it is
recipe to execute (from 'scripts/Makefile.build', line 474):
pointing to the scripts/Makefile.build
entry which in my case is
$(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)