2019-08-10 15:57:03

by Masahiro Yamada

[permalink] [raw]
Subject: [PATCH 00/11] kbuild: clean-ups and improvement of single targets


01/11-09/11 are trivial clean-ups.

10/11 makes the single targets work more correctly.

11/11 cleans up Makefiles that have been added
to work aroud the single target issues.



Masahiro Yamada (11):
kbuild: move the Module.symvers check for external module build
kbuild: refactor part-of-module more
kbuild: fix modkern_aflags implementation
kbuild: remove 'make /' support
kbuild: remove meaningless 'targets' in ./Kbuild
kbuild: do not descend to ./Kbuild when cleaning
kbuild: unset variables in top Makefile instead of setting 0
kbuild: unify vmlinux-dirs and module-dirs rules
kbuild: unify clean-dirs rule for in-kernel and external module
kbuild: make single targets work more correctly
treewide: remove dummy Makefiles for single targets

Kbuild | 7 -
Makefile | 193 ++++++++++--------
.../aquantia/atlantic/hw_atl/Makefile | 2 -
.../mellanox/mlx5/core/accel/Makefile | 2 -
.../ethernet/mellanox/mlx5/core/diag/Makefile | 2 -
.../ethernet/mellanox/mlx5/core/en/Makefile | 2 -
.../mellanox/mlx5/core/en/xsk/Makefile | 1 -
.../mellanox/mlx5/core/en_accel/Makefile | 2 -
.../ethernet/mellanox/mlx5/core/fpga/Makefile | 2 -
.../mellanox/mlx5/core/ipoib/Makefile | 2 -
.../ethernet/mellanox/mlx5/core/lib/Makefile | 2 -
.../net/ethernet/netronome/nfp/bpf/Makefile | 2 -
.../ethernet/netronome/nfp/flower/Makefile | 2 -
.../ethernet/netronome/nfp/nfpcore/Makefile | 2 -
.../netronome/nfp/nfpcore/nfp6000/Makefile | 2 -
.../net/ethernet/netronome/nfp/nic/Makefile | 2 -
scripts/Makefile.build | 55 +++--
17 files changed, 149 insertions(+), 133 deletions(-)
delete mode 100644 drivers/net/ethernet/aquantia/atlantic/hw_atl/Makefile
delete mode 100644 drivers/net/ethernet/mellanox/mlx5/core/accel/Makefile
delete mode 100644 drivers/net/ethernet/mellanox/mlx5/core/diag/Makefile
delete mode 100644 drivers/net/ethernet/mellanox/mlx5/core/en/Makefile
delete mode 100644 drivers/net/ethernet/mellanox/mlx5/core/en/xsk/Makefile
delete mode 100644 drivers/net/ethernet/mellanox/mlx5/core/en_accel/Makefile
delete mode 100644 drivers/net/ethernet/mellanox/mlx5/core/fpga/Makefile
delete mode 100644 drivers/net/ethernet/mellanox/mlx5/core/ipoib/Makefile
delete mode 100644 drivers/net/ethernet/mellanox/mlx5/core/lib/Makefile
delete mode 100644 drivers/net/ethernet/netronome/nfp/bpf/Makefile
delete mode 100644 drivers/net/ethernet/netronome/nfp/flower/Makefile
delete mode 100644 drivers/net/ethernet/netronome/nfp/nfpcore/Makefile
delete mode 100644 drivers/net/ethernet/netronome/nfp/nfpcore/nfp6000/Makefile
delete mode 100644 drivers/net/ethernet/netronome/nfp/nic/Makefile

--
2.17.1


2019-08-10 15:57:04

by Masahiro Yamada

[permalink] [raw]
Subject: [PATCH 06/11] kbuild: do not descend to ./Kbuild when cleaning

'make clean' descends into ./Kbuild, but does not clean anything
since everything is added to no-clean-files.

There is no need to descend to ./Kbuild in the first place.
We can drop the no-clean-files assignment.

Signed-off-by: Masahiro Yamada <[email protected]>
---

Kbuild | 3 ---
Makefile | 2 +-
2 files changed, 1 insertion(+), 4 deletions(-)

diff --git a/Kbuild b/Kbuild
index d40366e967d7..3109ac786e76 100644
--- a/Kbuild
+++ b/Kbuild
@@ -57,6 +57,3 @@ quiet_cmd_atomics = CALL $<

