# Build apk using SDK build tools.

# Common parameters:
# - LOCAL_NAME
# - LOCAL_PROJECT_DIR
# - LOCAL_SDK_PATH
# - LOCAL_BUILD_TOOLS_VERSION
# - LOCAL_PLATFORM_VERSION
# - LOCAL_SRC_DIR
# - LOCAL_RESOURCE_DIR
# Optional:
# - LOCAL_CUSTOM_LIBS
# - LOCAL_MANIFEST_FILE
# - LOCAL_JAVA_START_VERSION
# - LOCAL_JAVA_END_VERSION
# - LOCAL_AAPT_ARGS
# - LOCAL_JAVAC_ARGS
# - LOCAL_DX_ARGS

_sdk_dir := $(realpath $(dir $(lastword $(MAKEFILE_LIST))))

include $(_sdk_dir)/path-utilities.mk

####################################
# Check necessary input parameters #
####################################

LOCAL_NAME := $(strip $(LOCAL_NAME))
LOCAL_PROJECT_DIR := $(strip $(LOCAL_PROJECT_DIR))
LOCAL_SDK_PATH := $(strip $(LOCAL_SDK_PATH))
LOCAL_BUILD_TOOLS_VERSION := $(strip $(LOCAL_BUILD_TOOLS_VERSION))
LOCAL_PLATFORM_VERSION := $(strip $(LOCAL_PLATFORM_VERSION))
LOCAL_SRC_DIR := $(strip $(LOCAL_SRC_DIR))
LOCAL_RESOURCE_DIR := $(strip $(LOCAL_RESOURCE_DIR))
LOCAL_CUSTOM_LIBS := $(strip $(LOCAL_CUSTOM_LIBS))
LOCAL_MANIFEST_FILE := $(strip $(LOCAL_MANIFEST_FILE))
LOCAL_JAVA_START_VERSION := $(strip $(LOCAL_JAVA_START_VERSION))
LOCAL_JAVA_END_VERSION := $(strip $(LOCAL_JAVA_END_VERSION))
LOCAL_AAPT_ARGS := $(strip $(LOCAL_AAPT_ARGS))
LOCAL_JAVAC_ARGS := $(strip $(LOCAL_JAVAC_ARGS))
LOCAL_DX_ARGS := $(strip $(LOCAL_DX_ARGS))

ifeq ($(LOCAL_NAME),)
  $(error LOCAL_NAME is not specified)
endif

ifeq ($(LOCAL_PROJECT_DIR),)
  $(error LOCAL_PROJECT_DIR is not specified)
endif

ifeq ($(LOCAL_SDK_PATH),)
  $(error LOCAL_SDK_PATH is not specified)
endif

ifeq ($(LOCAL_BUILD_TOOLS_VERSION),)
  $(error LOCAL_BUILD_TOOLS_VERSION is not specified)
endif

ifeq ($(LOCAL_PLATFORM_VERSION),)
  $(error LOCAL_PLATFORM_VERSION is not specified)
endif

_local_aapt := $(strip $(LOCAL_SDK_PATH)/build-tools/$(LOCAL_BUILD_TOOLS_VERSION)/aapt)
_local_dx := $(strip $(LOCAL_SDK_PATH)/build-tools/$(LOCAL_BUILD_TOOLS_VERSION)/dx)
_local_zipalign := $(strip $(LOCAL_SDK_PATH)/build-tools/$(LOCAL_BUILD_TOOLS_VERSION)/zipalign)
_local_platform := $(strip $(LOCAL_SDK_PATH)/platforms/$(LOCAL_PLATFORM_VERSION)/android.jar)

ifeq ($(wildcard $(_local_aapt)),)
  $(error $(_local_aapt) is missing)
endif

ifeq ($(wildcard $(_local_dx)),)
  $(error $(_local_dx) is missing)
endif

ifeq ($(wildcard $(_local_zipalign)),)
  $(error $(_local_zipalign) is missing)
endif

ifeq ($(wildcard $(_local_platform)),)
  $(error $(_local_platform) is missing)
endif

