cmake: Refactor mbed_set_mbed_target_linker_script

Move the mbed_set_mbed_target_linker_script function into its own file
and make it set the linkerscript on the target passed in, rather than
setting the linkerscript on the top level mbed-core target. We use
CMake's automatic forwarding of usage requirements to forward the linker
script to the top level target.

This commit also adds a condition to check whether the MBED_TARGET is a
CMake buildsystem target. If it is we will just link to it in the
idiomatic CMake way, if it's not then we use the 'old' mechanism of
setting the linkerscript for the mbed-core target. This check will be
useful when we refactor MBED_TARGETS to be CMake buildsystem targets as
it will allow us to do the refactoring incrementally.
pull/14199/head
Robert Walton 2021-01-27 12:27:48 +00:00 committed by Jaeden Amero
parent 8f47212085
commit 0e491cc0cf
3 changed files with 77 additions and 41 deletions

View File

@ -6,6 +6,7 @@
cmake_minimum_required(VERSION 3.19.0 FATAL_ERROR)
include(${MBED_CONFIG_PATH}/mbed_config.cmake)
include(tools/cmake/set_linker_script.cmake)
add_library(mbed-core INTERFACE)
@ -86,6 +87,15 @@ target_include_directories(mbed-core
${CMAKE_CURRENT_SOURCE_DIR}
)
# We need to generate a "response file" to pass to the C preprocessor because of path length
# limitations on Windows. We set the response file and bind the path to a global property here.
# We query this global property when we set the linker script for the MBED_TARGET being built.
#
# TODO: Remove this and find a more idiomatic way of passing compile definitions to CPP without
# using global properties.
mbed_generate_options_for_linker(${APP_TARGET} LINKER_PREPROCESS_DEFINITIONS)
set_property(GLOBAL PROPERTY COMPILE_DEFS_RESPONSE_FILE ${LINKER_PREPROCESS_DEFINITIONS})
# These targets are made visible here so their source files which
# are spread in different directories can be referenced and can be linked against
# by libraries that depend on them.
@ -110,6 +120,22 @@ add_subdirectory(features EXCLUDE_FROM_ALL)
add_subdirectory(cmsis/CMSIS_5/CMSIS/RTOS2 EXCLUDE_FROM_ALL)
add_subdirectory(cmsis/device/rtos EXCLUDE_FROM_ALL)
# This is a temporary workaround to prevent the build from failing for MBED_TARGETS that
# haven't been converted to build system targets yet.
# The refactored MBED_TARGETS set the linker script and forward it to the build system as a
# usage requirement. The 'old' mechanism was to set the linker script on the top level mbed-core
# target. This was needed because MBED_TARGETS were not registered as buildsystem targets,
# preventing CMake from working its usage requirements magic and forcing us to set the linker
# script globally.
#
# TODO: Remove when all MBED_TARGETS have been converted to build system targets.
if(TARGET ${MBED_TARGET})
target_link_libraries(mbed-core INTERFACE ${MBED_TARGET})
else()
get_property(LINKER_SCRIPT GLOBAL PROPERTY MBED_TARGET_LINKER_FILE)
mbed_set_linker_script(mbed-core ${LINKER_SCRIPT})
endif()
#
# Configures the application
#
@ -122,45 +148,6 @@ function(mbed_configure_app_target target)
)
endfunction()
#
# Specifies linker script used for linking `target`.
#
function(mbed_set_mbed_target_linker_script target)
get_property(mbed_target_linker_script GLOBAL PROPERTY MBED_TARGET_LINKER_FILE)
mbed_generate_options_for_linker(${target} _linker_preprocess_definitions)
if(MBED_TOOLCHAIN STREQUAL "GCC_ARM")
set(CMAKE_PRE_BUILD_COMMAND
COMMAND "arm-none-eabi-cpp" ${_linker_preprocess_definitions} -x assembler-with-cpp -E -Wp,-P
${mbed_target_linker_script} -o ${CMAKE_BINARY_DIR}/${target}.link_script.ld
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
BYPRODUCTS "${CMAKE_BINARY_DIR}/${target}.link_script.ld"
)
target_link_options(mbed-core
INTERFACE
"-T" "${CMAKE_BINARY_DIR}/${target}.link_script.ld"
"-Wl,-Map=${CMAKE_BINARY_DIR}/${target}${CMAKE_EXECUTABLE_SUFFIX}.map"
)
elseif(MBED_TOOLCHAIN STREQUAL "ARM")
set(CMAKE_PRE_BUILD_COMMAND COMMAND "")
target_link_options(mbed-core
INTERFACE
"--scatter=${mbed_target_linker_script}"
"--predefine=${_linker_preprocess_definitions}"
"--map"
)
endif()
add_custom_command(
TARGET
${target}
PRE_LINK
${CMAKE_PRE_BUILD_COMMAND}
COMMENT
"Link line:"
VERBATIM
)
endfunction()
#
# Converts output file of `target` to binary file and to Intel HEX file.
#

View File

@ -43,8 +43,6 @@ macro(mbed_greentea_add_test)
mbed_configure_app_target(${TEST_NAME})
mbed_set_mbed_target_linker_script(${TEST_NAME})
target_include_directories(${TEST_NAME}
PRIVATE
.

View File

@ -0,0 +1,51 @@
# Copyright (c) 2021 ARM Limited. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
# Preprocesses and sets the linker script for an Mbed target.
#
function(mbed_set_linker_script input_target raw_linker_script_path)
set(LINKER_SCRIPT_PATH ${CMAKE_BINARY_DIR}/${input_target}.link_script.ld)
# To avoid path limits on Windows, we create a "response file" and set the path to it as a
# global property. We need this solely to pass the compile definitions to GCC's preprocessor,
# so it can expand any macro definitions in the linker script.
get_property(_linker_preprocess_definitions GLOBAL PROPERTY COMPILE_DEFS_RESPONSE_FILE)
if(MBED_TOOLCHAIN STREQUAL "GCC_ARM")
add_custom_command(
OUTPUT
${LINKER_SCRIPT_PATH}
PRE_LINK
COMMAND
${CMAKE_C_COMPILER} ${_linker_preprocess_definitions}
-E -x assembler-with-cpp
-P ${raw_linker_script_path}
-o ${LINKER_SCRIPT_PATH}
WORKING_DIRECTORY
${CMAKE_CURRENT_SOURCE_DIR}
COMMENT
"Link line:"
VERBATIM
)
# CMake will not let us add PRE_LINK commands to INTERFACE targets, and input_target could
# be an INTERFACE target.
# To get around this we create an intermediate custom target depending on the preprocessed
# linker script output by CPP. We add this custom target as a dependency of input_target.
# This ensures CMake runs our custom command to preprocess the linker script before trying
# to build input_target.
set(LinkerScriptTarget ${input_target}LinkerScript)
add_custom_target(${LinkerScriptTarget} DEPENDS ${LINKER_SCRIPT_PATH} VERBATIM)
add_dependencies(${input_target} ${LinkerScriptTarget})
target_link_options(${input_target}
INTERFACE
"-T" "${LINKER_SCRIPT_PATH}"
"-Wl,-Map=${CMAKE_BINARY_DIR}/${APP_TARGET}${CMAKE_EXECUTABLE_SUFFIX}.map"
)
elseif(MBED_TOOLCHAIN STREQUAL "ARM")
target_link_options(${input_target}
INTERFACE
"--scatter=${raw_linker_script_path}"
"--predefine=${_linker_preprocess_definitions}"
"--map"
)
endif()
endfunction()