PREFIX ?= ..

ifeq ($(TARGET_ARCH),arm64)
TOOLCHAIN_PREFIX ?= ../tools/aarch64-linux-android-4.8/bin/aarch64-linux-android-
TOOLCHAIN_PREFIX64 ?= ../tools/aarch64-linux-android-4.8/bin/aarch64-linux-android-
else
TOOLCHAIN_PREFIX ?= ../tools/arm-eabi-4.7/bin/arm-eabi-
TOOLCHAIN_PREFIX64 ?= ../tools/aarch64-linux-android-4.8/bin/aarch64-linux-android-
endif

ifeq ($(MAKECMDGOALS),spotless)
spotless:
	rm -rf $(PREFIX)/build-* $(LK_IMAGE)
else

-include local.mk
include make/macros.mk

# If one of our goals (from the commandline) happens to have a
# matching project/goal.mk, then we should re-invoke make with
# that project name specified...

project-name := $(firstword $(MAKECMDGOALS))

ifneq ($(project-name),)
ifneq ($(wildcard project/$(project-name).mk),)
do-nothing := 1
$(MAKECMDGOALS) _all: make-make
make-make:
	@PROJECT=$(project-name) $(MAKE) $(filter-out $(project-name), $(MAKECMDGOALS))
endif
endif

ifeq ($(do-nothing),)

ifeq ($(PROJECT),)
$(error No project specified.  Use "make projectname" or put "PROJECT := projectname" in local.mk)
endif

DEBUG ?= 2

BUILDDIR := $(PREFIX)/build-$(TARGET)
OUTBIN := $(BUILDDIR)/lk.bin
OUTELF := $(BUILDDIR)/lk
OUTSYS := $(BUILDDIR)/lk.sys
OUTTASK := $(BUILDDIR)/lk.task
CONFIGHEADER := $(BUILDDIR)/config.h
IMGBIN := $(BUILDDIR)/img.bin
TOSIMAGE ?= $(BUILDDIR)/tos.img
MONLIB := $(BUILDDIR)/secure_monitor/libmonitor.a

TASK_MODULES := \
	trusted_app \
	trusted_app2

TASKS ?= \
	$(foreach task,$(TASK_MODULES), ../out/tasks/$(task)/$(task))

ifneq ($(TARGET),t124)
DEFINES += \
	WITH_MONITOR_BIN=1
MONLIB :=
MONBIN := $(BUILDDIR)/secure_monitor/monitor.bin
endif

INCLUDES := -I$(BUILDDIR) -Iinclude -I../lib/include
GLOBAL_OPTFLAGS ?= -Os
GLOBAL_COMPILEFLAGS := -g -fno-builtin -finline -W -Wall -Wno-multichar -Wno-unused-parameter -Wno-unused-function -include $(CONFIGHEADER)
GLOBAL_CFLAGS := --std=c99 -Werror-implicit-function-declaration
#GLOBAL_CFLAGS += -Werror
GLOBAL_CPPFLAGS := -fno-exceptions -fno-rtti -fno-threadsafe-statics
#GLOBAL_CPPFLAGS += -Weffc++
GLOBAL_ASMFLAGS := -DASSEMBLY
GLOBAL_LDFLAGS :=

GLOBAL_COMPILEFLAGS += -ffunction-sections -fdata-sections
GLOBAL_LDFLAGS += -gc-sections

# top level rule
all:: $(TOSIMAGE) $(OUTTASK) $(OUTELF).lst $(OUTELF).debug.lst $(OUTELF).sym $(OUTELF).size

# master module object list
ALLOBJS_MODULE :=

# master object list (for dep generation)
ALLOBJS :=

# a linker script needs to be declared in one of the project/target/platform files
LINKER_SCRIPT :=
MON_LINKER_SCRIPT :=

# anything you add here will be deleted in make clean
GENERATED := $(CONFIGHEADER)

# anything added to DEFINES will be put into $(BUILDDIR)/config.h
DEFINES += LK=1

# Anything added to SRCDEPS will become a dependency of every source file in the system.
# Useful for header files that may be included by one or more source files.
SRCDEPS := $(CONFIGHEADER)

# these need to be filled out by the project/target/platform rules.mk files
TARGET :=
PLATFORM :=
ARCH :=
ALLMODULES :=
MODULES :=

# any rules you put here will also be built by the system before considered being complete
EXTRA_BUILDDEPS :=

# any rules you put here will be depended on in clean builds
EXTRA_CLEANDEPS :=

# any objects you put here get linked with the final image
EXTRA_OBJS :=

include project/$(PROJECT).mk
include target/$(TARGET)/rules.mk
include platform/$(PLATFORM)/rules.mk