old-atomics: scripts/atomic/check-atomics.sh FORCE
$(call cmd,atomics)
-
-# Keep these three files during make clean
-no-clean-files := $(bounds-file) $(offsets-file) $(timeconst-file)
diff --git a/Makefile b/Makefile
index 86afce391582..3c186f59f152 100644
--- a/Makefile
+++ b/Makefile
@@ -1396,7 +1396,7 @@ DISTCLEAN_FILES += tags TAGS cscope* GPATH GTAGS GRTAGS GSYMS
#
clean: rm-dirs := $(CLEAN_DIRS)
clean: rm-files := $(CLEAN_FILES)
-clean-dirs := $(addprefix _clean_, . $(vmlinux-alldirs))
+clean-dirs := $(addprefix _clean_, $(vmlinux-alldirs))

PHONY += $(clean-dirs) clean archclean vmlinuxclean
$(clean-dirs):
--
2.17.1

2019-08-10 15:57:07

by Masahiro Yamada

[permalink] [raw]
Subject: [PATCH 10/11] kbuild: make single targets work more correctly

Currently, the single target build directly descends into the directory
of the target. For example,

$ make foo/bar/baz.o

... directly descends into foo/bar/.

On the other hand, the normal build usually descends one directory at
a time, i.e. descends into foo/, and then foo/bar/.

This difference causes some problems.

[1] miss subdir-asflags-y, subdir-ccflags-y in upper Makefiles

The options in subdir-{as,cc}flags-y take effect in the current
and its sub-directories. In other words, they are inherited
downward. In the example above, the single target will miss
subdir-{as,cc}flags-y if they are defined in foo/Makefile.

[2] could be built in a different directory

As Documentation/kbuild/modules.rst section 4.3 says, Kbuild can
handle files that are spread over several sub-directories.

The build rule of foo/bar/baz.o may not necessarily be specified in
foo/bar/Makefile. It might be specifies in foo/Makefile as follows:

[foo/Makefile]
obj-y := bar/baz.o

This often happens when a module is so big that its source files
are divided into sub-directories.

In this case, there is no Makefile in the foo/bar/ level, yet the
single target descends into foo/bar/, then fails due to the missing
Makefile. You can still do 'make foo/bar/' for partial building,
but cannot do 'make foo/bar/baz.s'. I beleive the single target
'%.s' is a useful feature for inspecting the compiler output.

Some modules work around this issue by putting an empty Makefile
in every sub-directory.

This commit fixes those issues by letting the single target build
descend in the same way as the normal build does.

Another change is the single target build now will observe the CONFIG
options. Previously, it allowed users to build the foo.o even when
the corresponding CONFIG_FOO is disabled:

obj-$(CONFIG_FOO) += foo.o

In the new behavior, the single target build will just fail and show
"No rule to make target ..." (or "Nothing to be done for ..." if the
stale object already exists, but cannot be updated).

The disadvantage of this commit is the build speed. Now that the
single target build visits every directory and parses lots of
Makefiles, it is slower than before. (But, I hope it will not be
too slow.)

Signed-off-by: Masahiro Yamada <[email protected]>
---

Makefile | 83 +++++++++++++++++++++++++++---------------
scripts/Makefile.build | 45 ++++++++++++++++++++---
2 files changed, 92 insertions(+), 36 deletions(-)

diff --git a/Makefile b/Makefile
index 871c42e241a6..a93d6f6b996a 100644
--- a/Makefile
+++ b/Makefile
@@ -271,11 +271,16 @@ no-dot-config-targets := $(clean-targets) \
%asm-generic kernelversion %src-pkg
no-sync-config-targets := $(no-dot-config-targets) install %install \
kernelrelease
+single-targets := %.a %.i %.ko %.lds %.lst %.mod %o %.s %.symtypes %/
+ifdef CONFIG_CC_IS_CLANG
+single-targets += %.ll
+endif

config-build :=
mixed-build :=
need-config := 1
may-sync-config := 1
+single-build :=

ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),)
ifeq ($(filter-out $(no-dot-config-targets), $(MAKECMDGOALS)),)
@@ -302,6 +307,14 @@ ifeq ($(KBUILD_EXTMOD),)
endif
endif

+# We cannot build single targets and the others at the same time
+ifneq ($(filter $(single-targets), $(MAKECMDGOALS)),)
+ single-build := 1
+ ifneq ($(filter-out $(single-targets), $(MAKECMDGOALS)),)
+ mixed-build := 1
+ endif
+endif
+
# For "make -j clean all", "make -j mrproper defconfig all", etc.
ifneq ($(filter $(clean-targets),$(MAKECMDGOALS)),)
ifneq ($(filter-out $(clean-targets),$(MAKECMDGOALS)),)
@@ -1655,7 +1668,7 @@ endif # KBUILD_EXTMOD
PHONY += descend $(build-dirs)
descend: $(build-dirs)
$(build-dirs): prepare
- $(Q)$(MAKE) $(build)=$@ need-builtin=1 need-modorder=1
+ $(Q)$(MAKE) $(build)=$@ single-build=$(single-build) need-builtin=1 need-modorder=1

