Skip to content

Commit ad88230

Browse files
committed
cmake: linker: Use the same linker for cmake checks and final build
Currently, the linker that is used when performing various cmake checks (check_c_compiler_flag, for example) may be different than the linker that will be used during the actual build. This happens as we currently specify '-fuse-ld' to force the appropriate linker a) after many such checks have already happened and b) in a way which is not automatically propagated to check_c_compiler_flag (and friends). As a result, the toolchain's default linker will generally be used for such checks regardless of which linker was selected in Zephyr. This can lead to a number of surprises when building Zephyr, particularly when building with clang. For example: - If the linker is misconfigured, where the build will fail can vary depending on whether the linker is the toolchain's default. When the configured linker happens to be the toolchain's default, the build (helpfully) fails quickly on the checks for a basic working toochain. When the configured linker isn't the default, the build won't fail until the final link steps. - The build can fail due to issues with a linker other than the one configured by the user in Zephyr. For example, LLVM toolchains without lld will generally fail to build Zephyr (the checks for a basic working toochain will fail) for targets where lld is the default in LLVM even if GNU ld is configured in Zephyr and would otherwise be used in the final build. - Flags which are only added if check_c_compiler_flag (or similar) succeeds may be unexpectedly omitted during the final build if the flag is supported in the configured linker but is unsupported in the toolchain's default linker (as check_c_compiler_flag will test using the default one). Note that this isn't limited to clang--even when we are building with Zephyr's SDK and force ld.bfd, we seem to use the 'ld' variant during the cmake checks (though this generally seems fairly harmless compared to mixing ld/lld or other proprietary linkers). To fix this, ensure the appropriate 'fuse-ld' is set early enough and in such a way that the same linker will be used throughout the entire build. Signed-off-by: Jonathon Penix <[email protected]>
1 parent eeb933b commit ad88230

File tree

3 files changed

+12
-14
lines changed

3 files changed

+12
-14
lines changed

cmake/linker/ld/target.cmake

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,14 @@ set(CMAKE_LINKER ${GNULD_LINKER})
66

77
set_ifndef(LINKERFLAGPREFIX -Wl)
88

9+
if((${CMAKE_LINKER} STREQUAL "${CROSS_COMPILE}ld.bfd") OR
10+
${GNULD_LINKER_IS_BFD})
11+
# ld.bfd was found so let's explicitly use that for linking, see #32237
12+
list(APPEND TOOLCHAIN_LD_FLAGS -fuse-ld=bfd)
13+
list(APPEND CMAKE_REQUIRED_FLAGS -fuse-ld=bfd)
14+
string(REPLACE ";" " " CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
15+
endif()
16+
917
if(NOT "${ZEPHYR_TOOLCHAIN_VARIANT}" STREQUAL "host")
1018
if(CONFIG_CPP_EXCEPTIONS AND LIBGCC_DIR)
1119
# When building with C++ Exceptions, it is important that crtbegin and crtend
@@ -118,16 +126,9 @@ function(toolchain_ld_link_elf)
118126
${ARGN} # input args to parse
119127
)
120128

121-
if((${CMAKE_LINKER} STREQUAL "${CROSS_COMPILE}ld.bfd") OR
122-
${GNULD_LINKER_IS_BFD})
123-
# ld.bfd was found so let's explicitly use that for linking, see #32237
124-
set(use_linker "-fuse-ld=bfd")
125-
endif()
126-
127129
target_link_libraries(
128130
${TOOLCHAIN_LD_LINK_ELF_TARGET_ELF}
129131
${TOOLCHAIN_LD_LINK_ELF_LIBRARIES_PRE_SCRIPT}
130-
${use_linker}
131132
${TOPT}
132133
${TOOLCHAIN_LD_LINK_ELF_LINKER_SCRIPT}
133134
${TOOLCHAIN_LD_LINK_ELF_LIBRARIES_POST_SCRIPT}

cmake/linker/lld/target.cmake

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ set(CMAKE_LINKER ${LLVMLLD_LINKER})
66

77
set_ifndef(LINKERFLAGPREFIX -Wl)
88

9+
list(APPEND TOOLCHAIN_LD_FLAGS -fuse-ld=lld)
10+
list(APPEND CMAKE_REQUIRED_FLAGS -fuse-ld=lld)
11+
string(REPLACE ";" " " CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
12+
913
# Run $LINKER_SCRIPT file through the C preprocessor, producing ${linker_script_gen}
1014
# NOTE: ${linker_script_gen} will be produced at build-time; not at configure-time
1115
macro(configure_linker_script linker_script_gen linker_pass_define)

cmake/linker/lld/target_baremetal.cmake

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,6 @@ macro(toolchain_ld_baremetal)
1212
${LINKERFLAGPREFIX},-N
1313
)
1414

15-
# Force LLVM to use built-in lld linker
16-
if(NOT CONFIG_LLVM_USE_LD)
17-
zephyr_ld_options(
18-
-fuse-ld=lld
19-
)
20-
endif()
21-
2215
# Funny thing is if this is set to =error, some architectures will
2316
# skip this flag even though the compiler flag check passes
2417
# (e.g. ARC and Xtensa). So warning should be the default for now.

0 commit comments

Comments
 (0)