$(info PROJECT = $(PROJECT))
$(info PLATFORM = $(PLATFORM))
$(info TARGET = $(TARGET))
$(info MONLIB = $(MONLIB))
$(info TARGET_ARCH = $(TARGET_ARCH))

include arch/$(ARCH)/rules.mk
include platform/rules.mk
include target/rules.mk
include kernel/rules.mk
include dev/rules.mk
include app/rules.mk
include task/rules.mk

# recursively include any modules in the MODULE variable, leaving a trail of included
# modules in the ALLMODULES list
include make/recurse.mk

# any extra top level build dependencies that someone declared
all:: $(EXTRA_BUILDDEPS)

# add some automatic configuration defines
DEFINES += \
	PROJECT_$(PROJECT)=1 \
	TARGET_$(TARGET)=1 \
	PLATFORM_$(PLATFORM)=1 \
	ARCH_$(ARCH)=1 \
	$(addsuffix =1,$(addprefix WITH_,$(ALLMODULES)))

# debug build?
ifneq ($(DEBUG),)
DEFINES += \
	DEBUG=$(DEBUG)
endif

# allow additional defines from outside the build system
ifneq ($(EXTERNAL_DEFINES),)
DEFINES += $(EXTERNAL_DEFINES)
$(info EXTERNAL_DEFINES = $(EXTERNAL_DEFINES))
endif

DEPS := $(ALLOBJS:%o=%d)

#$(warning DEPS=$(DEPS))

# default to no ccache
CCACHE ?=
CC := $(CCACHE) $(TOOLCHAIN_PREFIX)gcc
LD := $(TOOLCHAIN_PREFIX)ld
OBJDUMP := $(TOOLCHAIN_PREFIX)objdump
OBJCOPY := $(TOOLCHAIN_PREFIX)objcopy
CPPFILT := $(TOOLCHAIN_PREFIX)c++filt
SIZE := $(TOOLCHAIN_PREFIX)size
NM := $(TOOLCHAIN_PREFIX)nm

# put all of the global build flags in config.h to force a rebuild if any change
DEFINES += INCLUDES=\"$(subst $(SPACE),_,$(INCLUDES))\"
DEFINES += GLOBAL_COMPILEFLAGS=\"$(subst $(SPACE),_,$(GLOBAL_COMPILEFLAGS))\"
DEFINES += GLOBAL_OPTFLAGS=\"$(subst $(SPACE),_,$(GLOBAL_OPTFLAGS))\"
DEFINES += GLOBAL_CFLAGS=\"$(subst $(SPACE),_,$(GLOBAL_CFLAGS))\"
DEFINES += GLOBAL_CPPFLAGS=\"$(subst $(SPACE),_,$(GLOBAL_CPPFLAGS))\"
DEFINES += GLOBAL_ASMFLAGS=\"$(subst $(SPACE),_,$(GLOBAL_ASMFLAGS))\"
DEFINES += GLOBAL_LDFLAGS=\"$(subst $(SPACE),_,$(GLOBAL_LDFLAGS))\"

# comment out or override if you want to see the full output of each command
NOECHO ?= @

#$(warning ALLMODULE_OBJS=$(ALLMODULE_OBJS))

ifneq ($(OBJS),)
$(warning OBJS=$(OBJS))
$(error OBJS is not empty, please convert to new module format)
endif
ifneq ($(OPTFLAGS),)
$(warning OPTFLAGS=$(OPTFLAGS))
$(error OPTFLAGS is not empty, please use GLOBAL_OPTFLAGS or MODULE_OPTFLAGS)
endif
ifneq ($(CFLAGS),)
$(warning CFLAGS=$(CFLAGS))
$(error CFLAGS is not empty, please use GLOBAL_CFLAGS or MODULE_CFLAGS)
endif
ifneq ($(CPPFLAGS),)
$(warning CPPFLAGS=$(CPPFLAGS))
$(error CPPFLAGS is not empty, please use GLOBAL_CPPFLAGS or MODULE_CPPFLAGS)
endif

include lib/version/version.mk

# the logic to compile and link stuff is in here
include make/build.mk

clean: $(EXTRA_CLEANDEPS)
	rm -f $(ALLOBJS) $(DEPS) $(GENERATED) $(OUTBIN) $(OUTELF) $(OUTSYS) $(OUTTASK) $(OUTELF).lst

install: all
	scp $(OUTBIN) 192.168.0.4:/tftproot

# generate a config.h file with all of the DEFINES laid out in #define format
configheader:

$(CONFIGHEADER): configheader
	$(call MAKECONFIGHEADER,$@,DEFINES)

# Empty rule for the .d files. The above rules will build .d files as a side
# effect. Only works on gcc 3.x and above, however.
%.d:

ifeq ($(filter $(MAKECMDGOALS), clean), )
-include $(DEPS)
endif

.PHONY: configheader
endif

endif # make spotless
