| # 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. |
| # |
| # 'GNULD_LINKER_IS_BFD' |
| # True if linker is ld.bfd (or compatible) |
| # |
| # Note that this will use CROSS_COMPILE, if defined, |
| # as a prefix to the linker executable. |
| |
| include(FindPackageHandleStandardArgs) |
| |
| # GNULD_LINKER exists on repeated builds or defined manually... |
| if(EXISTS "${GNULD_LINKER}") |
| if(NOT DEFINED GNULD_LINKER_IS_BFD) |
| # ... issue warning if GNULD_LINKER_IS_BFD is not already set. |
| message( |
| WARNING |
| "GNULD_LINKER specified directly in cache, but GNULD_LINKER_IS_BFD is not " |
| "defined. Assuming GNULD_LINKER_IS_BFD as OFF, please set GNULD_LINKER_IS_BFD " |
| "to correct value in cache to silence this warning" |
| ) |
| set(GNULD_LINKER_IS_BFD OFF) |
| endif() |
| |
| # Since GNULD_LINKER already exists, there is no need to find it again (below). |
| return() |
| endif() |
| |
| # See if the compiler has a preferred linker |
| execute_process(COMMAND ${CMAKE_C_COMPILER} --print-prog-name=ld.bfd |
| OUTPUT_VARIABLE GNULD_LINKER |
| OUTPUT_STRIP_TRAILING_WHITESPACE) |
| |
| if(EXISTS "${GNULD_LINKER}") |
| cmake_path(NORMAL_PATH GNULD_LINKER) |
| set(GNULD_LINKER_IS_BFD ON CACHE BOOL "Linker BFD compatibility (compiler reported)" FORCE) |
| else() |
| # Need to clear it or else find_program() won't replace the value. |
| set(GNULD_LINKER) |
| |
| 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(GNULD_LINKER) |
| set(GNULD_LINKER_IS_BFD ON CACHE BOOL "Linker BFD compatibility (inferred from binary)" FORCE) |
| else() |
| find_program(GNULD_LINKER ${CROSS_COMPILE}ld ${LD_SEARCH_PATH}) |
| set(GNULD_LINKER_IS_BFD OFF CACHE BOOL "Linker BFD compatibility (inferred from binary)" FORCE) |
| endif() |
| 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 |
| ) |
| |
| 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} CACHE STRING "GNU ld version" FORCE) |
| endif() |
| endif() |
| |
| find_package_handle_standard_args(GnuLd |
| REQUIRED_VARS GNULD_LINKER |
| VERSION_VAR GNULD_VERSION_STRING |
| ) |