Skip to content

Commit

Permalink
cmake: linker: Use the same linker for cmake checks and final build
Browse files Browse the repository at this point in the history
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.

(cherry picked from commit 9fe6c5e)

Original-Signed-off-by: Jonathon Penix <jpenix@quicinc.com>
Original-Signed-off-by: Torsten Rasmussen <Torsten.Rasmussen@nordicsemi.no>
GitOrigin-RevId: 9fe6c5e
Cr-Build-Id: 8734742957433546641
Cr-Build-Url: https://cr-buildbucket.appspot.com/build/8734742957433546641
Copybot-Job-Name: zephyr-main-copybot-downstream
Change-Id: Ibbfbd56f0e2edb93f4402b69be3c0d210c6c08b6
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/zephyr/+/5908563
Reviewed-by: Jeremy Bettis <jbettis@chromium.org>
Tested-by: Jeremy Bettis <jbettis@chromium.org>
Tested-by: ChromeOS Prod (Robot) <chromeos-ci-prod@chromeos-bot.iam.gserviceaccount.com>
Commit-Queue: Jeremy Bettis <jbettis@chromium.org>
  • Loading branch information
jonathonpenix authored and Chromeos LUCI committed Oct 7, 2024
1 parent dbf26e4 commit e1be731
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 7 deletions.
15 changes: 8 additions & 7 deletions cmake/linker/ld/target.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ set(CMAKE_LINKER ${GNULD_LINKER})

set_ifndef(LINKERFLAGPREFIX -Wl)

if((${CMAKE_LINKER} STREQUAL "${CROSS_COMPILE}ld.bfd") OR
${GNULD_LINKER_IS_BFD})
# ld.bfd was found so let's explicitly use that for linking, see #32237
list(APPEND TOOLCHAIN_LD_FLAGS -fuse-ld=bfd)
list(APPEND CMAKE_REQUIRED_FLAGS -fuse-ld=bfd)
string(REPLACE ";" " " CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
endif()

if(NOT "${ZEPHYR_TOOLCHAIN_VARIANT}" STREQUAL "host")
if(CONFIG_CPP_EXCEPTIONS AND LIBGCC_DIR)
# When building with C++ Exceptions, it is important that crtbegin and crtend
Expand Down Expand Up @@ -117,16 +125,9 @@ function(toolchain_ld_link_elf)
${ARGN} # input args to parse
)

if((${CMAKE_LINKER} STREQUAL "${CROSS_COMPILE}ld.bfd") OR
${GNULD_LINKER_IS_BFD})
# ld.bfd was found so let's explicitly use that for linking, see #32237
set(use_linker "-fuse-ld=bfd")
endif()

target_link_libraries(
${TOOLCHAIN_LD_LINK_ELF_TARGET_ELF}
${TOOLCHAIN_LD_LINK_ELF_LIBRARIES_PRE_SCRIPT}
${use_linker}
${TOPT}
${TOOLCHAIN_LD_LINK_ELF_LINKER_SCRIPT}
${TOOLCHAIN_LD_LINK_ELF_LIBRARIES_POST_SCRIPT}
Expand Down
4 changes: 4 additions & 0 deletions cmake/linker/lld/target.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ set(CMAKE_LINKER ${LLVMLLD_LINKER})

set_ifndef(LINKERFLAGPREFIX -Wl)

list(APPEND TOOLCHAIN_LD_FLAGS -fuse-ld=lld)
list(APPEND CMAKE_REQUIRED_FLAGS -fuse-ld=lld)
string(REPLACE ";" " " CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")

# Run $LINKER_SCRIPT file through the C preprocessor, producing ${linker_script_gen}
# NOTE: ${linker_script_gen} will be produced at build-time; not at configure-time
macro(configure_linker_script linker_script_gen linker_pass_define)
Expand Down

0 comments on commit e1be731

Please sign in to comment.