Skip to content

Commit 5b3cfaf

Browse files
committed
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.
1 parent ca65112 commit 5b3cfaf

File tree

2 files changed

+75
-39
lines changed

2 files changed

+75
-39
lines changed

CMakeLists.txt

Lines changed: 27 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
cmake_minimum_required(VERSION 3.19.0 FATAL_ERROR)
77

88
include(${MBED_CONFIG_PATH}/mbed_config.cmake)
9+
include(tools/cmake/SetLinkerScript.cmake)
910

1011
add_library(mbed-core INTERFACE)
1112

@@ -110,6 +111,32 @@ add_subdirectory(features EXCLUDE_FROM_ALL)
110111
add_subdirectory(cmsis/CMSIS_5/CMSIS/RTOS2 EXCLUDE_FROM_ALL)
111112
add_subdirectory(cmsis/device/rtos EXCLUDE_FROM_ALL)
112113

114+
115+
# We need to generate a "response file" to pass to the C preprocessor because of path length
116+
# limitations on Windows. We set the response file and bind the path to a global property here.
117+
# We query this global property when we set the linker script for the MBED_TARGET being built.
118+
#
119+
# TODO: Remove this and find a more idiomatic way of passing compile definitions to CPP without
120+
# using global properties.
121+
mbed_generate_options_for_linker(${APP_TARGET} LINKER_PREPROCESS_DEFINITIONS)
122+
set_property(GLOBAL PROPERTY COMPILE_DEFS_RESPONSE_FILE ${LINKER_PREPROCESS_DEFINITIONS})
123+
124+
# This is a temporary workaround to prevent the build from failing for MBED_TARGETS that
125+
# haven't been converted to build system targets yet.
126+
# The refactored MBED_TARGETS set the linker script and forward it to the build system as a
127+
# usage requirement. The 'old' mechanism was to set the linker script on the top level mbed-core
128+
# target. This was needed because MBED_TARGETS were not registered as buildsystem targets,
129+
# preventing CMake from working its usage requirements magic and forcing us to set the linker
130+
# script globally.
131+
#
132+
# TODO: Remove when all MBED_TARGETS have been converted to build system targets.
133+
if(TARGET ${MBED_TARGET})
134+
target_link_libraries(mbed-core INTERFACE ${MBED_TARGET})
135+
else()
136+
get_property(LINKER_SCRIPT GLOBAL PROPERTY MBED_TARGET_LINKER_FILE)
137+
mbed_set_linker_script(mbed-core ${LINKER_SCRIPT})
138+
endif()
139+
113140
#
114141
# Configures the application
115142
#
@@ -122,45 +149,6 @@ function(mbed_configure_app_target target)
122149
)
123150
endfunction()
124151

125-
#
126-
# Specifies linker script used for linking `target`.
127-
#
128-
function(mbed_set_mbed_target_linker_script target)
129-
get_property(mbed_target_linker_script GLOBAL PROPERTY MBED_TARGET_LINKER_FILE)
130-
mbed_generate_options_for_linker(${target} _linker_preprocess_definitions)
131-
if(MBED_TOOLCHAIN STREQUAL "GCC_ARM")
132-
set(CMAKE_PRE_BUILD_COMMAND
133-
COMMAND "arm-none-eabi-cpp" ${_linker_preprocess_definitions} -x assembler-with-cpp -E -Wp,-P
134-
${mbed_target_linker_script} -o ${CMAKE_BINARY_DIR}/${target}.link_script.ld
135-
136-
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
137-
BYPRODUCTS "${CMAKE_BINARY_DIR}/${target}.link_script.ld"
138-
)
139-
target_link_options(mbed-core
140-
INTERFACE
141-
"-T" "${CMAKE_BINARY_DIR}/${target}.link_script.ld"
142-
"-Wl,-Map=${CMAKE_BINARY_DIR}/${target}.map"
143-
)
144-
elseif(MBED_TOOLCHAIN STREQUAL "ARM")
145-
set(CMAKE_PRE_BUILD_COMMAND COMMAND "")
146-
target_link_options(mbed-core
147-
INTERFACE
148-
"--scatter=${mbed_target_linker_script}"
149-
"--predefine=${_linker_preprocess_definitions}"
150-
"--map"
151-
)
152-
endif()
153-
add_custom_command(
154-
TARGET
155-
${target}
156-
PRE_LINK
157-
${CMAKE_PRE_BUILD_COMMAND}
158-
COMMENT
159-
"Link line:"
160-
VERBATIM
161-
)
162-
endfunction()
163-
164152
#
165153
# Converts output file of `target` to binary file and to Intel HEX file.
166154
#

tools/cmake/SetLinkerScript.cmake

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#
2+
# Preprocesses and sets the linker script for an Mbed target.
3+
#
4+
function(mbed_set_linker_script input_target raw_linker_script_path)
5+
set(LINKER_SCRIPT_PATH ${CMAKE_BINARY_DIR}/${input_target}.link_script.ld)
6+
# To avoid path limits on Windows, we create a "response file" and set the path to it as a
7+
# global property. We need this solely to pass the compile definitions to GCC's preprocessor,
8+
# so it can expand any macro definitions in the linker script.
9+
get_property(_linker_preprocess_definitions GLOBAL PROPERTY COMPILE_DEFS_RESPONSE_FILE)
10+
if(MBED_TOOLCHAIN STREQUAL "GCC_ARM")
11+
add_custom_command(
12+
OUTPUT
13+
${LINKER_SCRIPT_PATH}
14+
PRE_LINK
15+
COMMAND
16+
${CMAKE_C_COMPILER} ${_linker_preprocess_definitions}
17+
-E -x c
18+
-P ${raw_linker_script_path}
19+
-o ${LINKER_SCRIPT_PATH}
20+
WORKING_DIRECTORY
21+
${CMAKE_CURRENT_SOURCE_DIR}
22+
COMMENT
23+
"Link line:"
24+
VERBATIM
25+
)
26+
# CMake will not let us add PRE_LINK commands to INTERFACE targets, and input_target could
27+
# be an INTERFACE target.
28+
# To get around this we create an intermediate custom target depending on the preprocessed
29+
# linker script output by CPP. We add this custom target as a dependency of input_target.
30+
# This ensures CMake runs our custom command to preprocess the linker script before trying
31+
# to build input_target.
32+
set(LinkerScriptTarget ${input_target}LinkerScript)
33+
add_custom_target(${LinkerScriptTarget} DEPENDS ${LINKER_SCRIPT_PATH} VERBATIM)
34+
add_dependencies(${input_target} ${LinkerScriptTarget})
35+
target_link_options(${input_target}
36+
INTERFACE
37+
"-T" "${LINKER_SCRIPT_PATH}"
38+
"-Wl,-Map=${CMAKE_BINARY_DIR}/${APP_TARGET}.map"
39+
)
40+
elseif(MBED_TOOLCHAIN STREQUAL "ARM")
41+
target_link_options(${input_target}
42+
INTERFACE
43+
"--scatter=${raw_linker_script_path}"
44+
"--predefine=${_linker_preprocess_definitions}"
45+
"--map"
46+
)
47+
endif()
48+
endfunction()

0 commit comments

Comments
 (0)