clean-dirs := $(addprefix _clean_, $(clean-dirs))
PHONY += $(clean-dirs) clean
@@ -1752,40 +1765,50 @@ tools/%: FORCE

# Single targets
# ---------------------------------------------------------------------------
-# Single targets are compatible with:
-# - build with mixed source and output
-# - build with separate output dir 'make O=...'
-# - external modules
+# To build individual files in subdirectories, you can do like this:
+#
+# make foo/bar/baz.s
#
-# target-dir => where to store outputfile
-# build-dir => directory in kernel source tree to use
-
-build-target = $(if $(KBUILD_EXTMOD), $(KBUILD_EXTMOD)/)$@
-build-dir = $(patsubst %/,%,$(dir $(build-target)))
-
-%.i: prepare FORCE
- $(Q)$(MAKE) $(build)=$(build-dir) $(build-target)
-%.ll: prepare FORCE
- $(Q)$(MAKE) $(build)=$(build-dir) $(build-target)
-%.lst: prepare FORCE
- $(Q)$(MAKE) $(build)=$(build-dir) $(build-target)
-%.o: prepare FORCE
- $(Q)$(MAKE) $(build)=$(build-dir) $(build-target)
-%.s: prepare FORCE
- $(Q)$(MAKE) $(build)=$(build-dir) $(build-target)
-%.symtypes: prepare FORCE
- $(Q)$(MAKE) $(build)=$(build-dir) $(build-target)
+# The supported suffixes for single-target are listed in 'single-targets'
+#
+# To build only under specific subdirectories, you can do like this:
+#
+# make foo/bar/baz/
+
+ifdef single-build
+
+single-all := $(filter $(single-targets), $(MAKECMDGOALS))
+
ifeq ($(KBUILD_EXTMOD),)
-# For the single build of an in-tree module, use a temporary file to avoid
+# For the single build of in-tree modules, use a temporary file to avoid
# the situation of modules_install installing an invalid modules.order.
-%.ko: MODORDER := .modules.tmp
+MODORDER := .modules.tmp
+else
+single-all := $(addprefix $(KBUILD_EXTMOD)/, $(single-all)))
endif
-%.ko: prepare FORCE
- $(Q)$(MAKE) $(build)=$(build-dir) $(build-target:.ko=.mod)
- $(Q)echo $(build-target) > $(MODORDER)
+
+# .ko is special because modpost is needed
+single-ko := $(sort $(filter %.ko, $(single-all)))
+single-non-ko := $(sort $(patsubst %.ko,%.mod, $(single-all)))
+
+$(single-ko): single_modpost
+ @:
+
+PHONY += single_modpost
+single_modpost: $(single-non-ko)
+ $(Q){ $(foreach m, $(single-ko), echo $m;) } > $(MODORDER)
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
-%/: prepare FORCE
- $(Q)$(MAKE) KBUILD_MODULES=1 $(build)=$(build-dir) need-modorder=1
+
+KBUILD_MODULES := 1
+
+$(single-non-ko): descend
+ @:
+
+export KBUILD_SINGLE_TARGETS := $(single-non-ko)
+
+single-build = $(if $(filter-out $@/, $(single-non-ko)),1)
+
+endif

# FIXME Should go into a make.lib or something
# ===========================================================================
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 3633558f7861..5e58db1d01b2 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -52,7 +52,7 @@ ifndef obj
$(warning kbuild: Makefile.build is included improperly)
endif

-ifeq ($(MAKECMDGOALS)$(need-modorder),)
+ifeq ($(need-modorder),)
ifneq ($(obj-m),)
$(warning $(patsubst %.o,'%.ko',$(obj-m)) will not be built even though obj-m is specified.)
$(warning You cannot use subdir-y/m to visit a module Makefile. Use obj-y/m instead.)
@@ -76,11 +76,6 @@ endif

mod-targets := $(patsubst %.o, %.mod, $(obj-m))

