#
#  Copyright (c) 2018, The OpenThread Authors.
#  All rights reserved.
#
#  Redistribution and use in source and binary forms, with or without
#  modification, are permitted provided that the following conditions are met:
#  1. Redistributions of source code must retain the above copyright
#     notice, this list of conditions and the following disclaimer.
#  2. Redistributions in binary form must reproduce the above copyright
#     notice, this list of conditions and the following disclaimer in the
#     documentation and/or other materials provided with the distribution.
#  3. Neither the name of the copyright holder nor the
#     names of its contributors may be used to endorse or promote products
#     derived from this software without specific prior written permission.
#
#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
#  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
#  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
#  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
#  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
#  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
#  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
#  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
#  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
#  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
#  POSSIBILITY OF SUCH DAMAGE.
#

.NOTPARALLEL:

AR      = arm-none-eabi-ar
CCAS    = arm-none-eabi-as
CPP     = arm-none-eabi-cpp
CC      = arm-none-eabi-gcc
CXX     = arm-none-eabi-g++
LD      = arm-none-eabi-ld
STRIP   = arm-none-eabi-strip
NM      = arm-none-eabi-nm
RANLIB  = arm-none-eabi-ranlib
OBJCOPY = arm-none-eabi-objcopy

BuildJobs                                                 ?= 10

configure_OPTIONS                                          = \
    --enable-cli                                             \
    --enable-diag                                            \
    --enable-ftd                                             \
    --enable-mtd                                             \
    --enable-ncp                                             \
    --with-ncp-bus=uart                                      \
    --enable-radio-only                                      \
    --with-examples=cc1352                                   \
    MBEDTLS_CPPFLAGS="$(CC1352_MBEDTLS_CPPFLAGS)"            \
    $(NULL)

ifneq ($(DISABLE_BUILTIN_MBEDTLS), 1)
configure_OPTIONS              += MBEDTLS_CPPFLAGS="$(CC1352_MBEDTLS_CPPFLAGS)"
endif

DEFAULT_LOGGING                                           ?= 1

CC1352_MBEDTLS_CPPFLAGS                                    = \
    -DMBEDTLS_CONFIG_FILE='\"mbedtls-config.h\"'             \
    -DMBEDTLS_USER_CONFIG_FILE='\"cc1352-mbedtls-config.h\"' \
    -I$(PWD)/examples/platforms/cc1352/crypto                \
    -I$(PWD)/third_party/ti/devices/cc13x2_cc26x2            \
    -I$(PWD)/third_party/mbedtls                             \
    -I$(PWD)/third_party/mbedtls/repo/include                \
    $(NULL)

CC1352_CONFIG_FILE_CPPFLAGS                                                   = \
    -DOPENTHREAD_PROJECT_CORE_CONFIG_FILE='\"openthread-core-cc1352-config.h\"' \
    -I$(PWD)/examples/platforms/cc1352/                                         \
    $(NULL)

COMMONCFLAGS                                              := \
    -fdata-sections                                          \
    -ffunction-sections                                      \
    -Os                                                      \
    -g                                                       \
    $(CC1352_CONFIG_FILE_CPPFLAGS)                           \
    $(NULL)

include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/common-switches.mk

CPPFLAGS                                                  += \
    $(COMMONCFLAGS)                                          \
    $(target_CPPFLAGS)                                       \
    $(NULL)

CFLAGS                                                    += \
    $(COMMONCFLAGS)                                          \
    $(target_CFLAGS)                                         \
    $(NULL)

CXXFLAGS                                                  += \
    $(COMMONCFLAGS)                                          \
    $(target_CXXFLAGS)                                       \
    -fno-exceptions                                          \
    -fno-rtti                                                \
    $(NULL)

LDFLAGS                                                   += \
    $(COMMONCFLAGS)                                          \
    $(target_LDFLAGS)                                        \
    -nostartfiles                                            \
    -specs=nano.specs                                        \
    -specs=nosys.specs                                       \
    -Wl,--gc-sections                                        \
    -Wl,-Map=map.map                                         \
    $(NULL)

ECHO    := @echo
MAKE    := make
MKDIR_P := mkdir -p
LN_S    := ln -s
RM_F    := rm -f

INSTALL      := /usr/bin/install
INSTALLFLAGS := -p

TopSourceDir    := $(dir $(shell readlink $(firstword $(MAKEFILE_LIST))))..
AbsTopSourceDir := $(dir $(realpath $(firstword $(MAKEFILE_LIST))))..

BuildPath      = build
TopBuildDir    = $(BuildPath)
AbsTopBuildDir = $(PWD)/$(TopBuildDir)

ResultPath      = output
TopResultDir    = $(ResultPath)
AbsTopResultDir = $(PWD)/$(TopResultDir)

TargetTuple = cc1352

ARCHS = cortex-m4f

TopTargetLibDir = $(TopResultDir)/$(TargetTuple)/lib

ifndef BuildJobs
BuildJobs := $(shell getconf _NPROCESSORS_ONLN)
endif
JOBSFLAG := -j$(BuildJobs)