ifeq ($(LOCAL_SRC_DIR),)
  $(error LOCAL_SRC_DIR is not specified)
endif

ifeq ($(LOCAL_RESOURCE_DIR),)
  $(error LOCAL_RESOURCE_DIR is not specified)
endif

############################
# Default build parameters #
############################

LOCAL_R_JAVA := $(shell find $(LOCAL_PROJECT_DIR) -name R.java)
_local_output_dir := $(strip $(call get-absolute-path,./out/android/$(LOCAL_NAME)))
ifeq ($(LOCAL_MANIFEST_FILE),)
  LOCAL_MANIFEST_FILE := $(LOCAL_PROJECT_DIR)/AndroidManifest.xml
endif

##########################
# Set args for sdk utils #
##########################

_local_aapt_args := $(LOCAL_AAPT_ARGS)
_local_aapt_args := $(_local_aapt_args) -f -m
_local_aapt_args := $(_local_aapt_args) -S $(LOCAL_RESOURCE_DIR)
_local_aapt_args := $(_local_aapt_args) -I $(_local_platform)
_local_aapt_args := $(_local_aapt_args) -M $(LOCAL_MANIFEST_FILE)
_local_dx_args := $(LOCAL_DX_ARGS)
_local_javac_args := $(LOCAL_JAVAC_ARGS)

######################
# Internal functions #
######################

get-lib-destination-path = \
  $(eval path := $(1)) \
  $(if $(filter %.so,$(path)), \
    $(eval _dir := $(dir $(path))) $(notdir $(_dir:%/=%))/$(notdir $(path)), \
    $(notdir $(path)))

copy-libs-to-apk = \
  $(eval _libs := $(1)) \
  $(eval _dest_dir := $(2)) \
  $(shell mkdir -p $(_dest_dir)) \
  $(foreach _lib,$(_libs), \
     $(shell mkdir -p $(dir $(_dest_dir)/$(strip $(call get-lib-destination-path,$(_lib)))) && cp $(_lib) $(_dest_dir)/$(strip $(call get-lib-destination-path,$(_lib)))))

###################
# Default targets #
###################

.PHONY: build
build: $(LOCAL_NAME)

.PHONY: $(LOCAL_NAME)
$(LOCAL_NAME): $(_local_output_dir)/$(LOCAL_NAME).apk

.PHONY: $(_local_output_dir)/$(LOCAL_NAME).apk
$(_local_output_dir)/$(LOCAL_NAME).apk: _LOCAL_NAME := $(LOCAL_NAME)
$(_local_output_dir)/$(LOCAL_NAME).apk: _local_project_dir := $(LOCAL_PROJECT_DIR)
$(_local_output_dir)/$(LOCAL_NAME).apk: _local_src_dir := $(LOCAL_SRC_DIR)
$(_local_output_dir)/$(LOCAL_NAME).apk: _local_output_dir := $(_local_output_dir)
$(_local_output_dir)/$(LOCAL_NAME).apk: _local_aapt := $(_local_aapt)
$(_local_output_dir)/$(LOCAL_NAME).apk: _local_aapt_args := $(_local_aapt_args)
$(_local_output_dir)/$(LOCAL_NAME).apk: _local_dx := $(_local_dx)
$(_local_output_dir)/$(LOCAL_NAME).apk: _local_dx_args := $(_local_dx_args)
$(_local_output_dir)/$(LOCAL_NAME).apk: _local_javac_args := $(_local_javac_args)
$(_local_output_dir)/$(LOCAL_NAME).apk: _local_zipalign := $(_local_zipalign)
$(_local_output_dir)/$(LOCAL_NAME).apk: _local_platform := $(_local_platform)
$(_local_output_dir)/$(LOCAL_NAME).apk: _local_obj_dir := $(_local_output_dir)/local/obj/
$(_local_output_dir)/$(LOCAL_NAME).apk: _local_java_start_version := $(LOCAL_JAVA_START_VERSION)
$(_local_output_dir)/$(LOCAL_NAME).apk: _local_java_end_version := $(LOCAL_JAVA_END_VERSION)
$(_local_output_dir)/$(LOCAL_NAME).apk: $(LOCAL_NAME)_libs_for_apk
$(_local_output_dir)/$(LOCAL_NAME).apk: $(LOCAL_NAME)_local_src_list
$(_local_output_dir)/$(LOCAL_NAME).apk:
	@echo "Compiling $(_LOCAL_NAME).apk"
	@mkdir -p $(_local_output_dir) $(_local_obj_dir)
	$(foreach _java_file,$(_local_src_list), \
            javac \
                $(_local_javac_args) \
                -d $(_local_obj_dir) \
                -classpath $(_local_src_dir) \
                -bootclasspath $(_local_platform) \
                -source $(_local_java_start_version) \
                -target $(_local_java_end_version) \
                $(_java_file);)
	$(_local_dx) $(_local_dx_args) --dex --output=$(_local_project_dir)/classes.dex $(_local_obj_dir)
	$(_local_aapt) package $(_local_aapt_args) -F $(_local_output_dir)/$(_LOCAL_NAME).unaligned.apk
	cd $(_local_project_dir) && $(_local_aapt) add $(_local_output_dir)/$(_LOCAL_NAME).unaligned.apk classes.dex
	cd $(_local_project_dir) && \
            $(foreach _file,$(_local_libs_list), \
                $(_local_aapt) add $(_local_output_dir)/$(_LOCAL_NAME).unaligned.apk $(_file);)
	$(_local_zipalign) -f 4 $(_local_output_dir)/$(_LOCAL_NAME).unaligned.apk $@
	@echo "Compiling $(_LOCAL_NAME).apk done"

