Build: Enable nested macros for image script

This change enables the usage of nested macros in flash_layout.h
for setting the offset and max size for secure and non-secure images.

Change-Id: I87e2aec67550debb4d36286ed46bfe935a9003c8
Signed-off-by: Sverteczky, Marcell <marcell.sverteczky@arm.com>
diff --git a/cmake/Common/CompilerGNUARMCommon.cmake b/cmake/Common/CompilerGNUARMCommon.cmake
index 51945c6..2f7639f 100644
--- a/cmake/Common/CompilerGNUARMCommon.cmake
+++ b/cmake/Common/CompilerGNUARMCommon.cmake
@@ -1,5 +1,5 @@
 #-------------------------------------------------------------------------------
-# Copyright (c) 2017-2018, Arm Limited. All rights reserved.
+# Copyright (c) 2017-2019, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -75,37 +75,20 @@
 	endif()
 	set(_FILE_PATH ${_MY_PARAMS_PATH})
 
-	#Compose additional command line switches from macro definitions.
-	set(_FLAGS "")
-	if (_MY_PARAMS_DEFINES)
-		foreach(_DEFINE IN LISTS _MY_PARAMS_DEFINES)
-			list(APPEND _FLAGS "-D${_DEFINE}")
-		endforeach()
-	endif()
-	#Compose additional command line switches from include paths.
-	if (_MY_PARAMS_INCLUDES)
-		foreach(_INCLUDE_P IN LISTS _MY_PARAMS_INCLUDES)
-			list(APPEND _FLAGS "-I${_INCLUDE_P}")
-		endforeach()
-	endif()
-
 	#Create additional target if linker script needs to be pre-processed.
 	if (_MY_PARAMS_DEFINES OR _MY_PARAMS_INCLUDES)
 		#Name of pre-processed linker script file.
 		set(FINAL_LD_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/${_MY_PARAMS_TARGET}.ld.i")
 		#Name of the target doing the pre-processing
 		set(LD_PP_TARGET_NAME "${_MY_PARAMS_TARGET}_ldpp")
-		#The target definition.
-		add_custom_target(${LD_PP_TARGET_NAME}
-			COMMENT "Pre-processing linker command file ${_MY_PARAMS_PATH}..."
-			COMMAND ${CMAKE_C_COMPILER} -E -P -xc ${_FLAGS} -o ${FINAL_LD_FILE_NAME} ${_MY_PARAMS_PATH}
-			DEPENDS ${_MY_PARAMS_PATH}
-			BYPRODUCTS ${FINAL_LD_FILE_NAME}
-		)
-		#Make the original target depend on the new one.
-		add_dependencies(${_MY_PARAMS_TARGET} ${LD_PP_TARGET_NAME})
-		#Tell cmake to delete the intermediate linker script when the clean rule
-		#is executed.
+		compiler_preprocess_file(SRC ${_MY_PARAMS_PATH}
+	                 DST ${FINAL_LD_FILE_NAME}
+	                 TARGET_PREFIX ${_MY_PARAMS_TARGET}
+	                 BEFORE_TARGET ${_MY_PARAMS_TARGET}
+	                 DEFINES ${_MY_PARAMS_DEFINES}
+	                 INCLUDES ${_MY_PARAMS_INCLUDES})
+
+		#Tell cmake to delete the intermediate linker script when the clean rule is executed.
 		get_directory_property(_ADDITIONAL_MAKE_CLEAN_FILES DIRECTORY "./" ADDITIONAL_MAKE_CLEAN_FILES)
 		set_directory_properties(PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${_ADDITIONAL_MAKE_CLEAN_FILES} ${FINAL_LD_FILE_NAME}")
 		#Set the path to linker script point to the intermediate file.
@@ -169,3 +152,92 @@
 function(compiler_generate_binary_output TARGET)
 	add_custom_command(TARGET ${TARGET} POST_BUILD COMMAND ${CMAKE_GNUARM_OBJCOPY} ARGS -O binary $<TARGET_FILE:${TARGET}> $<TARGET_FILE_DIR:${TARGET}>/${TARGET}.bin)
 endfunction()
+
+# Function for creating a new target that preprocesses a .c file
+#INPUTS:
+#    SRC - (mandatory) - file to be preprocessed
+#    DST - (mandatory) - output file for the preprocessing
+#    TARGET_PREFIX - (optional) - prefix for the target that this function creates and which manages the preprocessing
+#    BEFORE_TARGET - (optional) - target which is dependent on the preprocessing target in the below function
+#    DEFINES - (optional) - additional command line switches from macro definitions for preprocessing
+#    INCLUDES - (optional) - additional command line switches from include paths for preprocessing
+function(compiler_preprocess_file)
+	#Option (on/off) arguments.
+	set( _OPTIONS_ARGS)
+	#Single option arguments.
+	set( _ONE_VALUE_ARGS SRC DST TARGET_PREFIX BEFORE_TARGET)
+	#List arguments
+	set( _MULTI_VALUE_ARGS DEFINES INCLUDES)
+	cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN} )
+
+	#Check passed parameters
+	if(NOT DEFINED _MY_PARAMS_SRC)
+		message(FATAL_ERROR "compiler_preprocess_file: mandatory parameter 'SRC' is missing.")
+	endif()
+
+	if(NOT DEFINED _MY_PARAMS_DST)
+		message(FATAL_ERROR "compiler_preprocess_file: mandatory parameter 'DST' is missing.")
+	endif()
+
+	if(DEFINED _MY_PARAMS_BEFORE_TARGET)
+		if(NOT TARGET ${_MY_PARAMS_BEFORE_TARGET})
+			message(FATAL_ERROR "compiler_preprocess_file: optional parameter 'BEFORE_TARGET' is not target.")
+		endif()
+	endif()
+
+	#Compose additional command line switches from macro definitions.
+	set(_FLAGS "")
+	if (_MY_PARAMS_DEFINES)
+		foreach(_DEFINE IN LISTS _MY_PARAMS_DEFINES)
+			list(APPEND _FLAGS "-D${_DEFINE}")
+		endforeach()
+	endif()
+
+	#Compose additional command line switches from include paths.
+	if (_MY_PARAMS_INCLUDES)
+		foreach(_INCLUDE IN LISTS _MY_PARAMS_INCLUDES)
+			list(APPEND _FLAGS "-I${_INCLUDE}")
+		endforeach()
+	endif()
+
+	#The compiler flag might contain leading spaces which can fail the preprocess operation, these are removed
+	STRING(STRIP ${CMAKE_C_FLAGS_CPU} _MY_TEMP_CMAKE_C_FLAGS_CPU)
+	#If a string contains spaces, then it is inserted amongst quotation marks. Furthermore the compiler fails if it is
+	#called with multiple switches included in one quotation mark. If the extra spaces are replaced by semicolons,
+	#then the insertion will be advantageous for the compiler.
+	STRING(REPLACE " " ";" _MY_TEMP2_CMAKE_C_FLAGS_CPU ${_MY_TEMP_CMAKE_C_FLAGS_CPU})
+	set(_LOCAL_CMAKE_C_FLAGS_CPU "")
+	foreach(_C_FLAG IN LISTS _MY_TEMP2_CMAKE_C_FLAGS_CPU)
+		list(APPEND _LOCAL_CMAKE_C_FLAGS_CPU "${_C_FLAG}")
+	endforeach()
+
+	add_custom_command(OUTPUT ${_MY_PARAMS_DST}
+		COMMAND ${CMAKE_C_COMPILER} ${_LOCAL_CMAKE_C_FLAGS_CPU} -E -P -xc ${_FLAGS} ${_MY_PARAMS_SRC} -o ${_MY_PARAMS_DST}
+		DEPENDS ${_MY_PARAMS_SRC}
+		COMMENT "Preprocess the ${_MY_PARAMS_SRC} file"
+	)
+
+	set(_MY_TARGET_PREFIX "")
+	if(TARGET ${_MY_PARAMS_TARGET_PREFIX})
+		set(_MY_TARGET_PREFIX "${_MY_PARAMS_TARGET_PREFIX}")
+	endif()
+	#The preprocessing related target name is obtained by indexing the file's name that is to be preprocessed
+	get_filename_component(_MY_FILENAME_TO_BE_INDEXED ${_MY_PARAMS_SRC} NAME_WE)
+	foreach(_SUFFIX RANGE 1 100)
+		if (NOT TARGET ${_MY_TARGET_PREFIX}_pp_${_MY_FILENAME_TO_BE_INDEXED}_${_SUFFIX})
+				set(_PREPROCESS_TARGET_NAME "${_MY_TARGET_PREFIX}_pp_${_MY_FILENAME_TO_BE_INDEXED}_${_SUFFIX}")
+				break()
+		endif()
+		if (_SUFFIX EQUAL 100)
+			message(FATAL_ERROR "You have called 'compiler_preprocess_file' too many times (${_SUFFIX} function calls).")
+		endif()
+	endforeach()
+
+	#Make the original target depend on the new one.
+	if(TARGET ${_MY_PARAMS_BEFORE_TARGET})
+		add_custom_target(${_PREPROCESS_TARGET_NAME} DEPENDS ${_MY_PARAMS_DST})
+		add_dependencies(${_MY_PARAMS_BEFORE_TARGET} ${_PREPROCESS_TARGET_NAME})
+	else()
+		add_custom_target(${_PREPROCESS_TARGET_NAME} ALL DEPENDS ${_MY_PARAMS_DST})
+	endif()
+endfunction()