-__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
- $(if $(KBUILD_MODULES),$(obj-m) $(mod-targets) $(modorder-target)) \
- $(subdir-ym) $(always)
- @:
-
# Linus' kernel sanity checking tool
ifeq ($(KBUILD_CHECKSRC),1)
quiet_cmd_checksrc = CHECK $<
@@ -487,12 +482,50 @@ targets += $(call intermediate_targets, .asn1.o, .asn1.c .asn1.h) \
$(call intermediate_targets, .lex.o, .lex.c) \
$(call intermediate_targets, .tab.o, .tab.c .tab.h)

+# Build
+# ---------------------------------------------------------------------------
+
+ifdef single-build
+
+curdir-single := $(sort $(foreach x, $(KBUILD_SINGLE_TARGETS), \
+ $(if $(filter $(x) $(basename $(x)).o, $(targets)), $(x))))
+
+# Handle single targets without any rule: show "Nothing to be done for ..." or
+# "No rule to make target ..." depending on whether the target exists.
+unknown-single := $(filter-out $(addsuffix /%, $(subdir-ym)), \
+ $(filter $(obj)/%, \
+ $(filter-out $(curdir-single), \
+ $(KBUILD_SINGLE_TARGETS))))
+
+__build: $(curdir-single) $(subdir-ym)
+ifneq ($(unknown-single),)
+ $(Q)$(MAKE) -f /dev/null $(unknown-single)
+endif
+ @:
+
+ifeq ($(curdir-single),)
+# Nothing to do in this directory. Do not include any .*.cmd file for speed-up
+targets :=
+else
+targets += $(curdir-single)
+endif
+
+else
+
+__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
+ $(if $(KBUILD_MODULES),$(obj-m) $(mod-targets) $(modorder-target)) \
+ $(subdir-ym) $(always)
+ @:
+
+endif
+
# Descending
# ---------------------------------------------------------------------------

PHONY += $(subdir-ym)
$(subdir-ym):
$(Q)$(MAKE) $(build)=$@ \
+ $(if $(filter $@/, $(KBUILD_SINGLE_TARGETS)),single-build=) \
need-builtin=$(if $(filter $@/built-in.a, $(subdir-obj-y)),1) \
need-modorder=$(if $(need-modorder),$(if $(filter $@/modules.order, $(modorder)),1))

--
2.17.1

2019-08-10 15:57:15

by Masahiro Yamada

[permalink] [raw]
Subject: [PATCH 04/11] kbuild: remove 'make /' support

'make /' is just an alias for 'make ./'; this builds all objects of an
external module, but skips the modpost stage.

I am not a big fan of 'make /' since it looks as if it were touching
the root directory of the system. I like 'make ./' better.

I do not know how many people are using it, but let's show a hint if
it is used. Also, move it close to the external module rules since
this only makes sense for external modules.

Signed-off-by: Masahiro Yamada <[email protected]>
---

Makefile | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/Makefile b/Makefile
index 24c9ed272b5f..86afce391582 100644
--- a/Makefile
+++ b/Makefile
@@ -1648,6 +1648,10 @@ $(clean-dirs):

clean: rm-files := $(KBUILD_EXTMOD)/Module.symvers

+PHONY += /
+/:
+ @echo >&2 '"$(MAKE) /" is no longer supported. Please use "$(MAKE) ./" instead.'
+
PHONY += help
help:
@echo ' Building external modules.'
@@ -1783,11 +1787,6 @@ endif
$(Q)$(MAKE) $(build)=$(build-dir) $(build-target:.ko=.mod)
$(Q)echo $(build-target) > $(MODORDER)
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
-
-# Modules
-PHONY += /
-/: ./
-
%/: prepare FORCE
$(Q)$(MAKE) KBUILD_MODULES=1 $(build)=$(build-dir) need-modorder=1

--
2.17.1

2019-08-10 15:57:45

by Masahiro Yamada

[permalink] [raw]
Subject: [PATCH 05/11] kbuild: remove meaningless 'targets' in ./Kbuild

timeconst.h is generated by $(call filechk,...), missing-syscalls and
old-atomics are invoked by $(call cmd,...)

None of them needs to be added to 'targets'.

Signed-off-by: Masahiro Yamada <[email protected]>
---

Kbuild | 4 ----
1 file changed, 4 deletions(-)

diff --git a/Kbuild b/Kbuild
index 8637fd14135f..d40366e967d7 100644
--- a/Kbuild
+++ b/Kbuild
@@ -18,8 +18,6 @@ $(bounds-file): kernel/bounds.s FORCE

timeconst-file := include/generated/timeconst.h

-targets += $(timeconst-file)
-
filechk_gentimeconst = echo $(CONFIG_HZ) | bc -q $<

