# $Id$ ## @file # kBuild - File included at bottom of a makefile. # # # Copyright (c) 2004-2017 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version source of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # ifndef __footer_kmk__ # start-of-file-content ifdef KBUILD_PROFILE_SELF $(evalcall def_profile_self, start of footer.kmk) _KBUILD_TS_FOOTER_START := $(_KBUILD_TS_PREV) endif # # Variables. # (Some of these need initialization before including definitions using them.) # # All targets of each types. _ALL_BLDPROGS := $(BLDPROGS) $(BLDPROGS.$(KBUILD_HOST)) $(BLDPROGS.$(KBUILD_HOST).$(KBUILD_HOST_ARCH)) $(BLDPROGS.$(KBUILD_HOST_ARCH)) $(BLDPROGS.$(KBUILD_HOST_CPU)) $(BLDPROGS.$(KBUILD_TYPE)) _ALL_LIBRARIES := $(LIBRARIES) $(LIBRARIES.$(KBUILD_TARGET)) $(LIBRARIES.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(LIBRARIES.$(KBUILD_TARGET_ARCH)) $(LIBRARIES.$(KBUILD_TARGET_CPU)) $(LIBRARIES.$(KBUILD_TYPE)) _ALL_IMPORT_LIBS := $(IMPORT_LIBS) $(IMPORT_LIBS.$(KBUILD_TARGET)) $(IMPORT_LIBS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(IMPORT_LIBS.$(KBUILD_TARGET_ARCH)) $(IMPORT_LIBS.$(KBUILD_TARGET_CPU)) $(IMPORT_LIBS.$(KBUILD_TYPE)) _ALL_DLLS := $(DLLS) $(DLLS.$(KBUILD_TARGET)) $(DLLS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(DLLS.$(KBUILD_TARGET_ARCH)) $(DLLS.$(KBUILD_TARGET_CPU)) $(DLLS.$(KBUILD_TYPE)) _ALL_PROGRAMS := $(PROGRAMS) $(PROGRAMS.$(KBUILD_TARGET)) $(PROGRAMS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(PROGRAMS.$(KBUILD_TARGET_ARCH)) $(PROGRAMS.$(KBUILD_TARGET_CPU)) $(PROGRAMS.$(KBUILD_TYPE)) _ALL_SYSMODS := $(SYSMODS) $(SYSMODS.$(KBUILD_TARGET)) $(SYSMODS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(SYSMODS.$(KBUILD_TARGET_ARCH)) $(SYSMODS.$(KBUILD_TARGET_CPU)) $(SYSMODS.$(KBUILD_TYPE)) _ALL_MISCBINS := $(MISCBINS) $(MISCBINS.$(KBUILD_TARGET)) $(MISCBINS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(MISCBINS.$(KBUILD_TARGET_ARCH)) $(MISCBINS.$(KBUILD_TARGET_CPU)) $(MISCBINS.$(KBUILD_TYPE)) _ALL_OTHERS := $(OTHERS) $(OTHERS.$(KBUILD_TARGET)) $(OTHERS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(OTHERS.$(KBUILD_TARGET_ARCH)) $(OTHERS.$(KBUILD_TARGET_CPU)) $(OTHERS.$(KBUILD_TYPE)) _ALL_INSTALLS := $(INSTALLS) $(INSTALLS.$(KBUILD_TARGET)) $(INSTALLS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(INSTALLS.$(KBUILD_TARGET_ARCH)) $(INSTALLS.$(KBUILD_TARGET_CPU)) $(INSTALLS.$(KBUILD_TYPE)) _ALL_FETCHES := $(FETCHES) $(FETCHES.$(KBUILD_TARGET)) $(FETCHES.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(FETCHES.$(KBUILD_TARGET_ARCH)) $(FETCHES.$(KBUILD_TARGET_CPU)) $(FETCHES.$(KBUILD_TYPE)) _ALL_PATCHES := $(PATCHES) $(PATCHES.$(KBUILD_TARGET)) $(PATCHES.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(PATCHES.$(KBUILD_TARGET_ARCH)) $(PATCHES.$(KBUILD_TARGET_CPU)) $(PATCHES.$(KBUILD_TYPE)) # all targets. _ALL_TARGETS = \ $(_ALL_FETCHES) \ $(_ALL_PATCHES) \ $(_ALL_BLDPROGS) \ $(_ALL_LIBRARIES) \ $(_ALL_IMPORT_LIBS) \ $(_ALL_DLLS) \ $(_ALL_PROGRAMS) \ $(_ALL_SYSMODS) \ $(_ALL_MISCBINS) \ $(_ALL_INSTALLS) \ $(_ALL_OTHERS) # all $(KBUILD_TARGET) targets. _ALL_TARGET_TARGETS = \ $(_ALL_FETCHES) \ $(_ALL_PATCHES) \ $(_ALL_LIBRARIES) \ $(_ALL_IMPORT_LIBS) \ $(_ALL_DLLS) \ $(_ALL_PROGRAMS) \ $(_ALL_SYSMODS) \ $(_ALL_MISCBINS) \ $(_ALL_INSTALLS) \ $(_ALL_OTHERS) # all $(KBUILD_HOST) targets. _ALL_HOST_TARGETS = \ $(_ALL_BLDPROGS) # all targets making use of srcname. _ALL_SRCNAME_TARGETS = \ $(_ALL_FETCHES) \ $(_ALL_PATCHES) # Dependency files. (currently not on target level, only this global stuff) _DEPFILES := $(DEPFILES) $(DEPFILES.$(KBUILD_TARGET)) $(DEPFILES.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(DEPFILES.$(KBUILD_TARGET_ARCH)) $(DEPFILES.$(KBUILD_TARGET_CPU)) $(DEPFILES.$(KBUILD_TYPE)) # All kind of output files except for _OBJS and _DEPFILES. # Compiling or linking definition outputting other things that $@ and any # required dependency file must add those output files to this variable. _OUT_FILES := # Files which only requires cleaning up. _CLEAN_FILES := # all of a type _OBJS := _FETCHES := _DOWNLOADS:= _UNPACKS := _PATCHES := _UNFETCHES:= _BLDPROGS := _LIBS := _DLLS := _PROGRAMS := _SYSMODS := _MISCBINS := _STAGE_FILES := _STAGE_DIRS := _INSTALLS := _INSTALLS_FILES := _INSTALLS_DIRS := _DEBUG_STAGE_FILES := _DEBUG_STAGE_DIRS := _DEBUG_INSTALL_FILES := _DEBUG_INSTALL_DIRS := _OTHERS := _PACKING := _DIRS := $(PATH_TARGET)/ $(PATH_TARGET) $(BLDDIRS) _IMPORT_LIBS := # Implicit targets added while processing other targets (usually by units). _ALL_INSTALLS_IMPLICIT := # misc pass_prev := # # Footer macros # ## Figure out the tool for a target. # @param $1 normalized target. # @param $2 tooltype. # @param bld_trg build target. # @param bld_trg_arch build target architecture. # @param bld_type build target type. if 0 _TARGET_TOOL = $(strip $(firstword \ $($(1)_$(2)TOOL.$(bld_trg).$(bld_trg_arch)) \ $($(1)_$(2)TOOL.$(bld_trg)) \ $($(1)_$(2)TOOL) \ $($(1)_TOOL.$(bld_trg).$(bld_trg_arch)) \ $($(1)_TOOL.$(bld_trg)) \ $($(1)_TOOL) \ $($(2)TOOL.$(bld_trg).$(bld_trg_arch)) \ $($(2)TOOL.$(bld_trg)) \ $($(2)TOOL) \ $(TOOL.$(bld_trg).$(bld_trg_arch)) \ $(TOOL.$(bld_trg)) \ $(TOOL) \ )) else _TARGET_TOOL = $(strip $(firstword \ $($(1)_$(2)TOOL.$(bld_trg).$(bld_trg_arch).$(bld_type)) \ $($(1)_$(2)TOOL.$(bld_trg).$(bld_trg_arch)) \ $($(1)_$(2)TOOL.$(bld_trg).$(bld_type)) \ $($(1)_$(2)TOOL.$(bld_trg_arch)) \ $($(1)_$(2)TOOL.$(bld_trg)) \ $($(1)_$(2)TOOL.$(bld_type)) \ $($(1)_$(2)TOOL) \ $($(1)_TOOL.$(bld_trg).$(bld_trg_arch).$(bld_type)) \ $($(1)_TOOL.$(bld_trg).$(bld_trg_arch)) \ $($(1)_TOOL.$(bld_trg).$(bld_type)) \ $($(1)_TOOL.$(bld_trg_arch)) \ $($(1)_TOOL.$(bld_trg)) \ $($(1)_TOOL.$(bld_type)) \ $($(1)_TOOL) \ $($(2)TOOL.$(bld_trg).$(bld_trg_arch).$(bld_type)) \ $($(2)TOOL.$(bld_trg).$(bld_trg_arch)) \ $($(2)TOOL.$(bld_trg).$(bld_type)) \ $($(2)TOOL.$(bld_trg_arch)) \ $($(2)TOOL.$(bld_trg)) \ $($(2)TOOL.$(bld_type)) \ $($(2)TOOL) \ $(TOOL.$(bld_trg).$(bld_trg_arch).$(bld_type)) \ $(TOOL.$(bld_trg).$(bld_trg_arch)) \ $(TOOL.$(bld_trg).$(bld_type)) \ $(TOOL.$(bld_trg_arch)) \ $(TOOL.$(bld_trg)) \ $(TOOL.$(bld_type)) \ $(TOOL) \ )) endif ## Figure out the actual name of an installed file. # @param $1 The file to install. # @param $2 The target name. # @param $3 The _INST value (can be empty). # @param $4 The installation root directory. _INSTALL_FILE = $(patsubst %/,%/$(notdir $(1)),$(if $(3),$(4)/$(3),$(4)/)) ## # Function for getting the first defined propert value. # # @param 1 The property name. # @param 2 The default property name, empty if none. # @param 3 What to return if all variables are empty. (optional) # @note Implicit parameters: target, bld_trg, bld_trg_arch, bld_trg_cpu, bld_type. # @returns Expanded property value. # define def_fn_prop_get_first_defined local .RETURN := $(firstdefined \ $(target)_$(1).$(bld_trg).$(bld_trg_arch).$(bld_type) \ $(target)_$(1).$(bld_trg).$(bld_trg_arch) \ $(target)_$(1).$(bld_trg).$(bld_type) \ $(target)_$(1).$(bld_trg_cpu) \ $(target)_$(1).$(bld_trg_arch) \ $(target)_$(1).$(bld_trg) \ $(target)_$(1).$(bld_type) \ $(target)_$(1) \ ) ifeq ($(.RETURN),) ifneq ($(2),) local .RETURN := $(firstdefined \ $(2).$(bld_trg).$(bld_trg_arch).$(bld_type) \ $(2).$(bld_trg).$(bld_trg_arch) \ $(2).$(bld_trg).$(bld_type) \ $(2).$(bld_trg_cpu) \ $(2).$(bld_trg_arch) \ $(2).$(bld_trg) \ $(2).$(bld_type) \ $(2) \ 3 \ ) else local .RETURN := $(firstdefined \ kBuildGlobalDefaults_$(1).$(bld_trg).$(bld_trg_arch).$(bld_type) \ kBuildGlobalDefaults_$(1).$(bld_trg).$(bld_trg_arch) \ kBuildGlobalDefaults_$(1).$(bld_trg).$(bld_type) \ kBuildGlobalDefaults_$(1).$(bld_trg_cpu) \ kBuildGlobalDefaults_$(1).$(bld_trg_arch) \ kBuildGlobalDefaults_$(1).$(bld_trg) \ kBuildGlobalDefaults_$(1).$(bld_type) \ kBuildGlobalDefaults_$(1) \ 3 \ ) endif endif local .RETURN := $(strip $($(.RETURN))) endef # def_fn_prop_get_first_defined ## # Function for getting the first property value (ignoring empty defines). # # @param 1 The property name. # @param 2 The default property name, empty if none. # @param 3 What to return if all variables are empty. (optional) # @note Implicit parameters: target, bld_trg, bld_trg_arch, bld_trg_cpu, bld_type. # @returns First word. # define def_fn_prop_get_first_word local .RETURN := $(firstword \ $($(target)_$(1).$(bld_trg).$(bld_trg_arch).$(bld_type)) \ $($(target)_$(1).$(bld_trg).$(bld_trg_arch)) \ $($(target)_$(1).$(bld_trg).$(bld_type)) \ $($(target)_$(1).$(bld_trg_cpu)) \ $($(target)_$(1).$(bld_trg_arch)) \ $($(target)_$(1).$(bld_trg)) \ $($(target)_$(1).$(bld_type)) \ $($(target)_$(1)) \ ) ifeq ($(.RETURN),) ifneq ($(2),) local .RETURN := $(firstword \ $($(2).$(bld_trg).$(bld_trg_arch).$(bld_type)) \ $($(2).$(bld_trg).$(bld_trg_arch)) \ $($(2).$(bld_trg).$(bld_type)) \ $($(2).$(bld_trg_cpu)) \ $($(2).$(bld_trg_arch)) \ $($(2).$(bld_trg)) \ $($(2).$(bld_type)) \ $($(2)) \ $(3) \ ) else local .RETURN := $(firstword \ $(kBuildGlobalDefaults_$(1).$(bld_trg).$(bld_trg_arch).$(bld_type)) \ $(kBuildGlobalDefaults_$(1).$(bld_trg).$(bld_trg_arch)) \ $(kBuildGlobalDefaults_$(1).$(bld_trg).$(bld_type)) \ $(kBuildGlobalDefaults_$(1).$(bld_trg_cpu)) \ $(kBuildGlobalDefaults_$(1).$(bld_trg_arch)) \ $(kBuildGlobalDefaults_$(1).$(bld_trg)) \ $(kBuildGlobalDefaults_$(1).$(bld_type)) \ $(kBuildGlobalDefaults_$(1)) \ $(3) \ ) endif endif endef # def_fn_prop_get_first_word ## # Function for collecting properties, priority ones last. # # @param 1 The property name. # @param 2 The default property name, empty if none. # @note Implicit parameters: target, bld_trg, bld_trg_arch, bld_trg_cpu, bld_type. # @returns All properties. # define def_fn_prop_get_all_priority_last local .RETURN := \ $($(target)_$(1)) \ $($(target)_$(1).$(bld_type)) \ $($(target)_$(1).$(bld_trg)) \ $($(target)_$(1).$(bld_trg_arch)) \ $($(target)_$(1).$(bld_trg_cpu)) \ $($(target)_$(1).$(bld_trg).$(bld_type)) \ $($(target)_$(1).$(bld_trg).$(bld_trg_arch)) \ $($(target)_$(1).$(bld_trg).$(bld_trg_arch).$(bld_type)) endef # def_fn_prop_get_all_priority_last ## # Function for collecting properties with prefixing, priority ones last. # # @param 1 The property name. # @param 2 Something like $(NLTAB). # @note Implicit parameters: target, bld_trg, bld_trg_arch, bld_trg_cpu, bld_type. # @returns All properties. # define def_fn_prop_get_all_prefixed_priority_last local .RETURN := \ $(if $($(target)_$(1)),$(2),)$($(target)_$(1)) \ $(if $($(target)_$(1).$(bld_type)),$(2),)$($(target)_$(1).$(bld_type)) \ $(if $($(target)_$(1).$(bld_trg)),$(2),)$($(target)_$(1).$(bld_trg)) \ $(if $($(target)_$(1).$(bld_trg_arch)),$(2),)$($(target)_$(1).$(bld_trg_arch)) \ $(if $($(target)_$(1).$(bld_trg_cpu)),$(2),)$($(target)_$(1).$(bld_trg_cpu)) \ $(if $($(target)_$(1).$(bld_trg).$(bld_type)),$(2),)$($(target)_$(1).$(bld_trg).$(bld_type)) \ $(if $($(target)_$(1).$(bld_trg).$(bld_trg_arch)),$(2),)$($(target)_$(1).$(bld_trg).$(bld_trg_arch)) \ $(if $($(target)_$(1).$(bld_trg).$(bld_trg_arch).$(bld_type)),$(2),)$($(target)_$(1).$(bld_trg).$(bld_trg_arch).$(bld_type)) endef # def_fn_prop_get_all_prefixed_priority_last # # The main body. # include $(KBUILD_PATH)/footer-inherit-uses-tools.kmk include $(KBUILD_PATH)/footer-pass1.kmk include $(KBUILD_PATH)/footer-pass2-fetches.kmk include $(KBUILD_PATH)/footer-pass2-patches.kmk include $(KBUILD_PATH)/footer-pass2-compiling-targets.kmk include $(KBUILD_PATH)/footer-pass2-installs.kmk include $(KBUILD_PATH)/footer-misc.kmk include $(KBUILD_PATH)/footer-passes.kmk # # THE MAIN RULES # all_recursive: $(pass_prev) rebuild: clean + $(MAKE) -f $(firstword $(MAKEFILE_LIST)) all_recursive # @todo make this a non-default pass! uninstall:: $(RM) -f -- $(_INSTALLS_FILES) install:: pass_installs # misc shortcuts (use secondary expansion here to save strcache[file] space). targets: bldprogs libraries dlls programs sysmods miscbins others installs objects: $$(_OBJS) bldprogs: $$(_BLDPROGS) libraries: $$(_LIBS) $$(_IMPORT_LIBS) $$(_OTHER_LIBRARIES) dlls: $$(_DLLS) programs: $$(_PROGRAMS) sysmods: $$(_SYSMODS) miscbins: $$(_MISCBINS) others: $$(_OTHERS) stagings: $$(_INSTALLS) $$(_STAGE_DIRS) $$(_STAGE_FILES) installs: $$(_INSTALLS_DIRS) $$(_INSTALLS_FILES) install-debug: $$(_DEBUG_INSTALL_DIRS) $$(_DEBUG_INSTALL_FILES) # # kBuild debugging stuff. # ## @todo this doesn't work. Move to a debug unit and expand it. show_targets: @$(foreach target, $(_ALL_TARGETS),\ @$(ECHO) "target: $(target)" $(NLTAB)\ @$(ECHO) " $(target)_0_OUTDIR=$($(target)_0_OUTDIR)" $(NLTAB)\ @$(ECHO) " $(target)_1_TARGET=$($(target)_1_TARGET)" $(NLTAB)\ @$(ECHO) " INSTARGET_$(target)=$(INSTARGET_$(target))" $(NLTAB)\ $(foreach prop,$(PROPS_SINGLE) $(PROPS_ACCUMULATE_L) $(PROPS_ACCUMULATE_R) 2_OBJS CLEAN, \ $(eval _tmp:=$(firstword $($(target)_BLD_TRG) $(KBUILD_TARGET))) \ $(if $($(target)_$(prop).$(_tmp)),\ @$(ECHO) " $(target)_$(prop).$(_tmp)=$($(target)_$(prop).$(_tmp))" $(NLTAB)) \ $(if $($(target)_$(prop)), $(NLTAB)@$(ECHO) " $(target)_$(prop)=$($(target)_$(prop))" $(NLTAB)) \ )\ $(foreach prop,$(PROPS_DEFERRED), \ $(eval _tmp:=$(firstword $($(target)_BLD_TRG) $(KBUILD_TARGET))) \ $(if $(value $(target)_$(prop).$(_tmp)),\ @$(ECHO) ' $(target)_$(prop).$(_tmp)=$(value $(TARGET)_$(prop).$(_tmp))' $(NLTAB)) \ $(if $(value $(target)_$(prop)), $(NLTAB)@$(ECHO) ' $(target)_$(prop)=$(value $(target)_$(prop))' $(NLTAB)) \ )) # # Include dependency files. # ifdef _DEPFILES # TODO: first works the second doesn't, provided _KB_INCLUDE_DEPS is undefined: # if "$(_KB_INCLUDE_DEPS)" == "1" # if $(_KB_INCLUDE_DEPS) == "1" ifdef KB_HAVE_INCLUDEDEP_QUEUE includedep-queue $(_DEPFILES) else $(foreach dep, $(_DEPFILES), $(eval includedep $(dep))) endif endif ifdef KBUILD_PROFILE_SELF $(evalcall def_profile_self, end of footer.kmk) _KBUILD_TS_FOOTER_END := $(_KBUILD_TS_PREV) ifneq ($(KBUILD_PROFILE_SELF),0) $(info prof: ALL=$(words $(_ALL_TARGETS)) BLDPROGS=$(words $(_ALL_BLDPROGS)) LIBRARIES=$(words $(_ALL_LIBRARIES)) IMPORT_LIBS=$(words $(IMPORT_LIBS)) DLLS=$(words $(DLLS)) PROGRAMS=$(words $(_ALL_PROGRAMS)) ) $(info prof: SYSMODS=$(words $(_ALL_SYSMODS)) MISCBINS=$(words $(_ALL_MISCBINS)) OTHERS=$(words $(_ALL_OTHERS)) INSTALLS=$(words $(_ALL_INSTALLS)) FETCHES=$(words $(_ALL_FETCHES)) PACKING=$(words $(_PACKING)) TESTING=$(words $(TESTING)) ) $(info prof: DIRS=$(words $(_DIR_ALL)) TOOLS=$(words $(_TOOLS)) SDKS=$(words $(_SDKS)) USES=$(words $(_USES)) OUT_FILES=$(words $(_OUT_FILES)) OBJS=$(words $(_OBJS)) CLEAN_FILES=$(words $(CLEAN_FILES) $(OTHER_CLEAN)) ) $(info prof: DEPFILES_INCLUDED=$(words $(_DEPFILES_INCLUDED)) DEPFILES=$(words $(_DEPFILES)) MAKEFILES=$(words $(MAKEFILE_LIST)) ) endif endif # end-of-file-content __footer_kmk__ := target endif # !defined(__footer_kmk__)