Skip to content

Commit

Permalink
kbuild: unify two modpost invocations
Browse files Browse the repository at this point in the history
Currently, modpost is executed twice; first for vmlinux, second
for modules.

This commit merges them.

Current build flow
==================

  1) build obj-y and obj-m objects
    2) link vmlinux.o
      3) modpost for vmlinux
        4) link vmlinux
          5) modpost for modules
            6) link modules (*.ko)

The build steps 1) through 6) are serialized, that is, modules are
built after vmlinux. You do not get benefits of parallel builds when
scripts/link-vmlinux.sh is being run.

New build flow
==============

  1) build obj-y and obj-m objects
    2) link vmlinux.o
      3) modpost for vmlinux and modules
        4a) link vmlinux
        4b) link modules (*.ko)

In the new build flow, modpost is invoked just once.

vmlinux and modules are built in parallel. One exception is
CONFIG_DEBUG_INFO_BTF_MODULES=y, where modules depend on vmlinux.

Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
Tested-by: Nick Desaulniers <ndesaulniers@google.com>
Reviewed-by: Nicolas Schier <nicolas@fjasle.eu>
  • Loading branch information
masahir0y committed Sep 28, 2022
1 parent 9c5a0ac commit f73edc8
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 76 deletions.
32 changes: 25 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -1150,7 +1150,7 @@ cmd_link-vmlinux = \
$(CONFIG_SHELL) $< "$(LD)" "$(KBUILD_LDFLAGS)" "$(LDFLAGS_vmlinux)"; \
$(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true)

vmlinux: scripts/link-vmlinux.sh vmlinux.o $(KBUILD_LDS) FORCE
vmlinux: scripts/link-vmlinux.sh vmlinux.o $(KBUILD_LDS) modpost FORCE
+$(call if_changed_dep,link-vmlinux)

targets := vmlinux
Expand Down Expand Up @@ -1426,7 +1426,13 @@ endif
# Build modules
#

modules: $(if $(KBUILD_BUILTIN),vmlinux) modules_prepare
# *.ko are usually independent of vmlinux, but CONFIG_DEBUG_INFOBTF_MODULES
# is an exception.
ifdef CONFIG_DEBUG_INFO_BTF_MODULES
modules: vmlinux
endif

modules: modules_prepare

# Target to prepare building external modules
modules_prepare: prepare
Expand Down Expand Up @@ -1739,8 +1745,12 @@ ifdef CONFIG_MODULES
$(MODORDER): $(build-dir)
@:

modules: modules_check
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
# KBUILD_MODPOST_NOFINAL can be set to skip the final link of modules.
# This is solely useful to speed up test compiles.
modules: modpost
ifneq ($(KBUILD_MODPOST_NOFINAL),1)
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modfinal
endif

PHONY += modules_check
modules_check: $(MODORDER)
Expand Down Expand Up @@ -1771,6 +1781,11 @@ KBUILD_MODULES :=

endif # CONFIG_MODULES

PHONY += modpost
modpost: $(if $(single-build),, $(if $(KBUILD_BUILTIN), vmlinux.o)) \
$(if $(KBUILD_MODULES), modules_check)
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost

# Single targets
# ---------------------------------------------------------------------------
# To build individual files in subdirectories, you can do like this:
Expand All @@ -1790,16 +1805,19 @@ single-ko := $(sort $(filter %.ko, $(MAKECMDGOALS)))
single-no-ko := $(filter-out $(single-ko), $(MAKECMDGOALS)) \
$(foreach x, o mod, $(patsubst %.ko, %.$x, $(single-ko)))

$(single-ko): single_modpost
$(single-ko): single_modules
@:
$(single-no-ko): $(build-dir)
@:

# Remove MODORDER when done because it is not the real one.
PHONY += single_modpost
single_modpost: $(single-no-ko) modules_prepare
PHONY += single_modules
single_modules: $(single-no-ko) modules_prepare
$(Q){ $(foreach m, $(single-ko), echo $(extmod_prefix)$m;) } > $(MODORDER)
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
ifneq ($(KBUILD_MODPOST_NOFINAL),1)
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modfinal
endif
$(Q)rm -f $(MODORDER)

single-goals := $(addprefix $(build-dir)/, $(single-no-ko))
Expand Down
2 changes: 1 addition & 1 deletion scripts/Makefile.modfinal
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ if_changed_except = $(if $(call newer_prereqs_except,$(2))$(cmd-check), \
printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd, @:)

# Re-generate module BTFs if either module's .ko or vmlinux changed
$(modules): %.ko: %.o %.mod.o scripts/module.lds $(if $(KBUILD_BUILTIN),vmlinux) FORCE
$(modules): %.ko: %.o %.mod.o scripts/module.lds $(and $(CONFIG_DEBUG_INFO_BTF_MODULES),$(KBUILD_BUILTIN),vmlinux) FORCE
+$(call if_changed_except,ld_ko_o,vmlinux)
ifdef CONFIG_DEBUG_INFO_BTF_MODULES
+$(if $(newer-prereqs),$(call cmd,btf_ko))
Expand Down
93 changes: 28 additions & 65 deletions scripts/Makefile.modpost
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,6 @@
# Step 4 is solely used to allow module versioning in external modules,
# where the CRC of each module is retrieved from the Module.symvers file.

# KBUILD_MODPOST_NOFINAL can be set to skip the final link of modules.
# This is solely useful to speed up test compiles

PHONY := __modpost
__modpost:

Expand All @@ -45,24 +42,23 @@ MODPOST = scripts/mod/modpost \
$(if $(CONFIG_MODVERSIONS),-m) \
$(if $(CONFIG_MODULE_SRCVERSION_ALL),-a) \
$(if $(CONFIG_SECTION_MISMATCH_WARN_ONLY),,-E) \
$(if $(KBUILD_NSDEPS),-d $(MODULES_NSDEPS)) \
$(if $(CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS)$(KBUILD_NSDEPS),-N) \
-o $@

ifdef MODPOST_VMLINUX

quiet_cmd_modpost = MODPOST $@
cmd_modpost = $(MODPOST) $<

vmlinux.symvers: vmlinux.o
$(call cmd,modpost)
# 'make -i -k' ignores compile errors, and builds as many modules as possible.
ifneq ($(findstring i,$(filter-out --%,$(MAKEFLAGS))),)
MODPOST += -n
endif

__modpost: vmlinux.symvers
ifeq ($(KBUILD_EXTMOD),)

# Generate the list of in-tree objects in vmlinux
# ---------------------------------------------------------------------------

# This is used to retrieve symbol versions generated by genksyms.
ifdef CONFIG_MODVERSIONS
vmlinux.symvers: .vmlinux.objs
vmlinux.symvers Module.symvers: .vmlinux.objs
endif

# Ignore libgcc.a
Expand All @@ -83,24 +79,12 @@ targets += .vmlinux.objs
.vmlinux.objs: $(KBUILD_VMLINUX_OBJS) $(KBUILD_VMLINUX_LIBS) FORCE
$(call if_changed,vmlinux_objs)

else

ifeq ($(KBUILD_EXTMOD),)

input-symdump := vmlinux.symvers
output-symdump := modules-only.symvers

quiet_cmd_cat = GEN $@
cmd_cat = cat $(real-prereqs) > $@

ifneq ($(wildcard vmlinux.symvers),)

__modpost: Module.symvers
Module.symvers: vmlinux.symvers modules-only.symvers FORCE
$(call if_changed,cat)

targets += Module.symvers
vmlinux.o-if-present := $(wildcard vmlinux.o)
output-symdump := vmlinux.symvers

ifdef KBUILD_MODULES
output-symdump := $(if $(vmlinux.o-if-present), Module.symvers, modules-only.symvers)
missing-input := $(filter-out $(vmlinux.o-if-present),vmlinux.o)
endif