.PHONY: $(LOCAL_NAME)_libs_for_apk
$(LOCAL_NAME)_libs_for_apk: _local_custom_libs := $(LOCAL_CUSTOM_LIBS)
$(LOCAL_NAME)_libs_for_apk: _local_project_dir := $(LOCAL_PROJECT_DIR)
$(LOCAL_NAME)_libs_for_apk:
	$(call copy-libs-to-apk,$(_local_custom_libs),$(_local_project_dir)/lib)
	$(eval _local_libs_list := $(shell cd $(_local_project_dir) && find lib -type f))

.PHONY: $(LOCAL_NAME)_r_java
$(LOCAL_NAME)_r_java: _local_aapt := $(_local_aapt)
$(LOCAL_NAME)_r_java: _local_aapt_args := $(_local_aapt_args)
$(LOCAL_NAME)_r_java: _local_src_dir := $(LOCAL_SRC_DIR)
$(LOCAL_NAME)_r_java: 
	$(_local_aapt) package $(_local_aapt_args) -J $(_local_src_dir)

.PHONY: $(LOCAL_NAME)_local_src_list
$(LOCAL_NAME)_local_src_list: $(LOCAL_NAME)_r_java
$(LOCAL_NAME)_local_src_list: _local_src_dir := $(LOCAL_SRC_DIR)
$(LOCAL_NAME)_local_src_list:
	$(eval _local_src_list := $(shell find $(_local_src_dir) -name *.java))

.PHONY: clean
clean: $(LOCAL_NAME)-clean

.PHONY: $(LOCAL_NAME)-clean
$(LOCAL_NAME)-clean: $(_local_output_dir)/$(LOCAL_NAME).apk-clean

.PHONY: $(_local_output_dir)/$(LOCAL_NAME).apk-clean
$(_local_output_dir)/$(LOCAL_NAME).apk-clean: _local_output_dir := $(_local_output_dir)
$(_local_output_dir)/$(LOCAL_NAME).apk-clean: _local_project_dir := $(LOCAL_PROJECT_DIR)
$(_local_output_dir)/$(LOCAL_NAME).apk-clean: _local_r_java := $(LOCAL_R_JAVA)
$(_local_output_dir)/$(LOCAL_NAME).apk-clean:
	rm -rf  $(_local_output_dir) \
                $(_local_r_java) \
                $(_local_project_dir)/classes.dex \
                $(_local_project_dir)/lib

##############
# Clear vars #
##############

include $(_sdk_dir)/clear-vars.mk
