# $Id: footer.kmk 3121 2017-10-31 10:58:59Z bird $
## @file
# kBuild - File included at bottom of a makefile.
#

#
# Copyright (c) 2004-2017 knut st. osmundsen <bird-kBuild-spam-xviiv@anduin.net>
#
# 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))

# included dependency files.
_DEPFILES_INCLUDED :=


# 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


#
# 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__)

