# Internal build of executable and/or library in any hierarchical structure of folders.

# Inputs:
#  LOCAL_INCLUDE_DIRS
#  LOCAL_SRC_LIB_C
#  LOCAL_SRC_CPP
#  LOCAL_SRC_C
#  LOCAL_SRC_S
#  LOCAL_CFLAGS
#  LOCAL_CUSTOM_LIBS
#  LOCAL_STATIC_LIBRARIES
#  LOCAL_IMPRINT_TOOL

# Internal inputs:
#  _cc
#  _cxx
#  _ar
#  _platform_libs
#  _local_output_base
#  _local_output_dir
#  _start_group
#  _end_group

_sdk_dir := $(realpath $(dir $(lastword $(MAKEFILE_LIST))))

ifeq ($(TEESDK_VERBOSE),y)
  Q=
else
  Q=@
endif

#########################
# Prepare local sources #
#########################

LOCAL_INCLUDE_DIRS := $(call get-absolute-path,$(LOCAL_INCLUDE_DIRS))
LOCAL_SRC_LIB_C := $(call get-absolute-path,$(LOCAL_SRC_LIB_C))
# Relative paths of following sources will be transformed later in target definition.
# - LOCAL_SRC_CPP
# - LOCAL_SRC_C
# - LOCAL_SRC_S
# - LOCAL_CFLAGS

###################
# Prepare imprint #
###################

LOCAL_IMPRINT_TOOL := $(strip $(LOCAL_IMPRINT_TOOL))

ifeq ($(LOCAL_IMPRINT_TOOL),)
  LOCAL_IMPRINT_TOOL := echo No imprint required for
endif

######################
# Build dependencies #
######################

$(foreach _lib,$(LOCAL_STATIC_LIBRARIES),\
  $(if $(filter _exported_$(LOCAL_TARGET_NAME)_$(LOCAL_PLATFORM)_$(_lib),$(_global_exported_libs)),\
    $(eval LOCAL_CUSTOM_LIBS += $(_exported_$(LOCAL_TARGET_NAME)_$(LOCAL_PLATFORM)_$(_lib))),\
    $(eval LOCAL_CUSTOM_LIBS += $(_local_output_base)/$(_lib)/$(_lib).a)))

##################
# Build binaries #
##################

define -get-objects
  $(foreach _ext,$(1), \
    $(addprefix $(_local_output_dir)/obj/, \
      $(patsubst %.$(_ext),%.o,$(filter %.$(_ext),$(2)))))
endef

# Custom libraries.
ifeq ($(LOCAL_FIPS_CRYPTO)$(LOCAL_PLATFORM),yhost)
  _local_custom_libs := $(_platform_libs) $(LOCAL_CUSTOM_LIBS) $(_platform_libs)
else
  _local_custom_libs := $(LOCAL_CUSTOM_LIBS) $(_platform_libs)
endif
# Custom ldflags.
_local_ldflags := $(strip $(LOCAL_LDFLAGS))
# Compiler options.
_cc_opts := $(addprefix -I,$(LOCAL_INCLUDE_DIRS)) $(LOCAL_CFLAGS)
_cxx_opts := $(addprefix -I,$(LOCAL_INCLUDE_DIRS)) $(LOCAL_CPPFLAGS)
# Archivator options.
ifeq ($(_ar:%/armar=armar),armar)
  _ar_opts := --create -v
else
  _ar_opts := rcs
endif

# Library target.
_lib := $(_local_output_dir)/$(LOCAL_NAME).a
# TA target.
_bin := $(_local_output_dir)/$(LOCAL_NAME)
# TA target (unstripped).
_bin_unstripped := $(_local_output_dir)/unstripped/$(LOCAL_NAME)
# C objects targets.
_obj_c := $(call -get-objects,c,$(LOCAL_SRC_C))
# C++ objects targets.
_obj_cpp := $(call -get-objects,cpp cc,$(LOCAL_SRC_CPP))

#################
# Build library #
#################

$(_lib): _ar := $(_ar)
$(_lib): _ar_opts := $(_ar_opts)
$(_lib): $(_obj_c) $(_obj_cpp)
	@echo "["$(notdir $(_ar))" ] StaticLibrary:" $(notdir $@)
	$(Q)$(_ar) $(_ar_opts) $(@) $^

############
# Build TA #
############

# _local_ldflags is included twice to handle both
# Blowfish teesl lib (should be included before object
# files) and regular libs linking.

$(_bin): _strip := $(_strip)
$(_bin): _post_link_command := $(LOCAL_IMPRINT_TOOL)
$(_bin): $(_bin_unstripped)
	$(Q)cp -f $< $@
	@echo "[   ] Stripping    :" $(notdir $@)
	$(Q)$(_strip) $@
	$(Q)$(_post_link_command) $@

$(_bin_unstripped): _ld := $(_ld)
$(_bin_unstripped): _local_custom_libs := $(_local_custom_libs)
$(_bin_unstripped): _start_group := $(_start_group)
$(_bin_unstripped): _end_group := $(_end_group)
$(_bin_unstripped): _local_ldflags := $(_local_ldflags)
$(_bin_unstripped): $(_obj_c) $(_obj_cpp) $(_local_custom_libs)
	$(Q)mkdir -p $(dir $(abspath $@))
	@echo "["$(notdir $(_ld))"] Executable   :" $(notdir $@)
	$(Q)$(_ld) $(_start_group) $^ $(_end_group) $(_local_ldflags) -o $@

_start_group :=
_end_group :=

#################
# Build objects #
#################

define -build-single-file
  _file := $(1)
  _ext := $(2)
  _command := $(3) $(4)
  _obj := $$(call -get-objects,$$(_ext),$$(_file))

$$(_obj): _command := $$(_command)
$$(_obj): $$(call get-absolute-path,$$(_file))
	$(Q)mkdir -p $$(dir $$(@))
	@echo "["$(notdir $(3))"] Compile      :" $(notdir $(_bin)) "<=" $(notdir $(_file))
	$(Q)$$(_command) -c -o $$(@) $$(<)
endef

$(foreach _file,$(LOCAL_SRC_C),\
  $(eval $(call -build-single-file,$(_file),c,$(_cc), $(_cc_opts))))

$(foreach _file,$(LOCAL_SRC_CPP),\
  $(eval $(call -build-single-file,$(_file),cpp cc,$(_cxx), $(_cxx_opts))))

#########################
# Default clean targets #
#########################

include $(_sdk_dir)/build-binary-goal-clean.mk
