#===============================================================================
#
# Multibuild build script
#
# GENERAL DESCRIPTION
#    Build script
#
# Copyright (c) Samsung Electronics Co, Ltd 2016. All rights reserved.
#
#===============================================================================
import os
Import('env')

env = env.Clone()

def get_multibuild_variable(local_name):
    var = None
    if None != os.getenv(local_name):
        var = os.getenv(local_name).strip()
    return var

def get_multibuild_array(local_name):
    arr = get_multibuild_variable(local_name)
    if None != arr:
        return arr.split()
    return []

multibuild_build_tool = os.getenv("LOCAL_BUILD_TOOL", "arm").strip()
multibuild_scl_path = get_multibuild_variable("LOCAL_SCL_PATH")
multibuild_proc = os.getenv("LOCAL_QSEE_PROC", "scorpion").strip()
multibuild_bsp_defines = get_multibuild_array("LOCAL_BSP_DEFINES")
multibuild_bsp_cflags = []
multibuild_bsp_cpp_defines = []
for s in multibuild_bsp_defines:
    if not s.startswith('-D'):
        multibuild_bsp_cflags.append(s.replace('"','\\"'))
    else:
        multibuild_bsp_cpp_defines.append(s.replace('-D', '').replace('"','\\"'))

multibuild_imprint_tool_path = os.getenv("LOCAL_IMPRINT_TOOL", "echo No imprint for").strip()
#------------------------------------------------------------------------------
# Check if we need to load this script or just bail-out
#------------------------------------------------------------------------------
# alias - First alias is always the target then the other possible aliases
aliases = [
   'multibuild', 'genboot', 'boot', 'boot_arm11',
   'amss', 'amss_arm11', 'arm11', 'all'
]
env.InitImageVars(
   alias_list = aliases,       # list of aliases, unique name index [0]
   proc = multibuild_proc,     # proc settings
   config = 'apps',            # config settings
   build_tags = [
      'APPS_PROC',
      'MULTIBUILD_IMAGE'
   ],  # list of build tags for sub lib scripts
   tools = [
      "${BUILD_ROOT}/core/bsp/build/scripts/scl_builder.py",
      "${BUILD_ROOT}/core/bsp/build/scripts/mbn_builder.py",
      "buildspec_builder.py",
      "${BUILD_ROOT}/tools/build/scons/sectools/sectools_builder.py",
   ],
)

if not env.CheckAlias():
   Return()

#------------------------------------------------------------------------------
# Init default values for this PROC/Image
#------------------------------------------------------------------------------

#===============================================================================
# Multibuild build rules
#===============================================================================

#------------------------------------------------------------------------------
# Configure and load in USES and path variables
#------------------------------------------------------------------------------
env.InitBuildConfig()

#---------------------------------------------------------------------------
# Load in the tools scripts
#---------------------------------------------------------------------------
env.LoadToolScript(multibuild_build_tool, toolpath = ['${BUILD_SCRIPTS_ROOT}'])
env.LoadToolScript('apps_defs', toolpath = ['${BUILD_SCRIPTS_ROOT}'])

#------------------------------------------------------------------------------
# Add extension flags for multibuild
#------------------------------------------------------------------------------
if env['BUILD_VER'] == "":
   env.Replace(BUILD_VER = '0')

#----------------------------------------------------------------------------
# Enable Stack protection
#----------------------------------------------------------------------------
if multibuild_build_tool == "llvm":
  env.Append(CFLAGS = ' -fPIC')
  env.Append(CCFLAGS = " -fstack-protector")
  env.Append(CFLAGS = multibuild_bsp_cflags)

else:
  env.Append(CCFLAGS = " --protect_stack ")
  env.Append(CFLAGS = ' --apcs=/ropi/rwpi --lower_ropi --lower_rwpi')
  env.Append(ASFLAGS = ' --apcs=/ropi/rwpi ')
  env.Append(ARMCC_OPT = ' --diag_remark=9931,9933') # remove error waiting for license...

env.Append(CPPDEFINES = [
   "BUILD_BOOT_CHAIN",
   "BUILD_BOOT_CHAIN_SPBL",
   "BOOT_LOADER",
   "BOOT_WATCHDOG_DISABLED",
   "FLASH_NAND_SINGLE_THREADED",
   "FLASH_CLIENT_BOOT",
   "FLASH_USE_DM_PAGES",
   "FEATURE_HS_USB_BASIC",
   "BOOT_SBL_H=\\\"boot_comdef.h\\\"",
   "BOOT_CUSTSBL_H=\\\"custsbl.h\\\"",
   "BOOT_MODULE_BUILD_VERSION=" + env['BUILD_VER'],
   "FEATURE_USES_TURBO",
   "RUMIBUILD",
] + multibuild_bsp_cpp_defines)

env.Append(USES_NO_DEBUG="USES_NO_DEBUG")

#------------------------------------------------------------------------------
# Decide which build steps to perform
#------------------------------------------------------------------------------
# Regular build steps (no filter) is build everything, once a user starts
# using filters we have to make decisions depending on user input.
#
# The LoadAUSoftwareUnits function will take care of filtering subsystem, units,
# etc.  This is to take care of what steps to enable disable from the top level
# script, such as building files specify in this script i.e. quartz, stubs, etc.

do_local_files = True
do_link = True
do_post_link = True

