Currently, Kbuild always operates in the output directory of the kernel,
even when building external modules. This increases the risk of external
module Makefiles attempting to write to the kernel directory.
This commit switches the working directory to the external module
directory, allowing the removal of the $(KBUILD_EXTMOD)/ prefix from
some build artifacts.
The command for building external modules maintains backward
compatibility, but Makefiles that rely on working in the kernel
directory may break. In such cases, $(objtree) and $(srctree) should
be used to refer to the output and source directories of the kernel.
The appearance of the build log will change as follows:
[Before]
$ make -C /path/to/my/linux M=/path/to/my/externel/module
make: Entering directory '/path/to/my/linux'
CC [M] /path/to/my/externel/module/helloworld.o
MODPOST /path/to/my/externel/module/Module.symvers
CC [M] /path/to/my/externel/module/helloworld.mod.o
CC [M] /path/to/my/externel/module/.module-common.o
LD [M] /path/to/my/externel/module/helloworld.ko
make: Leaving directory '/path/to/my/linux'
[After]
$ make -C /path/to/my/linux M=/path/to/my/externel/module
make: Entering directory '/path/to/my/linux'
make[1]: Entering directory '/path/to/my/externel/module'
CC [M] helloworld.o
MODPOST Module.symvers
CC [M] helloworld.mod.o
CC [M] .module-common.o
LD [M] helloworld.ko
make[1]: Leaving directory '/path/to/my/externel/module'
make: Leaving directory '/path/to/my/linux'
Printing "Entering directory" twice is cumbersome. This will be
addressed later.
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
---
Changes in v2:
- Introduce a new 'srcroot' variable and clean-up code
- Reword Documentation/dev-tools/coccinelle.rst
Documentation/dev-tools/coccinelle.rst | 20 ++-----
Documentation/kbuild/makefiles.rst | 14 +++++
Makefile | 80 +++++++++++++++-----------
rust/Makefile | 4 +-
scripts/Makefile.build | 2 +-
scripts/Makefile.clean | 2 +-
scripts/Makefile.compiler | 2 +-
scripts/Makefile.modpost | 6 +-
scripts/coccicheck | 6 +-
scripts/nsdeps | 8 +--
scripts/package/install-extmod-build | 7 +++
11 files changed, 85 insertions(+), 66 deletions(-)
diff --git a/Documentation/dev-tools/coccinelle.rst b/Documentation/dev-tools/coccinelle.rst
index 535ce126fb4f..6e70a1e9a3c0 100644
--- a/Documentation/dev-tools/coccinelle.rst
+++ b/Documentation/dev-tools/coccinelle.rst
@@ -250,25 +250,17 @@ variables for .cocciconfig is as follows:
- Your directory from which spatch is called is processed next
- The directory provided with the ``--dir`` option is processed last, if used
-Since coccicheck runs through make, it naturally runs from the kernel
-proper dir; as such the second rule above would be implied for picking up a
-.cocciconfig when using ``make coccicheck``.
-
``make coccicheck`` also supports using M= targets. If you do not supply
any M= target, it is assumed you want to target the entire kernel.
The kernel coccicheck script has::
- if [ "$KBUILD_EXTMOD" = "" ] ; then
- OPTIONS="--dir $srctree $COCCIINCLUDE"
- else
- OPTIONS="--dir $KBUILD_EXTMOD $COCCIINCLUDE"
- fi
+ OPTIONS="--dir $srcroot $COCCIINCLUDE"
-KBUILD_EXTMOD is set when an explicit target with M= is used. For both cases
-the spatch ``--dir`` argument is used, as such third rule applies when whether
-M= is used or not, and when M= is used the target directory can have its own
-.cocciconfig file. When M= is not passed as an argument to coccicheck the
-target directory is the same as the directory from where spatch was called.
+Here, $srcroot refers to the source directory of the target: it points to the
+external module's source directory when M= used, and otherwise, to the kernel
+source directory. The third rule ensures the spatch reads the .cocciconfig from
+the target directory, allowing external modules to have their own .cocciconfig
+file.
If not using the kernel's coccicheck target, keep the above precedence
order logic of .cocciconfig reading. If using the kernel's coccicheck target,
diff --git a/Documentation/kbuild/makefiles.rst b/Documentation/kbuild/makefiles.rst
index 7964e0c245ae..d36519f194dc 100644
--- a/Documentation/kbuild/makefiles.rst
+++ b/Documentation/kbuild/makefiles.rst
@@ -449,6 +449,20 @@ $(obj)
to prerequisites are referenced with $(src) (because they are not
generated files).
+$(srcroot)
+ $(srcroot) refers to the root of the source you are building, which can be
+ either the kernel source or the external modules source, depending on whether
+ KBUILD_EXTMOD is set. This can be either a relative or an absolute path, but
+ if KBUILD_ABS_SRCTREE=1 is set, it is always an absolute path.
+
+$(srctree)
+ $(srctree) refers to the root of the kernel source tree. When building the
+ kernel, this is the same as $(srcroot).
+
+$(objtree)
+ $(objtree) refers to the root of the kernel object tree. It is ``.`` when
+ building the kernel, but it is different when building external modules.
+
$(kecho)
echoing information to user in a rule is often a good practice
but when execution ``make -s`` one does not expect to see any output
diff --git a/Makefile b/Makefile
index cf1d55560ae2..e5f7ac7647a7 100644
--- a/Makefile
+++ b/Makefile
@@ -180,7 +180,24 @@ ifeq ("$(origin O)", "command line")
KBUILD_OUTPUT := $(O)
endif
-output := $(KBUILD_OUTPUT)
+ifdef KBUILD_EXTMOD
+ ifdef KBUILD_OUTPUT
+ objtree := $(realpath $(KBUILD_OUTPUT))
+ $(if $(objtree),,$(error specified kernel directory "$(KBUILD_OUTPUT)" does not exist))
+ else
+ objtree := $(CURDIR)
+ endif
+ output := $(KBUILD_EXTMOD)
+ # KBUILD_EXTMOD might be a relative path. Remember its absolute path before
+ # Make changes the working directory.
+ srcroot := $(realpath $(KBUILD_EXTMOD))
+ $(if $(srcroot),,$(error specified external module directory "$(KBUILD_EXTMOD)" does not exist))
+else
+ objtree := .
+ output := $(KBUILD_OUTPUT)
+endif
+
+export objtree srcroot
# Do we want to change the working directory?
ifneq ($(output),)
@@ -230,35 +247,33 @@ else # need-sub-make
# We process the rest of the Makefile if this is the final invocation of make
-ifeq ($(abs_srctree),$(CURDIR))
- # building in the source tree
- srctree := .
- building_out_of_srctree :=
+ifndef KBUILD_EXTMOD
+srcroot := $(abs_srctree)
+endif
+
+ifeq ($(srcroot),$(CURDIR))
+building_out_of_srctree :=
else
- ifeq ($(abs_srctree)/,$(dir $(CURDIR)))
- # building in a subdirectory of the source tree
- srctree := ..
- else
- srctree := $(abs_srctree)
- endif
- building_out_of_srctree := 1
+export building_out_of_srctree :=1
endif
-ifneq ($(KBUILD_ABS_SRCTREE),)
-srctree := $(abs_srctree)
+ifdef KBUILD_ABS_SRCTREE
+ # Do not nothing. Use the absolute path.
+else ifeq ($(srcroot),$(CURDIR))
+ # Building in the source.
+ srcroot := .
+else ifeq ($(srcroot)/,$(dir $(CURDIR)))
+ # Building in a subdirectory of the source.
+ srcroot := ..
endif
-objtree := .
+export srctree := $(if $(KBUILD_EXTMOD),$(abs_srctree),$(srcroot))
-VPATH :=
-
-ifeq ($(KBUILD_EXTMOD),)
ifdef building_out_of_srctree
-VPATH := $(srctree)
+export VPATH := $(srcroot)
+else
+VPATH :=
endif
-endif
-
-export building_out_of_srctree srctree objtree VPATH
# To make sure we do not include .config for any of the *config targets
# catch them early, and hand them over to scripts/kconfig/Makefile
@@ -711,7 +726,7 @@ endif
# in addition to whatever we do anyway.
# Just "make" or "make all" shall build modules as well
-ifneq ($(filter all modules nsdeps %compile_commands.json clang-%,$(MAKECMDGOALS)),)
+ifneq ($(filter all modules nsdeps compile_commands.json clang-%,$(MAKECMDGOALS)),)
KBUILD_MODULES := 1
endif
@@ -1107,7 +1122,7 @@ export MODLIB
PHONY += prepare0
-export extmod_prefix = $(if $(KBUILD_EXTMOD),$(KBUILD_EXTMOD)/)
+export extmod_prefix =
export MODORDER := $(extmod_prefix)modules.order
export MODULES_NSDEPS := $(extmod_prefix)modules.nsdeps
@@ -1799,14 +1814,10 @@ filechk_kernel.release = echo $(KERNELRELEASE)
KBUILD_BUILTIN :=
KBUILD_MODULES := 1
-build-dir := $(KBUILD_EXTMOD)
+build-dir := .
-compile_commands.json: $(extmod_prefix)compile_commands.json
-PHONY += compile_commands.json
-
-clean-dirs := $(KBUILD_EXTMOD)
-clean: private rm-files := $(KBUILD_EXTMOD)/Module.symvers $(KBUILD_EXTMOD)/modules.nsdeps \
- $(KBUILD_EXTMOD)/compile_commands.json
+clean-dirs := .
+clean: private rm-files := Module.symvers modules.nsdeps compile_commands.json
PHONY += prepare
# now expand this into a simple variable to reduce the cost of shell evaluations
@@ -1948,7 +1959,7 @@ $(clean-dirs):
clean: $(clean-dirs)
$(call cmd,rmfiles)
- @find $(or $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \
+ @find . $(RCS_FIND_IGNORE) \
\( -name '*.[aios]' -o -name '*.rsi' -o -name '*.ko' -o -name '.*.cmd' \
-o -name '*.ko.*' \
-o -name '*.dtb' -o -name '*.dtbo' \
@@ -1981,7 +1992,12 @@ tags TAGS cscope gtags: FORCE
PHONY += rust-analyzer
rust-analyzer:
+$(Q)$(CONFIG_SHELL) $(srctree)/scripts/rust_is_available.sh
+ifdef KBUILD_EXTMOD
+# FIXME: external modules must not descend into a sub-directory of the kernel
+ $(Q)$(MAKE) $(build)=$(objtree)/rust src=$(srctree)/rust $@
+else
$(Q)$(MAKE) $(build)=rust $@
+endif
# Script to generate missing namespace dependencies
# ---------------------------------------------------------------------------
diff --git a/rust/Makefile b/rust/Makefile
index b5e0a73b78f3..742740816c4b 100644
--- a/rust/Makefile
+++ b/rust/Makefile
@@ -362,8 +362,8 @@ rust-analyzer:
$(Q)$(srctree)/scripts/generate_rust_analyzer.py \
--cfgs='core=$(core-cfgs)' --cfgs='alloc=$(alloc-cfgs)' \
$(realpath $(srctree)) $(realpath $(objtree)) \
- $(rustc_sysroot) $(RUST_LIB_SRC) $(KBUILD_EXTMOD) > \
- $(if $(KBUILD_EXTMOD),$(extmod_prefix),$(objtree))/rust-project.json
+ $(rustc_sysroot) $(RUST_LIB_SRC) $(if $(KBUILD_EXTMOD),$(srcroot)) \
+ > rust-project.json
redirect-intrinsics = \
__addsf3 __eqsf2 __extendsfdf2 __gesf2 __lesf2 __ltsf2 __mulsf3 __nesf2 __truncdfsf2 __unordsf2 \
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 64cd046f8fd8..1aa928a6fb4f 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -3,7 +3,7 @@
# Building
# ==========================================================================
-src := $(if $(VPATH),$(VPATH)/)$(obj)
+src := $(srcroot)/$(obj)
PHONY := $(obj)/
$(obj)/:
diff --git a/scripts/Makefile.clean b/scripts/Makefile.clean
index 4fcfab40ed61..6ead00ec7313 100644
--- a/scripts/Makefile.clean
+++ b/scripts/Makefile.clean
@@ -3,7 +3,7 @@
# Cleaning up
# ==========================================================================
-src := $(if $(VPATH),$(VPATH)/)$(obj)
+src := $(srcroot)/$(obj)
PHONY := __clean
__clean:
diff --git a/scripts/Makefile.compiler b/scripts/Makefile.compiler
index e0842496d26e..8c1029687e2e 100644
--- a/scripts/Makefile.compiler
+++ b/scripts/Makefile.compiler
@@ -13,7 +13,7 @@ cc-cross-prefix = $(firstword $(foreach c, $(1), \
$(if $(shell command -v -- $(c)gcc 2>/dev/null), $(c))))
# output directory for tests below
-TMPOUT = $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/).tmp_$$$$
+TMPOUT = .tmp_$$$$
# try-run
# Usage: option = $(call try-run, $(CC)...-o "$$TMP",option-ok,otherwise)
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
index 12e7c15d099c..78d2ca4f25f5 100644
--- a/scripts/Makefile.modpost
+++ b/scripts/Makefile.modpost
@@ -111,13 +111,13 @@ endif
else
# set src + obj - they may be used in the modules's Makefile
-obj := $(KBUILD_EXTMOD)
-src := $(if $(VPATH),$(VPATH)/)$(obj)
+obj := .
+src := $(srcroot)
# Include the module's Makefile to find KBUILD_EXTRA_SYMBOLS
include $(kbuild-file)
-output-symdump := $(KBUILD_EXTMOD)/Module.symvers
+output-symdump := Module.symvers
ifeq ($(wildcard $(objtree)/Module.symvers),)
missing-input := $(objtree)/Module.symvers
diff --git a/scripts/coccicheck b/scripts/coccicheck
index e52cb43fede6..0e6bc5a10320 100755
--- a/scripts/coccicheck
+++ b/scripts/coccicheck
@@ -80,11 +80,7 @@ command results in a shift count error.'
NPROC=1
else
ONLINE=0
- if [ "$KBUILD_EXTMOD" = "" ] ; then
- OPTIONS="--dir $srctree $COCCIINCLUDE"
- else
- OPTIONS="--dir $KBUILD_EXTMOD $COCCIINCLUDE"
- fi
+ OPTIONS="--dir $srcroot $COCCIINCLUDE"
# Use only one thread per core by default if hyperthreading is enabled
THREADS_PER_CORE=$(LANG=C lscpu | grep "Thread(s) per core: " | tr -cd "[:digit:]")
diff --git a/scripts/nsdeps b/scripts/nsdeps
index f1718cc0d700..8ca12e2b5c03 100644
--- a/scripts/nsdeps
+++ b/scripts/nsdeps
@@ -19,12 +19,6 @@ if ! { echo "$SPATCH_REQ_VERSION"; echo "$SPATCH_VERSION"; } | sort -CV ; then
exit 1
fi
-if [ "$KBUILD_EXTMOD" ]; then
- src_prefix=
-else
- src_prefix=$srctree/
-fi
-
generate_deps_for_ns() {
$SPATCH --very-quiet --in-place --sp-file \
$srctree/scripts/coccinelle/misc/add_namespace.cocci -D nsdeps -D ns=$1 $2
@@ -34,7 +28,7 @@ generate_deps() {
local mod=${1%.ko:}
shift
local namespaces="$*"
- local mod_source_files=$(sed "s|^\(.*\)\.o$|${src_prefix}\1.c|" $mod.mod)
+ local mod_source_files=$(sed "s|^\(.*\)\.o$|${srcroot}/\1.c|" $mod.mod)
for ns in $namespaces; do
echo "Adding namespace $ns to module $mod.ko."
diff --git a/scripts/package/install-extmod-build b/scripts/package/install-extmod-build
index 7ec1f061a519..64d958ee45f3 100755
--- a/scripts/package/install-extmod-build
+++ b/scripts/package/install-extmod-build
@@ -51,6 +51,13 @@ mkdir -p "${destdir}"
if [ "${CC}" != "${HOSTCC}" ]; then
echo "Rebuilding host programs with ${CC}..."
+ # This leverages external module building.
+ # - Clear sub_make_done to allow the top-level Makefile to redo sub-make.
+ # - Filter out --no-print-directory to print "Entering directory" logs
+ # when Make changes the working directory.
+ unset sub_make_done
+ MAKEFLAGS=$(echo "${MAKEFLAGS}" | sed s/--no-print-directory//)
+
cat <<-'EOF' > "${destdir}/Kbuild"
subdir-y := scripts
EOF
--
2.43.0
Hi Masahiro-san,
Thanks for your contribution, but it looks like this is breaking quite
some vim/nvim quick fixes.
If there is some compiling errors/warnings, the path will be the one
inside the module directory, no matter if it's out-of-tree or upstreamed.
Is there anyway to get back the full filename so that vim/nvim quick fix
can work again?
Thanks,
Qu
在 2024/11/10 12:04, Masahiro Yamada 写道:
> Currently, Kbuild always operates in the output directory of the kernel,
> even when building external modules. This increases the risk of external
> module Makefiles attempting to write to the kernel directory.
>
> This commit switches the working directory to the external module
> directory, allowing the removal of the $(KBUILD_EXTMOD)/ prefix from
> some build artifacts.
>
> The command for building external modules maintains backward
> compatibility, but Makefiles that rely on working in the kernel
> directory may break. In such cases, $(objtree) and $(srctree) should
> be used to refer to the output and source directories of the kernel.
>
> The appearance of the build log will change as follows:
>
> [Before]
>
> $ make -C /path/to/my/linux M=/path/to/my/externel/module
> make: Entering directory '/path/to/my/linux'
> CC [M] /path/to/my/externel/module/helloworld.o
> MODPOST /path/to/my/externel/module/Module.symvers
> CC [M] /path/to/my/externel/module/helloworld.mod.o
> CC [M] /path/to/my/externel/module/.module-common.o
> LD [M] /path/to/my/externel/module/helloworld.ko
> make: Leaving directory '/path/to/my/linux'
>
> [After]
>
> $ make -C /path/to/my/linux M=/path/to/my/externel/module
> make: Entering directory '/path/to/my/linux'
> make[1]: Entering directory '/path/to/my/externel/module'
> CC [M] helloworld.o
> MODPOST Module.symvers
> CC [M] helloworld.mod.o
> CC [M] .module-common.o
> LD [M] helloworld.ko
> make[1]: Leaving directory '/path/to/my/externel/module'
> make: Leaving directory '/path/to/my/linux'
>
> Printing "Entering directory" twice is cumbersome. This will be
> addressed later.
>
> Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
> ---
>
> Changes in v2:
> - Introduce a new 'srcroot' variable and clean-up code
> - Reword Documentation/dev-tools/coccinelle.rst
>
> Documentation/dev-tools/coccinelle.rst | 20 ++-----
> Documentation/kbuild/makefiles.rst | 14 +++++
> Makefile | 80 +++++++++++++++-----------
> rust/Makefile | 4 +-
> scripts/Makefile.build | 2 +-
> scripts/Makefile.clean | 2 +-
> scripts/Makefile.compiler | 2 +-
> scripts/Makefile.modpost | 6 +-
> scripts/coccicheck | 6 +-
> scripts/nsdeps | 8 +--
> scripts/package/install-extmod-build | 7 +++
> 11 files changed, 85 insertions(+), 66 deletions(-)
>
> diff --git a/Documentation/dev-tools/coccinelle.rst b/Documentation/dev-tools/coccinelle.rst
> index 535ce126fb4f..6e70a1e9a3c0 100644
> --- a/Documentation/dev-tools/coccinelle.rst
> +++ b/Documentation/dev-tools/coccinelle.rst
> @@ -250,25 +250,17 @@ variables for .cocciconfig is as follows:
> - Your directory from which spatch is called is processed next
> - The directory provided with the ``--dir`` option is processed last, if used
>
> -Since coccicheck runs through make, it naturally runs from the kernel
> -proper dir; as such the second rule above would be implied for picking up a
> -.cocciconfig when using ``make coccicheck``.
> -
> ``make coccicheck`` also supports using M= targets. If you do not supply
> any M= target, it is assumed you want to target the entire kernel.
> The kernel coccicheck script has::
>
> - if [ "$KBUILD_EXTMOD" = "" ] ; then
> - OPTIONS="--dir $srctree $COCCIINCLUDE"
> - else
> - OPTIONS="--dir $KBUILD_EXTMOD $COCCIINCLUDE"
> - fi
> + OPTIONS="--dir $srcroot $COCCIINCLUDE"
>
> -KBUILD_EXTMOD is set when an explicit target with M= is used. For both cases
> -the spatch ``--dir`` argument is used, as such third rule applies when whether
> -M= is used or not, and when M= is used the target directory can have its own
> -.cocciconfig file. When M= is not passed as an argument to coccicheck the
> -target directory is the same as the directory from where spatch was called.
> +Here, $srcroot refers to the source directory of the target: it points to the
> +external module's source directory when M= used, and otherwise, to the kernel
> +source directory. The third rule ensures the spatch reads the .cocciconfig from
> +the target directory, allowing external modules to have their own .cocciconfig
> +file.
>
> If not using the kernel's coccicheck target, keep the above precedence
> order logic of .cocciconfig reading. If using the kernel's coccicheck target,
> diff --git a/Documentation/kbuild/makefiles.rst b/Documentation/kbuild/makefiles.rst
> index 7964e0c245ae..d36519f194dc 100644
> --- a/Documentation/kbuild/makefiles.rst
> +++ b/Documentation/kbuild/makefiles.rst
> @@ -449,6 +449,20 @@ $(obj)
> to prerequisites are referenced with $(src) (because they are not
> generated files).
>
> +$(srcroot)
> + $(srcroot) refers to the root of the source you are building, which can be
> + either the kernel source or the external modules source, depending on whether
> + KBUILD_EXTMOD is set. This can be either a relative or an absolute path, but
> + if KBUILD_ABS_SRCTREE=1 is set, it is always an absolute path.
> +
> +$(srctree)
> + $(srctree) refers to the root of the kernel source tree. When building the
> + kernel, this is the same as $(srcroot).
> +
> +$(objtree)
> + $(objtree) refers to the root of the kernel object tree. It is ``.`` when
> + building the kernel, but it is different when building external modules.
> +
> $(kecho)
> echoing information to user in a rule is often a good practice
> but when execution ``make -s`` one does not expect to see any output
> diff --git a/Makefile b/Makefile
> index cf1d55560ae2..e5f7ac7647a7 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -180,7 +180,24 @@ ifeq ("$(origin O)", "command line")
> KBUILD_OUTPUT := $(O)
> endif
>
> -output := $(KBUILD_OUTPUT)
> +ifdef KBUILD_EXTMOD
> + ifdef KBUILD_OUTPUT
> + objtree := $(realpath $(KBUILD_OUTPUT))
> + $(if $(objtree),,$(error specified kernel directory "$(KBUILD_OUTPUT)" does not exist))
> + else
> + objtree := $(CURDIR)
> + endif
> + output := $(KBUILD_EXTMOD)
> + # KBUILD_EXTMOD might be a relative path. Remember its absolute path before
> + # Make changes the working directory.
> + srcroot := $(realpath $(KBUILD_EXTMOD))
> + $(if $(srcroot),,$(error specified external module directory "$(KBUILD_EXTMOD)" does not exist))
> +else
> + objtree := .
> + output := $(KBUILD_OUTPUT)
> +endif
> +
> +export objtree srcroot
>
> # Do we want to change the working directory?
> ifneq ($(output),)
> @@ -230,35 +247,33 @@ else # need-sub-make
>
> # We process the rest of the Makefile if this is the final invocation of make
>
> -ifeq ($(abs_srctree),$(CURDIR))
> - # building in the source tree
> - srctree := .
> - building_out_of_srctree :=
> +ifndef KBUILD_EXTMOD
> +srcroot := $(abs_srctree)
> +endif
> +
> +ifeq ($(srcroot),$(CURDIR))
> +building_out_of_srctree :=
> else
> - ifeq ($(abs_srctree)/,$(dir $(CURDIR)))
> - # building in a subdirectory of the source tree
> - srctree := ..
> - else
> - srctree := $(abs_srctree)
> - endif
> - building_out_of_srctree := 1
> +export building_out_of_srctree :=1
> endif
>
> -ifneq ($(KBUILD_ABS_SRCTREE),)
> -srctree := $(abs_srctree)
> +ifdef KBUILD_ABS_SRCTREE
> + # Do not nothing. Use the absolute path.
> +else ifeq ($(srcroot),$(CURDIR))
> + # Building in the source.
> + srcroot := .
> +else ifeq ($(srcroot)/,$(dir $(CURDIR)))
> + # Building in a subdirectory of the source.
> + srcroot := ..
> endif
>
> -objtree := .
> +export srctree := $(if $(KBUILD_EXTMOD),$(abs_srctree),$(srcroot))
>
> -VPATH :=
> -
> -ifeq ($(KBUILD_EXTMOD),)
> ifdef building_out_of_srctree
> -VPATH := $(srctree)
> +export VPATH := $(srcroot)
> +else
> +VPATH :=
> endif
> -endif
> -
> -export building_out_of_srctree srctree objtree VPATH
>
> # To make sure we do not include .config for any of the *config targets
> # catch them early, and hand them over to scripts/kconfig/Makefile
> @@ -711,7 +726,7 @@ endif
> # in addition to whatever we do anyway.
> # Just "make" or "make all" shall build modules as well
>
> -ifneq ($(filter all modules nsdeps %compile_commands.json clang-%,$(MAKECMDGOALS)),)
> +ifneq ($(filter all modules nsdeps compile_commands.json clang-%,$(MAKECMDGOALS)),)
> KBUILD_MODULES := 1
> endif
>
> @@ -1107,7 +1122,7 @@ export MODLIB
>
> PHONY += prepare0
>
> -export extmod_prefix = $(if $(KBUILD_EXTMOD),$(KBUILD_EXTMOD)/)
> +export extmod_prefix =
> export MODORDER := $(extmod_prefix)modules.order
> export MODULES_NSDEPS := $(extmod_prefix)modules.nsdeps
>
> @@ -1799,14 +1814,10 @@ filechk_kernel.release = echo $(KERNELRELEASE)
> KBUILD_BUILTIN :=
> KBUILD_MODULES := 1
>
> -build-dir := $(KBUILD_EXTMOD)
> +build-dir := .
>
> -compile_commands.json: $(extmod_prefix)compile_commands.json
> -PHONY += compile_commands.json
> -
> -clean-dirs := $(KBUILD_EXTMOD)
> -clean: private rm-files := $(KBUILD_EXTMOD)/Module.symvers $(KBUILD_EXTMOD)/modules.nsdeps \
> - $(KBUILD_EXTMOD)/compile_commands.json
> +clean-dirs := .
> +clean: private rm-files := Module.symvers modules.nsdeps compile_commands.json
>
> PHONY += prepare
> # now expand this into a simple variable to reduce the cost of shell evaluations
> @@ -1948,7 +1959,7 @@ $(clean-dirs):
>
> clean: $(clean-dirs)
> $(call cmd,rmfiles)
> - @find $(or $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \
> + @find . $(RCS_FIND_IGNORE) \
> \( -name '*.[aios]' -o -name '*.rsi' -o -name '*.ko' -o -name '.*.cmd' \
> -o -name '*.ko.*' \
> -o -name '*.dtb' -o -name '*.dtbo' \
> @@ -1981,7 +1992,12 @@ tags TAGS cscope gtags: FORCE
> PHONY += rust-analyzer
> rust-analyzer:
> +$(Q)$(CONFIG_SHELL) $(srctree)/scripts/rust_is_available.sh
> +ifdef KBUILD_EXTMOD
> +# FIXME: external modules must not descend into a sub-directory of the kernel
> + $(Q)$(MAKE) $(build)=$(objtree)/rust src=$(srctree)/rust $@
> +else
> $(Q)$(MAKE) $(build)=rust $@
> +endif
>
> # Script to generate missing namespace dependencies
> # ---------------------------------------------------------------------------
> diff --git a/rust/Makefile b/rust/Makefile
> index b5e0a73b78f3..742740816c4b 100644
> --- a/rust/Makefile
> +++ b/rust/Makefile
> @@ -362,8 +362,8 @@ rust-analyzer:
> $(Q)$(srctree)/scripts/generate_rust_analyzer.py \
> --cfgs='core=$(core-cfgs)' --cfgs='alloc=$(alloc-cfgs)' \
> $(realpath $(srctree)) $(realpath $(objtree)) \
> - $(rustc_sysroot) $(RUST_LIB_SRC) $(KBUILD_EXTMOD) > \
> - $(if $(KBUILD_EXTMOD),$(extmod_prefix),$(objtree))/rust-project.json
> + $(rustc_sysroot) $(RUST_LIB_SRC) $(if $(KBUILD_EXTMOD),$(srcroot)) \
> + > rust-project.json
>
> redirect-intrinsics = \
> __addsf3 __eqsf2 __extendsfdf2 __gesf2 __lesf2 __ltsf2 __mulsf3 __nesf2 __truncdfsf2 __unordsf2 \
> diff --git a/scripts/Makefile.build b/scripts/Makefile.build
> index 64cd046f8fd8..1aa928a6fb4f 100644
> --- a/scripts/Makefile.build
> +++ b/scripts/Makefile.build
> @@ -3,7 +3,7 @@
> # Building
> # ==========================================================================
>
> -src := $(if $(VPATH),$(VPATH)/)$(obj)
> +src := $(srcroot)/$(obj)
>
> PHONY := $(obj)/
> $(obj)/:
> diff --git a/scripts/Makefile.clean b/scripts/Makefile.clean
> index 4fcfab40ed61..6ead00ec7313 100644
> --- a/scripts/Makefile.clean
> +++ b/scripts/Makefile.clean
> @@ -3,7 +3,7 @@
> # Cleaning up
> # ==========================================================================
>
> -src := $(if $(VPATH),$(VPATH)/)$(obj)
> +src := $(srcroot)/$(obj)
>
> PHONY := __clean
> __clean:
> diff --git a/scripts/Makefile.compiler b/scripts/Makefile.compiler
> index e0842496d26e..8c1029687e2e 100644
> --- a/scripts/Makefile.compiler
> +++ b/scripts/Makefile.compiler
> @@ -13,7 +13,7 @@ cc-cross-prefix = $(firstword $(foreach c, $(1), \
> $(if $(shell command -v -- $(c)gcc 2>/dev/null), $(c))))
>
> # output directory for tests below
> -TMPOUT = $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/).tmp_$$$$
> +TMPOUT = .tmp_$$$$
>
> # try-run
> # Usage: option = $(call try-run, $(CC)...-o "$$TMP",option-ok,otherwise)
> diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
> index 12e7c15d099c..78d2ca4f25f5 100644
> --- a/scripts/Makefile.modpost
> +++ b/scripts/Makefile.modpost
> @@ -111,13 +111,13 @@ endif
> else
>
> # set src + obj - they may be used in the modules's Makefile
> -obj := $(KBUILD_EXTMOD)
> -src := $(if $(VPATH),$(VPATH)/)$(obj)
> +obj := .
> +src := $(srcroot)
>
> # Include the module's Makefile to find KBUILD_EXTRA_SYMBOLS
> include $(kbuild-file)
>
> -output-symdump := $(KBUILD_EXTMOD)/Module.symvers
> +output-symdump := Module.symvers
>
> ifeq ($(wildcard $(objtree)/Module.symvers),)
> missing-input := $(objtree)/Module.symvers
> diff --git a/scripts/coccicheck b/scripts/coccicheck
> index e52cb43fede6..0e6bc5a10320 100755
> --- a/scripts/coccicheck
> +++ b/scripts/coccicheck
> @@ -80,11 +80,7 @@ command results in a shift count error.'
> NPROC=1
> else
> ONLINE=0
> - if [ "$KBUILD_EXTMOD" = "" ] ; then
> - OPTIONS="--dir $srctree $COCCIINCLUDE"
> - else
> - OPTIONS="--dir $KBUILD_EXTMOD $COCCIINCLUDE"
> - fi
> + OPTIONS="--dir $srcroot $COCCIINCLUDE"
>
> # Use only one thread per core by default if hyperthreading is enabled
> THREADS_PER_CORE=$(LANG=C lscpu | grep "Thread(s) per core: " | tr -cd "[:digit:]")
> diff --git a/scripts/nsdeps b/scripts/nsdeps
> index f1718cc0d700..8ca12e2b5c03 100644
> --- a/scripts/nsdeps
> +++ b/scripts/nsdeps
> @@ -19,12 +19,6 @@ if ! { echo "$SPATCH_REQ_VERSION"; echo "$SPATCH_VERSION"; } | sort -CV ; then
> exit 1
> fi
>
> -if [ "$KBUILD_EXTMOD" ]; then
> - src_prefix=
> -else
> - src_prefix=$srctree/
> -fi
> -
> generate_deps_for_ns() {
> $SPATCH --very-quiet --in-place --sp-file \
> $srctree/scripts/coccinelle/misc/add_namespace.cocci -D nsdeps -D ns=$1 $2
> @@ -34,7 +28,7 @@ generate_deps() {
> local mod=${1%.ko:}
> shift
> local namespaces="$*"
> - local mod_source_files=$(sed "s|^\(.*\)\.o$|${src_prefix}\1.c|" $mod.mod)
> + local mod_source_files=$(sed "s|^\(.*\)\.o$|${srcroot}/\1.c|" $mod.mod)
>
> for ns in $namespaces; do
> echo "Adding namespace $ns to module $mod.ko."
> diff --git a/scripts/package/install-extmod-build b/scripts/package/install-extmod-build
> index 7ec1f061a519..64d958ee45f3 100755
> --- a/scripts/package/install-extmod-build
> +++ b/scripts/package/install-extmod-build
> @@ -51,6 +51,13 @@ mkdir -p "${destdir}"
> if [ "${CC}" != "${HOSTCC}" ]; then
> echo "Rebuilding host programs with ${CC}..."
>
> + # This leverages external module building.
> + # - Clear sub_make_done to allow the top-level Makefile to redo sub-make.
> + # - Filter out --no-print-directory to print "Entering directory" logs
> + # when Make changes the working directory.
> + unset sub_make_done
> + MAKEFLAGS=$(echo "${MAKEFLAGS}" | sed s/--no-print-directory//)
> +
> cat <<-'EOF' > "${destdir}/Kbuild"
> subdir-y := scripts
> EOF
Hi Masahiro,
On 10/11/2024 01:34, Masahiro Yamada wrote:
> Currently, Kbuild always operates in the output directory of the kernel,
> even when building external modules. This increases the risk of external
> module Makefiles attempting to write to the kernel directory.
>
> This commit switches the working directory to the external module
> directory, allowing the removal of the $(KBUILD_EXTMOD)/ prefix from
> some build artifacts.
>
> The command for building external modules maintains backward
> compatibility, but Makefiles that rely on working in the kernel
> directory may break. In such cases, $(objtree) and $(srctree) should
> be used to refer to the output and source directories of the kernel.
>
> The appearance of the build log will change as follows:
>
> [Before]
>
> $ make -C /path/to/my/linux M=/path/to/my/externel/module
> make: Entering directory '/path/to/my/linux'
> CC [M] /path/to/my/externel/module/helloworld.o
> MODPOST /path/to/my/externel/module/Module.symvers
> CC [M] /path/to/my/externel/module/helloworld.mod.o
> CC [M] /path/to/my/externel/module/.module-common.o
> LD [M] /path/to/my/externel/module/helloworld.ko
> make: Leaving directory '/path/to/my/linux'
>
> [After]
>
> $ make -C /path/to/my/linux M=/path/to/my/externel/module
> make: Entering directory '/path/to/my/linux'
> make[1]: Entering directory '/path/to/my/externel/module'
> CC [M] helloworld.o
> MODPOST Module.symvers
> CC [M] helloworld.mod.o
> CC [M] .module-common.o
> LD [M] helloworld.ko
> make[1]: Leaving directory '/path/to/my/externel/module'
> make: Leaving directory '/path/to/my/linux'
>
> Printing "Entering directory" twice is cumbersome. This will be
> addressed later.
>
> Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
Since this change I have been observing the following build error when
building an external module ...
MODPOST Module.symvers
ERROR: modpost: drivers/gpu/host1x/host1x: 'host1x_device_init' exported
twice. Previous export was in drivers/gpu/host1x/host1x.ko
ERROR: modpost: drivers/gpu/host1x/host1x: 'host1x_device_exit' exported
twice. Previous export was in drivers/gpu/host1x/host1x.ko
Now host1x is an upstream driver, but I have a local copy that using to
stage development changes (and avoid polluting the upstream driver).
Plus I can swap between which version I am using on a live system.
What I noticed is that previously the Modules.symvers for the external
module had the full path of the external module for the name. However,
now the name is just the relative path and in this case
'drivers/gpu/host1x/host1x'. Hence, this clashes with the in-kernel
driver and we get the 'exported twice' error.
I have been looking to see if there is a way to fix this because it has
been a useful feature to override an upstream driver with a locally
modified version.
Thanks
Jon
--
nvpublic
On Wed, Dec 11, 2024 at 12:34 AM Jon Hunter <jonathanh@nvidia.com> wrote:
>
> Hi Masahiro,
>
> On 10/11/2024 01:34, Masahiro Yamada wrote:
> > Currently, Kbuild always operates in the output directory of the kernel,
> > even when building external modules. This increases the risk of external
> > module Makefiles attempting to write to the kernel directory.
> >
> > This commit switches the working directory to the external module
> > directory, allowing the removal of the $(KBUILD_EXTMOD)/ prefix from
> > some build artifacts.
> >
> > The command for building external modules maintains backward
> > compatibility, but Makefiles that rely on working in the kernel
> > directory may break. In such cases, $(objtree) and $(srctree) should
> > be used to refer to the output and source directories of the kernel.
> >
> > The appearance of the build log will change as follows:
> >
> > [Before]
> >
> > $ make -C /path/to/my/linux M=/path/to/my/externel/module
> > make: Entering directory '/path/to/my/linux'
> > CC [M] /path/to/my/externel/module/helloworld.o
> > MODPOST /path/to/my/externel/module/Module.symvers
> > CC [M] /path/to/my/externel/module/helloworld.mod.o
> > CC [M] /path/to/my/externel/module/.module-common.o
> > LD [M] /path/to/my/externel/module/helloworld.ko
> > make: Leaving directory '/path/to/my/linux'
> >
> > [After]
> >
> > $ make -C /path/to/my/linux M=/path/to/my/externel/module
> > make: Entering directory '/path/to/my/linux'
> > make[1]: Entering directory '/path/to/my/externel/module'
> > CC [M] helloworld.o
> > MODPOST Module.symvers
> > CC [M] helloworld.mod.o
> > CC [M] .module-common.o
> > LD [M] helloworld.ko
> > make[1]: Leaving directory '/path/to/my/externel/module'
> > make: Leaving directory '/path/to/my/linux'
> >
> > Printing "Entering directory" twice is cumbersome. This will be
> > addressed later.
> >
> > Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
>
>
> Since this change I have been observing the following build error when
> building an external module ...
>
> MODPOST Module.symvers
> ERROR: modpost: drivers/gpu/host1x/host1x: 'host1x_device_init' exported
> twice. Previous export was in drivers/gpu/host1x/host1x.ko
> ERROR: modpost: drivers/gpu/host1x/host1x: 'host1x_device_exit' exported
> twice. Previous export was in drivers/gpu/host1x/host1x.ko
>
> Now host1x is an upstream driver, but I have a local copy that using to
> stage development changes (and avoid polluting the upstream driver).
> Plus I can swap between which version I am using on a live system.
>
> What I noticed is that previously the Modules.symvers for the external
> module had the full path of the external module for the name. However,
> now the name is just the relative path and in this case
> 'drivers/gpu/host1x/host1x'. Hence, this clashes with the in-kernel
> driver and we get the 'exported twice' error.
>
> I have been looking to see if there is a way to fix this because it has
> been a useful feature to override an upstream driver with a locally
> modified version.
I do not know how to reproduce it.
if (s && (!external_module || s->module->is_vmlinux || s->module == mod)) {
is not checking the module path at all.
I do not understand why it was affected.
--
Best Regards
Masahiro Yamada
On 11/12/2024 02:39, Masahiro Yamada wrote:
> On Wed, Dec 11, 2024 at 12:34 AM Jon Hunter <jonathanh@nvidia.com> wrote:
>>
>> Hi Masahiro,
>>
>> On 10/11/2024 01:34, Masahiro Yamada wrote:
>>> Currently, Kbuild always operates in the output directory of the kernel,
>>> even when building external modules. This increases the risk of external
>>> module Makefiles attempting to write to the kernel directory.
>>>
>>> This commit switches the working directory to the external module
>>> directory, allowing the removal of the $(KBUILD_EXTMOD)/ prefix from
>>> some build artifacts.
>>>
>>> The command for building external modules maintains backward
>>> compatibility, but Makefiles that rely on working in the kernel
>>> directory may break. In such cases, $(objtree) and $(srctree) should
>>> be used to refer to the output and source directories of the kernel.
>>>
>>> The appearance of the build log will change as follows:
>>>
>>> [Before]
>>>
>>> $ make -C /path/to/my/linux M=/path/to/my/externel/module
>>> make: Entering directory '/path/to/my/linux'
>>> CC [M] /path/to/my/externel/module/helloworld.o
>>> MODPOST /path/to/my/externel/module/Module.symvers
>>> CC [M] /path/to/my/externel/module/helloworld.mod.o
>>> CC [M] /path/to/my/externel/module/.module-common.o
>>> LD [M] /path/to/my/externel/module/helloworld.ko
>>> make: Leaving directory '/path/to/my/linux'
>>>
>>> [After]
>>>
>>> $ make -C /path/to/my/linux M=/path/to/my/externel/module
>>> make: Entering directory '/path/to/my/linux'
>>> make[1]: Entering directory '/path/to/my/externel/module'
>>> CC [M] helloworld.o
>>> MODPOST Module.symvers
>>> CC [M] helloworld.mod.o
>>> CC [M] .module-common.o
>>> LD [M] helloworld.ko
>>> make[1]: Leaving directory '/path/to/my/externel/module'
>>> make: Leaving directory '/path/to/my/linux'
>>>
>>> Printing "Entering directory" twice is cumbersome. This will be
>>> addressed later.
>>>
>>> Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
>>
>>
>> Since this change I have been observing the following build error when
>> building an external module ...
>>
>> MODPOST Module.symvers
>> ERROR: modpost: drivers/gpu/host1x/host1x: 'host1x_device_init' exported
>> twice. Previous export was in drivers/gpu/host1x/host1x.ko
>> ERROR: modpost: drivers/gpu/host1x/host1x: 'host1x_device_exit' exported
>> twice. Previous export was in drivers/gpu/host1x/host1x.ko
>>
>> Now host1x is an upstream driver, but I have a local copy that using to
>> stage development changes (and avoid polluting the upstream driver).
>> Plus I can swap between which version I am using on a live system.
>>
>> What I noticed is that previously the Modules.symvers for the external
>> module had the full path of the external module for the name. However,
>> now the name is just the relative path and in this case
>> 'drivers/gpu/host1x/host1x'. Hence, this clashes with the in-kernel
>> driver and we get the 'exported twice' error.
>>
>> I have been looking to see if there is a way to fix this because it has
>> been a useful feature to override an upstream driver with a locally
>> modified version.
>
>
> I do not know how to reproduce it.
>
> if (s && (!external_module || s->module->is_vmlinux || s->module == mod)) {
>
> is not checking the module path at all.
> I do not understand why it was affected.
So this is not explicitly checking the path, but comparing the contents
of the Module.symvers before and after this change for the external
module I see ...
$ grep -r host1x_device_init Module.symvers
0x00000000 host1x_device_init /absolute/path/to/drivers/gpu/host1x/host1x EXPORT_SYMBOL
And now I see ...
$ grep -r host1x_device_init Module.symvers
0x00000000 host1x_device_init drivers/gpu/host1x/host1x EXPORT_SYMBOL
So the problem is that now there is no longer an absolute path in the
external modules Module.symvers and so conflicts with the kernel's.
Does that make sense?
Jon
--
nvpublic
On Wed, Dec 11, 2024 at 9:21 PM Jon Hunter <jonathanh@nvidia.com> wrote:
>
>
> On 11/12/2024 02:39, Masahiro Yamada wrote:
> > On Wed, Dec 11, 2024 at 12:34 AM Jon Hunter <jonathanh@nvidia.com> wrote:
> >>
> >> Hi Masahiro,
> >>
> >> On 10/11/2024 01:34, Masahiro Yamada wrote:
> >>> Currently, Kbuild always operates in the output directory of the kernel,
> >>> even when building external modules. This increases the risk of external
> >>> module Makefiles attempting to write to the kernel directory.
> >>>
> >>> This commit switches the working directory to the external module
> >>> directory, allowing the removal of the $(KBUILD_EXTMOD)/ prefix from
> >>> some build artifacts.
> >>>
> >>> The command for building external modules maintains backward
> >>> compatibility, but Makefiles that rely on working in the kernel
> >>> directory may break. In such cases, $(objtree) and $(srctree) should
> >>> be used to refer to the output and source directories of the kernel.
> >>>
> >>> The appearance of the build log will change as follows:
> >>>
> >>> [Before]
> >>>
> >>> $ make -C /path/to/my/linux M=/path/to/my/externel/module
> >>> make: Entering directory '/path/to/my/linux'
> >>> CC [M] /path/to/my/externel/module/helloworld.o
> >>> MODPOST /path/to/my/externel/module/Module.symvers
> >>> CC [M] /path/to/my/externel/module/helloworld.mod.o
> >>> CC [M] /path/to/my/externel/module/.module-common.o
> >>> LD [M] /path/to/my/externel/module/helloworld.ko
> >>> make: Leaving directory '/path/to/my/linux'
> >>>
> >>> [After]
> >>>
> >>> $ make -C /path/to/my/linux M=/path/to/my/externel/module
> >>> make: Entering directory '/path/to/my/linux'
> >>> make[1]: Entering directory '/path/to/my/externel/module'
> >>> CC [M] helloworld.o
> >>> MODPOST Module.symvers
> >>> CC [M] helloworld.mod.o
> >>> CC [M] .module-common.o
> >>> LD [M] helloworld.ko
> >>> make[1]: Leaving directory '/path/to/my/externel/module'
> >>> make: Leaving directory '/path/to/my/linux'
> >>>
> >>> Printing "Entering directory" twice is cumbersome. This will be
> >>> addressed later.
> >>>
> >>> Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
> >>
> >>
> >> Since this change I have been observing the following build error when
> >> building an external module ...
> >>
> >> MODPOST Module.symvers
> >> ERROR: modpost: drivers/gpu/host1x/host1x: 'host1x_device_init' exported
> >> twice. Previous export was in drivers/gpu/host1x/host1x.ko
> >> ERROR: modpost: drivers/gpu/host1x/host1x: 'host1x_device_exit' exported
> >> twice. Previous export was in drivers/gpu/host1x/host1x.ko
> >>
> >> Now host1x is an upstream driver, but I have a local copy that using to
> >> stage development changes (and avoid polluting the upstream driver).
> >> Plus I can swap between which version I am using on a live system.
> >>
> >> What I noticed is that previously the Modules.symvers for the external
> >> module had the full path of the external module for the name. However,
> >> now the name is just the relative path and in this case
> >> 'drivers/gpu/host1x/host1x'. Hence, this clashes with the in-kernel
> >> driver and we get the 'exported twice' error.
> >>
> >> I have been looking to see if there is a way to fix this because it has
> >> been a useful feature to override an upstream driver with a locally
> >> modified version.
> >
> >
> > I do not know how to reproduce it.
> >
> > if (s && (!external_module || s->module->is_vmlinux || s->module == mod)) {
> >
> > is not checking the module path at all.
> > I do not understand why it was affected.
>
>
> So this is not explicitly checking the path, but comparing the contents
> of the Module.symvers before and after this change for the external
> module I see ...
>
> $ grep -r host1x_device_init Module.symvers
> 0x00000000 host1x_device_init /absolute/path/to/drivers/gpu/host1x/host1x EXPORT_SYMBOL
>
> And now I see ...
>
> $ grep -r host1x_device_init Module.symvers
> 0x00000000 host1x_device_init drivers/gpu/host1x/host1x EXPORT_SYMBOL
>
> So the problem is that now there is no longer an absolute path in the
> external modules Module.symvers and so conflicts with the kernel's.
>
> Does that make sense?
As I said, I do not know how to reproduce it.
Please provide the steps to reproduce it.
--
Best Regards
Masahiro Yamada
On 12/12/2024 02:08, Masahiro Yamada wrote:
> On Wed, Dec 11, 2024 at 9:21 PM Jon Hunter <jonathanh@nvidia.com> wrote:
>>
>>
>> On 11/12/2024 02:39, Masahiro Yamada wrote:
>>> On Wed, Dec 11, 2024 at 12:34 AM Jon Hunter <jonathanh@nvidia.com> wrote:
>>>>
>>>> Hi Masahiro,
>>>>
>>>> On 10/11/2024 01:34, Masahiro Yamada wrote:
>>>>> Currently, Kbuild always operates in the output directory of the kernel,
>>>>> even when building external modules. This increases the risk of external
>>>>> module Makefiles attempting to write to the kernel directory.
>>>>>
>>>>> This commit switches the working directory to the external module
>>>>> directory, allowing the removal of the $(KBUILD_EXTMOD)/ prefix from
>>>>> some build artifacts.
>>>>>
>>>>> The command for building external modules maintains backward
>>>>> compatibility, but Makefiles that rely on working in the kernel
>>>>> directory may break. In such cases, $(objtree) and $(srctree) should
>>>>> be used to refer to the output and source directories of the kernel.
>>>>>
>>>>> The appearance of the build log will change as follows:
>>>>>
>>>>> [Before]
>>>>>
>>>>> $ make -C /path/to/my/linux M=/path/to/my/externel/module
>>>>> make: Entering directory '/path/to/my/linux'
>>>>> CC [M] /path/to/my/externel/module/helloworld.o
>>>>> MODPOST /path/to/my/externel/module/Module.symvers
>>>>> CC [M] /path/to/my/externel/module/helloworld.mod.o
>>>>> CC [M] /path/to/my/externel/module/.module-common.o
>>>>> LD [M] /path/to/my/externel/module/helloworld.ko
>>>>> make: Leaving directory '/path/to/my/linux'
>>>>>
>>>>> [After]
>>>>>
>>>>> $ make -C /path/to/my/linux M=/path/to/my/externel/module
>>>>> make: Entering directory '/path/to/my/linux'
>>>>> make[1]: Entering directory '/path/to/my/externel/module'
>>>>> CC [M] helloworld.o
>>>>> MODPOST Module.symvers
>>>>> CC [M] helloworld.mod.o
>>>>> CC [M] .module-common.o
>>>>> LD [M] helloworld.ko
>>>>> make[1]: Leaving directory '/path/to/my/externel/module'
>>>>> make: Leaving directory '/path/to/my/linux'
>>>>>
>>>>> Printing "Entering directory" twice is cumbersome. This will be
>>>>> addressed later.
>>>>>
>>>>> Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
>>>>
>>>>
>>>> Since this change I have been observing the following build error when
>>>> building an external module ...
>>>>
>>>> MODPOST Module.symvers
>>>> ERROR: modpost: drivers/gpu/host1x/host1x: 'host1x_device_init' exported
>>>> twice. Previous export was in drivers/gpu/host1x/host1x.ko
>>>> ERROR: modpost: drivers/gpu/host1x/host1x: 'host1x_device_exit' exported
>>>> twice. Previous export was in drivers/gpu/host1x/host1x.ko
>>>>
>>>> Now host1x is an upstream driver, but I have a local copy that using to
>>>> stage development changes (and avoid polluting the upstream driver).
>>>> Plus I can swap between which version I am using on a live system.
>>>>
>>>> What I noticed is that previously the Modules.symvers for the external
>>>> module had the full path of the external module for the name. However,
>>>> now the name is just the relative path and in this case
>>>> 'drivers/gpu/host1x/host1x'. Hence, this clashes with the in-kernel
>>>> driver and we get the 'exported twice' error.
>>>>
>>>> I have been looking to see if there is a way to fix this because it has
>>>> been a useful feature to override an upstream driver with a locally
>>>> modified version.
>>>
>>>
>>> I do not know how to reproduce it.
>>>
>>> if (s && (!external_module || s->module->is_vmlinux || s->module == mod)) {
>>>
>>> is not checking the module path at all.
>>> I do not understand why it was affected.
>>
>>
>> So this is not explicitly checking the path, but comparing the contents
>> of the Module.symvers before and after this change for the external
>> module I see ...
>>
>> $ grep -r host1x_device_init Module.symvers
>> 0x00000000 host1x_device_init /absolute/path/to/drivers/gpu/host1x/host1x EXPORT_SYMBOL
>>
>> And now I see ...
>>
>> $ grep -r host1x_device_init Module.symvers
>> 0x00000000 host1x_device_init drivers/gpu/host1x/host1x EXPORT_SYMBOL
>>
>> So the problem is that now there is no longer an absolute path in the
>> external modules Module.symvers and so conflicts with the kernel's.
>>
>> Does that make sense?
>
>
> As I said, I do not know how to reproduce it.
>
> Please provide the steps to reproduce it.
Got it! The steps would be ...
1. Create an external module by copying using an existing upstream
driver (such as host1x).
2. Create a new external module that uses the external module from step
1 and uses KBUILD_EXTRA_SYMBOLS to reference the Module.symvers for
the driver in step 1.
Thanks!
Jon
--
nvpublic
On Thu, Dec 12, 2024 at 3:00 PM Jon Hunter <jonathanh@nvidia.com> wrote:
>
>
> On 12/12/2024 02:08, Masahiro Yamada wrote:
> > On Wed, Dec 11, 2024 at 9:21 PM Jon Hunter <jonathanh@nvidia.com> wrote:
> >>
> >>
> >> On 11/12/2024 02:39, Masahiro Yamada wrote:
> >>> On Wed, Dec 11, 2024 at 12:34 AM Jon Hunter <jonathanh@nvidia.com> wrote:
> >>>>
> >>>> Hi Masahiro,
> >>>>
> >>>> On 10/11/2024 01:34, Masahiro Yamada wrote:
> >>>>> Currently, Kbuild always operates in the output directory of the kernel,
> >>>>> even when building external modules. This increases the risk of external
> >>>>> module Makefiles attempting to write to the kernel directory.
> >>>>>
> >>>>> This commit switches the working directory to the external module
> >>>>> directory, allowing the removal of the $(KBUILD_EXTMOD)/ prefix from
> >>>>> some build artifacts.
> >>>>>
> >>>>> The command for building external modules maintains backward
> >>>>> compatibility, but Makefiles that rely on working in the kernel
> >>>>> directory may break. In such cases, $(objtree) and $(srctree) should
> >>>>> be used to refer to the output and source directories of the kernel.
> >>>>>
> >>>>> The appearance of the build log will change as follows:
> >>>>>
> >>>>> [Before]
> >>>>>
> >>>>> $ make -C /path/to/my/linux M=/path/to/my/externel/module
> >>>>> make: Entering directory '/path/to/my/linux'
> >>>>> CC [M] /path/to/my/externel/module/helloworld.o
> >>>>> MODPOST /path/to/my/externel/module/Module.symvers
> >>>>> CC [M] /path/to/my/externel/module/helloworld.mod.o
> >>>>> CC [M] /path/to/my/externel/module/.module-common.o
> >>>>> LD [M] /path/to/my/externel/module/helloworld.ko
> >>>>> make: Leaving directory '/path/to/my/linux'
> >>>>>
> >>>>> [After]
> >>>>>
> >>>>> $ make -C /path/to/my/linux M=/path/to/my/externel/module
> >>>>> make: Entering directory '/path/to/my/linux'
> >>>>> make[1]: Entering directory '/path/to/my/externel/module'
> >>>>> CC [M] helloworld.o
> >>>>> MODPOST Module.symvers
> >>>>> CC [M] helloworld.mod.o
> >>>>> CC [M] .module-common.o
> >>>>> LD [M] helloworld.ko
> >>>>> make[1]: Leaving directory '/path/to/my/externel/module'
> >>>>> make: Leaving directory '/path/to/my/linux'
> >>>>>
> >>>>> Printing "Entering directory" twice is cumbersome. This will be
> >>>>> addressed later.
> >>>>>
> >>>>> Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
> >>>>
> >>>>
> >>>> Since this change I have been observing the following build error when
> >>>> building an external module ...
> >>>>
> >>>> MODPOST Module.symvers
> >>>> ERROR: modpost: drivers/gpu/host1x/host1x: 'host1x_device_init' exported
> >>>> twice. Previous export was in drivers/gpu/host1x/host1x.ko
> >>>> ERROR: modpost: drivers/gpu/host1x/host1x: 'host1x_device_exit' exported
> >>>> twice. Previous export was in drivers/gpu/host1x/host1x.ko
> >>>>
> >>>> Now host1x is an upstream driver, but I have a local copy that using to
> >>>> stage development changes (and avoid polluting the upstream driver).
> >>>> Plus I can swap between which version I am using on a live system.
> >>>>
> >>>> What I noticed is that previously the Modules.symvers for the external
> >>>> module had the full path of the external module for the name. However,
> >>>> now the name is just the relative path and in this case
> >>>> 'drivers/gpu/host1x/host1x'. Hence, this clashes with the in-kernel
> >>>> driver and we get the 'exported twice' error.
> >>>>
> >>>> I have been looking to see if there is a way to fix this because it has
> >>>> been a useful feature to override an upstream driver with a locally
> >>>> modified version.
> >>>
> >>>
> >>> I do not know how to reproduce it.
> >>>
> >>> if (s && (!external_module || s->module->is_vmlinux || s->module == mod)) {
> >>>
> >>> is not checking the module path at all.
> >>> I do not understand why it was affected.
> >>
> >>
> >> So this is not explicitly checking the path, but comparing the contents
> >> of the Module.symvers before and after this change for the external
> >> module I see ...
> >>
> >> $ grep -r host1x_device_init Module.symvers
> >> 0x00000000 host1x_device_init /absolute/path/to/drivers/gpu/host1x/host1x EXPORT_SYMBOL
> >>
> >> And now I see ...
> >>
> >> $ grep -r host1x_device_init Module.symvers
> >> 0x00000000 host1x_device_init drivers/gpu/host1x/host1x EXPORT_SYMBOL
> >>
> >> So the problem is that now there is no longer an absolute path in the
> >> external modules Module.symvers and so conflicts with the kernel's.
> >>
> >> Does that make sense?
> >
> >
> > As I said, I do not know how to reproduce it.
> >
> > Please provide the steps to reproduce it.
>
> Got it! The steps would be ...
>
> 1. Create an external module by copying using an existing upstream
> driver (such as host1x).
> 2. Create a new external module that uses the external module from step
> 1 and uses KBUILD_EXTRA_SYMBOLS to reference the Module.symvers for
> the driver in step 1.
>
> Thanks!
> Jon
OK, now I understand, and posted a patch.
Thanks.
--
Best Regards
Masahiro Yamada
On 10. Nov 2024, at 02:34, Masahiro Yamada wrote:
>
> Currently, Kbuild always operates in the output directory of the kernel,
> even when building external modules. This increases the risk of external
> module Makefiles attempting to write to the kernel directory.
>
> This commit switches the working directory to the external module
> directory, allowing the removal of the $(KBUILD_EXTMOD)/ prefix from
> some build artifacts.
>
> The command for building external modules maintains backward
> compatibility, but Makefiles that rely on working in the kernel
> directory may break. In such cases, $(objtree) and $(srctree) should
> be used to refer to the output and source directories of the kernel.
>
> The appearance of the build log will change as follows:
>
> [Before]
>
> $ make -C /path/to/my/linux M=/path/to/my/externel/module
> make: Entering directory '/path/to/my/linux'
> CC [M] /path/to/my/externel/module/helloworld.o
> MODPOST /path/to/my/externel/module/Module.symvers
> CC [M] /path/to/my/externel/module/helloworld.mod.o
> CC [M] /path/to/my/externel/module/.module-common.o
> LD [M] /path/to/my/externel/module/helloworld.ko
> make: Leaving directory '/path/to/my/linux'
>
> [After]
>
> $ make -C /path/to/my/linux M=/path/to/my/externel/module
> make: Entering directory '/path/to/my/linux'
> make[1]: Entering directory '/path/to/my/externel/module'
> CC [M] helloworld.o
> MODPOST Module.symvers
> CC [M] helloworld.mod.o
> CC [M] .module-common.o
> LD [M] helloworld.ko
> make[1]: Leaving directory '/path/to/my/externel/module'
> make: Leaving directory '/path/to/my/linux'
>
> Printing "Entering directory" twice is cumbersome. This will be
> addressed later.
>
> Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
> ---
Hi Masahiro,
I get the following error since this patch is in master, but only when
using COCCI= in combination with M=<relative or absolute path>.
It works when I either use COCCI= or M=, but not with both.
$ make coccicheck COCCI=scripts/coccinelle/misc/flexible_array.cocci M=arch/
make[1]: Entering directory '/home/fedora/linux/arch'
You have not explicitly specified the mode to use. Using default "report" mode.
Available modes are the following: patch, report, context, org, chain
You can specify the mode with "make coccicheck MODE=<mode>"
Note however that some modes are not implemented by some semantic patches.
Please check for false positives in the output before submitting a patch.
When using "patch" mode, carefully review the patch before submitting it.
grep: scripts/coccinelle/misc/flexible_array.cocci: No such file or directory
grep: scripts/coccinelle/misc/flexible_array.cocci: No such file or directory
/usr/bin/spatch -D report --no-show-diff --very-quiet --cocci-file scripts/coccinelle/misc/flexible_array.cocci --patch /home/fedora/linux --dir . -I /home/fedora/linux/arch/arm64/include -I /home/fedora/linux/arch/arm64/include/generated -I /home/fedora/linux/include -I /home/fedora/linux/include -I /home/fedora/linux/arch/arm64/include/uapi -I /home/fedora/linux/arch/arm64/include/generated/uapi -I /home/fedora/linux/include/uapi -I /home/fedora/linux/include/generated/uapi --include /home/fedora/linux/include/linux/compiler-version.h --include /home/fedora/linux/include/linux/kconfig.h --jobs 4 --chunksize 1
Fatal error: exception Sys_error("scripts/coccinelle/misc/flexible_array.cocci: No such file or directory")
coccicheck failed
make[2]: *** [/home/fedora/linux/Makefile:2089: coccicheck] Error 2
make[1]: *** [/home/fedora/linux/Makefile:251: __sub-make] Error 2
make[1]: Leaving directory '/home/fedora/linux/arch'
make: *** [Makefile:251: __sub-make] Error 2
Thanks,
Thorsten
On 9. Dec 2024, at 14:46, Thorsten Blum wrote: > On 10. Nov 2024, at 02:34, Masahiro Yamada wrote: >> >> Currently, Kbuild always operates in the output directory of the kernel, >> even when building external modules. This increases the risk of external >> module Makefiles attempting to write to the kernel directory. >> >> This commit switches the working directory to the external module >> directory, allowing the removal of the $(KBUILD_EXTMOD)/ prefix from >> some build artifacts. >> >> The command for building external modules maintains backward >> compatibility, but Makefiles that rely on working in the kernel >> directory may break. In such cases, $(objtree) and $(srctree) should >> be used to refer to the output and source directories of the kernel. >> >> The appearance of the build log will change as follows: >> >> [Before] >> >> $ make -C /path/to/my/linux M=/path/to/my/externel/module >> make: Entering directory '/path/to/my/linux' >> CC [M] /path/to/my/externel/module/helloworld.o >> MODPOST /path/to/my/externel/module/Module.symvers >> CC [M] /path/to/my/externel/module/helloworld.mod.o >> CC [M] /path/to/my/externel/module/.module-common.o >> LD [M] /path/to/my/externel/module/helloworld.ko >> make: Leaving directory '/path/to/my/linux' >> >> [After] >> >> $ make -C /path/to/my/linux M=/path/to/my/externel/module >> make: Entering directory '/path/to/my/linux' >> make[1]: Entering directory '/path/to/my/externel/module' >> CC [M] helloworld.o >> MODPOST Module.symvers >> CC [M] helloworld.mod.o >> CC [M] .module-common.o >> LD [M] helloworld.ko >> make[1]: Leaving directory '/path/to/my/externel/module' >> make: Leaving directory '/path/to/my/linux' >> >> Printing "Entering directory" twice is cumbersome. This will be >> addressed later. >> >> Signed-off-by: Masahiro Yamada <masahiroy@kernel.org> >> --- > > Hi Masahiro, > > I get the following error since this patch is in master, but only when > using COCCI= in combination with M=<relative or absolute path>. > > It works when I either use COCCI= or M=, but not with both. Using the absolute path of the cocci script fixes my problem, but this used to work with relative paths too. $ make coccicheck COCCI=$(pwd)/scripts/coccinelle/misc/flexible_array.cocci M=arch/ Thanks, Thorsten
On Mon, Dec 9, 2024 at 10:56 PM Thorsten Blum <thorsten.blum@linux.dev> wrote: > > On 9. Dec 2024, at 14:46, Thorsten Blum wrote: > > On 10. Nov 2024, at 02:34, Masahiro Yamada wrote: > >> > >> Currently, Kbuild always operates in the output directory of the kernel, > >> even when building external modules. This increases the risk of external > >> module Makefiles attempting to write to the kernel directory. > >> > >> This commit switches the working directory to the external module > >> directory, allowing the removal of the $(KBUILD_EXTMOD)/ prefix from > >> some build artifacts. > >> > >> The command for building external modules maintains backward > >> compatibility, but Makefiles that rely on working in the kernel > >> directory may break. In such cases, $(objtree) and $(srctree) should > >> be used to refer to the output and source directories of the kernel. > >> > >> The appearance of the build log will change as follows: > >> > >> [Before] > >> > >> $ make -C /path/to/my/linux M=/path/to/my/externel/module > >> make: Entering directory '/path/to/my/linux' > >> CC [M] /path/to/my/externel/module/helloworld.o > >> MODPOST /path/to/my/externel/module/Module.symvers > >> CC [M] /path/to/my/externel/module/helloworld.mod.o > >> CC [M] /path/to/my/externel/module/.module-common.o > >> LD [M] /path/to/my/externel/module/helloworld.ko > >> make: Leaving directory '/path/to/my/linux' > >> > >> [After] > >> > >> $ make -C /path/to/my/linux M=/path/to/my/externel/module > >> make: Entering directory '/path/to/my/linux' > >> make[1]: Entering directory '/path/to/my/externel/module' > >> CC [M] helloworld.o > >> MODPOST Module.symvers > >> CC [M] helloworld.mod.o > >> CC [M] .module-common.o > >> LD [M] helloworld.ko > >> make[1]: Leaving directory '/path/to/my/externel/module' > >> make: Leaving directory '/path/to/my/linux' > >> > >> Printing "Entering directory" twice is cumbersome. This will be > >> addressed later. > >> > >> Signed-off-by: Masahiro Yamada <masahiroy@kernel.org> > >> --- > > > > Hi Masahiro, > > > > I get the following error since this patch is in master, but only when > > using COCCI= in combination with M=<relative or absolute path>. > > > > It works when I either use COCCI= or M=, but not with both. > > Using the absolute path of the cocci script fixes my problem, but this > used to work with relative paths too. > > $ make coccicheck COCCI=$(pwd)/scripts/coccinelle/misc/flexible_array.cocci M=arch/ M= looks a bit weird for the upstream code, but I think using the absolute path is the right thing to do. -- Best Regards Masahiro Yamada
On 10. Dec 2024, at 11:47, Masahiro Yamada wrote: > On Mon, Dec 9, 2024 at 10:56 PM Thorsten Blum wrote: >> On 9. Dec 2024, at 14:46, Thorsten Blum wrote: >>> On 10. Nov 2024, at 02:34, Masahiro Yamada wrote: >>>> >>>> Currently, Kbuild always operates in the output directory of the kernel, >>>> even when building external modules. This increases the risk of external >>>> module Makefiles attempting to write to the kernel directory. >>>> >>>> This commit switches the working directory to the external module >>>> directory, allowing the removal of the $(KBUILD_EXTMOD)/ prefix from >>>> some build artifacts. >>>> >>>> The command for building external modules maintains backward >>>> compatibility, but Makefiles that rely on working in the kernel >>>> directory may break. In such cases, $(objtree) and $(srctree) should >>>> be used to refer to the output and source directories of the kernel. >>>> >>>> The appearance of the build log will change as follows: >>>> >>>> [Before] >>>> >>>> $ make -C /path/to/my/linux M=/path/to/my/externel/module >>>> make: Entering directory '/path/to/my/linux' >>>> CC [M] /path/to/my/externel/module/helloworld.o >>>> MODPOST /path/to/my/externel/module/Module.symvers >>>> CC [M] /path/to/my/externel/module/helloworld.mod.o >>>> CC [M] /path/to/my/externel/module/.module-common.o >>>> LD [M] /path/to/my/externel/module/helloworld.ko >>>> make: Leaving directory '/path/to/my/linux' >>>> >>>> [After] >>>> >>>> $ make -C /path/to/my/linux M=/path/to/my/externel/module >>>> make: Entering directory '/path/to/my/linux' >>>> make[1]: Entering directory '/path/to/my/externel/module' >>>> CC [M] helloworld.o >>>> MODPOST Module.symvers >>>> CC [M] helloworld.mod.o >>>> CC [M] .module-common.o >>>> LD [M] helloworld.ko >>>> make[1]: Leaving directory '/path/to/my/externel/module' >>>> make: Leaving directory '/path/to/my/linux' >>>> >>>> Printing "Entering directory" twice is cumbersome. This will be >>>> addressed later. >>>> >>>> Signed-off-by: Masahiro Yamada <masahiroy@kernel.org> >>>> --- >>> >>> Hi Masahiro, >>> >>> I get the following error since this patch is in master, but only when >>> using COCCI= in combination with M=<relative or absolute path>. >>> >>> It works when I either use COCCI= or M=, but not with both. >> >> Using the absolute path of the cocci script fixes my problem, but this >> used to work with relative paths too. >> >> $ make coccicheck COCCI=$(pwd)/scripts/coccinelle/misc/flexible_array.cocci M=arch/ > > M= looks a bit weird for the upstream code, but > I think using the absolute path is the right thing to do. The documentation[1] uses M= and also COCCI= with relative paths and some of the examples don't work anymore. Could you try this one? ``` export COCCI=scripts/coccinelle/misc/irqf_oneshot.cocci make coccicheck DEBUG_FILE="err.log" MODE=report SPFLAGS="--profile --show-trying" M=./drivers/mfd ``` I get this: $ export COCCI=scripts/coccinelle/misc/irqf_oneshot.cocci $ make coccicheck DEBUG_FILE="err.log" MODE=report SPFLAGS="--profile --show-trying" M=./drivers/mfd make[1]: Entering directory '/home/fedora/linux/drivers/mfd' Please check for false positives in the output before submitting a patch. When using "patch" mode, carefully review the patch before submitting it. grep: scripts/coccinelle/misc/irqf_oneshot.cocci: No such file or directory grep: scripts/coccinelle/misc/irqf_oneshot.cocci: No such file or directory coccicheck failed make[2]: *** [/home/fedora/linux/Makefile:2089: coccicheck] Error 2 make[1]: *** [/home/fedora/linux/Makefile:251: __sub-make] Error 2 make[1]: Leaving directory '/home/fedora/linux/drivers/mfd' make: *** [Makefile:251: __sub-make] Error 2 Thanks, Thorsten [1] https://www.kernel.org/doc/html/latest/dev-tools/coccinelle.html
On Tue, Dec 10, 2024 at 8:06 PM Thorsten Blum <thorsten.blum@linux.dev> wrote: > > On 10. Dec 2024, at 11:47, Masahiro Yamada wrote: > > On Mon, Dec 9, 2024 at 10:56 PM Thorsten Blum wrote: > >> On 9. Dec 2024, at 14:46, Thorsten Blum wrote: > >>> On 10. Nov 2024, at 02:34, Masahiro Yamada wrote: > >>>> > >>>> Currently, Kbuild always operates in the output directory of the kernel, > >>>> even when building external modules. This increases the risk of external > >>>> module Makefiles attempting to write to the kernel directory. > >>>> > >>>> This commit switches the working directory to the external module > >>>> directory, allowing the removal of the $(KBUILD_EXTMOD)/ prefix from > >>>> some build artifacts. > >>>> > >>>> The command for building external modules maintains backward > >>>> compatibility, but Makefiles that rely on working in the kernel > >>>> directory may break. In such cases, $(objtree) and $(srctree) should > >>>> be used to refer to the output and source directories of the kernel. > >>>> > >>>> The appearance of the build log will change as follows: > >>>> > >>>> [Before] > >>>> > >>>> $ make -C /path/to/my/linux M=/path/to/my/externel/module > >>>> make: Entering directory '/path/to/my/linux' > >>>> CC [M] /path/to/my/externel/module/helloworld.o > >>>> MODPOST /path/to/my/externel/module/Module.symvers > >>>> CC [M] /path/to/my/externel/module/helloworld.mod.o > >>>> CC [M] /path/to/my/externel/module/.module-common.o > >>>> LD [M] /path/to/my/externel/module/helloworld.ko > >>>> make: Leaving directory '/path/to/my/linux' > >>>> > >>>> [After] > >>>> > >>>> $ make -C /path/to/my/linux M=/path/to/my/externel/module > >>>> make: Entering directory '/path/to/my/linux' > >>>> make[1]: Entering directory '/path/to/my/externel/module' > >>>> CC [M] helloworld.o > >>>> MODPOST Module.symvers > >>>> CC [M] helloworld.mod.o > >>>> CC [M] .module-common.o > >>>> LD [M] helloworld.ko > >>>> make[1]: Leaving directory '/path/to/my/externel/module' > >>>> make: Leaving directory '/path/to/my/linux' > >>>> > >>>> Printing "Entering directory" twice is cumbersome. This will be > >>>> addressed later. > >>>> > >>>> Signed-off-by: Masahiro Yamada <masahiroy@kernel.org> > >>>> --- > >>> > >>> Hi Masahiro, > >>> > >>> I get the following error since this patch is in master, but only when > >>> using COCCI= in combination with M=<relative or absolute path>. > >>> > >>> It works when I either use COCCI= or M=, but not with both. > >> > >> Using the absolute path of the cocci script fixes my problem, but this > >> used to work with relative paths too. > >> > >> $ make coccicheck COCCI=$(pwd)/scripts/coccinelle/misc/flexible_array.cocci M=arch/ > > > > M= looks a bit weird for the upstream code, but > > I think using the absolute path is the right thing to do. > > The documentation[1] uses M= and also COCCI= with relative paths and > some of the examples don't work anymore. I know. This is what cocci people hoped to work. If something is broken in coccicheck, it must be fixed. -- Best Regards Masahiro Yamada
On Sun, Nov 10, 2024 at 10:34:33AM +0900, Masahiro Yamada wrote:
> Currently, Kbuild always operates in the output directory of the kernel,
> even when building external modules. This increases the risk of external
> module Makefiles attempting to write to the kernel directory.
>
> This commit switches the working directory to the external module
> directory, allowing the removal of the $(KBUILD_EXTMOD)/ prefix from
> some build artifacts.
>
> The command for building external modules maintains backward
> compatibility, but Makefiles that rely on working in the kernel
> directory may break. In such cases, $(objtree) and $(srctree) should
> be used to refer to the output and source directories of the kernel.
>
> The appearance of the build log will change as follows:
>
> [Before]
>
> $ make -C /path/to/my/linux M=/path/to/my/externel/module
> make: Entering directory '/path/to/my/linux'
> CC [M] /path/to/my/externel/module/helloworld.o
> MODPOST /path/to/my/externel/module/Module.symvers
> CC [M] /path/to/my/externel/module/helloworld.mod.o
> CC [M] /path/to/my/externel/module/.module-common.o
> LD [M] /path/to/my/externel/module/helloworld.ko
> make: Leaving directory '/path/to/my/linux'
>
> [After]
>
> $ make -C /path/to/my/linux M=/path/to/my/externel/module
> make: Entering directory '/path/to/my/linux'
> make[1]: Entering directory '/path/to/my/externel/module'
> CC [M] helloworld.o
> MODPOST Module.symvers
> CC [M] helloworld.mod.o
> CC [M] .module-common.o
> LD [M] helloworld.ko
> make[1]: Leaving directory '/path/to/my/externel/module'
> make: Leaving directory '/path/to/my/linux'
>
> Printing "Entering directory" twice is cumbersome. This will be
> addressed later.
This change has caused O=<relative directory> to fail.
For example:
make O=build defconfig
make -j$(nproc) V=1 O=build bindeb-pkg
outputs:
make ARCH=x86 KERNELRELEASE=6.13.0-rc1 KBUILD_BUILD_VERSION=3 run-command KBUILD_RUN_COMMAND='+$(srctree)/scripts/package/builddeb linux-libc-dev'
dh_installchangelogs -plinux-image-6.13.0-rc1
../scripts/package/builddeb linux-headers-6.13.0-rc1
dh_compress -plinux-image-6.13.0-rc1
dh_fixperms -plinux-image-6.13.0-rc1
dh_gencontrol -plinux-image-6.13.0-rc1 -- -fdebian/image.files
Rebuilding host programs with x86_64-linux-gnu-gcc...
make[6]: Entering directory '/scratch/kernels/linux/build'
/scratch/kernels/linux/Makefile:190: *** specified kernel directory "build" does not exist. Stop.
It is stepping into this directory and then trying to find the directory
it just stepped into so $(realpath $(KBUILD_OUTPUT)) returns an empty
string.
Using an absolute directory resolves this problem, but I believe it
shouldn't be necessary.
- Charlie
>
> Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
> ---
>
> Changes in v2:
> - Introduce a new 'srcroot' variable and clean-up code
> - Reword Documentation/dev-tools/coccinelle.rst
>
> Documentation/dev-tools/coccinelle.rst | 20 ++-----
> Documentation/kbuild/makefiles.rst | 14 +++++
> Makefile | 80 +++++++++++++++-----------
> rust/Makefile | 4 +-
> scripts/Makefile.build | 2 +-
> scripts/Makefile.clean | 2 +-
> scripts/Makefile.compiler | 2 +-
> scripts/Makefile.modpost | 6 +-
> scripts/coccicheck | 6 +-
> scripts/nsdeps | 8 +--
> scripts/package/install-extmod-build | 7 +++
> 11 files changed, 85 insertions(+), 66 deletions(-)
>
> diff --git a/Documentation/dev-tools/coccinelle.rst b/Documentation/dev-tools/coccinelle.rst
> index 535ce126fb4f..6e70a1e9a3c0 100644
> --- a/Documentation/dev-tools/coccinelle.rst
> +++ b/Documentation/dev-tools/coccinelle.rst
> @@ -250,25 +250,17 @@ variables for .cocciconfig is as follows:
> - Your directory from which spatch is called is processed next
> - The directory provided with the ``--dir`` option is processed last, if used
>
> -Since coccicheck runs through make, it naturally runs from the kernel
> -proper dir; as such the second rule above would be implied for picking up a
> -.cocciconfig when using ``make coccicheck``.
> -
> ``make coccicheck`` also supports using M= targets. If you do not supply
> any M= target, it is assumed you want to target the entire kernel.
> The kernel coccicheck script has::
>
> - if [ "$KBUILD_EXTMOD" = "" ] ; then
> - OPTIONS="--dir $srctree $COCCIINCLUDE"
> - else
> - OPTIONS="--dir $KBUILD_EXTMOD $COCCIINCLUDE"
> - fi
> + OPTIONS="--dir $srcroot $COCCIINCLUDE"
>
> -KBUILD_EXTMOD is set when an explicit target with M= is used. For both cases
> -the spatch ``--dir`` argument is used, as such third rule applies when whether
> -M= is used or not, and when M= is used the target directory can have its own
> -.cocciconfig file. When M= is not passed as an argument to coccicheck the
> -target directory is the same as the directory from where spatch was called.
> +Here, $srcroot refers to the source directory of the target: it points to the
> +external module's source directory when M= used, and otherwise, to the kernel
> +source directory. The third rule ensures the spatch reads the .cocciconfig from
> +the target directory, allowing external modules to have their own .cocciconfig
> +file.
>
> If not using the kernel's coccicheck target, keep the above precedence
> order logic of .cocciconfig reading. If using the kernel's coccicheck target,
> diff --git a/Documentation/kbuild/makefiles.rst b/Documentation/kbuild/makefiles.rst
> index 7964e0c245ae..d36519f194dc 100644
> --- a/Documentation/kbuild/makefiles.rst
> +++ b/Documentation/kbuild/makefiles.rst
> @@ -449,6 +449,20 @@ $(obj)
> to prerequisites are referenced with $(src) (because they are not
> generated files).
>
> +$(srcroot)
> + $(srcroot) refers to the root of the source you are building, which can be
> + either the kernel source or the external modules source, depending on whether
> + KBUILD_EXTMOD is set. This can be either a relative or an absolute path, but
> + if KBUILD_ABS_SRCTREE=1 is set, it is always an absolute path.
> +
> +$(srctree)
> + $(srctree) refers to the root of the kernel source tree. When building the
> + kernel, this is the same as $(srcroot).
> +
> +$(objtree)
> + $(objtree) refers to the root of the kernel object tree. It is ``.`` when
> + building the kernel, but it is different when building external modules.
> +
> $(kecho)
> echoing information to user in a rule is often a good practice
> but when execution ``make -s`` one does not expect to see any output
> diff --git a/Makefile b/Makefile
> index cf1d55560ae2..e5f7ac7647a7 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -180,7 +180,24 @@ ifeq ("$(origin O)", "command line")
> KBUILD_OUTPUT := $(O)
> endif
>
> -output := $(KBUILD_OUTPUT)
> +ifdef KBUILD_EXTMOD
> + ifdef KBUILD_OUTPUT
> + objtree := $(realpath $(KBUILD_OUTPUT))
> + $(if $(objtree),,$(error specified kernel directory "$(KBUILD_OUTPUT)" does not exist))
> + else
> + objtree := $(CURDIR)
> + endif
> + output := $(KBUILD_EXTMOD)
> + # KBUILD_EXTMOD might be a relative path. Remember its absolute path before
> + # Make changes the working directory.
> + srcroot := $(realpath $(KBUILD_EXTMOD))
> + $(if $(srcroot),,$(error specified external module directory "$(KBUILD_EXTMOD)" does not exist))
> +else
> + objtree := .
> + output := $(KBUILD_OUTPUT)
> +endif
> +
> +export objtree srcroot
>
> # Do we want to change the working directory?
> ifneq ($(output),)
> @@ -230,35 +247,33 @@ else # need-sub-make
>
> # We process the rest of the Makefile if this is the final invocation of make
>
> -ifeq ($(abs_srctree),$(CURDIR))
> - # building in the source tree
> - srctree := .
> - building_out_of_srctree :=
> +ifndef KBUILD_EXTMOD
> +srcroot := $(abs_srctree)
> +endif
> +
> +ifeq ($(srcroot),$(CURDIR))
> +building_out_of_srctree :=
> else
> - ifeq ($(abs_srctree)/,$(dir $(CURDIR)))
> - # building in a subdirectory of the source tree
> - srctree := ..
> - else
> - srctree := $(abs_srctree)
> - endif
> - building_out_of_srctree := 1
> +export building_out_of_srctree :=1
> endif
>
> -ifneq ($(KBUILD_ABS_SRCTREE),)
> -srctree := $(abs_srctree)
> +ifdef KBUILD_ABS_SRCTREE
> + # Do not nothing. Use the absolute path.
> +else ifeq ($(srcroot),$(CURDIR))
> + # Building in the source.
> + srcroot := .
> +else ifeq ($(srcroot)/,$(dir $(CURDIR)))
> + # Building in a subdirectory of the source.
> + srcroot := ..
> endif
>
> -objtree := .
> +export srctree := $(if $(KBUILD_EXTMOD),$(abs_srctree),$(srcroot))
>
> -VPATH :=
> -
> -ifeq ($(KBUILD_EXTMOD),)
> ifdef building_out_of_srctree
> -VPATH := $(srctree)
> +export VPATH := $(srcroot)
> +else
> +VPATH :=
> endif
> -endif
> -
> -export building_out_of_srctree srctree objtree VPATH
>
> # To make sure we do not include .config for any of the *config targets
> # catch them early, and hand them over to scripts/kconfig/Makefile
> @@ -711,7 +726,7 @@ endif
> # in addition to whatever we do anyway.
> # Just "make" or "make all" shall build modules as well
>
> -ifneq ($(filter all modules nsdeps %compile_commands.json clang-%,$(MAKECMDGOALS)),)
> +ifneq ($(filter all modules nsdeps compile_commands.json clang-%,$(MAKECMDGOALS)),)
> KBUILD_MODULES := 1
> endif
>
> @@ -1107,7 +1122,7 @@ export MODLIB
>
> PHONY += prepare0
>
> -export extmod_prefix = $(if $(KBUILD_EXTMOD),$(KBUILD_EXTMOD)/)
> +export extmod_prefix =
> export MODORDER := $(extmod_prefix)modules.order
> export MODULES_NSDEPS := $(extmod_prefix)modules.nsdeps
>
> @@ -1799,14 +1814,10 @@ filechk_kernel.release = echo $(KERNELRELEASE)
> KBUILD_BUILTIN :=
> KBUILD_MODULES := 1
>
> -build-dir := $(KBUILD_EXTMOD)
> +build-dir := .
>
> -compile_commands.json: $(extmod_prefix)compile_commands.json
> -PHONY += compile_commands.json
> -
> -clean-dirs := $(KBUILD_EXTMOD)
> -clean: private rm-files := $(KBUILD_EXTMOD)/Module.symvers $(KBUILD_EXTMOD)/modules.nsdeps \
> - $(KBUILD_EXTMOD)/compile_commands.json
> +clean-dirs := .
> +clean: private rm-files := Module.symvers modules.nsdeps compile_commands.json
>
> PHONY += prepare
> # now expand this into a simple variable to reduce the cost of shell evaluations
> @@ -1948,7 +1959,7 @@ $(clean-dirs):
>
> clean: $(clean-dirs)
> $(call cmd,rmfiles)
> - @find $(or $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \
> + @find . $(RCS_FIND_IGNORE) \
> \( -name '*.[aios]' -o -name '*.rsi' -o -name '*.ko' -o -name '.*.cmd' \
> -o -name '*.ko.*' \
> -o -name '*.dtb' -o -name '*.dtbo' \
> @@ -1981,7 +1992,12 @@ tags TAGS cscope gtags: FORCE
> PHONY += rust-analyzer
> rust-analyzer:
> +$(Q)$(CONFIG_SHELL) $(srctree)/scripts/rust_is_available.sh
> +ifdef KBUILD_EXTMOD
> +# FIXME: external modules must not descend into a sub-directory of the kernel
> + $(Q)$(MAKE) $(build)=$(objtree)/rust src=$(srctree)/rust $@
> +else
> $(Q)$(MAKE) $(build)=rust $@
> +endif
>
> # Script to generate missing namespace dependencies
> # ---------------------------------------------------------------------------
> diff --git a/rust/Makefile b/rust/Makefile
> index b5e0a73b78f3..742740816c4b 100644
> --- a/rust/Makefile
> +++ b/rust/Makefile
> @@ -362,8 +362,8 @@ rust-analyzer:
> $(Q)$(srctree)/scripts/generate_rust_analyzer.py \
> --cfgs='core=$(core-cfgs)' --cfgs='alloc=$(alloc-cfgs)' \
> $(realpath $(srctree)) $(realpath $(objtree)) \
> - $(rustc_sysroot) $(RUST_LIB_SRC) $(KBUILD_EXTMOD) > \
> - $(if $(KBUILD_EXTMOD),$(extmod_prefix),$(objtree))/rust-project.json
> + $(rustc_sysroot) $(RUST_LIB_SRC) $(if $(KBUILD_EXTMOD),$(srcroot)) \
> + > rust-project.json
>
> redirect-intrinsics = \
> __addsf3 __eqsf2 __extendsfdf2 __gesf2 __lesf2 __ltsf2 __mulsf3 __nesf2 __truncdfsf2 __unordsf2 \
> diff --git a/scripts/Makefile.build b/scripts/Makefile.build
> index 64cd046f8fd8..1aa928a6fb4f 100644
> --- a/scripts/Makefile.build
> +++ b/scripts/Makefile.build
> @@ -3,7 +3,7 @@
> # Building
> # ==========================================================================
>
> -src := $(if $(VPATH),$(VPATH)/)$(obj)
> +src := $(srcroot)/$(obj)
>
> PHONY := $(obj)/
> $(obj)/:
> diff --git a/scripts/Makefile.clean b/scripts/Makefile.clean
> index 4fcfab40ed61..6ead00ec7313 100644
> --- a/scripts/Makefile.clean
> +++ b/scripts/Makefile.clean
> @@ -3,7 +3,7 @@
> # Cleaning up
> # ==========================================================================
>
> -src := $(if $(VPATH),$(VPATH)/)$(obj)
> +src := $(srcroot)/$(obj)
>
> PHONY := __clean
> __clean:
> diff --git a/scripts/Makefile.compiler b/scripts/Makefile.compiler
> index e0842496d26e..8c1029687e2e 100644
> --- a/scripts/Makefile.compiler
> +++ b/scripts/Makefile.compiler
> @@ -13,7 +13,7 @@ cc-cross-prefix = $(firstword $(foreach c, $(1), \
> $(if $(shell command -v -- $(c)gcc 2>/dev/null), $(c))))
>
> # output directory for tests below
> -TMPOUT = $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/).tmp_$$$$
> +TMPOUT = .tmp_$$$$
>
> # try-run
> # Usage: option = $(call try-run, $(CC)...-o "$$TMP",option-ok,otherwise)
> diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
> index 12e7c15d099c..78d2ca4f25f5 100644
> --- a/scripts/Makefile.modpost
> +++ b/scripts/Makefile.modpost
> @@ -111,13 +111,13 @@ endif
> else
>
> # set src + obj - they may be used in the modules's Makefile
> -obj := $(KBUILD_EXTMOD)
> -src := $(if $(VPATH),$(VPATH)/)$(obj)
> +obj := .
> +src := $(srcroot)
>
> # Include the module's Makefile to find KBUILD_EXTRA_SYMBOLS
> include $(kbuild-file)
>
> -output-symdump := $(KBUILD_EXTMOD)/Module.symvers
> +output-symdump := Module.symvers
>
> ifeq ($(wildcard $(objtree)/Module.symvers),)
> missing-input := $(objtree)/Module.symvers
> diff --git a/scripts/coccicheck b/scripts/coccicheck
> index e52cb43fede6..0e6bc5a10320 100755
> --- a/scripts/coccicheck
> +++ b/scripts/coccicheck
> @@ -80,11 +80,7 @@ command results in a shift count error.'
> NPROC=1
> else
> ONLINE=0
> - if [ "$KBUILD_EXTMOD" = "" ] ; then
> - OPTIONS="--dir $srctree $COCCIINCLUDE"
> - else
> - OPTIONS="--dir $KBUILD_EXTMOD $COCCIINCLUDE"
> - fi
> + OPTIONS="--dir $srcroot $COCCIINCLUDE"
>
> # Use only one thread per core by default if hyperthreading is enabled
> THREADS_PER_CORE=$(LANG=C lscpu | grep "Thread(s) per core: " | tr -cd "[:digit:]")
> diff --git a/scripts/nsdeps b/scripts/nsdeps
> index f1718cc0d700..8ca12e2b5c03 100644
> --- a/scripts/nsdeps
> +++ b/scripts/nsdeps
> @@ -19,12 +19,6 @@ if ! { echo "$SPATCH_REQ_VERSION"; echo "$SPATCH_VERSION"; } | sort -CV ; then
> exit 1
> fi
>
> -if [ "$KBUILD_EXTMOD" ]; then
> - src_prefix=
> -else
> - src_prefix=$srctree/
> -fi
> -
> generate_deps_for_ns() {
> $SPATCH --very-quiet --in-place --sp-file \
> $srctree/scripts/coccinelle/misc/add_namespace.cocci -D nsdeps -D ns=$1 $2
> @@ -34,7 +28,7 @@ generate_deps() {
> local mod=${1%.ko:}
> shift
> local namespaces="$*"
> - local mod_source_files=$(sed "s|^\(.*\)\.o$|${src_prefix}\1.c|" $mod.mod)
> + local mod_source_files=$(sed "s|^\(.*\)\.o$|${srcroot}/\1.c|" $mod.mod)
>
> for ns in $namespaces; do
> echo "Adding namespace $ns to module $mod.ko."
> diff --git a/scripts/package/install-extmod-build b/scripts/package/install-extmod-build
> index 7ec1f061a519..64d958ee45f3 100755
> --- a/scripts/package/install-extmod-build
> +++ b/scripts/package/install-extmod-build
> @@ -51,6 +51,13 @@ mkdir -p "${destdir}"
> if [ "${CC}" != "${HOSTCC}" ]; then
> echo "Rebuilding host programs with ${CC}..."
>
> + # This leverages external module building.
> + # - Clear sub_make_done to allow the top-level Makefile to redo sub-make.
> + # - Filter out --no-print-directory to print "Entering directory" logs
> + # when Make changes the working directory.
> + unset sub_make_done
> + MAKEFLAGS=$(echo "${MAKEFLAGS}" | sed s/--no-print-directory//)
> +
> cat <<-'EOF' > "${destdir}/Kbuild"
> subdir-y := scripts
> EOF
> --
> 2.43.0
On Thu, Dec 5, 2024 at 8:35 AM Charlie Jenkins <charlie@rivosinc.com> wrote:
>
> On Sun, Nov 10, 2024 at 10:34:33AM +0900, Masahiro Yamada wrote:
> > Currently, Kbuild always operates in the output directory of the kernel,
> > even when building external modules. This increases the risk of external
> > module Makefiles attempting to write to the kernel directory.
> >
> > This commit switches the working directory to the external module
> > directory, allowing the removal of the $(KBUILD_EXTMOD)/ prefix from
> > some build artifacts.
> >
> > The command for building external modules maintains backward
> > compatibility, but Makefiles that rely on working in the kernel
> > directory may break. In such cases, $(objtree) and $(srctree) should
> > be used to refer to the output and source directories of the kernel.
> >
> > The appearance of the build log will change as follows:
> >
> > [Before]
> >
> > $ make -C /path/to/my/linux M=/path/to/my/externel/module
> > make: Entering directory '/path/to/my/linux'
> > CC [M] /path/to/my/externel/module/helloworld.o
> > MODPOST /path/to/my/externel/module/Module.symvers
> > CC [M] /path/to/my/externel/module/helloworld.mod.o
> > CC [M] /path/to/my/externel/module/.module-common.o
> > LD [M] /path/to/my/externel/module/helloworld.ko
> > make: Leaving directory '/path/to/my/linux'
> >
> > [After]
> >
> > $ make -C /path/to/my/linux M=/path/to/my/externel/module
> > make: Entering directory '/path/to/my/linux'
> > make[1]: Entering directory '/path/to/my/externel/module'
> > CC [M] helloworld.o
> > MODPOST Module.symvers
> > CC [M] helloworld.mod.o
> > CC [M] .module-common.o
> > LD [M] helloworld.ko
> > make[1]: Leaving directory '/path/to/my/externel/module'
> > make: Leaving directory '/path/to/my/linux'
> >
> > Printing "Entering directory" twice is cumbersome. This will be
> > addressed later.
>
> This change has caused O=<relative directory> to fail.
>
> For example:
>
> make O=build defconfig
> make -j$(nproc) V=1 O=build bindeb-pkg
>
> outputs:
>
> make ARCH=x86 KERNELRELEASE=6.13.0-rc1 KBUILD_BUILD_VERSION=3 run-command KBUILD_RUN_COMMAND='+$(srctree)/scripts/package/builddeb linux-libc-dev'
> dh_installchangelogs -plinux-image-6.13.0-rc1
> ../scripts/package/builddeb linux-headers-6.13.0-rc1
> dh_compress -plinux-image-6.13.0-rc1
> dh_fixperms -plinux-image-6.13.0-rc1
> dh_gencontrol -plinux-image-6.13.0-rc1 -- -fdebian/image.files
> Rebuilding host programs with x86_64-linux-gnu-gcc...
> make[6]: Entering directory '/scratch/kernels/linux/build'
> /scratch/kernels/linux/Makefile:190: *** specified kernel directory "build" does not exist. Stop.
>
> It is stepping into this directory and then trying to find the directory
> it just stepped into so $(realpath $(KBUILD_OUTPUT)) returns an empty
> string.
>
> Using an absolute directory resolves this problem, but I believe it
> shouldn't be necessary.
Agree.
I will apply the following fixup unless I have a better idea.
diff --git a/scripts/package/install-extmod-build
b/scripts/package/install-extmod-build
index 64d958ee45f3..85af1573db31 100755
--- a/scripts/package/install-extmod-build
+++ b/scripts/package/install-extmod-build
@@ -69,7 +69,7 @@ if [ "${CC}" != "${HOSTCC}" ]; then
#
# Use the single-target build to avoid the modpost invocation, which
# would overwrite Module.symvers.
- "${MAKE}" HOSTCC="${CC}" KBUILD_EXTMOD="${destdir}" scripts/
+ "${MAKE}" O=. HOSTCC="${CC}" KBUILD_EXTMOD="${destdir}" scripts/
cat <<-'EOF' > "${destdir}/scripts/Kbuild"
subdir-y := basic
@@ -78,7 +78,7 @@ if [ "${CC}" != "${HOSTCC}" ]; then
EOF
# Run once again to rebuild scripts/basic/ and scripts/mod/modpost.
- "${MAKE}" HOSTCC="${CC}" KBUILD_EXTMOD="${destdir}" scripts/
+ "${MAKE}" O=. HOSTCC="${CC}" KBUILD_EXTMOD="${destdir}" scripts/
rm -f "${destdir}/Kbuild" "${destdir}/scripts/Kbuild"
fi
--
Best Regards
Masahiro Yamada
On Thu, Dec 05, 2024 at 11:48:08AM +0900, Masahiro Yamada wrote:
> On Thu, Dec 5, 2024 at 8:35 AM Charlie Jenkins <charlie@rivosinc.com> wrote:
> >
> > On Sun, Nov 10, 2024 at 10:34:33AM +0900, Masahiro Yamada wrote:
> > > Currently, Kbuild always operates in the output directory of the kernel,
> > > even when building external modules. This increases the risk of external
> > > module Makefiles attempting to write to the kernel directory.
> > >
> > > This commit switches the working directory to the external module
> > > directory, allowing the removal of the $(KBUILD_EXTMOD)/ prefix from
> > > some build artifacts.
> > >
> > > The command for building external modules maintains backward
> > > compatibility, but Makefiles that rely on working in the kernel
> > > directory may break. In such cases, $(objtree) and $(srctree) should
> > > be used to refer to the output and source directories of the kernel.
> > >
> > > The appearance of the build log will change as follows:
> > >
> > > [Before]
> > >
> > > $ make -C /path/to/my/linux M=/path/to/my/externel/module
> > > make: Entering directory '/path/to/my/linux'
> > > CC [M] /path/to/my/externel/module/helloworld.o
> > > MODPOST /path/to/my/externel/module/Module.symvers
> > > CC [M] /path/to/my/externel/module/helloworld.mod.o
> > > CC [M] /path/to/my/externel/module/.module-common.o
> > > LD [M] /path/to/my/externel/module/helloworld.ko
> > > make: Leaving directory '/path/to/my/linux'
> > >
> > > [After]
> > >
> > > $ make -C /path/to/my/linux M=/path/to/my/externel/module
> > > make: Entering directory '/path/to/my/linux'
> > > make[1]: Entering directory '/path/to/my/externel/module'
> > > CC [M] helloworld.o
> > > MODPOST Module.symvers
> > > CC [M] helloworld.mod.o
> > > CC [M] .module-common.o
> > > LD [M] helloworld.ko
> > > make[1]: Leaving directory '/path/to/my/externel/module'
> > > make: Leaving directory '/path/to/my/linux'
> > >
> > > Printing "Entering directory" twice is cumbersome. This will be
> > > addressed later.
> >
> > This change has caused O=<relative directory> to fail.
> >
> > For example:
> >
> > make O=build defconfig
> > make -j$(nproc) V=1 O=build bindeb-pkg
> >
> > outputs:
> >
> > make ARCH=x86 KERNELRELEASE=6.13.0-rc1 KBUILD_BUILD_VERSION=3 run-command KBUILD_RUN_COMMAND='+$(srctree)/scripts/package/builddeb linux-libc-dev'
> > dh_installchangelogs -plinux-image-6.13.0-rc1
> > ../scripts/package/builddeb linux-headers-6.13.0-rc1
> > dh_compress -plinux-image-6.13.0-rc1
> > dh_fixperms -plinux-image-6.13.0-rc1
> > dh_gencontrol -plinux-image-6.13.0-rc1 -- -fdebian/image.files
> > Rebuilding host programs with x86_64-linux-gnu-gcc...
> > make[6]: Entering directory '/scratch/kernels/linux/build'
> > /scratch/kernels/linux/Makefile:190: *** specified kernel directory "build" does not exist. Stop.
> >
> > It is stepping into this directory and then trying to find the directory
> > it just stepped into so $(realpath $(KBUILD_OUTPUT)) returns an empty
> > string.
> >
> > Using an absolute directory resolves this problem, but I believe it
> > shouldn't be necessary.
>
>
> Agree.
>
> I will apply the following fixup unless I have a better idea.
>
>
>
>
> diff --git a/scripts/package/install-extmod-build
> b/scripts/package/install-extmod-build
> index 64d958ee45f3..85af1573db31 100755
> --- a/scripts/package/install-extmod-build
> +++ b/scripts/package/install-extmod-build
> @@ -69,7 +69,7 @@ if [ "${CC}" != "${HOSTCC}" ]; then
> #
> # Use the single-target build to avoid the modpost invocation, which
> # would overwrite Module.symvers.
> - "${MAKE}" HOSTCC="${CC}" KBUILD_EXTMOD="${destdir}" scripts/
> + "${MAKE}" O=. HOSTCC="${CC}" KBUILD_EXTMOD="${destdir}" scripts/
>
> cat <<-'EOF' > "${destdir}/scripts/Kbuild"
> subdir-y := basic
> @@ -78,7 +78,7 @@ if [ "${CC}" != "${HOSTCC}" ]; then
> EOF
>
> # Run once again to rebuild scripts/basic/ and scripts/mod/modpost.
> - "${MAKE}" HOSTCC="${CC}" KBUILD_EXTMOD="${destdir}" scripts/
> + "${MAKE}" O=. HOSTCC="${CC}" KBUILD_EXTMOD="${destdir}" scripts/
>
> rm -f "${destdir}/Kbuild" "${destdir}/scripts/Kbuild"
> fi
>
Looks fine to me :)
If this is what you decide on, feel free to add my tags.
Tested-by: Charlie Jenkins <charlie@rivosinc.com>
Reviewed-by: Charlie Jenkins <charlie@rivosinc.com>
>
>
> --
> Best Regards
> Masahiro Yamada
On Sun, Nov 10, 2024 at 10:34:33AM +0900, Masahiro Yamada wrote:
> Currently, Kbuild always operates in the output directory of the kernel,
> even when building external modules. This increases the risk of external
> module Makefiles attempting to write to the kernel directory.
>
> This commit switches the working directory to the external module
> directory, allowing the removal of the $(KBUILD_EXTMOD)/ prefix from
> some build artifacts.
>
> The command for building external modules maintains backward
> compatibility, but Makefiles that rely on working in the kernel
> directory may break. In such cases, $(objtree) and $(srctree) should
> be used to refer to the output and source directories of the kernel.
>
> The appearance of the build log will change as follows:
>
> [Before]
>
> $ make -C /path/to/my/linux M=/path/to/my/externel/module
> make: Entering directory '/path/to/my/linux'
> CC [M] /path/to/my/externel/module/helloworld.o
> MODPOST /path/to/my/externel/module/Module.symvers
> CC [M] /path/to/my/externel/module/helloworld.mod.o
> CC [M] /path/to/my/externel/module/.module-common.o
> LD [M] /path/to/my/externel/module/helloworld.ko
> make: Leaving directory '/path/to/my/linux'
>
> [After]
>
> $ make -C /path/to/my/linux M=/path/to/my/externel/module
> make: Entering directory '/path/to/my/linux'
> make[1]: Entering directory '/path/to/my/externel/module'
> CC [M] helloworld.o
> MODPOST Module.symvers
> CC [M] helloworld.mod.o
> CC [M] .module-common.o
> LD [M] helloworld.ko
> make[1]: Leaving directory '/path/to/my/externel/module'
> make: Leaving directory '/path/to/my/linux'
>
> Printing "Entering directory" twice is cumbersome. This will be
> addressed later.
>
> Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
> ---
With this in v6.13-rc1 the cxl-test module fails depmod.
It causes depmod to be invoked from the incorrect place
(or something doesn't respect INSTALL_MOD_PATH)
Is there something additional that this cxl-test module needs
to do?
Repro:
/git/new$ make V=1 M=tools/testing/cxl INSTALL_MOD_PATH=qbuild/mkosi.extra/ modules_install
Outputs:
make -C /home/cxluser/git/new/tools/testing/cxl \
-f /home/cxluser/git/new/Makefile modules_install
make[1]: Entering directory '/home/cxluser/git/new/tools/testing/cxl'
make --no-print-directory -C /home/cxluser/git/new/tools/testing/cxl \
-f /home/cxluser/git/new/Makefile modules_install
make -f /home/cxluser/git/new/scripts/Makefile.modinst \
sign-only=
# INSTALL qbuild/mkosi.extra//lib/modules/6.13.0-rc1+/updates/cxl_acpi.ko
cp cxl_acpi.ko qbuild/mkosi.extra//lib/modules/6.13.0-rc1+/updates/cxl_acpi.ko
# cmd_strip qbuild/mkosi.extra//lib/modules/6.13.0-rc1+/updates/cxl_acpi.ko
:
# cmd_sign qbuild/mkosi.extra//lib/modules/6.13.0-rc1+/updates/cxl_acpi.ko
:
# INSTALL qbuild/mkosi.extra//lib/modules/6.13.0-rc1+/updates/cxl_pmem.ko
cp cxl_pmem.ko qbuild/mkosi.extra//lib/modules/6.13.0-rc1+/updates/cxl_pmem.ko
# cmd_strip qbuild/mkosi.extra//lib/modules/6.13.0-rc1+/updates/cxl_pmem.ko
:
# cmd_sign qbuild/mkosi.extra//lib/modules/6.13.0-rc1+/updates/cxl_pmem.ko
:
# INSTALL qbuild/mkosi.extra//lib/modules/6.13.0-rc1+/updates/cxl_port.ko
cp cxl_port.ko qbuild/mkosi.extra//lib/modules/6.13.0-rc1+/updates/cxl_port.ko
# cmd_strip qbuild/mkosi.extra//lib/modules/6.13.0-rc1+/updates/cxl_port.ko
:
# cmd_sign qbuild/mkosi.extra//lib/modules/6.13.0-rc1+/updates/cxl_port.ko
:
# INSTALL qbuild/mkosi.extra//lib/modules/6.13.0-rc1+/updates/cxl_mem.ko
cp cxl_mem.ko qbuild/mkosi.extra//lib/modules/6.13.0-rc1+/updates/cxl_mem.ko
# cmd_strip qbuild/mkosi.extra//lib/modules/6.13.0-rc1+/updates/cxl_mem.ko
:
# cmd_sign qbuild/mkosi.extra//lib/modules/6.13.0-rc1+/updates/cxl_mem.ko
:
# INSTALL qbuild/mkosi.extra//lib/modules/6.13.0-rc1+/updates/cxl_core.ko
cp cxl_core.ko qbuild/mkosi.extra//lib/modules/6.13.0-rc1+/updates/cxl_core.ko
# cmd_strip qbuild/mkosi.extra//lib/modules/6.13.0-rc1+/updates/cxl_core.ko
:
# cmd_sign qbuild/mkosi.extra//lib/modules/6.13.0-rc1+/updates/cxl_core.ko
:
# INSTALL qbuild/mkosi.extra//lib/modules/6.13.0-rc1+/updates/test/cxl_test.ko
cp test/cxl_test.ko qbuild/mkosi.extra//lib/modules/6.13.0-rc1+/updates/test/cxl_test.ko
# cmd_strip qbuild/mkosi.extra//lib/modules/6.13.0-rc1+/updates/test/cxl_test.ko
:
# cmd_sign qbuild/mkosi.extra//lib/modules/6.13.0-rc1+/updates/test/cxl_test.ko
:
# INSTALL qbuild/mkosi.extra//lib/modules/6.13.0-rc1+/updates/test/cxl_mock.ko
cp test/cxl_mock.ko qbuild/mkosi.extra//lib/modules/6.13.0-rc1+/updates/test/cxl_mock.ko
# cmd_strip qbuild/mkosi.extra//lib/modules/6.13.0-rc1+/updates/test/cxl_mock.ko
:
# cmd_sign qbuild/mkosi.extra//lib/modules/6.13.0-rc1+/updates/test/cxl_mock.ko
:
# INSTALL qbuild/mkosi.extra//lib/modules/6.13.0-rc1+/updates/test/cxl_mock_mem.ko
cp test/cxl_mock_mem.ko qbuild/mkosi.extra//lib/modules/6.13.0-rc1+/updates/test/cxl_mock_mem.ko
# cmd_strip qbuild/mkosi.extra//lib/modules/6.13.0-rc1+/updates/test/cxl_mock_mem.ko
:
# cmd_sign qbuild/mkosi.extra//lib/modules/6.13.0-rc1+/updates/test/cxl_mock_mem.ko
:
# DEPMOD qbuild/mkosi.extra//lib/modules/6.13.0-rc1+
/home/cxluser/git/new/scripts/depmod.sh 6.13.0-rc1+
depmod: WARNING: could not open modules.order at /home/cxluser/git/new/tools/testing/cxl/qbuild/mkosi.extra//lib/modules/6.13.0-rc1+: No such file or directory
depmod: WARNING: /home/cxluser/git/new/tools/testing/cxl/qbuild/mkosi.extra//lib/modules/6.13.0-rc1+/updates/test/cxl_mock.ko needs unknown symbol nvdimm_bus_register
depmod: WARNING: /home/cxluser/git/new/tools/testing/cxl/qbuild/mkosi.extra//lib/modules/6.13.0-rc1+/updates/cxl_pmem.ko needs unknown symbol to_nvdimm
depmod: WARNING: /home/cxluser/git/new/tools/testing/cxl/qbuild/mkosi.extra//lib/modules/6.13.0-rc1+/updates/cxl_pmem.ko needs unknown symbol __nvdimm_create
depmod: WARNING: /home/cxluser/git/new/tools/testing/cxl/qbuild/mkosi.extra//lib/modules/6.13.0-rc1+/updates/cxl_pmem.ko needs unknown symbol nvdimm_bus_unregister
depmod: WARNING: /home/cxluser/git/new/tools/testing/cxl/qbuild/mkosi.extra//lib/modules/6.13.0-rc1+/updates/cxl_pmem.ko needs unknown symbol nvdimm_region_delete
depmod: WARNING: /home/cxluser/git/new/tools/testing/cxl/qbuild/mkosi.extra//lib/modules/6.13.0-rc1+/updates/cxl_pmem.ko needs unknown symbol nvdimm_delete
depmod: WARNING: /home/cxluser/git/new/tools/testing/cxl/qbuild/mkosi.extra//lib/modules/6.13.0-rc1+/updates/cxl_pmem.ko needs unknown symbol nvdimm_provider_data
depmod: WARNING: /home/cxluser/git/new/tools/testing/cxl/qbuild/mkosi.extra//lib/modules/6.13.0-rc1+/updates/cxl_pmem.ko needs unknown symbol nvdimm_pmem_region_create
depmod: WARNING: /home/cxluser/git/new/tools/testing/cxl/qbuild/mkosi.extra//lib/modules/6.13.0-rc1+/updates/cxl_pmem.ko needs unknown symbol nd_fletcher64
depmod: WARNING: /home/cxluser/git/new/tools/testing/cxl/qbuild/mkosi.extra//lib/modules/6.13.0-rc1+/updates/cxl_pmem.ko needs unknown symbol nvdimm_cmd_mask
depmod: WARNING: could not open modules.builtin at /home/cxluser/git/new/tools/testing/cxl/qbuild/mkosi.extra//lib/modules/6.13.0-rc1+: No such file or directory
make[1]: Leaving directory '/home/cxluser/git/new/tools/testing/cxl'
cxluser@MySS:~/git/new$
>
> Changes in v2:
> - Introduce a new 'srcroot' variable and clean-up code
> - Reword Documentation/dev-tools/coccinelle.rst
>
> Documentation/dev-tools/coccinelle.rst | 20 ++-----
> Documentation/kbuild/makefiles.rst | 14 +++++
> Makefile | 80 +++++++++++++++-----------
> rust/Makefile | 4 +-
> scripts/Makefile.build | 2 +-
> scripts/Makefile.clean | 2 +-
> scripts/Makefile.compiler | 2 +-
> scripts/Makefile.modpost | 6 +-
> scripts/coccicheck | 6 +-
> scripts/nsdeps | 8 +--
> scripts/package/install-extmod-build | 7 +++
> 11 files changed, 85 insertions(+), 66 deletions(-)
>
> diff --git a/Documentation/dev-tools/coccinelle.rst b/Documentation/dev-tools/coccinelle.rst
> index 535ce126fb4f..6e70a1e9a3c0 100644
> --- a/Documentation/dev-tools/coccinelle.rst
> +++ b/Documentation/dev-tools/coccinelle.rst
> @@ -250,25 +250,17 @@ variables for .cocciconfig is as follows:
> - Your directory from which spatch is called is processed next
> - The directory provided with the ``--dir`` option is processed last, if used
>
> -Since coccicheck runs through make, it naturally runs from the kernel
> -proper dir; as such the second rule above would be implied for picking up a
> -.cocciconfig when using ``make coccicheck``.
> -
> ``make coccicheck`` also supports using M= targets. If you do not supply
> any M= target, it is assumed you want to target the entire kernel.
> The kernel coccicheck script has::
>
> - if [ "$KBUILD_EXTMOD" = "" ] ; then
> - OPTIONS="--dir $srctree $COCCIINCLUDE"
> - else
> - OPTIONS="--dir $KBUILD_EXTMOD $COCCIINCLUDE"
> - fi
> + OPTIONS="--dir $srcroot $COCCIINCLUDE"
>
> -KBUILD_EXTMOD is set when an explicit target with M= is used. For both cases
> -the spatch ``--dir`` argument is used, as such third rule applies when whether
> -M= is used or not, and when M= is used the target directory can have its own
> -.cocciconfig file. When M= is not passed as an argument to coccicheck the
> -target directory is the same as the directory from where spatch was called.
> +Here, $srcroot refers to the source directory of the target: it points to the
> +external module's source directory when M= used, and otherwise, to the kernel
> +source directory. The third rule ensures the spatch reads the .cocciconfig from
> +the target directory, allowing external modules to have their own .cocciconfig
> +file.
>
> If not using the kernel's coccicheck target, keep the above precedence
> order logic of .cocciconfig reading. If using the kernel's coccicheck target,
> diff --git a/Documentation/kbuild/makefiles.rst b/Documentation/kbuild/makefiles.rst
> index 7964e0c245ae..d36519f194dc 100644
> --- a/Documentation/kbuild/makefiles.rst
> +++ b/Documentation/kbuild/makefiles.rst
> @@ -449,6 +449,20 @@ $(obj)
> to prerequisites are referenced with $(src) (because they are not
> generated files).
>
> +$(srcroot)
> + $(srcroot) refers to the root of the source you are building, which can be
> + either the kernel source or the external modules source, depending on whether
> + KBUILD_EXTMOD is set. This can be either a relative or an absolute path, but
> + if KBUILD_ABS_SRCTREE=1 is set, it is always an absolute path.
> +
> +$(srctree)
> + $(srctree) refers to the root of the kernel source tree. When building the
> + kernel, this is the same as $(srcroot).
> +
> +$(objtree)
> + $(objtree) refers to the root of the kernel object tree. It is ``.`` when
> + building the kernel, but it is different when building external modules.
> +
> $(kecho)
> echoing information to user in a rule is often a good practice
> but when execution ``make -s`` one does not expect to see any output
> diff --git a/Makefile b/Makefile
> index cf1d55560ae2..e5f7ac7647a7 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -180,7 +180,24 @@ ifeq ("$(origin O)", "command line")
> KBUILD_OUTPUT := $(O)
> endif
>
> -output := $(KBUILD_OUTPUT)
> +ifdef KBUILD_EXTMOD
> + ifdef KBUILD_OUTPUT
> + objtree := $(realpath $(KBUILD_OUTPUT))
> + $(if $(objtree),,$(error specified kernel directory "$(KBUILD_OUTPUT)" does not exist))
> + else
> + objtree := $(CURDIR)
> + endif
> + output := $(KBUILD_EXTMOD)
> + # KBUILD_EXTMOD might be a relative path. Remember its absolute path before
> + # Make changes the working directory.
> + srcroot := $(realpath $(KBUILD_EXTMOD))
> + $(if $(srcroot),,$(error specified external module directory "$(KBUILD_EXTMOD)" does not exist))
> +else
> + objtree := .
> + output := $(KBUILD_OUTPUT)
> +endif
> +
> +export objtree srcroot
>
> # Do we want to change the working directory?
> ifneq ($(output),)
> @@ -230,35 +247,33 @@ else # need-sub-make
>
> # We process the rest of the Makefile if this is the final invocation of make
>
> -ifeq ($(abs_srctree),$(CURDIR))
> - # building in the source tree
> - srctree := .
> - building_out_of_srctree :=
> +ifndef KBUILD_EXTMOD
> +srcroot := $(abs_srctree)
> +endif
> +
> +ifeq ($(srcroot),$(CURDIR))
> +building_out_of_srctree :=
> else
> - ifeq ($(abs_srctree)/,$(dir $(CURDIR)))
> - # building in a subdirectory of the source tree
> - srctree := ..
> - else
> - srctree := $(abs_srctree)
> - endif
> - building_out_of_srctree := 1
> +export building_out_of_srctree :=1
> endif
>
> -ifneq ($(KBUILD_ABS_SRCTREE),)
> -srctree := $(abs_srctree)
> +ifdef KBUILD_ABS_SRCTREE
> + # Do not nothing. Use the absolute path.
> +else ifeq ($(srcroot),$(CURDIR))
> + # Building in the source.
> + srcroot := .
> +else ifeq ($(srcroot)/,$(dir $(CURDIR)))
> + # Building in a subdirectory of the source.
> + srcroot := ..
> endif
>
> -objtree := .
> +export srctree := $(if $(KBUILD_EXTMOD),$(abs_srctree),$(srcroot))
>
> -VPATH :=
> -
> -ifeq ($(KBUILD_EXTMOD),)
> ifdef building_out_of_srctree
> -VPATH := $(srctree)
> +export VPATH := $(srcroot)
> +else
> +VPATH :=
> endif
> -endif
> -
> -export building_out_of_srctree srctree objtree VPATH
>
> # To make sure we do not include .config for any of the *config targets
> # catch them early, and hand them over to scripts/kconfig/Makefile
> @@ -711,7 +726,7 @@ endif
> # in addition to whatever we do anyway.
> # Just "make" or "make all" shall build modules as well
>
> -ifneq ($(filter all modules nsdeps %compile_commands.json clang-%,$(MAKECMDGOALS)),)
> +ifneq ($(filter all modules nsdeps compile_commands.json clang-%,$(MAKECMDGOALS)),)
> KBUILD_MODULES := 1
> endif
>
> @@ -1107,7 +1122,7 @@ export MODLIB
>
> PHONY += prepare0
>
> -export extmod_prefix = $(if $(KBUILD_EXTMOD),$(KBUILD_EXTMOD)/)
> +export extmod_prefix =
> export MODORDER := $(extmod_prefix)modules.order
> export MODULES_NSDEPS := $(extmod_prefix)modules.nsdeps
>
> @@ -1799,14 +1814,10 @@ filechk_kernel.release = echo $(KERNELRELEASE)
> KBUILD_BUILTIN :=
> KBUILD_MODULES := 1
>
> -build-dir := $(KBUILD_EXTMOD)
> +build-dir := .
>
> -compile_commands.json: $(extmod_prefix)compile_commands.json
> -PHONY += compile_commands.json
> -
> -clean-dirs := $(KBUILD_EXTMOD)
> -clean: private rm-files := $(KBUILD_EXTMOD)/Module.symvers $(KBUILD_EXTMOD)/modules.nsdeps \
> - $(KBUILD_EXTMOD)/compile_commands.json
> +clean-dirs := .
> +clean: private rm-files := Module.symvers modules.nsdeps compile_commands.json
>
> PHONY += prepare
> # now expand this into a simple variable to reduce the cost of shell evaluations
> @@ -1948,7 +1959,7 @@ $(clean-dirs):
>
> clean: $(clean-dirs)
> $(call cmd,rmfiles)
> - @find $(or $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \
> + @find . $(RCS_FIND_IGNORE) \
> \( -name '*.[aios]' -o -name '*.rsi' -o -name '*.ko' -o -name '.*.cmd' \
> -o -name '*.ko.*' \
> -o -name '*.dtb' -o -name '*.dtbo' \
> @@ -1981,7 +1992,12 @@ tags TAGS cscope gtags: FORCE
> PHONY += rust-analyzer
> rust-analyzer:
> +$(Q)$(CONFIG_SHELL) $(srctree)/scripts/rust_is_available.sh
> +ifdef KBUILD_EXTMOD
> +# FIXME: external modules must not descend into a sub-directory of the kernel
> + $(Q)$(MAKE) $(build)=$(objtree)/rust src=$(srctree)/rust $@
> +else
> $(Q)$(MAKE) $(build)=rust $@
> +endif
>
> # Script to generate missing namespace dependencies
> # ---------------------------------------------------------------------------
> diff --git a/rust/Makefile b/rust/Makefile
> index b5e0a73b78f3..742740816c4b 100644
> --- a/rust/Makefile
> +++ b/rust/Makefile
> @@ -362,8 +362,8 @@ rust-analyzer:
> $(Q)$(srctree)/scripts/generate_rust_analyzer.py \
> --cfgs='core=$(core-cfgs)' --cfgs='alloc=$(alloc-cfgs)' \
> $(realpath $(srctree)) $(realpath $(objtree)) \
> - $(rustc_sysroot) $(RUST_LIB_SRC) $(KBUILD_EXTMOD) > \
> - $(if $(KBUILD_EXTMOD),$(extmod_prefix),$(objtree))/rust-project.json
> + $(rustc_sysroot) $(RUST_LIB_SRC) $(if $(KBUILD_EXTMOD),$(srcroot)) \
> + > rust-project.json
>
> redirect-intrinsics = \
> __addsf3 __eqsf2 __extendsfdf2 __gesf2 __lesf2 __ltsf2 __mulsf3 __nesf2 __truncdfsf2 __unordsf2 \
> diff --git a/scripts/Makefile.build b/scripts/Makefile.build
> index 64cd046f8fd8..1aa928a6fb4f 100644
> --- a/scripts/Makefile.build
> +++ b/scripts/Makefile.build
> @@ -3,7 +3,7 @@
> # Building
> # ==========================================================================
>
> -src := $(if $(VPATH),$(VPATH)/)$(obj)
> +src := $(srcroot)/$(obj)
>
> PHONY := $(obj)/
> $(obj)/:
> diff --git a/scripts/Makefile.clean b/scripts/Makefile.clean
> index 4fcfab40ed61..6ead00ec7313 100644
> --- a/scripts/Makefile.clean
> +++ b/scripts/Makefile.clean
> @@ -3,7 +3,7 @@
> # Cleaning up
> # ==========================================================================
>
> -src := $(if $(VPATH),$(VPATH)/)$(obj)
> +src := $(srcroot)/$(obj)
>
> PHONY := __clean
> __clean:
> diff --git a/scripts/Makefile.compiler b/scripts/Makefile.compiler
> index e0842496d26e..8c1029687e2e 100644
> --- a/scripts/Makefile.compiler
> +++ b/scripts/Makefile.compiler
> @@ -13,7 +13,7 @@ cc-cross-prefix = $(firstword $(foreach c, $(1), \
> $(if $(shell command -v -- $(c)gcc 2>/dev/null), $(c))))
>
> # output directory for tests below
> -TMPOUT = $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/).tmp_$$$$
> +TMPOUT = .tmp_$$$$
>
> # try-run
> # Usage: option = $(call try-run, $(CC)...-o "$$TMP",option-ok,otherwise)
> diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
> index 12e7c15d099c..78d2ca4f25f5 100644
> --- a/scripts/Makefile.modpost
> +++ b/scripts/Makefile.modpost
> @@ -111,13 +111,13 @@ endif
> else
>
> # set src + obj - they may be used in the modules's Makefile
> -obj := $(KBUILD_EXTMOD)
> -src := $(if $(VPATH),$(VPATH)/)$(obj)
> +obj := .
> +src := $(srcroot)
>
> # Include the module's Makefile to find KBUILD_EXTRA_SYMBOLS
> include $(kbuild-file)
>
> -output-symdump := $(KBUILD_EXTMOD)/Module.symvers
> +output-symdump := Module.symvers
>
> ifeq ($(wildcard $(objtree)/Module.symvers),)
> missing-input := $(objtree)/Module.symvers
> diff --git a/scripts/coccicheck b/scripts/coccicheck
> index e52cb43fede6..0e6bc5a10320 100755
> --- a/scripts/coccicheck
> +++ b/scripts/coccicheck
> @@ -80,11 +80,7 @@ command results in a shift count error.'
> NPROC=1
> else
> ONLINE=0
> - if [ "$KBUILD_EXTMOD" = "" ] ; then
> - OPTIONS="--dir $srctree $COCCIINCLUDE"
> - else
> - OPTIONS="--dir $KBUILD_EXTMOD $COCCIINCLUDE"
> - fi
> + OPTIONS="--dir $srcroot $COCCIINCLUDE"
>
> # Use only one thread per core by default if hyperthreading is enabled
> THREADS_PER_CORE=$(LANG=C lscpu | grep "Thread(s) per core: " | tr -cd "[:digit:]")
> diff --git a/scripts/nsdeps b/scripts/nsdeps
> index f1718cc0d700..8ca12e2b5c03 100644
> --- a/scripts/nsdeps
> +++ b/scripts/nsdeps
> @@ -19,12 +19,6 @@ if ! { echo "$SPATCH_REQ_VERSION"; echo "$SPATCH_VERSION"; } | sort -CV ; then
> exit 1
> fi
>
> -if [ "$KBUILD_EXTMOD" ]; then
> - src_prefix=
> -else
> - src_prefix=$srctree/
> -fi
> -
> generate_deps_for_ns() {
> $SPATCH --very-quiet --in-place --sp-file \
> $srctree/scripts/coccinelle/misc/add_namespace.cocci -D nsdeps -D ns=$1 $2
> @@ -34,7 +28,7 @@ generate_deps() {
> local mod=${1%.ko:}
> shift
> local namespaces="$*"
> - local mod_source_files=$(sed "s|^\(.*\)\.o$|${src_prefix}\1.c|" $mod.mod)
> + local mod_source_files=$(sed "s|^\(.*\)\.o$|${srcroot}/\1.c|" $mod.mod)
>
> for ns in $namespaces; do
> echo "Adding namespace $ns to module $mod.ko."
> diff --git a/scripts/package/install-extmod-build b/scripts/package/install-extmod-build
> index 7ec1f061a519..64d958ee45f3 100755
> --- a/scripts/package/install-extmod-build
> +++ b/scripts/package/install-extmod-build
> @@ -51,6 +51,13 @@ mkdir -p "${destdir}"
> if [ "${CC}" != "${HOSTCC}" ]; then
> echo "Rebuilding host programs with ${CC}..."
>
> + # This leverages external module building.
> + # - Clear sub_make_done to allow the top-level Makefile to redo sub-make.
> + # - Filter out --no-print-directory to print "Entering directory" logs
> + # when Make changes the working directory.
> + unset sub_make_done
> + MAKEFLAGS=$(echo "${MAKEFLAGS}" | sed s/--no-print-directory//)
> +
> cat <<-'EOF' > "${destdir}/Kbuild"
> subdir-y := scripts
> EOF
> --
> 2.43.0
>
On Thu, Dec 5, 2024 at 5:51 AM Alison Schofield <alison.schofield@intel.com> wrote: > > On Sun, Nov 10, 2024 at 10:34:33AM +0900, Masahiro Yamada wrote: > > Currently, Kbuild always operates in the output directory of the kernel, > > even when building external modules. This increases the risk of external > > module Makefiles attempting to write to the kernel directory. > > > > This commit switches the working directory to the external module > > directory, allowing the removal of the $(KBUILD_EXTMOD)/ prefix from > > some build artifacts. > > > > The command for building external modules maintains backward > > compatibility, but Makefiles that rely on working in the kernel > > directory may break. In such cases, $(objtree) and $(srctree) should > > be used to refer to the output and source directories of the kernel. > > > > The appearance of the build log will change as follows: > > > > [Before] > > > > $ make -C /path/to/my/linux M=/path/to/my/externel/module > > make: Entering directory '/path/to/my/linux' > > CC [M] /path/to/my/externel/module/helloworld.o > > MODPOST /path/to/my/externel/module/Module.symvers > > CC [M] /path/to/my/externel/module/helloworld.mod.o > > CC [M] /path/to/my/externel/module/.module-common.o > > LD [M] /path/to/my/externel/module/helloworld.ko > > make: Leaving directory '/path/to/my/linux' > > > > [After] > > > > $ make -C /path/to/my/linux M=/path/to/my/externel/module > > make: Entering directory '/path/to/my/linux' > > make[1]: Entering directory '/path/to/my/externel/module' > > CC [M] helloworld.o > > MODPOST Module.symvers > > CC [M] helloworld.mod.o > > CC [M] .module-common.o > > LD [M] helloworld.ko > > make[1]: Leaving directory '/path/to/my/externel/module' > > make: Leaving directory '/path/to/my/linux' > > > > Printing "Entering directory" twice is cumbersome. This will be > > addressed later. > > > > Signed-off-by: Masahiro Yamada <masahiroy@kernel.org> > > --- > > With this in v6.13-rc1 the cxl-test module fails depmod. > It causes depmod to be invoked from the incorrect place > (or something doesn't respect INSTALL_MOD_PATH) > > Is there something additional that this cxl-test module needs > to do? > > Repro: > /git/new$ make V=1 M=tools/testing/cxl INSTALL_MOD_PATH=qbuild/mkosi.extra/ modules_install Kbuild changes the working directory, so you need to specify an absolute path for INSTALL_MOD_PATH. INSTALL_MOD_PATH=$(realpath qbuild/mkosi.extra/) -- Best Regards Masahiro Yamada
On Sun, Nov 10, 2024 at 10:34:33AM +0900, Masahiro Yamada wrote:
> Currently, Kbuild always operates in the output directory of the kernel,
> even when building external modules. This increases the risk of external
> module Makefiles attempting to write to the kernel directory.
>
> This commit switches the working directory to the external module
> directory, allowing the removal of the $(KBUILD_EXTMOD)/ prefix from
> some build artifacts.
>
> The command for building external modules maintains backward
> compatibility, but Makefiles that rely on working in the kernel
> directory may break. In such cases, $(objtree) and $(srctree) should
> be used to refer to the output and source directories of the kernel.
>
> The appearance of the build log will change as follows:
>
> [Before]
>
> $ make -C /path/to/my/linux M=/path/to/my/externel/module
> make: Entering directory '/path/to/my/linux'
> CC [M] /path/to/my/externel/module/helloworld.o
> MODPOST /path/to/my/externel/module/Module.symvers
> CC [M] /path/to/my/externel/module/helloworld.mod.o
> CC [M] /path/to/my/externel/module/.module-common.o
> LD [M] /path/to/my/externel/module/helloworld.ko
> make: Leaving directory '/path/to/my/linux'
>
> [After]
>
> $ make -C /path/to/my/linux M=/path/to/my/externel/module
> make: Entering directory '/path/to/my/linux'
> make[1]: Entering directory '/path/to/my/externel/module'
> CC [M] helloworld.o
> MODPOST Module.symvers
> CC [M] helloworld.mod.o
> CC [M] .module-common.o
> LD [M] helloworld.ko
> make[1]: Leaving directory '/path/to/my/externel/module'
> make: Leaving directory '/path/to/my/linux'
>
> Printing "Entering directory" twice is cumbersome. This will be
> addressed later.
>
> Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
> ---
>
> Changes in v2:
> - Introduce a new 'srcroot' variable and clean-up code
> - Reword Documentation/dev-tools/coccinelle.rst
>
> Documentation/dev-tools/coccinelle.rst | 20 ++-----
> Documentation/kbuild/makefiles.rst | 14 +++++
> Makefile | 80 +++++++++++++++-----------
> rust/Makefile | 4 +-
> scripts/Makefile.build | 2 +-
> scripts/Makefile.clean | 2 +-
> scripts/Makefile.compiler | 2 +-
> scripts/Makefile.modpost | 6 +-
> scripts/coccicheck | 6 +-
> scripts/nsdeps | 8 +--
> scripts/package/install-extmod-build | 7 +++
> 11 files changed, 85 insertions(+), 66 deletions(-)
>
> diff --git a/Documentation/dev-tools/coccinelle.rst b/Documentation/dev-tools/coccinelle.rst
> index 535ce126fb4f..6e70a1e9a3c0 100644
> --- a/Documentation/dev-tools/coccinelle.rst
> +++ b/Documentation/dev-tools/coccinelle.rst
> @@ -250,25 +250,17 @@ variables for .cocciconfig is as follows:
> - Your directory from which spatch is called is processed next
> - The directory provided with the ``--dir`` option is processed last, if used
>
> -Since coccicheck runs through make, it naturally runs from the kernel
> -proper dir; as such the second rule above would be implied for picking up a
> -.cocciconfig when using ``make coccicheck``.
> -
> ``make coccicheck`` also supports using M= targets. If you do not supply
> any M= target, it is assumed you want to target the entire kernel.
> The kernel coccicheck script has::
>
> - if [ "$KBUILD_EXTMOD" = "" ] ; then
> - OPTIONS="--dir $srctree $COCCIINCLUDE"
> - else
> - OPTIONS="--dir $KBUILD_EXTMOD $COCCIINCLUDE"
> - fi
> + OPTIONS="--dir $srcroot $COCCIINCLUDE"
>
> -KBUILD_EXTMOD is set when an explicit target with M= is used. For both cases
> -the spatch ``--dir`` argument is used, as such third rule applies when whether
> -M= is used or not, and when M= is used the target directory can have its own
> -.cocciconfig file. When M= is not passed as an argument to coccicheck the
> -target directory is the same as the directory from where spatch was called.
> +Here, $srcroot refers to the source directory of the target: it points to the
> +external module's source directory when M= used, and otherwise, to the kernel
> +source directory. The third rule ensures the spatch reads the .cocciconfig from
> +the target directory, allowing external modules to have their own .cocciconfig
> +file.
>
> If not using the kernel's coccicheck target, keep the above precedence
> order logic of .cocciconfig reading. If using the kernel's coccicheck target,
> diff --git a/Documentation/kbuild/makefiles.rst b/Documentation/kbuild/makefiles.rst
> index 7964e0c245ae..d36519f194dc 100644
> --- a/Documentation/kbuild/makefiles.rst
> +++ b/Documentation/kbuild/makefiles.rst
> @@ -449,6 +449,20 @@ $(obj)
> to prerequisites are referenced with $(src) (because they are not
> generated files).
>
> +$(srcroot)
> + $(srcroot) refers to the root of the source you are building, which can be
> + either the kernel source or the external modules source, depending on whether
> + KBUILD_EXTMOD is set. This can be either a relative or an absolute path, but
> + if KBUILD_ABS_SRCTREE=1 is set, it is always an absolute path.
> +
> +$(srctree)
> + $(srctree) refers to the root of the kernel source tree. When building the
> + kernel, this is the same as $(srcroot).
> +
> +$(objtree)
> + $(objtree) refers to the root of the kernel object tree. It is ``.`` when
> + building the kernel, but it is different when building external modules.
> +
Thanks, I think it's nice that there is now such a clear definition.
$(srcroot) sounds fine to me.
> $(kecho)
> echoing information to user in a rule is often a good practice
> but when execution ``make -s`` one does not expect to see any output
> diff --git a/Makefile b/Makefile
> index cf1d55560ae2..e5f7ac7647a7 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -180,7 +180,24 @@ ifeq ("$(origin O)", "command line")
> KBUILD_OUTPUT := $(O)
> endif
>
> -output := $(KBUILD_OUTPUT)
> +ifdef KBUILD_EXTMOD
> + ifdef KBUILD_OUTPUT
> + objtree := $(realpath $(KBUILD_OUTPUT))
> + $(if $(objtree),,$(error specified kernel directory "$(KBUILD_OUTPUT)" does not exist))
> + else
> + objtree := $(CURDIR)
> + endif
> + output := $(KBUILD_EXTMOD)
> + # KBUILD_EXTMOD might be a relative path. Remember its absolute path before
> + # Make changes the working directory.
> + srcroot := $(realpath $(KBUILD_EXTMOD))
> + $(if $(srcroot),,$(error specified external module directory "$(KBUILD_EXTMOD)" does not exist))
> +else
> + objtree := .
> + output := $(KBUILD_OUTPUT)
> +endif
> +
> +export objtree srcroot
>
> # Do we want to change the working directory?
> ifneq ($(output),)
> @@ -230,35 +247,33 @@ else # need-sub-make
>
> # We process the rest of the Makefile if this is the final invocation of make
>
> -ifeq ($(abs_srctree),$(CURDIR))
> - # building in the source tree
> - srctree := .
> - building_out_of_srctree :=
> +ifndef KBUILD_EXTMOD
> +srcroot := $(abs_srctree)
> +endif
> +
> +ifeq ($(srcroot),$(CURDIR))
> +building_out_of_srctree :=
> else
> - ifeq ($(abs_srctree)/,$(dir $(CURDIR)))
> - # building in a subdirectory of the source tree
> - srctree := ..
> - else
> - srctree := $(abs_srctree)
> - endif
> - building_out_of_srctree := 1
> +export building_out_of_srctree :=1
> endif
>
> -ifneq ($(KBUILD_ABS_SRCTREE),)
> -srctree := $(abs_srctree)
> +ifdef KBUILD_ABS_SRCTREE
> + # Do not nothing. Use the absolute path.
> +else ifeq ($(srcroot),$(CURDIR))
> + # Building in the source.
> + srcroot := .
> +else ifeq ($(srcroot)/,$(dir $(CURDIR)))
> + # Building in a subdirectory of the source.
> + srcroot := ..
> endif
>
> -objtree := .
> +export srctree := $(if $(KBUILD_EXTMOD),$(abs_srctree),$(srcroot))
With this patch applied, the following breaks for me:
$ make O=build M=fs/btrfs CONFIG_BTRFS_FS=m
make[1]: Entering directory '/data/linux/kbuild-review/fs/btrfs'
CC [M] super.o
In file included from <command-line>:
/data/linux/kbuild-review/include/linux/compiler_types.h:89:10: fatal error: linux/compiler_attributes.h: No such file or directory
89 | #include <linux/compiler_attributes.h>
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
Adding 'ccflags-y += -I$(srctree)/include' to fs/btrfs/Makefile breaks
the build loudly. I could make it build again with
diff --git a/Makefile b/Makefile
index e5f7ac7647a7b..3d95911f1a68f 100644
--- a/Makefile
+++ b/Makefile
@@ -555,7 +555,7 @@ USERINCLUDE := \
LINUXINCLUDE := \
-I$(srctree)/arch/$(SRCARCH)/include \
-I$(objtree)/arch/$(SRCARCH)/include/generated \
- $(if $(building_out_of_srctree),-I$(srctree)/include) \
+ $(if $(or $(building_out_of_srctree),$(filter $(srctree)/%, $(CURDIR))),-I$(srctree)/include) \
-I$(objtree)/include \
$(USERINCLUDE)
but this does not feel good. It building in-tree modules in this way a
valid thing to do?
Kind regards,
Nicolas
On Mon, Nov 18, 2024 at 11:47 PM Nicolas Schier <n.schier@avm.de> wrote:
>
> On Sun, Nov 10, 2024 at 10:34:33AM +0900, Masahiro Yamada wrote:
> > Currently, Kbuild always operates in the output directory of the kernel,
> > even when building external modules. This increases the risk of external
> > module Makefiles attempting to write to the kernel directory.
> >
> > This commit switches the working directory to the external module
> > directory, allowing the removal of the $(KBUILD_EXTMOD)/ prefix from
> > some build artifacts.
> >
> > The command for building external modules maintains backward
> > compatibility, but Makefiles that rely on working in the kernel
> > directory may break. In such cases, $(objtree) and $(srctree) should
> > be used to refer to the output and source directories of the kernel.
> >
> > The appearance of the build log will change as follows:
> >
> > [Before]
> >
> > $ make -C /path/to/my/linux M=/path/to/my/externel/module
> > make: Entering directory '/path/to/my/linux'
> > CC [M] /path/to/my/externel/module/helloworld.o
> > MODPOST /path/to/my/externel/module/Module.symvers
> > CC [M] /path/to/my/externel/module/helloworld.mod.o
> > CC [M] /path/to/my/externel/module/.module-common.o
> > LD [M] /path/to/my/externel/module/helloworld.ko
> > make: Leaving directory '/path/to/my/linux'
> >
> > [After]
> >
> > $ make -C /path/to/my/linux M=/path/to/my/externel/module
> > make: Entering directory '/path/to/my/linux'
> > make[1]: Entering directory '/path/to/my/externel/module'
> > CC [M] helloworld.o
> > MODPOST Module.symvers
> > CC [M] helloworld.mod.o
> > CC [M] .module-common.o
> > LD [M] helloworld.ko
> > make[1]: Leaving directory '/path/to/my/externel/module'
> > make: Leaving directory '/path/to/my/linux'
> >
> > Printing "Entering directory" twice is cumbersome. This will be
> > addressed later.
> >
> > Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
> > ---
> >
> > Changes in v2:
> > - Introduce a new 'srcroot' variable and clean-up code
> > - Reword Documentation/dev-tools/coccinelle.rst
> >
> > Documentation/dev-tools/coccinelle.rst | 20 ++-----
> > Documentation/kbuild/makefiles.rst | 14 +++++
> > Makefile | 80 +++++++++++++++-----------
> > rust/Makefile | 4 +-
> > scripts/Makefile.build | 2 +-
> > scripts/Makefile.clean | 2 +-
> > scripts/Makefile.compiler | 2 +-
> > scripts/Makefile.modpost | 6 +-
> > scripts/coccicheck | 6 +-
> > scripts/nsdeps | 8 +--
> > scripts/package/install-extmod-build | 7 +++
> > 11 files changed, 85 insertions(+), 66 deletions(-)
> >
> > diff --git a/Documentation/dev-tools/coccinelle.rst b/Documentation/dev-tools/coccinelle.rst
> > index 535ce126fb4f..6e70a1e9a3c0 100644
> > --- a/Documentation/dev-tools/coccinelle.rst
> > +++ b/Documentation/dev-tools/coccinelle.rst
> > @@ -250,25 +250,17 @@ variables for .cocciconfig is as follows:
> > - Your directory from which spatch is called is processed next
> > - The directory provided with the ``--dir`` option is processed last, if used
> >
> > -Since coccicheck runs through make, it naturally runs from the kernel
> > -proper dir; as such the second rule above would be implied for picking up a
> > -.cocciconfig when using ``make coccicheck``.
> > -
> > ``make coccicheck`` also supports using M= targets. If you do not supply
> > any M= target, it is assumed you want to target the entire kernel.
> > The kernel coccicheck script has::
> >
> > - if [ "$KBUILD_EXTMOD" = "" ] ; then
> > - OPTIONS="--dir $srctree $COCCIINCLUDE"
> > - else
> > - OPTIONS="--dir $KBUILD_EXTMOD $COCCIINCLUDE"
> > - fi
> > + OPTIONS="--dir $srcroot $COCCIINCLUDE"
> >
> > -KBUILD_EXTMOD is set when an explicit target with M= is used. For both cases
> > -the spatch ``--dir`` argument is used, as such third rule applies when whether
> > -M= is used or not, and when M= is used the target directory can have its own
> > -.cocciconfig file. When M= is not passed as an argument to coccicheck the
> > -target directory is the same as the directory from where spatch was called.
> > +Here, $srcroot refers to the source directory of the target: it points to the
> > +external module's source directory when M= used, and otherwise, to the kernel
> > +source directory. The third rule ensures the spatch reads the .cocciconfig from
> > +the target directory, allowing external modules to have their own .cocciconfig
> > +file.
> >
> > If not using the kernel's coccicheck target, keep the above precedence
> > order logic of .cocciconfig reading. If using the kernel's coccicheck target,
> > diff --git a/Documentation/kbuild/makefiles.rst b/Documentation/kbuild/makefiles.rst
> > index 7964e0c245ae..d36519f194dc 100644
> > --- a/Documentation/kbuild/makefiles.rst
> > +++ b/Documentation/kbuild/makefiles.rst
> > @@ -449,6 +449,20 @@ $(obj)
> > to prerequisites are referenced with $(src) (because they are not
> > generated files).
> >
> > +$(srcroot)
> > + $(srcroot) refers to the root of the source you are building, which can be
> > + either the kernel source or the external modules source, depending on whether
> > + KBUILD_EXTMOD is set. This can be either a relative or an absolute path, but
> > + if KBUILD_ABS_SRCTREE=1 is set, it is always an absolute path.
> > +
> > +$(srctree)
> > + $(srctree) refers to the root of the kernel source tree. When building the
> > + kernel, this is the same as $(srcroot).
> > +
> > +$(objtree)
> > + $(objtree) refers to the root of the kernel object tree. It is ``.`` when
> > + building the kernel, but it is different when building external modules.
> > +
>
> Thanks, I think it's nice that there is now such a clear definition.
> $(srcroot) sounds fine to me.
>
> > $(kecho)
> > echoing information to user in a rule is often a good practice
> > but when execution ``make -s`` one does not expect to see any output
> > diff --git a/Makefile b/Makefile
> > index cf1d55560ae2..e5f7ac7647a7 100644
> > --- a/Makefile
> > +++ b/Makefile
> > @@ -180,7 +180,24 @@ ifeq ("$(origin O)", "command line")
> > KBUILD_OUTPUT := $(O)
> > endif
> >
> > -output := $(KBUILD_OUTPUT)
> > +ifdef KBUILD_EXTMOD
> > + ifdef KBUILD_OUTPUT
> > + objtree := $(realpath $(KBUILD_OUTPUT))
> > + $(if $(objtree),,$(error specified kernel directory "$(KBUILD_OUTPUT)" does not exist))
> > + else
> > + objtree := $(CURDIR)
> > + endif
> > + output := $(KBUILD_EXTMOD)
> > + # KBUILD_EXTMOD might be a relative path. Remember its absolute path before
> > + # Make changes the working directory.
> > + srcroot := $(realpath $(KBUILD_EXTMOD))
> > + $(if $(srcroot),,$(error specified external module directory "$(KBUILD_EXTMOD)" does not exist))
> > +else
> > + objtree := .
> > + output := $(KBUILD_OUTPUT)
> > +endif
> > +
> > +export objtree srcroot
> >
> > # Do we want to change the working directory?
> > ifneq ($(output),)
> > @@ -230,35 +247,33 @@ else # need-sub-make
> >
> > # We process the rest of the Makefile if this is the final invocation of make
> >
> > -ifeq ($(abs_srctree),$(CURDIR))
> > - # building in the source tree
> > - srctree := .
> > - building_out_of_srctree :=
> > +ifndef KBUILD_EXTMOD
> > +srcroot := $(abs_srctree)
> > +endif
> > +
> > +ifeq ($(srcroot),$(CURDIR))
> > +building_out_of_srctree :=
> > else
> > - ifeq ($(abs_srctree)/,$(dir $(CURDIR)))
> > - # building in a subdirectory of the source tree
> > - srctree := ..
> > - else
> > - srctree := $(abs_srctree)
> > - endif
> > - building_out_of_srctree := 1
> > +export building_out_of_srctree :=1
> > endif
> >
> > -ifneq ($(KBUILD_ABS_SRCTREE),)
> > -srctree := $(abs_srctree)
> > +ifdef KBUILD_ABS_SRCTREE
> > + # Do not nothing. Use the absolute path.
> > +else ifeq ($(srcroot),$(CURDIR))
> > + # Building in the source.
> > + srcroot := .
> > +else ifeq ($(srcroot)/,$(dir $(CURDIR)))
> > + # Building in a subdirectory of the source.
> > + srcroot := ..
> > endif
> >
> > -objtree := .
> > +export srctree := $(if $(KBUILD_EXTMOD),$(abs_srctree),$(srcroot))
>
> With this patch applied, the following breaks for me:
>
> $ make O=build M=fs/btrfs CONFIG_BTRFS_FS=m
> make[1]: Entering directory '/data/linux/kbuild-review/fs/btrfs'
> CC [M] super.o
> In file included from <command-line>:
> /data/linux/kbuild-review/include/linux/compiler_types.h:89:10: fatal error: linux/compiler_attributes.h: No such file or directory
> 89 | #include <linux/compiler_attributes.h>
> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> compilation terminated.
>
> Adding 'ccflags-y += -I$(srctree)/include' to fs/btrfs/Makefile breaks
> the build loudly. I could make it build again with
>
> diff --git a/Makefile b/Makefile
> index e5f7ac7647a7b..3d95911f1a68f 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -555,7 +555,7 @@ USERINCLUDE := \
> LINUXINCLUDE := \
> -I$(srctree)/arch/$(SRCARCH)/include \
> -I$(objtree)/arch/$(SRCARCH)/include/generated \
> - $(if $(building_out_of_srctree),-I$(srctree)/include) \
> + $(if $(or $(building_out_of_srctree),$(filter $(srctree)/%, $(CURDIR))),-I$(srctree)/include) \
> -I$(objtree)/include \
> $(USERINCLUDE)
>
> but this does not feel good. It building in-tree modules in this way a
> valid thing to do?
Yes, it is a valid way.
This got broken with this commit, and fixed by the later commit,
"kbuild: support building external modules in a separate build directory".
I will move the change for LINUXINCLUDE to this commit.
Thanks for comprehensive testing!
--
Best Regards
Masahiro Yamada
On Tue, Nov 19, 2024 at 02:02:05AM +0900, Masahiro Yamada wrote:
> On Mon, Nov 18, 2024 at 11:47 PM Nicolas Schier <n.schier@avm.de> wrote:
> >
> > On Sun, Nov 10, 2024 at 10:34:33AM +0900, Masahiro Yamada wrote:
> > > Currently, Kbuild always operates in the output directory of the kernel,
> > > even when building external modules. This increases the risk of external
> > > module Makefiles attempting to write to the kernel directory.
> > >
> > > This commit switches the working directory to the external module
> > > directory, allowing the removal of the $(KBUILD_EXTMOD)/ prefix from
> > > some build artifacts.
> > >
> > > The command for building external modules maintains backward
> > > compatibility, but Makefiles that rely on working in the kernel
> > > directory may break. In such cases, $(objtree) and $(srctree) should
> > > be used to refer to the output and source directories of the kernel.
> > >
> > > The appearance of the build log will change as follows:
> > >
> > > [Before]
> > >
> > > $ make -C /path/to/my/linux M=/path/to/my/externel/module
> > > make: Entering directory '/path/to/my/linux'
> > > CC [M] /path/to/my/externel/module/helloworld.o
> > > MODPOST /path/to/my/externel/module/Module.symvers
> > > CC [M] /path/to/my/externel/module/helloworld.mod.o
> > > CC [M] /path/to/my/externel/module/.module-common.o
> > > LD [M] /path/to/my/externel/module/helloworld.ko
> > > make: Leaving directory '/path/to/my/linux'
> > >
> > > [After]
> > >
> > > $ make -C /path/to/my/linux M=/path/to/my/externel/module
> > > make: Entering directory '/path/to/my/linux'
> > > make[1]: Entering directory '/path/to/my/externel/module'
> > > CC [M] helloworld.o
> > > MODPOST Module.symvers
> > > CC [M] helloworld.mod.o
> > > CC [M] .module-common.o
> > > LD [M] helloworld.ko
> > > make[1]: Leaving directory '/path/to/my/externel/module'
> > > make: Leaving directory '/path/to/my/linux'
> > >
> > > Printing "Entering directory" twice is cumbersome. This will be
> > > addressed later.
> > >
> > > Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
> > > ---
> > >
> > > Changes in v2:
> > > - Introduce a new 'srcroot' variable and clean-up code
> > > - Reword Documentation/dev-tools/coccinelle.rst
> > >
> > > Documentation/dev-tools/coccinelle.rst | 20 ++-----
> > > Documentation/kbuild/makefiles.rst | 14 +++++
> > > Makefile | 80 +++++++++++++++-----------
> > > rust/Makefile | 4 +-
> > > scripts/Makefile.build | 2 +-
> > > scripts/Makefile.clean | 2 +-
> > > scripts/Makefile.compiler | 2 +-
> > > scripts/Makefile.modpost | 6 +-
> > > scripts/coccicheck | 6 +-
> > > scripts/nsdeps | 8 +--
> > > scripts/package/install-extmod-build | 7 +++
> > > 11 files changed, 85 insertions(+), 66 deletions(-)
> > >
> > > diff --git a/Documentation/dev-tools/coccinelle.rst b/Documentation/dev-tools/coccinelle.rst
> > > index 535ce126fb4f..6e70a1e9a3c0 100644
> > > --- a/Documentation/dev-tools/coccinelle.rst
> > > +++ b/Documentation/dev-tools/coccinelle.rst
> > > @@ -250,25 +250,17 @@ variables for .cocciconfig is as follows:
> > > - Your directory from which spatch is called is processed next
> > > - The directory provided with the ``--dir`` option is processed last, if used
> > >
> > > -Since coccicheck runs through make, it naturally runs from the kernel
> > > -proper dir; as such the second rule above would be implied for picking up a
> > > -.cocciconfig when using ``make coccicheck``.
> > > -
> > > ``make coccicheck`` also supports using M= targets. If you do not supply
> > > any M= target, it is assumed you want to target the entire kernel.
> > > The kernel coccicheck script has::
> > >
> > > - if [ "$KBUILD_EXTMOD" = "" ] ; then
> > > - OPTIONS="--dir $srctree $COCCIINCLUDE"
> > > - else
> > > - OPTIONS="--dir $KBUILD_EXTMOD $COCCIINCLUDE"
> > > - fi
> > > + OPTIONS="--dir $srcroot $COCCIINCLUDE"
> > >
> > > -KBUILD_EXTMOD is set when an explicit target with M= is used. For both cases
> > > -the spatch ``--dir`` argument is used, as such third rule applies when whether
> > > -M= is used or not, and when M= is used the target directory can have its own
> > > -.cocciconfig file. When M= is not passed as an argument to coccicheck the
> > > -target directory is the same as the directory from where spatch was called.
> > > +Here, $srcroot refers to the source directory of the target: it points to the
> > > +external module's source directory when M= used, and otherwise, to the kernel
> > > +source directory. The third rule ensures the spatch reads the .cocciconfig from
> > > +the target directory, allowing external modules to have their own .cocciconfig
> > > +file.
> > >
> > > If not using the kernel's coccicheck target, keep the above precedence
> > > order logic of .cocciconfig reading. If using the kernel's coccicheck target,
> > > diff --git a/Documentation/kbuild/makefiles.rst b/Documentation/kbuild/makefiles.rst
> > > index 7964e0c245ae..d36519f194dc 100644
> > > --- a/Documentation/kbuild/makefiles.rst
> > > +++ b/Documentation/kbuild/makefiles.rst
> > > @@ -449,6 +449,20 @@ $(obj)
> > > to prerequisites are referenced with $(src) (because they are not
> > > generated files).
> > >
> > > +$(srcroot)
> > > + $(srcroot) refers to the root of the source you are building, which can be
> > > + either the kernel source or the external modules source, depending on whether
> > > + KBUILD_EXTMOD is set. This can be either a relative or an absolute path, but
> > > + if KBUILD_ABS_SRCTREE=1 is set, it is always an absolute path.
> > > +
> > > +$(srctree)
> > > + $(srctree) refers to the root of the kernel source tree. When building the
> > > + kernel, this is the same as $(srcroot).
> > > +
> > > +$(objtree)
> > > + $(objtree) refers to the root of the kernel object tree. It is ``.`` when
> > > + building the kernel, but it is different when building external modules.
> > > +
> >
> > Thanks, I think it's nice that there is now such a clear definition.
> > $(srcroot) sounds fine to me.
> >
> > > $(kecho)
> > > echoing information to user in a rule is often a good practice
> > > but when execution ``make -s`` one does not expect to see any output
> > > diff --git a/Makefile b/Makefile
> > > index cf1d55560ae2..e5f7ac7647a7 100644
> > > --- a/Makefile
> > > +++ b/Makefile
> > > @@ -180,7 +180,24 @@ ifeq ("$(origin O)", "command line")
> > > KBUILD_OUTPUT := $(O)
> > > endif
> > >
> > > -output := $(KBUILD_OUTPUT)
> > > +ifdef KBUILD_EXTMOD
> > > + ifdef KBUILD_OUTPUT
> > > + objtree := $(realpath $(KBUILD_OUTPUT))
> > > + $(if $(objtree),,$(error specified kernel directory "$(KBUILD_OUTPUT)" does not exist))
> > > + else
> > > + objtree := $(CURDIR)
> > > + endif
> > > + output := $(KBUILD_EXTMOD)
> > > + # KBUILD_EXTMOD might be a relative path. Remember its absolute path before
> > > + # Make changes the working directory.
> > > + srcroot := $(realpath $(KBUILD_EXTMOD))
> > > + $(if $(srcroot),,$(error specified external module directory "$(KBUILD_EXTMOD)" does not exist))
> > > +else
> > > + objtree := .
> > > + output := $(KBUILD_OUTPUT)
> > > +endif
> > > +
> > > +export objtree srcroot
> > >
> > > # Do we want to change the working directory?
> > > ifneq ($(output),)
> > > @@ -230,35 +247,33 @@ else # need-sub-make
> > >
> > > # We process the rest of the Makefile if this is the final invocation of make
> > >
> > > -ifeq ($(abs_srctree),$(CURDIR))
> > > - # building in the source tree
> > > - srctree := .
> > > - building_out_of_srctree :=
> > > +ifndef KBUILD_EXTMOD
> > > +srcroot := $(abs_srctree)
> > > +endif
> > > +
> > > +ifeq ($(srcroot),$(CURDIR))
> > > +building_out_of_srctree :=
> > > else
> > > - ifeq ($(abs_srctree)/,$(dir $(CURDIR)))
> > > - # building in a subdirectory of the source tree
> > > - srctree := ..
> > > - else
> > > - srctree := $(abs_srctree)
> > > - endif
> > > - building_out_of_srctree := 1
> > > +export building_out_of_srctree :=1
Nit: Adding a space between ':=1' for consistency?
> > > endif
> > >
> > > -ifneq ($(KBUILD_ABS_SRCTREE),)
> > > -srctree := $(abs_srctree)
> > > +ifdef KBUILD_ABS_SRCTREE
> > > + # Do not nothing. Use the absolute path.
Is this a superfluous "not"?
"Do nothing. Use the absolute path."?
> > > +else ifeq ($(srcroot),$(CURDIR))
> > > + # Building in the source.
> > > + srcroot := .
> > > +else ifeq ($(srcroot)/,$(dir $(CURDIR)))
> > > + # Building in a subdirectory of the source.
> > > + srcroot := ..
> > > endif
> > >
> > > -objtree := .
> > > +export srctree := $(if $(KBUILD_EXTMOD),$(abs_srctree),$(srcroot))
> >
> > With this patch applied, the following breaks for me:
> >
> > $ make O=build M=fs/btrfs CONFIG_BTRFS_FS=m
> > make[1]: Entering directory '/data/linux/kbuild-review/fs/btrfs'
> > CC [M] super.o
> > In file included from <command-line>:
> > /data/linux/kbuild-review/include/linux/compiler_types.h:89:10: fatal error: linux/compiler_attributes.h: No such file or directory
> > 89 | #include <linux/compiler_attributes.h>
> > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > compilation terminated.
> >
> > Adding 'ccflags-y += -I$(srctree)/include' to fs/btrfs/Makefile breaks
> > the build loudly. I could make it build again with
> >
> > diff --git a/Makefile b/Makefile
> > index e5f7ac7647a7b..3d95911f1a68f 100644
> > --- a/Makefile
> > +++ b/Makefile
> > @@ -555,7 +555,7 @@ USERINCLUDE := \
> > LINUXINCLUDE := \
> > -I$(srctree)/arch/$(SRCARCH)/include \
> > -I$(objtree)/arch/$(SRCARCH)/include/generated \
> > - $(if $(building_out_of_srctree),-I$(srctree)/include) \
> > + $(if $(or $(building_out_of_srctree),$(filter $(srctree)/%, $(CURDIR))),-I$(srctree)/include) \
> > -I$(objtree)/include \
> > $(USERINCLUDE)
> >
> > but this does not feel good. It building in-tree modules in this way a
> > valid thing to do?
>
> Yes, it is a valid way.
>
> This got broken with this commit, and fixed by the later commit,
> "kbuild: support building external modules in a separate build directory".
>
> I will move the change for LINUXINCLUDE to this commit.
ah, thanks. I should have seen that.
> > -VPATH :=
> > -
> > -ifeq ($(KBUILD_EXTMOD),)
> > ifdef building_out_of_srctree
> > -VPATH := $(srctree)
> > +export VPATH := $(srcroot)
> > +else
> > +VPATH :=
> > endif
> > -endif
> > -
> > -export building_out_of_srctree srctree objtree VPATH
> >
> > # To make sure we do not include .config for any of the *config targets
> > # catch them early, and hand them over to scripts/kconfig/Makefile
> > @@ -711,7 +726,7 @@ endif
> > # in addition to whatever we do anyway.
> > # Just "make" or "make all" shall build modules as well
> >
> > -ifneq ($(filter all modules nsdeps %compile_commands.json clang-%,$(MAKECMDGOALS)),)
> > +ifneq ($(filter all modules nsdeps compile_commands.json clang-%,$(MAKECMDGOALS)),)
> > KBUILD_MODULES := 1
> > endif
> >
> > @@ -1107,7 +1122,7 @@ export MODLIB
> >
> > PHONY += prepare0
> >
> > -export extmod_prefix = $(if $(KBUILD_EXTMOD),$(KBUILD_EXTMOD)/)
> > +export extmod_prefix =
> > export MODORDER := $(extmod_prefix)modules.order
> > export MODULES_NSDEPS := $(extmod_prefix)modules.nsdeps
> >
> > @@ -1799,14 +1814,10 @@ filechk_kernel.release = echo $(KERNELRELEASE)
> > KBUILD_BUILTIN :=
> > KBUILD_MODULES := 1
> >
> > -build-dir := $(KBUILD_EXTMOD)
> > +build-dir := .
> >
> > -compile_commands.json: $(extmod_prefix)compile_commands.json
> > -PHONY += compile_commands.json
> > -
> > -clean-dirs := $(KBUILD_EXTMOD)
> > -clean: private rm-files := $(KBUILD_EXTMOD)/Module.symvers $(KBUILD_EXTMOD)/modules.nsdeps \
> > - $(KBUILD_EXTMOD)/compile_commands.json
> > +clean-dirs := .
> > +clean: private rm-files := Module.symvers modules.nsdeps compile_commands.json
> >
> > PHONY += prepare
> > # now expand this into a simple variable to reduce the cost of shell evaluations
> > @@ -1948,7 +1959,7 @@ $(clean-dirs):
> >
> > clean: $(clean-dirs)
> > $(call cmd,rmfiles)
> > - @find $(or $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \
> > + @find . $(RCS_FIND_IGNORE) \
> > \( -name '*.[aios]' -o -name '*.rsi' -o -name '*.ko' -o -name '.*.cmd' \
> > -o -name '*.ko.*' \
> > -o -name '*.dtb' -o -name '*.dtbo' \
> > @@ -1981,7 +1992,12 @@ tags TAGS cscope gtags: FORCE
> > PHONY += rust-analyzer
> > rust-analyzer:
> > +$(Q)$(CONFIG_SHELL) $(srctree)/scripts/rust_is_available.sh
> > +ifdef KBUILD_EXTMOD
> > +# FIXME: external modules must not descend into a sub-directory of the kernel
> > + $(Q)$(MAKE) $(build)=$(objtree)/rust src=$(srctree)/rust $@
> > +else
> > $(Q)$(MAKE) $(build)=rust $@
> > +endif
> >
> > # Script to generate missing namespace dependencies
> > # ---------------------------------------------------------------------------
> > diff --git a/rust/Makefile b/rust/Makefile
> > index b5e0a73b78f3..742740816c4b 100644
> > --- a/rust/Makefile
> > +++ b/rust/Makefile
> > @@ -362,8 +362,8 @@ rust-analyzer:
> > $(Q)$(srctree)/scripts/generate_rust_analyzer.py \
> > --cfgs='core=$(core-cfgs)' --cfgs='alloc=$(alloc-cfgs)' \
> > $(realpath $(srctree)) $(realpath $(objtree)) \
> > - $(rustc_sysroot) $(RUST_LIB_SRC) $(KBUILD_EXTMOD) > \
> > - $(if $(KBUILD_EXTMOD),$(extmod_prefix),$(objtree))/rust-project.json
> > + $(rustc_sysroot) $(RUST_LIB_SRC) $(if $(KBUILD_EXTMOD),$(srcroot)) \
> > + > rust-project.json
> >
> > redirect-intrinsics = \
> > __addsf3 __eqsf2 __extendsfdf2 __gesf2 __lesf2 __ltsf2 __mulsf3 __nesf2 __truncdfsf2 __unordsf2 \
> > diff --git a/scripts/Makefile.build b/scripts/Makefile.build
> > index 64cd046f8fd8..1aa928a6fb4f 100644
> > --- a/scripts/Makefile.build
> > +++ b/scripts/Makefile.build
> > @@ -3,7 +3,7 @@
> > # Building
> > # ==========================================================================
> >
> > -src := $(if $(VPATH),$(VPATH)/)$(obj)
> > +src := $(srcroot)/$(obj)
> >
> > PHONY := $(obj)/
> > $(obj)/:
> > diff --git a/scripts/Makefile.clean b/scripts/Makefile.clean
> > index 4fcfab40ed61..6ead00ec7313 100644
> > --- a/scripts/Makefile.clean
> > +++ b/scripts/Makefile.clean
> > @@ -3,7 +3,7 @@
> > # Cleaning up
> > # ==========================================================================
> >
> > -src := $(if $(VPATH),$(VPATH)/)$(obj)
> > +src := $(srcroot)/$(obj)
> >
> > PHONY := __clean
> > __clean:
> > diff --git a/scripts/Makefile.compiler b/scripts/Makefile.compiler
> > index e0842496d26e..8c1029687e2e 100644
> > --- a/scripts/Makefile.compiler
> > +++ b/scripts/Makefile.compiler
> > @@ -13,7 +13,7 @@ cc-cross-prefix = $(firstword $(foreach c, $(1), \
> > $(if $(shell command -v -- $(c)gcc 2>/dev/null), $(c))))
> >
> > # output directory for tests below
> > -TMPOUT = $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/).tmp_$$$$
> > +TMPOUT = .tmp_$$$$
> >
> > # try-run
> > # Usage: option = $(call try-run, $(CC)...-o "$$TMP",option-ok,otherwise)
> > diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
> > index 12e7c15d099c..78d2ca4f25f5 100644
> > --- a/scripts/Makefile.modpost
> > +++ b/scripts/Makefile.modpost
> > @@ -111,13 +111,13 @@ endif
> > else
> >
> > # set src + obj - they may be used in the modules's Makefile
> > -obj := $(KBUILD_EXTMOD)
> > -src := $(if $(VPATH),$(VPATH)/)$(obj)
> > +obj := .
> > +src := $(srcroot)
> >
> > # Include the module's Makefile to find KBUILD_EXTRA_SYMBOLS
> > include $(kbuild-file)
> >
> > -output-symdump := $(KBUILD_EXTMOD)/Module.symvers
> > +output-symdump := Module.symvers
> >
> > ifeq ($(wildcard $(objtree)/Module.symvers),)
> > missing-input := $(objtree)/Module.symvers
> > diff --git a/scripts/coccicheck b/scripts/coccicheck
> > index e52cb43fede6..0e6bc5a10320 100755
> > --- a/scripts/coccicheck
> > +++ b/scripts/coccicheck
> > @@ -80,11 +80,7 @@ command results in a shift count error.'
> > NPROC=1
> > else
> > ONLINE=0
> > - if [ "$KBUILD_EXTMOD" = "" ] ; then
> > - OPTIONS="--dir $srctree $COCCIINCLUDE"
> > - else
> > - OPTIONS="--dir $KBUILD_EXTMOD $COCCIINCLUDE"
> > - fi
> > + OPTIONS="--dir $srcroot $COCCIINCLUDE"
> >
> > # Use only one thread per core by default if hyperthreading is enabled
> > THREADS_PER_CORE=$(LANG=C lscpu | grep "Thread(s) per core: " | tr -cd "[:digit:]")
> > diff --git a/scripts/nsdeps b/scripts/nsdeps
> > index f1718cc0d700..8ca12e2b5c03 100644
> > --- a/scripts/nsdeps
> > +++ b/scripts/nsdeps
> > @@ -19,12 +19,6 @@ if ! { echo "$SPATCH_REQ_VERSION"; echo "$SPATCH_VERSION"; } | sort -CV ; then
> > exit 1
> > fi
> >
> > -if [ "$KBUILD_EXTMOD" ]; then
> > - src_prefix=
> > -else
> > - src_prefix=$srctree/
> > -fi
> > -
> > generate_deps_for_ns() {
> > $SPATCH --very-quiet --in-place --sp-file \
> > $srctree/scripts/coccinelle/misc/add_namespace.cocci -D nsdeps -D ns=$1 $2
> > @@ -34,7 +28,7 @@ generate_deps() {
> > local mod=${1%.ko:}
> > shift
> > local namespaces="$*"
> > - local mod_source_files=$(sed "s|^\(.*\)\.o$|${src_prefix}\1.c|" $mod.mod)
> > + local mod_source_files=$(sed "s|^\(.*\)\.o$|${srcroot}/\1.c|" $mod.mod)
> >
> > for ns in $namespaces; do
> > echo "Adding namespace $ns to module $mod.ko."
> > diff --git a/scripts/package/install-extmod-build b/scripts/package/install-extmod-build
> > index 7ec1f061a519..64d958ee45f3 100755
> > --- a/scripts/package/install-extmod-build
> > +++ b/scripts/package/install-extmod-build
> > @@ -51,6 +51,13 @@ mkdir -p "${destdir}"
> > if [ "${CC}" != "${HOSTCC}" ]; then
> > echo "Rebuilding host programs with ${CC}..."
> >
> > + # This leverages external module building.
> > + # - Clear sub_make_done to allow the top-level Makefile to redo sub-make.
> > + # - Filter out --no-print-directory to print "Entering directory" logs
> > + # when Make changes the working directory.
> > + unset sub_make_done
> > + MAKEFLAGS=$(echo "${MAKEFLAGS}" | sed s/--no-print-directory//)
> > +
> > cat <<-'EOF' > "${destdir}/Kbuild"
> > subdir-y := scripts
> > EOF
> > --
> > 2.43.0
Thanks, again!
Reviewed-by: Nicolas Schier <n.schier@avm.de>
On Thu, Nov 28, 2024 at 12:29 AM Nicolas Schier <n.schier@avm.de> wrote:
>
> On Tue, Nov 19, 2024 at 02:02:05AM +0900, Masahiro Yamada wrote:
> > On Mon, Nov 18, 2024 at 11:47 PM Nicolas Schier <n.schier@avm.de> wrote:
> > >
> > > On Sun, Nov 10, 2024 at 10:34:33AM +0900, Masahiro Yamada wrote:
> > > > Currently, Kbuild always operates in the output directory of the kernel,
> > > > even when building external modules. This increases the risk of external
> > > > module Makefiles attempting to write to the kernel directory.
> > > >
> > > > This commit switches the working directory to the external module
> > > > directory, allowing the removal of the $(KBUILD_EXTMOD)/ prefix from
> > > > some build artifacts.
> > > >
> > > > The command for building external modules maintains backward
> > > > compatibility, but Makefiles that rely on working in the kernel
> > > > directory may break. In such cases, $(objtree) and $(srctree) should
> > > > be used to refer to the output and source directories of the kernel.
> > > >
> > > > The appearance of the build log will change as follows:
> > > >
> > > > [Before]
> > > >
> > > > $ make -C /path/to/my/linux M=/path/to/my/externel/module
> > > > make: Entering directory '/path/to/my/linux'
> > > > CC [M] /path/to/my/externel/module/helloworld.o
> > > > MODPOST /path/to/my/externel/module/Module.symvers
> > > > CC [M] /path/to/my/externel/module/helloworld.mod.o
> > > > CC [M] /path/to/my/externel/module/.module-common.o
> > > > LD [M] /path/to/my/externel/module/helloworld.ko
> > > > make: Leaving directory '/path/to/my/linux'
> > > >
> > > > [After]
> > > >
> > > > $ make -C /path/to/my/linux M=/path/to/my/externel/module
> > > > make: Entering directory '/path/to/my/linux'
> > > > make[1]: Entering directory '/path/to/my/externel/module'
> > > > CC [M] helloworld.o
> > > > MODPOST Module.symvers
> > > > CC [M] helloworld.mod.o
> > > > CC [M] .module-common.o
> > > > LD [M] helloworld.ko
> > > > make[1]: Leaving directory '/path/to/my/externel/module'
> > > > make: Leaving directory '/path/to/my/linux'
> > > >
> > > > Printing "Entering directory" twice is cumbersome. This will be
> > > > addressed later.
> > > >
> > > > Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
> > > > ---
> > > >
> > > > Changes in v2:
> > > > - Introduce a new 'srcroot' variable and clean-up code
> > > > - Reword Documentation/dev-tools/coccinelle.rst
> > > >
> > > > Documentation/dev-tools/coccinelle.rst | 20 ++-----
> > > > Documentation/kbuild/makefiles.rst | 14 +++++
> > > > Makefile | 80 +++++++++++++++-----------
> > > > rust/Makefile | 4 +-
> > > > scripts/Makefile.build | 2 +-
> > > > scripts/Makefile.clean | 2 +-
> > > > scripts/Makefile.compiler | 2 +-
> > > > scripts/Makefile.modpost | 6 +-
> > > > scripts/coccicheck | 6 +-
> > > > scripts/nsdeps | 8 +--
> > > > scripts/package/install-extmod-build | 7 +++
> > > > 11 files changed, 85 insertions(+), 66 deletions(-)
> > > >
> > > > diff --git a/Documentation/dev-tools/coccinelle.rst b/Documentation/dev-tools/coccinelle.rst
> > > > index 535ce126fb4f..6e70a1e9a3c0 100644
> > > > --- a/Documentation/dev-tools/coccinelle.rst
> > > > +++ b/Documentation/dev-tools/coccinelle.rst
> > > > @@ -250,25 +250,17 @@ variables for .cocciconfig is as follows:
> > > > - Your directory from which spatch is called is processed next
> > > > - The directory provided with the ``--dir`` option is processed last, if used
> > > >
> > > > -Since coccicheck runs through make, it naturally runs from the kernel
> > > > -proper dir; as such the second rule above would be implied for picking up a
> > > > -.cocciconfig when using ``make coccicheck``.
> > > > -
> > > > ``make coccicheck`` also supports using M= targets. If you do not supply
> > > > any M= target, it is assumed you want to target the entire kernel.
> > > > The kernel coccicheck script has::
> > > >
> > > > - if [ "$KBUILD_EXTMOD" = "" ] ; then
> > > > - OPTIONS="--dir $srctree $COCCIINCLUDE"
> > > > - else
> > > > - OPTIONS="--dir $KBUILD_EXTMOD $COCCIINCLUDE"
> > > > - fi
> > > > + OPTIONS="--dir $srcroot $COCCIINCLUDE"
> > > >
> > > > -KBUILD_EXTMOD is set when an explicit target with M= is used. For both cases
> > > > -the spatch ``--dir`` argument is used, as such third rule applies when whether
> > > > -M= is used or not, and when M= is used the target directory can have its own
> > > > -.cocciconfig file. When M= is not passed as an argument to coccicheck the
> > > > -target directory is the same as the directory from where spatch was called.
> > > > +Here, $srcroot refers to the source directory of the target: it points to the
> > > > +external module's source directory when M= used, and otherwise, to the kernel
> > > > +source directory. The third rule ensures the spatch reads the .cocciconfig from
> > > > +the target directory, allowing external modules to have their own .cocciconfig
> > > > +file.
> > > >
> > > > If not using the kernel's coccicheck target, keep the above precedence
> > > > order logic of .cocciconfig reading. If using the kernel's coccicheck target,
> > > > diff --git a/Documentation/kbuild/makefiles.rst b/Documentation/kbuild/makefiles.rst
> > > > index 7964e0c245ae..d36519f194dc 100644
> > > > --- a/Documentation/kbuild/makefiles.rst
> > > > +++ b/Documentation/kbuild/makefiles.rst
> > > > @@ -449,6 +449,20 @@ $(obj)
> > > > to prerequisites are referenced with $(src) (because they are not
> > > > generated files).
> > > >
> > > > +$(srcroot)
> > > > + $(srcroot) refers to the root of the source you are building, which can be
> > > > + either the kernel source or the external modules source, depending on whether
> > > > + KBUILD_EXTMOD is set. This can be either a relative or an absolute path, but
> > > > + if KBUILD_ABS_SRCTREE=1 is set, it is always an absolute path.
> > > > +
> > > > +$(srctree)
> > > > + $(srctree) refers to the root of the kernel source tree. When building the
> > > > + kernel, this is the same as $(srcroot).
> > > > +
> > > > +$(objtree)
> > > > + $(objtree) refers to the root of the kernel object tree. It is ``.`` when
> > > > + building the kernel, but it is different when building external modules.
> > > > +
> > >
> > > Thanks, I think it's nice that there is now such a clear definition.
> > > $(srcroot) sounds fine to me.
> > >
> > > > $(kecho)
> > > > echoing information to user in a rule is often a good practice
> > > > but when execution ``make -s`` one does not expect to see any output
> > > > diff --git a/Makefile b/Makefile
> > > > index cf1d55560ae2..e5f7ac7647a7 100644
> > > > --- a/Makefile
> > > > +++ b/Makefile
> > > > @@ -180,7 +180,24 @@ ifeq ("$(origin O)", "command line")
> > > > KBUILD_OUTPUT := $(O)
> > > > endif
> > > >
> > > > -output := $(KBUILD_OUTPUT)
> > > > +ifdef KBUILD_EXTMOD
> > > > + ifdef KBUILD_OUTPUT
> > > > + objtree := $(realpath $(KBUILD_OUTPUT))
> > > > + $(if $(objtree),,$(error specified kernel directory "$(KBUILD_OUTPUT)" does not exist))
> > > > + else
> > > > + objtree := $(CURDIR)
> > > > + endif
> > > > + output := $(KBUILD_EXTMOD)
> > > > + # KBUILD_EXTMOD might be a relative path. Remember its absolute path before
> > > > + # Make changes the working directory.
> > > > + srcroot := $(realpath $(KBUILD_EXTMOD))
> > > > + $(if $(srcroot),,$(error specified external module directory "$(KBUILD_EXTMOD)" does not exist))
> > > > +else
> > > > + objtree := .
> > > > + output := $(KBUILD_OUTPUT)
> > > > +endif
> > > > +
> > > > +export objtree srcroot
> > > >
> > > > # Do we want to change the working directory?
> > > > ifneq ($(output),)
> > > > @@ -230,35 +247,33 @@ else # need-sub-make
> > > >
> > > > # We process the rest of the Makefile if this is the final invocation of make
> > > >
> > > > -ifeq ($(abs_srctree),$(CURDIR))
> > > > - # building in the source tree
> > > > - srctree := .
> > > > - building_out_of_srctree :=
> > > > +ifndef KBUILD_EXTMOD
> > > > +srcroot := $(abs_srctree)
> > > > +endif
> > > > +
> > > > +ifeq ($(srcroot),$(CURDIR))
> > > > +building_out_of_srctree :=
> > > > else
> > > > - ifeq ($(abs_srctree)/,$(dir $(CURDIR)))
> > > > - # building in a subdirectory of the source tree
> > > > - srctree := ..
> > > > - else
> > > > - srctree := $(abs_srctree)
> > > > - endif
> > > > - building_out_of_srctree := 1
> > > > +export building_out_of_srctree :=1
>
> Nit: Adding a space between ':=1' for consistency?
>
> > > > endif
> > > >
> > > > -ifneq ($(KBUILD_ABS_SRCTREE),)
> > > > -srctree := $(abs_srctree)
> > > > +ifdef KBUILD_ABS_SRCTREE
> > > > + # Do not nothing. Use the absolute path.
>
> Is this a superfluous "not"?
>
> "Do nothing. Use the absolute path."?
Thanks. I folded both.
>
>
> Thanks, again!
>
> Reviewed-by: Nicolas Schier <n.schier@avm.de>
Thanks for the review!
--
Best Regards
Masahiro Yamada
© 2016 - 2026 Red Hat, Inc.