Commit 394053f4 authored by Masahiro Yamada's avatar Masahiro Yamada

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/ directory, 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 believe 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 problems by making the single target build
descend in the same way as the normal build does.

Another change is the single target build 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: default avatarMasahiro Yamada <yamada.masahiro@socionext.com>
parent 8959e392
...@@ -230,6 +230,8 @@ endif ...@@ -230,6 +230,8 @@ endif
export KBUILD_CHECKSRC KBUILD_EXTMOD export KBUILD_CHECKSRC KBUILD_EXTMOD
extmod-prefix = $(if $(KBUILD_EXTMOD),$(KBUILD_EXTMOD)/)
ifeq ($(abs_srctree),$(abs_objtree)) ifeq ($(abs_srctree),$(abs_objtree))
# building in the source tree # building in the source tree
srctree := . srctree := .
...@@ -271,11 +273,13 @@ no-dot-config-targets := $(clean-targets) \ ...@@ -271,11 +273,13 @@ no-dot-config-targets := $(clean-targets) \
%asm-generic kernelversion %src-pkg %asm-generic kernelversion %src-pkg
no-sync-config-targets := $(no-dot-config-targets) install %install \ no-sync-config-targets := $(no-dot-config-targets) install %install \
kernelrelease kernelrelease
single-targets := %.a %.i %.ko %.lds %.ll %.lst %.mod %.o %.s %.symtypes %/
config-build := config-build :=
mixed-build := mixed-build :=
need-config := 1 need-config := 1
may-sync-config := 1 may-sync-config := 1
single-build :=
ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),) ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),)
ifeq ($(filter-out $(no-dot-config-targets), $(MAKECMDGOALS)),) ifeq ($(filter-out $(no-dot-config-targets), $(MAKECMDGOALS)),)
...@@ -302,6 +306,14 @@ ifeq ($(KBUILD_EXTMOD),) ...@@ -302,6 +306,14 @@ ifeq ($(KBUILD_EXTMOD),)
endif endif
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. # For "make -j clean all", "make -j mrproper defconfig all", etc.
ifneq ($(filter $(clean-targets),$(MAKECMDGOALS)),) ifneq ($(filter $(clean-targets),$(MAKECMDGOALS)),)
ifneq ($(filter-out $(clean-targets),$(MAKECMDGOALS)),) ifneq ($(filter-out $(clean-targets),$(MAKECMDGOALS)),)
...@@ -1003,7 +1015,7 @@ endif ...@@ -1003,7 +1015,7 @@ endif
PHONY += prepare0 PHONY += prepare0
export MODORDER := $(if $(KBUILD_EXTMOD),$(KBUILD_EXTMOD)/)modules.order export MODORDER := $(extmod-prefix)modules.order
ifeq ($(KBUILD_EXTMOD),) ifeq ($(KBUILD_EXTMOD),)
core-y += kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/ core-y += kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/
...@@ -1655,7 +1667,7 @@ endif # KBUILD_EXTMOD ...@@ -1655,7 +1667,7 @@ endif # KBUILD_EXTMOD
PHONY += descend $(build-dirs) PHONY += descend $(build-dirs)
descend: $(build-dirs) descend: $(build-dirs)
$(build-dirs): prepare $(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)) clean-dirs := $(addprefix _clean_, $(clean-dirs))
PHONY += $(clean-dirs) clean PHONY += $(clean-dirs) clean
...@@ -1752,40 +1764,47 @@ tools/%: FORCE ...@@ -1752,40 +1764,47 @@ tools/%: FORCE
# Single targets # Single targets
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Single targets are compatible with: # To build individual files in subdirectories, you can do like this:
# - build with mixed source and output #
# - build with separate output dir 'make O=...' # make foo/bar/baz.s
# - external modules
# #
# target-dir => where to store outputfile # The supported suffixes for single-target are listed in 'single-targets'
# build-dir => directory in kernel source tree to use #
# To build only under specific subdirectories, you can do like this:
build-target = $(if $(KBUILD_EXTMOD), $(KBUILD_EXTMOD)/)$@ #
build-dir = $(patsubst %/,%,$(dir $(build-target))) # make foo/bar/baz/
%.i: prepare FORCE ifdef single-build
$(Q)$(MAKE) $(build)=$(build-dir) $(build-target)
%.ll: prepare FORCE single-all := $(filter $(single-targets), $(MAKECMDGOALS))
$(Q)$(MAKE) $(build)=$(build-dir) $(build-target)
%.lst: prepare FORCE # .ko is special because modpost is needed
$(Q)$(MAKE) $(build)=$(build-dir) $(build-target) single-ko := $(sort $(filter %.ko, $(single-all)))
%.o: prepare FORCE single-no-ko := $(sort $(patsubst %.ko,%.mod, $(single-all)))
$(Q)$(MAKE) $(build)=$(build-dir) $(build-target)
%.s: prepare FORCE $(single-ko): single_modpost
$(Q)$(MAKE) $(build)=$(build-dir) $(build-target) @:
%.symtypes: prepare FORCE $(single-no-ko): descend
$(Q)$(MAKE) $(build)=$(build-dir) $(build-target) @:
ifeq ($(KBUILD_EXTMOD),) 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. # the situation of modules_install installing an invalid modules.order.
%.ko: MODORDER := .modules.tmp MODORDER := .modules.tmp
endif endif
%.ko: prepare FORCE
$(Q)$(MAKE) $(build)=$(build-dir) $(build-target:.ko=.mod) PHONY += single_modpost
$(Q)echo $(build-target) > $(MODORDER) single_modpost: $(single-no-ko)
$(Q){ $(foreach m, $(single-ko), echo $(extmod-prefix)$m;) } > $(MODORDER)
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
%/: prepare FORCE
$(Q)$(MAKE) KBUILD_MODULES=1 $(build)=$(build-dir) need-modorder=1 KBUILD_MODULES := 1
export KBUILD_SINGLE_TARGETS := $(addprefix $(extmod-prefix), $(single-no-ko))
single-build = $(if $(filter-out $@/, $(single-no-ko)),1)
endif
# FIXME Should go into a make.lib or something # FIXME Should go into a make.lib or something
# =========================================================================== # ===========================================================================
......
...@@ -52,7 +52,7 @@ ifndef obj ...@@ -52,7 +52,7 @@ ifndef obj
$(warning kbuild: Makefile.build is included improperly) $(warning kbuild: Makefile.build is included improperly)
endif endif
ifeq ($(MAKECMDGOALS)$(need-modorder),) ifeq ($(need-modorder),)
ifneq ($(obj-m),) ifneq ($(obj-m),)
$(warning $(patsubst %.o,'%.ko',$(obj-m)) will not be built even though obj-m is specified.) $(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.) $(warning You cannot use subdir-y/m to visit a module Makefile. Use obj-y/m instead.)
...@@ -76,11 +76,6 @@ endif ...@@ -76,11 +76,6 @@ endif
mod-targets := $(patsubst %.o, %.mod, $(obj-m)) 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 # Linus' kernel sanity checking tool
ifeq ($(KBUILD_CHECKSRC),1) ifeq ($(KBUILD_CHECKSRC),1)
quiet_cmd_checksrc = CHECK $< quiet_cmd_checksrc = CHECK $<
...@@ -487,12 +482,50 @@ targets += $(call intermediate_targets, .asn1.o, .asn1.c .asn1.h) \ ...@@ -487,12 +482,50 @@ targets += $(call intermediate_targets, .asn1.o, .asn1.c .asn1.h) \
$(call intermediate_targets, .lex.o, .lex.c) \ $(call intermediate_targets, .lex.o, .lex.c) \
$(call intermediate_targets, .tab.o, .tab.c .tab.h) $(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 # Descending
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
PHONY += $(subdir-ym) PHONY += $(subdir-ym)
$(subdir-ym): $(subdir-ym):
$(Q)$(MAKE) $(build)=$@ \ $(Q)$(MAKE) $(build)=$@ \
$(if $(filter $@/, $(KBUILD_SINGLE_TARGETS)),single-build=) \
need-builtin=$(if $(filter $@/built-in.a, $(subdir-obj-y)),1) \ need-builtin=$(if $(filter $@/built-in.a, $(subdir-obj-y)),1) \
need-modorder=$(if $(need-modorder),$(if $(filter $@/modules.order, $(modorder)),1)) need-modorder=$(if $(need-modorder),$(if $(filter $@/modules.order, $(modorder)),1))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment