From 29a67d1f2eed846a0cae25b58d0dfcc1e9e09e73 Mon Sep 17 00:00:00 2001 From: Daniel Leung Date: Thu, 2 Mar 2023 10:06:58 -0800 Subject: [PATCH] linker: use find_package() to find GNU ld This introduces a new cmake module FindGnuLd.cmake to do the work to discover GNU ld (of binutils). Signed-off-by: Daniel Leung --- cmake/linker/ld/target.cmake | 12 ++----- cmake/modules/FindGnuLd.cmake | 63 +++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 10 deletions(-) create mode 100644 cmake/modules/FindGnuLd.cmake diff --git a/cmake/linker/ld/target.cmake b/cmake/linker/ld/target.cmake index 03c490c68d7..6a5f3c24228 100644 --- a/cmake/linker/ld/target.cmake +++ b/cmake/linker/ld/target.cmake @@ -1,16 +1,8 @@ # SPDX-License-Identifier: Apache-2.0 set_property(TARGET linker PROPERTY devices_start_symbol "__device_start") -if(DEFINED TOOLCHAIN_HOME) - # When Toolchain home is defined, then we are cross-compiling, so only look - # for linker in that path, else we are using host tools. - set(LD_SEARCH_PATH PATHS ${TOOLCHAIN_HOME} NO_DEFAULT_PATH) -endif() - -find_program(CMAKE_LINKER ${CROSS_COMPILE}ld.bfd ${LD_SEARCH_PATH}) -if(NOT CMAKE_LINKER) - find_program(CMAKE_LINKER ${CROSS_COMPILE}ld ${LD_SEARCH_PATH}) -endif() +find_package(GnuLd REQUIRED) +set(CMAKE_LINKER ${GNULD_LINKER}) set_ifndef(LINKERFLAGPREFIX -Wl) diff --git a/cmake/modules/FindGnuLd.cmake b/cmake/modules/FindGnuLd.cmake new file mode 100644 index 00000000000..c6c17471ed7 --- /dev/null +++ b/cmake/modules/FindGnuLd.cmake @@ -0,0 +1,63 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (c) 2022, Nordic Semiconductor ASA +# Copyright (c) 2023, Intel Corporation + +# FindGnuLd module for locating GNU ld (linker from binutils). +# +# The module defines the following variables: +# +# 'GNULD_LINKER' +# Path to GNU ld linker +# Set to 'GNULD_LINKER-NOTFOUND' if ld was not found. +# +# 'GnuLd_FOUND', 'GNULD_FOUND' +# True if GNU ld was found. +# +# 'GNULD_VERSION_STRING' +# The version of GNU ld. +# +# Note that this will use CROSS_COMPILE, if defined, +# as a prefix to the linker executable. + +if(DEFINED TOOLCHAIN_HOME) + # Search for linker under TOOLCHAIN_HOME if it is defined + # to limit which linker to use, or else we would be using + # host tools. + set(LD_SEARCH_PATH PATHS ${TOOLCHAIN_HOME} NO_DEFAULT_PATH) +endif() + +find_program(GNULD_LINKER ${CROSS_COMPILE}ld.bfd ${LD_SEARCH_PATH}) +if(NOT GNULD_LINKER) + find_program(GNULD_LINKER ${CROSS_COMPILE}ld ${LD_SEARCH_PATH}) +endif() + +if(GNULD_LINKER) + # Parse the 'ld.bfd --version' output to find the installed version. + execute_process( + COMMAND + ${GNULD_LINKER} --version + OUTPUT_VARIABLE gnuld_version_output + ERROR_VARIABLE gnuld_error_output + RESULT_VARIABLE gnuld_status + ) + + set(GNULD_VERSION_STRING) + if(${gnuld_status} EQUAL 0) + # Extract GNU ld version. Different distros have their + # own version scheme so we need to account for that. + # Examples: + # - "GNU ld (GNU Binutils for Ubuntu) 2.34" + # - "GNU ld (Zephyr SDK 0.15.2) 2.38" + # - "GNU ld (Gentoo 2.39 p5) 2.39.0" + string(REGEX MATCH + "GNU ld \\(.+\\) ([0-9]+[.][0-9]+[.]?[0-9]*).*" + out_var ${gnuld_version_output}) + set(GNULD_VERSION_STRING ${CMAKE_MATCH_1}) + endif() +endif() + +find_package_handle_standard_args(GnuLd + REQUIRED_VARS GNULD_LINKER + VERSION_VAR GNULD_VERSION_STRING +)