kbuild: support building external modules in a separate build directory

There has been a long-standing request to support building external
modules in a separate build directory.

This commit introduces a new environment variable, KBUILD_EXTMOD_OUTPUT,
and its shorthand Make variable, MO.

A simple usage:

 $ make -C <kernel-dir> M=<module-src-dir> MO=<module-build-dir>

Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
Reviewed-by: Nicolas Schier <nicolas@fjasle.eu>
This commit is contained in:
Masahiro Yamada 2024-11-10 10:34:35 +09:00
parent bad6beb2c0
commit 11b3d5175e
5 changed files with 35 additions and 11 deletions

View File

@ -137,12 +137,18 @@ Specify the output directory when building the kernel.
This variable can also be used to point to the kernel output directory when This variable can also be used to point to the kernel output directory when
building external modules against a pre-built kernel in a separate build building external modules against a pre-built kernel in a separate build
directory. Please note that this does NOT specify the output directory for the directory. Please note that this does NOT specify the output directory for the
external modules themselves. external modules themselves. (Use KBUILD_EXTMOD_OUTPUT for that purpose.)
The output directory can also be specified using "O=...". The output directory can also be specified using "O=...".
Setting "O=..." takes precedence over KBUILD_OUTPUT. Setting "O=..." takes precedence over KBUILD_OUTPUT.
KBUILD_EXTMOD_OUTPUT
--------------------
Specify the output directory for external modules.
Setting "MO=..." takes precedence over KBUILD_EXTMOD_OUTPUT.
KBUILD_EXTRA_WARN KBUILD_EXTRA_WARN
----------------- -----------------
Specify the extra build checks. The same value can be assigned by passing Specify the extra build checks. The same value can be assigned by passing

View File

@ -66,7 +66,10 @@ Options
of the kernel output directory if the kernel was built in a separate of the kernel output directory if the kernel was built in a separate
build directory.) build directory.)
make -C $KDIR M=$PWD You can optionally pass MO= option if you want to build the modules in
a separate directory.
make -C $KDIR M=$PWD [MO=$BUILD_DIR]
-C $KDIR -C $KDIR
The directory that contains the kernel and relevant build The directory that contains the kernel and relevant build
@ -80,6 +83,9 @@ Options
directory where the external module (kbuild file) is directory where the external module (kbuild file) is
located. located.
MO=$BUILD_DIR
Specifies a separate output directory for the external module.
Targets Targets
------- -------

View File

@ -134,6 +134,10 @@ ifeq ("$(origin M)", "command line")
KBUILD_EXTMOD := $(M) KBUILD_EXTMOD := $(M)
endif endif
ifeq ("$(origin MO)", "command line")
KBUILD_EXTMOD_OUTPUT := $(MO)
endif
$(if $(word 2, $(KBUILD_EXTMOD)), \ $(if $(word 2, $(KBUILD_EXTMOD)), \
$(error building multiple external modules is not supported)) $(error building multiple external modules is not supported))
@ -187,7 +191,7 @@ ifdef KBUILD_EXTMOD
else else
objtree := $(CURDIR) objtree := $(CURDIR)
endif endif
output := $(KBUILD_EXTMOD) output := $(or $(KBUILD_EXTMOD_OUTPUT),$(KBUILD_EXTMOD))
# KBUILD_EXTMOD might be a relative path. Remember its absolute path before # KBUILD_EXTMOD might be a relative path. Remember its absolute path before
# Make changes the working directory. # Make changes the working directory.
srcroot := $(realpath $(KBUILD_EXTMOD)) srcroot := $(realpath $(KBUILD_EXTMOD))
@ -645,6 +649,7 @@ quiet_cmd_makefile = GEN Makefile
} > Makefile } > Makefile
outputmakefile: outputmakefile:
ifeq ($(KBUILD_EXTMOD),)
@if [ -f $(srctree)/.config -o \ @if [ -f $(srctree)/.config -o \
-d $(srctree)/include/config -o \ -d $(srctree)/include/config -o \
-d $(srctree)/arch/$(SRCARCH)/include/generated ]; then \ -d $(srctree)/arch/$(SRCARCH)/include/generated ]; then \
@ -654,7 +659,16 @@ outputmakefile:
echo >&2 "***"; \ echo >&2 "***"; \
false; \ false; \
fi fi
$(Q)ln -fsn $(srctree) source else
@if [ -f $(srcroot)/modules.order ]; then \
echo >&2 "***"; \
echo >&2 "*** The external module source tree is not clean."; \
echo >&2 "*** Please run 'make -C $(abs_srctree) M=$(realpath $(srcroot)) clean'"; \
echo >&2 "***"; \
false; \
fi
endif
$(Q)ln -fsn $(srcroot) source
$(call cmd,makefile) $(call cmd,makefile)
$(Q)test -e .gitignore || \ $(Q)test -e .gitignore || \
{ echo "# this is build directory, ignore it"; echo "*"; } > .gitignore { echo "# this is build directory, ignore it"; echo "*"; } > .gitignore
@ -1940,6 +1954,8 @@ KBUILD_MODULES := 1
endif endif
prepare: outputmakefile
# Preset locale variables to speed up the build process. Limit locale # Preset locale variables to speed up the build process. Limit locale
# tweaks to this spot to avoid wrong language settings when running # tweaks to this spot to avoid wrong language settings when running
# make menuconfig etc. # make menuconfig etc.

View File

@ -96,12 +96,10 @@ hostrust_flags = --out-dir $(dir $@) --emit=dep-info=$(depfile) \
$(KBUILD_HOSTRUSTFLAGS) $(HOST_EXTRARUSTFLAGS) \ $(KBUILD_HOSTRUSTFLAGS) $(HOST_EXTRARUSTFLAGS) \
$(HOSTRUSTFLAGS_$(target-stem)) $(HOSTRUSTFLAGS_$(target-stem))
# $(objtree)/$(obj) for including generated headers from checkin source files # $(obj) for including generated headers from checkin source files
ifeq ($(KBUILD_EXTMOD),)
ifdef building_out_of_srctree ifdef building_out_of_srctree
hostc_flags += -I $(objtree)/$(obj) hostc_flags += -I $(obj)
hostcxx_flags += -I $(objtree)/$(obj) hostcxx_flags += -I $(obj)
endif
endif endif
##### #####

View File

@ -213,13 +213,11 @@ endif
# $(src) for including checkin headers from generated source files # $(src) for including checkin headers from generated source files
# $(obj) for including generated headers from checkin source files # $(obj) for including generated headers from checkin source files
ifeq ($(KBUILD_EXTMOD),)
ifdef building_out_of_srctree ifdef building_out_of_srctree
_c_flags += $(addprefix -I, $(src) $(obj)) _c_flags += $(addprefix -I, $(src) $(obj))
_a_flags += $(addprefix -I, $(src) $(obj)) _a_flags += $(addprefix -I, $(src) $(obj))
_cpp_flags += $(addprefix -I, $(src) $(obj)) _cpp_flags += $(addprefix -I, $(src) $(obj))
endif endif
endif
# If $(is-kernel-object) is 'y', this object will be linked to vmlinux or modules # If $(is-kernel-object) is 'y', this object will be linked to vmlinux or modules
is-kernel-object = $(or $(part-of-builtin),$(part-of-module)) is-kernel-object = $(or $(part-of-builtin),$(part-of-module))