# Get user input from command line
filter_opt = env.get('FILTER_OPT')

# Limit build processing based on filter option
if filter_opt is not None:
   do_link = False
   do_post_link = False

   if not env.FilterMatch(os.getcwd()):
      do_local_files = False

#-------------------------------------------------------------------------------
# Libraries Section
#-------------------------------------------------------------------------------
core_libs, core_objs = env.LoadAUSoftwareUnits('core')
multibuild_units = [core_objs, core_libs]

if do_local_files:
   #============================================================================
   # multibuild Environment
   #============================================================================

   #----------------------------------------------------------------------------
   # Begin building multibuild
   #----------------------------------------------------------------------------
   env.Replace(TARGET_NAME = 'multibuild')
   env.Replace(MULTIBUILD_ROOT = '${COREBSP_ROOT}/securemsm/trustzone/qsapps/multibuild')

   #----------------------------------------------------------------------------
   # Generate Scatter Load File (SCL)
   #----------------------------------------------------------------------------
   if multibuild_build_tool == "llvm":
       if multibuild_proc == "scorpion":
           target_scl = env.SclBuilder('${SHORT_BUILDPATH}/${TARGET_NAME}',
              os.path.join(multibuild_scl_path, 'multibuild.ld'))
       else:
           target_scl = env.SclBuilder('${SHORT_BUILDPATH}/${TARGET_NAME}',
              os.path.join(multibuild_scl_path, 'multibuild64.ld'))
   else:
       target_scl = env.SclBuilder('${SHORT_BUILDPATH}/${TARGET_NAME}',
          os.path.join(multibuild_scl_path, 'multibuild.scl'))

   multibuild_units.extend(target_scl)

if do_link:
   #----------------------------------------------------------------------------
   # Generate multibuild ELF
   #----------------------------------------------------------------------------
   libs_path = env['INSTALL_LIBPATH']

   if multibuild_build_tool == "llvm":
      if multibuild_proc == "scorpion":
         arm_libs = [
            File(env.SubstRealPath('${LLVMLIB}/libclang_rt.builtins-arm.a'))
         ]
      else:
         arm_libs = [
            File(env.SubstRealPath('${LLVMLIB}/libclang_rt.builtins-aarch64.a'))
         ]

      if multibuild_proc == "scorpion":
          arm_libs.append(File(env.SubstRealPath('${MUSL32PATH}/lib/libc.a')))
      else:
          arm_libs.append(File(env.SubstRealPath('${MUSLPATH}/lib/libc.a')))

      env.Append(LINKFLAGS = "-shared -Bsymbolic")
      core_libs.extend(arm_libs)

   multibuild_elf = env.Program('${SHORT_BUILDPATH}/${TARGET_NAME}',
                                source=[core_objs], LIBS=[core_libs], LIBPATH=libs_path)
   env.Depends(multibuild_elf, target_scl)

   env.Clean(multibuild_elf, env.subst('${SHORT_BUILDPATH}/${TARGET_NAME}.map'))
   env.Clean(multibuild_elf, env.subst('${SHORT_BUILDPATH}/${TARGET_NAME}.sym'))

if do_post_link:
   #----------------------------------------------------------------------------
   # Imprint the elf if necessary
   #----------------------------------------------------------------------------
   imprint_command =  multibuild_imprint_tool_path + " $SOURCE"

   imprint = env.Command(None, multibuild_elf, imprint_command)

   env.AlwaysBuild(imprint)
   env.Depends(imprint, multibuild_elf)
   #----------------------------------------------------------------------------
   # Generate multibuild MBN
   #----------------------------------------------------------------------------
   multibuild_pbn = env.InstallAs('${SHORT_BUILDPATH}/${TARGET_NAME}.pbn',
                                  multibuild_elf)

   env.Depends(multibuild_pbn, imprint)
   install_root = env.subst('${MBN_ROOT}')
   image_name = "multibuild"

   if hasattr(env, "SectoolGetUnsignedInstallPath"):
     install_unsigned_root = env.SectoolGetUnsignedInstallPath(install_base_dir = install_root)
   else:
     install_unsigned_root = os.path.join(install_root, "unsigned")

   env.Replace(MBN_FILE = os.path.join(install_unsigned_root, image_name))
   multibuild_mbn = env.MbnBuilder('${SHORT_BUILDPATH}/${TARGET_NAME}',
      multibuild_pbn, IMAGE_TYPE="multibuild", MBN_TYPE="elf",
      IMAGE_ID=4, FLASH_TYPE="sdcc")

   env.Depends(multibuild_mbn, multibuild_pbn)
   #============================================================================
   # Define units that will be built
   #============================================================================

   env.LoadToolScript('pil_splitter_builder', toolpath = ['${BUILD_ROOT}/core/bsp/build/scripts'])
   image_pil = env.PilSplitterBuilder('${BUILD_ROOT}/build/ms/bin/PIL_IMAGES/SPLITBINS_${QC_SHORT_BUILDPATH}/${TARGET_NAME}.mdt', multibuild_mbn)
   multibuild_units = env.Alias ('arm11_multibuild_units', [
      multibuild_elf,
      imprint,
      multibuild_mbn,
      image_pil,
   ])

# Add aliases
for alias in aliases:
   env.Alias(alias, multibuild_units)
