0

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 greping the code base I did not find it depending on something...

St.Antario
  • 26,175
  • 41
  • 130
  • 318
  • "Why is building the target `/home/memyself/lkm/procfs_write_perm/pfsw.o` causes building `/home/memyself/lkm/procfs_write_perm/src/init.o`?" - Eh? Exactly the line `pfsw-objs := src/init.o` tells that `pfsw` module consists from `src/init.o` object. – Tsyvarev Dec 18 '19 at 16:28
  • @Tsyvarev That's right, but `pfsw-objs := src/init.o` is used to "Replace multi-part objects by their individual parts" as stated in the comments to the source code I referenced further. It results in [`real-obj-m := /home/memyself/lkm/procfs_write_perm/src/init.o`](https://github.com/torvalds/linux/blob/v5.0/scripts/Makefile.lib#L57) I did not find used anywhere as targets or prerequisites... – St.Antario Dec 18 '19 at 16:31
  • 3
    Hm, searching a string "-objs" in `scripts/Makefile.build` has found this line: `$(call multi_depend, $(multi-used-m), .o, -objs -y -m)`. It smells like exactly this line is responsible for dependency between `pfsw.o` and `init.o`. The macro `multi_depend` is defined in [scripts/Makefile.lib](https://github.com/torvalds/linux/blob/v5.0/scripts/Makefile.lib#L181). – Tsyvarev Dec 18 '19 at 16:47
  • @Tsyvarev Very likely to be so, thanks much! I checked the value of `multi-used-m`. It was `multi-used-m := /home/memyself/lkm/procfs_write_perm/pfsw.o` connecting it with `/home/memyself/lkm/procfs_write_perm/src/init.o`. If you post it as an answer I would accept it. – St.Antario Dec 18 '19 at 16:58
  • @Tsyvarev Judging by the `make -d` output this is definitely it. – St.Antario Dec 18 '19 at 17:01
  • 3
    No, I don't want to write an answer. I didn't read the KBuild makefiles in a deep manner. My comment was just a hint. Feel free to post your answer and use this hint in it. – Tsyvarev Dec 18 '19 at 19:49

1 Answers1

0

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)
St.Antario
  • 26,175
  • 41
  • 130
  • 318