mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-23 17:30:02 +00:00
![Masahiro Yamada](/assets/img/avatar_default.png)
Kbuild supports not only obj-y but also lib-y to list objects linked to
vmlinux.
The difference between them is that all the objects from obj-y are
forcibly linked to vmlinux, whereas the objects from lib-y are linked
as needed; if there is no user of a lib-y object, it is not linked.
lib-y is intended to list utility functions that may be called from all
over the place (and may be unused at all), but it is a problem for
EXPORT_SYMBOL(). Even if there is no call-site in the vmlinux, we need
to keep exported symbols for the use from loadable modules.
Commit 7f2084fa55
("[kbuild] handle exports in lib-y objects reliably")
worked around it by linking a dummy object, lib-ksyms.o, which contains
references to all the symbols exported from lib.a in that directory.
It uses the linker script command, EXTERN. Unfortunately, the meaning of
EXTERN of ld.lld is different from that of ld.bfd. Therefore, this does
not work with LD=ld.lld (CBL issue #515).
Anyway, the build rule of lib-ksyms.o is somewhat tricky. So, I want to
get rid of it.
At first, I was thinking of accumulating lib-y objects into obj-y
(or even replacing lib-y with obj-y entirely), but the lib-y syntax
is used beyond the ordinary use in lib/ and arch/*/lib/.
Examples:
- drivers/firmware/efi/libstub/Makefile builds lib.a, which is linked
into vmlinux in the own way (arm64), or linked to the decompressor
(arm, x86).
- arch/alpha/lib/Makefile builds lib.a which is linked not only to
vmlinux, but also to bootloaders in arch/alpha/boot/Makefile.
- arch/xtensa/boot/lib/Makefile builds lib.a for use from
arch/xtensa/boot/boot-redboot/Makefile.
One more thing, adding everything to obj-y would increase the vmlinux
size of allnoconfig (or tinyconfig).
For less impact, I tweaked the destination of lib.a at the top Makefile;
when CONFIG_MODULES=y, lib.a goes to KBUILD_VMLINUX_OBJS, which is
forcibly linked to vmlinux, otherwise lib.a goes to KBUILD_VMLINUX_LIBS
as before.
The size impact for normal usecases is quite small since at lease one
symbol in every lib-y object is eventually called by someone. In case
you are intrested, here are the figures.
x86_64_defconfig:
text data bss dec hex filename
19566602 5422072 1589328 26578002 1958c52 vmlinux.before
19566932 5422104 1589328 26578364 1958dbc vmlinux.after
The case with the biggest impact is allnoconfig + CONFIG_MODULES=y.
ARCH=x86 allnoconfig + CONFIG_MODULES=y:
text data bss dec hex filename
1175162 254740 1220608 2650510 28718e vmlinux.before
1177974 254836 1220608 2653418 287cea vmlinux.after
Hopefully this is still not a big deal. The per-file trimming with the
static library is not so effective after all.
If fine-grained optimization is desired, some architectures support
CONFIG_LD_DEAD_CODE_DATA_ELIMINATION, which trims dead code per-symbol
basis. When LTO is supported in mainline, even better optimization will
be possible.
Link: https://github.com/ClangBuiltLinux/linux/issues/515
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
Reported-by: kbuild test robot <lkp@intel.com>
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
520 lines
17 KiB
Makefile
520 lines
17 KiB
Makefile
# SPDX-License-Identifier: GPL-2.0
|
|
# ==========================================================================
|
|
# Building
|
|
# ==========================================================================
|
|
|
|
src := $(obj)
|
|
|
|
PHONY := __build
|
|
__build:
|
|
|
|
# Init all relevant variables used in kbuild files so
|
|
# 1) they have correct type
|
|
# 2) they do not inherit any value from the environment
|
|
obj-y :=
|
|
obj-m :=
|
|
lib-y :=
|
|
lib-m :=
|
|
always :=
|
|
always-y :=
|
|
always-m :=
|
|
targets :=
|
|
subdir-y :=
|
|
subdir-m :=
|
|
EXTRA_AFLAGS :=
|
|
EXTRA_CFLAGS :=
|
|
EXTRA_CPPFLAGS :=
|
|
EXTRA_LDFLAGS :=
|
|
asflags-y :=
|
|
ccflags-y :=
|
|
cppflags-y :=
|
|
ldflags-y :=
|
|
|
|
subdir-asflags-y :=
|
|
subdir-ccflags-y :=
|
|
|
|
# Read auto.conf if it exists, otherwise ignore
|
|
-include include/config/auto.conf
|
|
|
|
include scripts/Kbuild.include
|
|
|
|
# The filename Kbuild has precedence over Makefile
|
|
kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
|
|
kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)
|
|
include $(kbuild-file)
|
|
|
|
include scripts/Makefile.lib
|
|
|
|
# Do not include host rules unless needed
|
|
ifneq ($(hostprogs)$(hostcxxlibs-y)$(hostcxxlibs-m),)
|
|
include scripts/Makefile.host
|
|
endif
|
|
|
|
ifndef obj
|
|
$(warning kbuild: Makefile.build is included improperly)
|
|
endif
|
|
|
|
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.)
|
|
endif
|
|
endif
|
|
|
|
# ===========================================================================
|
|
|
|
ifneq ($(strip $(lib-y) $(lib-m) $(lib-)),)
|
|
lib-target := $(obj)/lib.a
|
|
endif
|
|
|
|
ifdef need-builtin
|
|
builtin-target := $(obj)/built-in.a
|
|
endif
|
|
|
|
ifeq ($(CONFIG_MODULES)$(need-modorder),y1)
|
|
modorder-target := $(obj)/modules.order
|
|
endif
|
|
|
|
mod-targets := $(patsubst %.o, %.mod, $(obj-m))
|
|
|
|
# Linus' kernel sanity checking tool
|
|
ifeq ($(KBUILD_CHECKSRC),1)
|
|
quiet_cmd_checksrc = CHECK $<
|
|
cmd_checksrc = $(CHECK) $(CHECKFLAGS) $(c_flags) $<
|
|
else ifeq ($(KBUILD_CHECKSRC),2)
|
|
quiet_cmd_force_checksrc = CHECK $<
|
|
cmd_force_checksrc = $(CHECK) $(CHECKFLAGS) $(c_flags) $<
|
|
endif
|
|
|
|
ifneq ($(KBUILD_EXTRA_WARN),)
|
|
cmd_checkdoc = $(srctree)/scripts/kernel-doc -none $<
|
|
endif
|
|
|
|
# Compile C sources (.c)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
quiet_cmd_cc_s_c = CC $(quiet_modtag) $@
|
|
cmd_cc_s_c = $(CC) $(filter-out $(DEBUG_CFLAGS), $(c_flags)) $(DISABLE_LTO) -fverbose-asm -S -o $@ $<
|
|
|
|
$(obj)/%.s: $(src)/%.c FORCE
|
|
$(call if_changed_dep,cc_s_c)
|
|
|
|
quiet_cmd_cpp_i_c = CPP $(quiet_modtag) $@
|
|
cmd_cpp_i_c = $(CPP) $(c_flags) -o $@ $<
|
|
|
|
$(obj)/%.i: $(src)/%.c FORCE
|
|
$(call if_changed_dep,cpp_i_c)
|
|
|
|
# These mirror gensymtypes_S and co below, keep them in synch.
|
|
cmd_gensymtypes_c = \
|
|
$(CPP) -D__GENKSYMS__ $(c_flags) $< | \
|
|
scripts/genksyms/genksyms $(if $(1), -T $(2)) \
|
|
$(patsubst y,-R,$(CONFIG_MODULE_REL_CRCS)) \
|
|
$(if $(KBUILD_PRESERVE),-p) \
|
|
-r $(firstword $(wildcard $(2:.symtypes=.symref) /dev/null))
|
|
|
|
quiet_cmd_cc_symtypes_c = SYM $(quiet_modtag) $@
|
|
cmd_cc_symtypes_c = \
|
|
$(call cmd_gensymtypes_c,true,$@) >/dev/null; \
|
|
test -s $@ || rm -f $@
|
|
|
|
$(obj)/%.symtypes : $(src)/%.c FORCE
|
|
$(call cmd,cc_symtypes_c)
|
|
|
|
# LLVM assembly
|
|
# Generate .ll files from .c
|
|
quiet_cmd_cc_ll_c = CC $(quiet_modtag) $@
|
|
cmd_cc_ll_c = $(CC) $(c_flags) -emit-llvm -S -o $@ $<
|
|
|
|
$(obj)/%.ll: $(src)/%.c FORCE
|
|
$(call if_changed_dep,cc_ll_c)
|
|
|
|
# C (.c) files
|
|
# The C file is compiled and updated dependency information is generated.
|
|
# (See cmd_cc_o_c + relevant part of rule_cc_o_c)
|
|
|
|
quiet_cmd_cc_o_c = CC $(quiet_modtag) $@
|
|
cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<
|
|
|
|
ifdef CONFIG_MODVERSIONS
|
|
# When module versioning is enabled the following steps are executed:
|
|
# o compile a <file>.o from <file>.c
|
|
# o if <file>.o doesn't contain a __ksymtab version, i.e. does
|
|
# not export symbols, it's done.
|
|
# o otherwise, we calculate symbol versions using the good old
|
|
# genksyms on the preprocessed source and postprocess them in a way
|
|
# that they are usable as a linker script
|
|
# o generate .tmp_<file>.o from <file>.o using the linker to
|
|
# replace the unresolved symbols __crc_exported_symbol with
|
|
# the actual value of the checksum generated by genksyms
|
|
# o remove .tmp_<file>.o to <file>.o
|
|
|
|
cmd_modversions_c = \
|
|
if $(OBJDUMP) -h $@ | grep -q __ksymtab; then \
|
|
$(call cmd_gensymtypes_c,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \
|
|
> $(@D)/.tmp_$(@F:.o=.ver); \
|
|
\
|
|
$(LD) $(KBUILD_LDFLAGS) -r -o $(@D)/.tmp_$(@F) $@ \
|
|
-T $(@D)/.tmp_$(@F:.o=.ver); \
|
|
mv -f $(@D)/.tmp_$(@F) $@; \
|
|
rm -f $(@D)/.tmp_$(@F:.o=.ver); \
|
|
fi
|
|
endif
|
|
|
|
ifdef CONFIG_FTRACE_MCOUNT_RECORD
|
|
ifndef CC_USING_RECORD_MCOUNT
|
|
# compiler will not generate __mcount_loc use recordmcount or recordmcount.pl
|
|
ifdef BUILD_C_RECORDMCOUNT
|
|
ifeq ("$(origin RECORDMCOUNT_WARN)", "command line")
|
|
RECORDMCOUNT_FLAGS = -w
|
|
endif
|
|
# Due to recursion, we must skip empty.o.
|
|
# The empty.o file is created in the make process in order to determine
|
|
# the target endianness and word size. It is made before all other C
|
|
# files, including recordmcount.
|
|
sub_cmd_record_mcount = \
|
|
if [ $(@) != "scripts/mod/empty.o" ]; then \
|
|
$(objtree)/scripts/recordmcount $(RECORDMCOUNT_FLAGS) "$(@)"; \
|
|
fi;
|
|
recordmcount_source := $(srctree)/scripts/recordmcount.c \
|
|
$(srctree)/scripts/recordmcount.h
|
|
else
|
|
sub_cmd_record_mcount = perl $(srctree)/scripts/recordmcount.pl "$(ARCH)" \
|
|
"$(if $(CONFIG_CPU_BIG_ENDIAN),big,little)" \
|
|
"$(if $(CONFIG_64BIT),64,32)" \
|
|
"$(OBJDUMP)" "$(OBJCOPY)" "$(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS)" \
|
|
"$(LD) $(KBUILD_LDFLAGS)" "$(NM)" "$(RM)" "$(MV)" \
|
|
"$(if $(part-of-module),1,0)" "$(@)";
|
|
recordmcount_source := $(srctree)/scripts/recordmcount.pl
|
|
endif # BUILD_C_RECORDMCOUNT
|
|
cmd_record_mcount = $(if $(findstring $(strip $(CC_FLAGS_FTRACE)),$(_c_flags)), \
|
|
$(sub_cmd_record_mcount))
|
|
endif # CC_USING_RECORD_MCOUNT
|
|
endif # CONFIG_FTRACE_MCOUNT_RECORD
|
|
|
|
ifdef CONFIG_STACK_VALIDATION
|
|
ifneq ($(SKIP_STACK_VALIDATION),1)
|
|
|
|
__objtool_obj := $(objtree)/tools/objtool/objtool
|
|
|
|
objtool_args = $(if $(CONFIG_UNWINDER_ORC),orc generate,check)
|
|
|
|
objtool_args += $(if $(part-of-module), --module,)
|
|
|
|
ifndef CONFIG_FRAME_POINTER
|
|
objtool_args += --no-fp
|
|
endif
|
|
ifdef CONFIG_GCOV_KERNEL
|
|
objtool_args += --no-unreachable
|
|
endif
|
|
ifdef CONFIG_RETPOLINE
|
|
objtool_args += --retpoline
|
|
endif
|
|
ifdef CONFIG_X86_SMAP
|
|
objtool_args += --uaccess
|
|
endif
|
|
|
|
# 'OBJECT_FILES_NON_STANDARD := y': skip objtool checking for a directory
|
|
# 'OBJECT_FILES_NON_STANDARD_foo.o := 'y': skip objtool checking for a file
|
|
# 'OBJECT_FILES_NON_STANDARD_foo.o := 'n': override directory skip for a file
|
|
cmd_objtool = $(if $(patsubst y%,, \
|
|
$(OBJECT_FILES_NON_STANDARD_$(basetarget).o)$(OBJECT_FILES_NON_STANDARD)n), \
|
|
$(__objtool_obj) $(objtool_args) $@)
|
|
objtool_obj = $(if $(patsubst y%,, \
|
|
$(OBJECT_FILES_NON_STANDARD_$(basetarget).o)$(OBJECT_FILES_NON_STANDARD)n), \
|
|
$(__objtool_obj))
|
|
|
|
endif # SKIP_STACK_VALIDATION
|
|
endif # CONFIG_STACK_VALIDATION
|
|
|
|
# Rebuild all objects when objtool changes, or is enabled/disabled.
|
|
objtool_dep = $(objtool_obj) \
|
|
$(wildcard include/config/orc/unwinder.h \
|
|
include/config/stack/validation.h)
|
|
|
|
ifdef CONFIG_TRIM_UNUSED_KSYMS
|
|
cmd_gen_ksymdeps = \
|
|
$(CONFIG_SHELL) $(srctree)/scripts/gen_ksymdeps.sh $@ >> $(dot-target).cmd
|
|
endif
|
|
|
|
define rule_cc_o_c
|
|
$(call cmd,checksrc)
|
|
$(call cmd_and_fixdep,cc_o_c)
|
|
$(call cmd,gen_ksymdeps)
|
|
$(call cmd,checkdoc)
|
|
$(call cmd,objtool)
|
|
$(call cmd,modversions_c)
|
|
$(call cmd,record_mcount)
|
|
endef
|
|
|
|
define rule_as_o_S
|
|
$(call cmd_and_fixdep,as_o_S)
|
|
$(call cmd,gen_ksymdeps)
|
|
$(call cmd,objtool)
|
|
$(call cmd,modversions_S)
|
|
endef
|
|
|
|
# List module undefined symbols (or empty line if not enabled)
|
|
ifdef CONFIG_TRIM_UNUSED_KSYMS
|
|
cmd_undef_syms = $(NM) $< | sed -n 's/^ *U //p' | xargs echo
|
|
else
|
|
cmd_undef_syms = echo
|
|
endif
|
|
|
|
# Built-in and composite module parts
|
|
$(obj)/%.o: $(src)/%.c $(recordmcount_source) $(objtool_dep) FORCE
|
|
$(call cmd,force_checksrc)
|
|
$(call if_changed_rule,cc_o_c)
|
|
|
|
cmd_mod = { \
|
|
echo $(if $($*-objs)$($*-y)$($*-m), $(addprefix $(obj)/, $($*-objs) $($*-y) $($*-m)), $(@:.mod=.o)); \
|
|
$(cmd_undef_syms); \
|
|
} > $@
|
|
|
|
$(obj)/%.mod: $(obj)/%.o FORCE
|
|
$(call if_changed,mod)
|
|
|
|
targets += $(mod-targets)
|
|
|
|
quiet_cmd_cc_lst_c = MKLST $@
|
|
cmd_cc_lst_c = $(CC) $(c_flags) -g -c -o $*.o $< && \
|
|
$(CONFIG_SHELL) $(srctree)/scripts/makelst $*.o \
|
|
System.map $(OBJDUMP) > $@
|
|
|
|
$(obj)/%.lst: $(src)/%.c FORCE
|
|
$(call if_changed_dep,cc_lst_c)
|
|
|
|
# Compile assembler sources (.S)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
# .S file exports must have their C prototypes defined in asm/asm-prototypes.h
|
|
# or a file that it includes, in order to get versioned symbols. We build a
|
|
# dummy C file that includes asm-prototypes and the EXPORT_SYMBOL lines from
|
|
# the .S file (with trailing ';'), and run genksyms on that, to extract vers.
|
|
#
|
|
# This is convoluted. The .S file must first be preprocessed to run guards and
|
|
# expand names, then the resulting exports must be constructed into plain
|
|
# EXPORT_SYMBOL(symbol); to build our dummy C file, and that gets preprocessed
|
|
# to make the genksyms input.
|
|
#
|
|
# These mirror gensymtypes_c and co above, keep them in synch.
|
|
cmd_gensymtypes_S = \
|
|
{ echo "\#include <linux/kernel.h>" ; \
|
|
echo "\#include <asm/asm-prototypes.h>" ; \
|
|
$(CPP) $(a_flags) $< | \
|
|
grep "\<___EXPORT_SYMBOL\>" | \
|
|
sed 's/.*___EXPORT_SYMBOL[[:space:]]*\([a-zA-Z0-9_]*\)[[:space:]]*,.*/EXPORT_SYMBOL(\1);/' ; } | \
|
|
$(CPP) -D__GENKSYMS__ $(c_flags) -xc - | \
|
|
scripts/genksyms/genksyms $(if $(1), -T $(2)) \
|
|
$(patsubst y,-R,$(CONFIG_MODULE_REL_CRCS)) \
|
|
$(if $(KBUILD_PRESERVE),-p) \
|
|
-r $(firstword $(wildcard $(2:.symtypes=.symref) /dev/null))
|
|
|
|
quiet_cmd_cc_symtypes_S = SYM $(quiet_modtag) $@
|
|
cmd_cc_symtypes_S = \
|
|
$(call cmd_gensymtypes_S,true,$@) >/dev/null; \
|
|
test -s $@ || rm -f $@
|
|
|
|
$(obj)/%.symtypes : $(src)/%.S FORCE
|
|
$(call cmd,cc_symtypes_S)
|
|
|
|
|
|
quiet_cmd_cpp_s_S = CPP $(quiet_modtag) $@
|
|
cmd_cpp_s_S = $(CPP) $(a_flags) -o $@ $<
|
|
|
|
$(obj)/%.s: $(src)/%.S FORCE
|
|
$(call if_changed_dep,cpp_s_S)
|
|
|
|
quiet_cmd_as_o_S = AS $(quiet_modtag) $@
|
|
cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $<
|
|
|
|
ifdef CONFIG_ASM_MODVERSIONS
|
|
|
|
# versioning matches the C process described above, with difference that
|
|
# we parse asm-prototypes.h C header to get function definitions.
|
|
|
|
cmd_modversions_S = \
|
|
if $(OBJDUMP) -h $@ | grep -q __ksymtab; then \
|
|
$(call cmd_gensymtypes_S,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \
|
|
> $(@D)/.tmp_$(@F:.o=.ver); \
|
|
\
|
|
$(LD) $(KBUILD_LDFLAGS) -r -o $(@D)/.tmp_$(@F) $@ \
|
|
-T $(@D)/.tmp_$(@F:.o=.ver); \
|
|
mv -f $(@D)/.tmp_$(@F) $@; \
|
|
rm -f $(@D)/.tmp_$(@F:.o=.ver); \
|
|
fi
|
|
endif
|
|
|
|
$(obj)/%.o: $(src)/%.S $(objtool_dep) FORCE
|
|
$(call if_changed_rule,as_o_S)
|
|
|
|
targets += $(filter-out $(subdir-obj-y), $(real-obj-y)) $(real-obj-m) $(lib-y)
|
|
targets += $(extra-y) $(always-y) $(MAKECMDGOALS)
|
|
|
|
# Linker scripts preprocessor (.lds.S -> .lds)
|
|
# ---------------------------------------------------------------------------
|
|
quiet_cmd_cpp_lds_S = LDS $@
|
|
cmd_cpp_lds_S = $(CPP) $(cpp_flags) -P -U$(ARCH) \
|
|
-D__ASSEMBLY__ -DLINKER_SCRIPT -o $@ $<
|
|
|
|
$(obj)/%.lds: $(src)/%.lds.S FORCE
|
|
$(call if_changed_dep,cpp_lds_S)
|
|
|
|
# ASN.1 grammar
|
|
# ---------------------------------------------------------------------------
|
|
quiet_cmd_asn1_compiler = ASN.1 $(basename $@).[ch]
|
|
cmd_asn1_compiler = $(objtree)/scripts/asn1_compiler $< \
|
|
$(basename $@).c $(basename $@).h
|
|
|
|
$(obj)/%.asn1.c $(obj)/%.asn1.h: $(src)/%.asn1 $(objtree)/scripts/asn1_compiler
|
|
$(call cmd,asn1_compiler)
|
|
|
|
# Build the compiled-in targets
|
|
# ---------------------------------------------------------------------------
|
|
|
|
# To build objects in subdirs, we need to descend into the directories
|
|
$(obj)/%/built-in.a: $(obj)/% ;
|
|
|
|
#
|
|
# Rule to compile a set of .o files into one .a file (without symbol table)
|
|
#
|
|
ifdef builtin-target
|
|
|
|
quiet_cmd_ar_builtin = AR $@
|
|
cmd_ar_builtin = rm -f $@; $(AR) cDPrST $@ $(real-prereqs)
|
|
|
|
$(builtin-target): $(real-obj-y) FORCE
|
|
$(call if_changed,ar_builtin)
|
|
|
|
targets += $(builtin-target)
|
|
endif # builtin-target
|
|
|
|
#
|
|
# Rule to create modules.order file
|
|
#
|
|
# Create commands to either record .ko file or cat modules.order from
|
|
# a subdirectory
|
|
$(modorder-target): $(subdir-ym) FORCE
|
|
$(Q){ $(foreach m, $(modorder), \
|
|
$(if $(filter %/modules.order, $m), cat $m, echo $m);) :; } \
|
|
| $(AWK) '!x[$$0]++' - > $@
|
|
|
|
#
|
|
# Rule to compile a set of .o files into one .a file (with symbol table)
|
|
#
|
|
ifdef lib-target
|
|
|
|
$(lib-target): $(lib-y) FORCE
|
|
$(call if_changed,ar)
|
|
|
|
targets += $(lib-target)
|
|
|
|
endif
|
|
|
|
# NOTE:
|
|
# Do not replace $(filter %.o,^) with $(real-prereqs). When a single object
|
|
# module is turned into a multi object module, $^ will contain header file
|
|
# dependencies recorded in the .*.cmd file.
|
|
quiet_cmd_link_multi-m = LD [M] $@
|
|
cmd_link_multi-m = $(LD) $(ld_flags) -r -o $@ $(filter %.o,$^)
|
|
|
|
$(multi-used-m): FORCE
|
|
$(call if_changed,link_multi-m)
|
|
$(call multi_depend, $(multi-used-m), .o, -objs -y -m)
|
|
|
|
targets += $(multi-used-m)
|
|
targets := $(filter-out $(PHONY), $(targets))
|
|
|
|
# Add intermediate targets:
|
|
# When building objects with specific suffix patterns, add intermediate
|
|
# targets that the final targets are derived from.
|
|
intermediate_targets = $(foreach sfx, $(2), \
|
|
$(patsubst %$(strip $(1)),%$(sfx), \
|
|
$(filter %$(strip $(1)), $(targets))))
|
|
# %.asn1.o <- %.asn1.[ch] <- %.asn1
|
|
# %.dtb.o <- %.dtb.S <- %.dtb <- %.dts
|
|
# %.lex.o <- %.lex.c <- %.l
|
|
# %.tab.o <- %.tab.[ch] <- %.y
|
|
targets += $(call intermediate_targets, .asn1.o, .asn1.c .asn1.h) \
|
|
$(call intermediate_targets, .dtb.o, .dtb.S .dtb) \
|
|
$(call intermediate_targets, .lex.o, .lex.c) \
|
|
$(call intermediate_targets, .tab.o, .tab.c .tab.h)
|
|
|
|
# Build
|
|
# ---------------------------------------------------------------------------
|
|
|
|
ifdef single-build
|
|
|
|
KBUILD_SINGLE_TARGETS := $(filter $(obj)/%, $(KBUILD_SINGLE_TARGETS))
|
|
|
|
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-out $(curdir-single), $(KBUILD_SINGLE_TARGETS)))
|
|
|
|
single-subdirs := $(foreach d, $(subdir-ym), \
|
|
$(if $(filter $(d)/%, $(KBUILD_SINGLE_TARGETS)), $(d)))
|
|
|
|
__build: $(curdir-single) $(single-subdirs)
|
|
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-y)
|
|
@:
|
|
|
|
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))
|
|
|
|
# Add FORCE to the prequisites of a target to force it to be always rebuilt.
|
|
# ---------------------------------------------------------------------------
|
|
|
|
PHONY += FORCE
|
|
|
|
FORCE:
|
|
|
|
# Read all saved command lines and dependencies for the $(targets) we
|
|
# may be building above, using $(if_changed{,_dep}). As an
|
|
# optimization, we don't need to read them if the target does not
|
|
# exist, we will rebuild anyway in that case.
|
|
|
|
existing-targets := $(wildcard $(sort $(targets)))
|
|
|
|
-include $(foreach f,$(existing-targets),$(dir $(f)).$(notdir $(f)).cmd)
|
|
|
|
ifdef building_out_of_srctree
|
|
# Create directories for object files if they do not exist
|
|
obj-dirs := $(sort $(obj) $(patsubst %/,%, $(dir $(targets))))
|
|
# If targets exist, their directories apparently exist. Skip mkdir.
|
|
existing-dirs := $(sort $(patsubst %/,%, $(dir $(existing-targets))))
|
|
obj-dirs := $(strip $(filter-out $(existing-dirs), $(obj-dirs)))
|
|
ifneq ($(obj-dirs),)
|
|
$(shell mkdir -p $(obj-dirs))
|
|
endif
|
|
endif
|
|
|
|
.PHONY: $(PHONY)
|