@@ -56,6 +56,8 @@ function(mbed_setup_linker_script mbed_os_target mbed_baremetal_target target_de
5656 OUTPUT
5757 ${LINKER_SCRIPT_PATH}
5858 PRE_LINK
59+ COMMAND
60+ ${CMAKE_COMMAND} -E echo "Preprocess linker script: ${RAW_LINKER_SCRIPT_NAME} -> ${LINKER_SCRIPT_NAME} "
5961 COMMAND
6062 ${CMAKE_C_COMPILER} @${linker_defs_response_file}
6163 -E -x assembler-with-cpp
@@ -68,23 +70,80 @@ function(mbed_setup_linker_script mbed_os_target mbed_baremetal_target target_de
6870 ${target_defines_header}
6971 WORKING_DIRECTORY
7072 ${CMAKE_CURRENT_SOURCE_DIR}
71- COMMENT
72- "Preprocess linker script: ${RAW_LINKER_SCRIPT_NAME} -> ${LINKER_SCRIPT_NAME} "
7373 VERBATIM
7474 )
7575
76+
7677 # The job to create the linker script gets attached to the mbed-linker-script target,
7778 # which is then added as a dependency of the MCU target. This ensures the linker script will exist
7879 # by the time we need it.
7980 add_custom_target (mbed-linker-script DEPENDS ${LINKER_SCRIPT_PATH} VERBATIM )
8081 foreach (TARGET ${mbed_baremetal_target} ${mbed_os_target} )
8182 add_dependencies (${TARGET} mbed-linker-script)
8283
83- # Add linker flags to the MCU target to pick up the preprocessed linker script
84- target_link_options (${TARGET}
84+ # When building the Mbed internal tests, the tests get created before the mbed-os target does. So, the normal logic
85+ # in mbed_set_post_build() to set the linker script does not work. So, we need to instead attach the linker script to
86+ # the mbed-os and mbed-baremetal libraries themselves, so it will get picked up automatically.
87+ # This prevents a custom linker script from being used in STANDALONE mode, but we don't need to do that.
88+ set_target_properties (${TARGET} PROPERTIES LINKER_SCRIPT_PATH ${LINKER_SCRIPT_PATH} )
89+
90+ # add linker script only for tests
91+ if (MBED_IS_STANDALONE)
92+ target_link_options (${TARGET}
8593 INTERFACE
8694 "-T" "${LINKER_SCRIPT_PATH} "
87- )
95+ )
96+ endif ()
8897 endforeach ()
8998
9099endfunction (mbed_setup_linker_script)
100+
101+
102+ #
103+ # Change the linker script to a custom supplied script instead of the built in.
104+ # this function is called by mbed_set_post_build(target linker_script)
105+ #
106+ # target: CMake target for Mbed OS
107+ # new_linker_script_path: raw linker script
108+ #
109+ function (mbed_set_custom_linker_script target new_linker_script_path)
110+
111+ set (RAW_LINKER_SCRIPT_PATHS ${CMAKE_CURRENT_SOURCE_DIR} /${new_linker_script_path} )
112+ set (CUSTOM_LINKER_SCRIPT_PATH ${CMAKE_CURRENT_BINARY_DIR} /${target} .link_spript.ld)
113+
114+ # To avoid path limits on Windows, we create a "response file" and set the path to it as a
115+ # global property. We need this solely to pass the compile definitions to GCC's preprocessor,
116+ # so it can expand any macro definitions in the linker script.
117+ get_property (linker_defs_response_file GLOBAL PROPERTY COMPILE_DEFS_RESPONSE_FILE)
118+
119+ get_filename_component (RAW_LINKER_SCRIPT_NAME ${RAW_LINKER_SCRIPT_PATHS} NAME )
120+ get_filename_component (LINKER_SCRIPT_NAME ${CUSTOM_LINKER_SCRIPT_PATH} NAME )
121+
122+ add_custom_command (
123+ TARGET
124+ ${target}
125+ PRE_LINK
126+ COMMAND
127+ ${CMAKE_COMMAND} -E echo "Preprocess custom linker script: ${RAW_LINKER_SCRIPT_NAME} -> ${LINKER_SCRIPT_NAME} "
128+ COMMAND
129+ ${CMAKE_C_COMPILER} @${linker_defs_response_file}
130+ -E -x assembler-with-cpp
131+ -include ${CMAKE_BINARY_DIR} /mbed-os/mbed-target -config.h
132+ -P ${RAW_LINKER_SCRIPT_PATHS}
133+ -o ${CUSTOM_LINKER_SCRIPT_PATH}
134+ DEPENDS
135+ ${RAW_LINKER_SCRIPT_PATHS}
136+ ${linker_defs_response_file}
137+ ${target_defines_header}
138+ WORKING_DIRECTORY
139+ ${CMAKE_CURRENT_SOURCE_DIR}
140+ VERBATIM
141+ )
142+
143+ # Add linker flags to the target to pick up the preprocessed linker script
144+ target_link_options (${target}
145+ PRIVATE
146+ "-T" "${CUSTOM_LINKER_SCRIPT_PATH} "
147+ )
148+
149+ endfunction (mbed_set_custom_linker_script)
0 commit comments