add custom linker script (#103)

* add custom linker script
a custom linker script can be applied by adding the .ld filepath
as 2nd argument to mbed_set_post_build

* more detailed comment

* add if is_standalone for text cases

* replace COMMENT in add_custom_command by echo
COMMENT is not reliable printed
pull/15381/head
JojoS 2022-11-28 18:01:49 +01:00 committed by GitHub
parent 310aac306f
commit 9d9ba58f68
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 89 additions and 5 deletions

View File

@ -56,6 +56,8 @@ function(mbed_setup_linker_script mbed_os_target mbed_baremetal_target target_de
OUTPUT
${LINKER_SCRIPT_PATH}
PRE_LINK
COMMAND
${CMAKE_COMMAND} -E echo "Preprocess linker script: ${RAW_LINKER_SCRIPT_NAME} -> ${LINKER_SCRIPT_NAME}"
COMMAND
${CMAKE_C_COMPILER} @${linker_defs_response_file}
-E -x assembler-with-cpp
@ -68,11 +70,10 @@ function(mbed_setup_linker_script mbed_os_target mbed_baremetal_target target_de
${target_defines_header}
WORKING_DIRECTORY
${CMAKE_CURRENT_SOURCE_DIR}
COMMENT
"Preprocess linker script: ${RAW_LINKER_SCRIPT_NAME} -> ${LINKER_SCRIPT_NAME}"
VERBATIM
)
# The job to create the linker script gets attached to the mbed-linker-script target,
# which is then added as a dependency of the MCU target. This ensures the linker script will exist
# by the time we need it.
@ -80,11 +81,69 @@ function(mbed_setup_linker_script mbed_os_target mbed_baremetal_target target_de
foreach(TARGET ${mbed_baremetal_target} ${mbed_os_target})
add_dependencies(${TARGET} mbed-linker-script)
# Add linker flags to the MCU target to pick up the preprocessed linker script
target_link_options(${TARGET}
# When building the Mbed internal tests, the tests get created before the mbed-os target does. So, the normal logic
# in mbed_set_post_build() to set the linker script does not work. So, we need to instead attach the linker script to
# the mbed-os and mbed-baremetal libraries themselves, so it will get picked up automatically.
# This prevents a custom linker script from being used in STANDALONE mode, but we don't need to do that.
set_target_properties(${TARGET} PROPERTIES LINKER_SCRIPT_PATH ${LINKER_SCRIPT_PATH})
# add linker script only for tests
if(MBED_IS_STANDALONE)
target_link_options(${TARGET}
INTERFACE
"-T" "${LINKER_SCRIPT_PATH}"
)
)
endif()
endforeach()
endfunction(mbed_setup_linker_script)
#
# Change the linker script to a custom supplied script instead of the built in.
# this function is called by mbed_set_post_build(target linker_script)
#
# target: CMake target for Mbed OS
# new_linker_script_path: raw linker script
#
function(mbed_set_custom_linker_script target new_linker_script_path)
set(RAW_LINKER_SCRIPT_PATHS ${CMAKE_CURRENT_SOURCE_DIR}/${new_linker_script_path})
set(CUSTOM_LINKER_SCRIPT_PATH ${CMAKE_CURRENT_BINARY_DIR}/${target}.link_spript.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_defs_response_file GLOBAL PROPERTY COMPILE_DEFS_RESPONSE_FILE)
get_filename_component(RAW_LINKER_SCRIPT_NAME ${RAW_LINKER_SCRIPT_PATHS} NAME)
get_filename_component(LINKER_SCRIPT_NAME ${CUSTOM_LINKER_SCRIPT_PATH} NAME)
add_custom_command(
TARGET
${target}
PRE_LINK
COMMAND
${CMAKE_COMMAND} -E echo "Preprocess custom linker script: ${RAW_LINKER_SCRIPT_NAME} -> ${LINKER_SCRIPT_NAME}"
COMMAND
${CMAKE_C_COMPILER} @${linker_defs_response_file}
-E -x assembler-with-cpp
-include ${CMAKE_BINARY_DIR}/mbed-os/mbed-target-config.h
-P ${RAW_LINKER_SCRIPT_PATHS}
-o ${CUSTOM_LINKER_SCRIPT_PATH}
DEPENDS
${RAW_LINKER_SCRIPT_PATHS}
${linker_defs_response_file}
${target_defines_header}
WORKING_DIRECTORY
${CMAKE_CURRENT_SOURCE_DIR}
VERBATIM
)
# Add linker flags to the target to pick up the preprocessed linker script
target_link_options(${target}
PRIVATE
"-T" "${CUSTOM_LINKER_SCRIPT_PATH}"
)
endfunction(mbed_set_custom_linker_script)

View File

@ -126,7 +126,32 @@ endfunction()
#
# Set post build operations
#
# target: the affected target
# 2nd arg: optional, linker script path
#
function(mbed_set_post_build target)
# add linker script. Skip for greentea test code, there the linker script is set in mbed_setup_linker_script()
if (NOT MBED_IS_STANDALONE)
if("${ARGN}" STREQUAL "")
if(TARGET mbed-os)
get_target_property(LINKER_SCRIPT_PATH mbed-os LINKER_SCRIPT_PATH)
target_link_options(${target}
PRIVATE
"-T" "${LINKER_SCRIPT_PATH}"
)
elseif(TARGET mbed-baremetal)
get_target_property(LINKER_SCRIPT_PATH mbed-baremetal LINKER_SCRIPT_PATH)
target_link_options(${target}
PRIVATE
"-T" "${LINKER_SCRIPT_PATH}"
)
endif()
else()
message(STATUS "${target} uses custom linker script ${ARGV2}")
mbed_set_custom_linker_script(${target} ${ARGV2})
endif()
endif()
# The mapfile name includes the top-level target name and the
# executable suffix for all toolchains as CMake hardcodes the name of the
# diagnostic output file for some toolchains.