$(timeconst-file): kernel/time/timeconst.bc FORCE
@@ -42,7 +40,6 @@ $(offsets-file): arch/$(SRCARCH)/kernel/asm-offsets.s FORCE
# Check for missing system calls

always += missing-syscalls
-targets += missing-syscalls

quiet_cmd_syscalls = CALL $<
cmd_syscalls = $(CONFIG_SHELL) $< $(CC) $(c_flags) $(missing_syscalls_flags)
@@ -54,7 +51,6 @@ missing-syscalls: scripts/checksyscalls.sh $(offsets-file) FORCE
# Check atomic headers are up-to-date

always += old-atomics
-targets += old-atomics

quiet_cmd_atomics = CALL $<
cmd_atomics = $(CONFIG_SHELL) $<
--
2.17.1

2019-08-10 15:57:46

by Masahiro Yamada

[permalink] [raw]
Subject: [PATCH 09/11] kbuild: unify clean-dirs rule for in-kernel and external module

Factor out the duplicated code for in-kernel and external module
cleaning.

Signed-off-by: Masahiro Yamada <[email protected]>
---

Makefile | 18 ++++++++----------
1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/Makefile b/Makefile
index e60c09d57b30..871c42e241a6 100644
--- a/Makefile
+++ b/Makefile
@@ -1017,6 +1017,7 @@ vmlinux-alldirs := $(sort $(vmlinux-dirs) Documentation \
$(drivers-) $(net-) $(libs-) $(virt-))))

build-dirs := $(vmlinux-dirs)
+clean-dirs := $(vmlinux-alldirs)

init-y := $(patsubst %/, %/built-in.a, $(init-y))
core-y := $(patsubst %/, %/built-in.a, $(core-y))
@@ -1388,11 +1389,8 @@ DISTCLEAN_FILES += tags TAGS cscope* GPATH GTAGS GRTAGS GSYMS
#
clean: rm-dirs := $(CLEAN_DIRS)
clean: rm-files := $(CLEAN_FILES)
-clean-dirs := $(addprefix _clean_, $(vmlinux-alldirs))

-PHONY += $(clean-dirs) clean archclean vmlinuxclean
-$(clean-dirs):
- $(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@)
+PHONY += archclean vmlinuxclean

vmlinuxclean:
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/link-vmlinux.sh clean
@@ -1629,12 +1627,7 @@ PHONY += _emodinst_post
_emodinst_post: _emodinst_
$(call cmd,depmod)

-clean-dirs := $(addprefix _clean_,$(KBUILD_EXTMOD))
-
-PHONY += $(clean-dirs) clean
-$(clean-dirs):
- $(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@)
-
+clean-dirs := $(KBUILD_EXTMOD)
clean: rm-files := $(KBUILD_EXTMOD)/Module.symvers

PHONY += /
@@ -1664,6 +1657,11 @@ descend: $(build-dirs)
$(build-dirs): prepare
$(Q)$(MAKE) $(build)=$@ need-builtin=1 need-modorder=1

+clean-dirs := $(addprefix _clean_, $(clean-dirs))
+PHONY += $(clean-dirs) clean
+$(clean-dirs):
+ $(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@)
+
clean: $(clean-dirs)
$(call cmd,rmdirs)
$(call cmd,rmfiles)
--
2.17.1

2019-08-19 14:55:32

by Masahiro Yamada

[permalink] [raw]
Subject: Re: [PATCH 00/11] kbuild: clean-ups and improvement of single targets

On Sun, Aug 11, 2019 at 12:55 AM Masahiro Yamada
<[email protected]> wrote:
>
>
> 01/11-09/11 are trivial clean-ups.
>
> 10/11 makes the single targets work more correctly.
>
> 11/11 cleans up Makefiles that have been added
> to work aroud the single target issues.
>
>
>
> Masahiro Yamada (11):
> kbuild: move the Module.symvers check for external module build
> kbuild: refactor part-of-module more
> kbuild: fix modkern_aflags implementation
> kbuild: remove 'make /' support
> kbuild: remove meaningless 'targets' in ./Kbuild
> kbuild: do not descend to ./Kbuild when cleaning
> kbuild: unset variables in top Makefile instead of setting 0
> kbuild: unify vmlinux-dirs and module-dirs rules
> kbuild: unify clean-dirs rule for in-kernel and external module
> kbuild: make single targets work more correctly
> treewide: remove dummy Makefiles for single targets


Patch 01-09 applied.

10-11 have been superseded.



--
Best Regards
Masahiro Yamada