#
# configure-arch <arch>
#
# Configure OpenThread for the specified architecture.
#
#   arch - The architecture to configure.
#
define configure-arch
$(ECHO) "  CONFIG   $(TargetTuple)..."
(cd $(BuildPath)/$(TargetTuple)          \
 && $(AbsTopSourceDir)/configure         \
    INSTALL="$(INSTALL) $(INSTALLFLAGS)" \
    CPP="$(CPP)"                         \
    CC="$(CC)"                           \
    CXX="$(CXX)"                         \
    OBJC="$(OBJC)"                       \
    OBJCXX="$(OBJCXX)"                   \
    AR="$(AR)"                           \
    RANLIB="$(RANLIB)"                   \
    NM="$(NM)"                           \
    STRIP="$(STRIP)"                     \
    CPPFLAGS="$(CPPFLAGS)"               \
    CFLAGS="$(CFLAGS)"                   \
    CXXFLAGS="$(CXXFLAGS)"               \
    LDFLAGS="$(LDFLAGS)"                 \
    --host=arm-none-eabi                 \
    --prefix=/                           \
    --exec-prefix=/$(TargetTuple)        \
    $(configure_OPTIONS))
endef # configure-arch

#
# build-arch <arch>
#
# Build the OpenThread intermediate build products for the specified
# architecture.
#
#   arch - The architecture to build.
#
define build-arch
$(ECHO) "  BUILD    $(TargetTuple)"
$(MAKE)                            \
    $(JOBSFLAG)                    \
    -C $(BuildPath)/$(TargetTuple) \
    --no-print-directory           \
    all
endef # build-arch

#
# stage-arch <arch>
#
# Stage (install) the OpenThread final build products for the specified
# architecture.
#
#   arch - The architecture to stage.
#
define stage-arch
$(ECHO) "  STAGE    $(TargetTuple)"
$(MAKE)                            \
    $(JOBSFLAG)                    \
    -C $(BuildPath)/$(TargetTuple) \
    --no-print-directory           \
    DESTDIR=$(AbsTopResultDir)     \
    install
endef # stage-arch

#
# ARCH_template <arch>
#
# Define macros, targets and rules to configure, build, and stage the
# OpenThread for a single architecture.
#
#   arch - The architecture to instantiate the template for.
#
define ARCH_template
CONFIGURE_TARGETS += configure-$(1)
BUILD_TARGETS     += do-build-$(1)
STAGE_TARGETS     += stage-$(1)
BUILD_DIRS        += $(BuildPath)/$(TargetTuple)
DIRECTORIES       += $(BuildPath)/$(TargetTuple)

configure-$(1): target_CPPFLAGS=$($(1)_target_CPPFLAGS)
configure-$(1): target_CFLAGS=$($(1)_target_CFLAGS)
configure-$(1): target_CXXFLAGS=$($(1)_target_CXXFLAGS)
configure-$(1): target_LDFLAGS=$($(1)_target_LDFLAGS)

configure-$(1): $(BuildPath)/$(TargetTuple)/config.status

$(BuildPath)/$(TargetTuple)/config.status: | $(BuildPath)/$(TargetTuple)
	$$(call configure-arch,$(1))

do-build-$(1): configure-$(1)

do-build-$(1):
	+$$(call build-arch,$(1))

stage-$(1): do-build-$(1)

stage-$(1): | $(TopResultDir)
	$$(call stage-arch,$(1))

$(1): stage-$(1)
endef # ARCH_template

.DEFAULT_GOAL := all

all: stage

#
# cortex-m4f
#

cortex-m4f_target_ABI      = cortex-m4f
cortex-m4f_target_CPPFLAGS = -mcpu=cortex-m4 -march=armv7e-m -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mthumb
cortex-m4f_target_CFLAGS   = -mcpu=cortex-m4 -march=armv7e-m -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mthumb
cortex-m4f_target_CXXFLAGS = -mcpu=cortex-m4 -march=armv7e-m -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mthumb
cortex-m4f_target_LDFLAGS  = -mcpu=cortex-m4 -march=armv7e-m -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mthumb

# Instantiate an architecture-specific build template for each target
# architecture.

$(foreach arch,$(ARCHS),$(eval $(call ARCH_template,$(arch))))

#
# Common / Finalization
#

configure: $(CONFIGURE_TARGETS)

build: $(BUILD_TARGETS)

stage: $(STAGE_TARGETS)

DIRECTORIES = $(TopResultDir) $(TopResultDir)/$(TargetTuple)/lib $(BUILD_DIRS)

CLEAN_DIRS  = $(TopResultDir) $(BUILD_DIRS)

all: stage

$(DIRECTORIES):
	$(ECHO) "  MKDIR    $@"
	@$(MKDIR_P) "$@"

clean:
	$(ECHO) "  CLEAN"
	@$(RM_F) -r $(CLEAN_DIRS)

help:
	$(ECHO) "Simply type 'make -f $(firstword $(MAKEFILE_LIST))' to build OpenThread for the following "
	$(ECHO) "architectures: "
	$(ECHO) ""
	$(ECHO) "    $(ARCHS)"
	$(ECHO) ""
	$(ECHO) "To build only a particular architecture, specify: "
	$(ECHO) ""
	$(ECHO) "    make -f $(firstword $(MAKEFILE_LIST)) <architecture>"
	$(ECHO) ""

