Build system refactoring

The source tree is configured for a specific target as defined in the
targets directory.

The common target components are defined in targets/common. Targets
for real platform should include this directory to get the default
target libraries setup.

Change-Id: I7fced4bfacec97432cbbd4125bd5b4cdd21122e3
diff --git a/cmake/helpers.cmake b/cmake/helpers.cmake
index e3b604a..686488b 100644
--- a/cmake/helpers.cmake
+++ b/cmake/helpers.cmake
@@ -16,26 +16,48 @@
 # limitations under the License.
 #
 
-function(ethosu_link_options target scope)
-    cmake_parse_arguments(ARG "" "LINK_FILE" "" ${ARGN})
+# Add .elf to all executables
+set(CMAKE_EXECUTABLE_SUFFIX ".elf")
+
+#############################################################################
+# Link options
+#############################################################################
+
+function(ethosu_target_link_options target scope)
+    cmake_parse_arguments(ARG "" "LINK_FILE;ENTRY" "" ${ARGN})
+
+    # Store the link file in a property to be evaluated by the executable.
+    set_property(GLOBAL PROPERTY ETHOSU_TARGET_LINK_FILE ${CMAKE_CURRENT_SOURCE_DIR}/${ARG_LINK_FILE})
+
+    if (ARG_ENTRY)
+        target_link_options(${target} ${scope} --entry Reset_Handler)
+    endif()
+endfunction()
+
+function(ethosu_eval_link_options target)
+    # Get the link file from the cache
+    get_property(LINK_FILE GLOBAL PROPERTY ETHOSU_TARGET_LINK_FILE)
+
+    set(prop "$<TARGET_PROPERTY:${target},COMPILE_DEFINITIONS>")
 
     if (CMAKE_CXX_COMPILER_ID STREQUAL "ARMClang")
-        set(LINK_FILE_OUT ${CMAKE_CURRENT_SOURCE_DIR}/${ARG_LINK_FILE}.scatter)
+        set(LINK_FILE_OUT ${LINK_FILE}.scatter)
         set(LINK_FILE_OPTION "--scatter")
 
+        target_link_options(${target} PUBLIC
+            --predefine=\"-D$<JOIN:${prop},\" ;--predefine=\"-D>\")
     elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
-        set(LINK_FILE ${ARG_LINK_FILE}.ld)
-        set(LINK_FILE_IN ${CMAKE_CURRENT_SOURCE_DIR}/${LINK_FILE})
-        set(LINK_FILE_OUT ${CMAKE_CURRENT_BINARY_DIR}/${LINK_FILE})
+        set(LINK_FILE_IN ${LINK_FILE}.ld)
+        get_filename_component(LINK_FILE_OUT_BASE ${LINK_FILE} NAME)
+        set(LINK_FILE_OUT ${CMAKE_CURRENT_BINARY_DIR}/${LINK_FILE_OUT_BASE}-${target}.ld)
         set(LINK_FILE_OPTION "-T")
 
-        set(prop "$<TARGET_PROPERTY:${target},COMPILE_DEFINITIONS>")
         add_custom_command(
             OUTPUT ${LINK_FILE_OUT}
             DEPENDS ${LINK_FILE_IN}
             BYPRODUCTS ${LINK_FILE_OUT}
             COMMAND ${CMAKE_C_COMPILER} -E -x c -P -o ${LINK_FILE_OUT} ${LINK_FILE_IN}
-            COMMAND_EXPAND_LISTS "$<$<BOOL:${prop}>:-D$<JOIN:${prop},;-D>>"
+            COMMAND_EXPAND_LISTS "-D$<JOIN:${prop},;-D>"
             COMMENT "Preprocessing and generating linker script"
             VERBATIM)
         add_custom_target(${target}-linker-script
@@ -44,6 +66,59 @@
         add_dependencies(${target} ${target}-linker-script)
     endif()
 
-    target_link_options(${target} ${scope} ${LINK_FILE_OPTION} ${LINK_FILE_OUT})
+    target_link_options(${target} PUBLIC ${LINK_FILE_OPTION} ${LINK_FILE_OUT})
     set_target_properties(${target} PROPERTIES LINK_DEPENDS ${LINK_FILE_OUT})
 endfunction()
+
+#############################################################################
+# Executable
+#############################################################################
+
+function(ethosu_add_executable target)
+    cmake_parse_arguments(ARGS "" "TARGET_LIBRARY" "SOURCES;LIBRARIES" ${ARGN})
+    add_executable(${target})
+
+    target_sources(${target} PRIVATE
+        ${ARGS_SOURCES})
+
+    if(NOT ARGS_TARGET_LIBRARY)
+        set(ARGS_TARGET_LIBRARY ethosu_target_init)
+    endif()
+
+    target_link_libraries(${target} PRIVATE
+        ${ARGS_TARGET_LIBRARY} ethosu_core ${ARGS_LIBRARIES})
+
+    ethosu_eval_link_options(${target})
+endfunction()
+
+#############################################################################
+# Test
+#############################################################################
+
+function(ethosu_add_test target)
+    if(NOT BUILD_TESTING)
+        return()
+    endif()
+
+    cmake_parse_arguments(ARGS "" "NAME" "COMMAND" ${ARGN})
+
+    if (NOT ARGS_COMMAND)
+        set(ARGS_COMMAND ${ETHOSU_COMMAND_DEFAULT})
+    endif()
+
+    if (NOT ARGS_NAME)
+        set(ARGS_NAME ${target})
+    endif()
+
+    add_test(NAME ${ARGS_NAME}
+        COMMAND ${ARGS_COMMAND} $<TARGET_FILE:${target}>)
+endfunction()
+
+#############################################################################
+# Executable and test
+#############################################################################
+
+function(ethosu_add_executable_test target)
+    ethosu_add_executable(${target} ${ARGN})
+    ethosu_add_test(${target} ${ARGN})
+endfunction()