else
Expand All @@ -112,56 +96,35 @@ src := $(obj)
# Include the module's Makefile to find KBUILD_EXTRA_SYMBOLS
include $(or $(wildcard $(src)/Kbuild), $(src)/Makefile)

# modpost option for external modules
MODPOST += -e

input-symdump := Module.symvers $(KBUILD_EXTRA_SYMBOLS)
module.symvers-if-present := $(wildcard Module.symvers)
output-symdump := $(KBUILD_EXTMOD)/Module.symvers
missing-input := $(filter-out $(module.symvers-if-present), Module.symvers)

endif

existing-input-symdump := $(wildcard $(input-symdump))

# modpost options for modules (both in-kernel and external)
MODPOST += \
$(addprefix -i ,$(existing-input-symdump)) \
$(if $(KBUILD_NSDEPS),-d $(MODULES_NSDEPS)) \
$(if $(CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS)$(KBUILD_NSDEPS),-N)

# 'make -i -k' ignores compile errors, and builds as many modules as possible.
ifneq ($(findstring i,$(filter-out --%,$(MAKEFLAGS))),)
MODPOST += -n
endif
MODPOST += -e $(addprefix -i ,$(module.symvers-if-present) $(KBUILD_EXTRA_SYMBOLS))

# Clear VPATH to not search for *.symvers in $(srctree). Check only $(objtree).
VPATH :=
$(input-symdump):
@echo >&2 'WARNING: Symbol version dump "$@" is missing.'
@echo >&2 ' Modules may not have dependencies or modversions.'
@echo >&2 ' You may get many unresolved symbol warnings.'
endif # ($(KBUILD_EXTMOD),)

# KBUILD_MODPOST_WARN can be set to avoid error out in case of undefined symbols
ifneq ($(KBUILD_MODPOST_WARN)$(filter-out $(existing-input-symdump), $(input-symdump)),)
ifneq ($(KBUILD_MODPOST_WARN)$(missing-input),)
MODPOST += -w
endif

modorder-if-needed := $(if $(KBUILD_MODULES), $(MODORDER))

# Read out modules.order to pass in modpost.
# Otherwise, allmodconfig would fail with "Argument list too long".
quiet_cmd_modpost = MODPOST $@
cmd_modpost = sed 's/ko$$/o/' $< | $(MODPOST) -T -

$(output-symdump): $(MODORDER) $(input-symdump) FORCE
$(call if_changed,modpost)
cmd_modpost = \
$(if $(missing-input), \
echo >&2 "WARNING: $(missing-input) is missing."; \
echo >&2 " Modules may not have dependencies or modversions."; \
echo >&2 " You may get many unresolved symbol warnings.";) \
sed 's/ko$$/o/' $(or $(modorder-if-needed), /dev/null) | $(MODPOST) $(vmlinux.o-if-present) -T -

targets += $(output-symdump)
$(output-symdump): $(modorder-if-needed) $(vmlinux.o-if-present) $(moudle.symvers-if-present) FORCE
$(call if_changed,modpost)

__modpost: $(output-symdump)
ifneq ($(KBUILD_MODPOST_NOFINAL),1)
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modfinal
endif

endif

PHONY += FORCE
FORCE:

Expand Down
3 changes: 0 additions & 3 deletions scripts/link-vmlinux.sh
Original file line number Diff line number Diff line change
Expand Up @@ -214,9 +214,6 @@ if [ "$1" = "clean" ]; then
exit 0
fi

# modpost vmlinux.o to check for section mismatches
${MAKE} -f "${srctree}/scripts/Makefile.modpost" MODPOST_VMLINUX=1

info MODINFO modules.builtin.modinfo
${OBJCOPY} -j .modinfo -O binary vmlinux.o modules.builtin.modinfo
info GEN modules.builtin
Expand Down

0 comments on commit f73edc8

Please sign in to comment.