Skip to content

Commit 2935ca6

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 2935ca6

File tree

3 files changed

+77
-41
lines changed

3 files changed

+77
-41
lines changed

CMakeLists.txt

Lines changed: 26 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/set_linker_script.cmake)
910

1011
add_library(mbed-core INTERFACE)
1112

@@ -86,6 +87,15 @@ target_include_directories(mbed-core
8687
${CMAKE_CURRENT_SOURCE_DIR}
8788
)
8889

90+
# We need to generate a "response file" to pass to the C preprocessor because of path length
91+
# limitations on Windows. We set the response file and bind the path to a global property here.
92+
# We query this global property when we set the linker script for the MBED_TARGET being built.
93+
#
94+
# TODO: Remove this and find a more idiomatic way of passing compile definitions to CPP without
95+
# using global properties.
96+
mbed_generate_options_for_linker(${APP_TARGET} LINKER_PREPROCESS_DEFINITIONS)
97+
set_property(GLOBAL PROPERTY COMPILE_DEFS_RESPONSE_FILE ${LINKER_PREPROCESS_DEFINITIONS})
98+
8999
# These targets are made visible here so their source files which
90100
# are spread in different directories can be referenced and can be linked against
91101
# by libraries that depend on them.
@@ -110,6 +120,22 @@ add_subdirectory(features EXCLUDE_FROM_ALL)
110120
add_subdirectory(cmsis/CMSIS_5/CMSIS/RTOS2 EXCLUDE_FROM_ALL)
111121
add_subdirectory(cmsis/device/rtos EXCLUDE_FROM_ALL)
112122

123+
# This is a temporary workaround to prevent the build from failing for MBED_TARGETS that
124+
# haven't been converted to build system targets yet.
125+
# The refactored MBED_TARGETS set the linker script and forward it to the build system as a
126+
# usage requirement. The 'old' mechanism was to set the linker script on the top level mbed-core
127+
# target. This was needed because MBED_TARGETS were not registered as buildsystem targets,
128+
# preventing CMake from working its usage requirements magic and forcing us to set the linker
129+
# script globally.
130+
#
131+
# TODO: Remove when all MBED_TARGETS have been converted to build system targets.
132+
if(TARGET ${MBED_TARGET})
133+
target_link_libraries(mbed-core INTERFACE ${MBED_TARGET})
134+
else()
135+
get_property(LINKER_SCRIPT GLOBAL PROPERTY MBED_TARGET_LINKER_FILE)
136+
mbed_set_linker_script(mbed-core ${LINKER_SCRIPT})
137+
endif()
138+
113139
#
114140
# Configures the application
115141
#
@@ -122,45 +148,6 @@ function(mbed_configure_app_target target)
122148
)
123149
endfunction()
124150

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-
164151
#
165152
# Converts output file of `target` to binary file and to Intel HEX file.
166153
#

tools/cmake/mbed_greentea.cmake

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,6 @@ macro(mbed_greentea_cmake_macro)
4343

4444
mbed_configure_app_target(${TEST_NAME})
4545

46-
mbed_set_mbed_target_linker_script(${TEST_NAME})
47-
4846
target_include_directories(${TEST_NAME}
4947
PRIVATE
5048
.

tools/cmake/set_linker_script.cmake

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

0 commit comments

Comments
 (0)