1# SPDX-License-Identifier: Apache-2.0 2# 3# Copyright (c) 2022, Nordic Semiconductor ASA 4# Copyright (c) 2023, Intel Corporation 5 6# FindGnuLd module for locating GNU ld (linker from binutils). 7# 8# The module defines the following variables: 9# 10# 'GNULD_LINKER' 11# Path to GNU ld linker 12# Set to 'GNULD_LINKER-NOTFOUND' if ld was not found. 13# 14# 'GnuLd_FOUND', 'GNULD_FOUND' 15# True if GNU ld was found. 16# 17# 'GNULD_VERSION_STRING' 18# The version of GNU ld. 19# 20# 'GNULD_LINKER_IS_BFD' 21# True if linker is ld.bfd (or compatible) 22# 23# Note that this will use CROSS_COMPILE, if defined, 24# as a prefix to the linker executable. 25 26include(FindPackageHandleStandardArgs) 27 28# GNULD_LINKER exists on repeated builds or defined manually... 29if(EXISTS "${GNULD_LINKER}") 30 if(NOT DEFINED GNULD_LINKER_IS_BFD) 31 # ... issue warning if GNULD_LINKER_IS_BFD is not already set. 32 message( 33 WARNING 34 "GNULD_LINKER specified directly in cache, but GNULD_LINKER_IS_BFD is not " 35 "defined. Assuming GNULD_LINKER_IS_BFD as OFF, please set GNULD_LINKER_IS_BFD " 36 "to correct value in cache to silence this warning" 37 ) 38 set(GNULD_LINKER_IS_BFD OFF) 39 endif() 40 41 # Since GNULD_LINKER already exists, there is no need to find it again (below). 42 return() 43endif() 44 45# See if the compiler has a preferred linker 46execute_process(COMMAND ${CMAKE_C_COMPILER} --print-prog-name=ld.bfd 47 OUTPUT_VARIABLE GNULD_LINKER 48 OUTPUT_STRIP_TRAILING_WHITESPACE) 49 50if(EXISTS "${GNULD_LINKER}") 51 cmake_path(NORMAL_PATH GNULD_LINKER) 52 set(GNULD_LINKER_IS_BFD ON CACHE BOOL "Linker BFD compatibility (compiler reported)" FORCE) 53else() 54 # Need to clear it or else find_program() won't replace the value. 55 set(GNULD_LINKER) 56 57 if(DEFINED TOOLCHAIN_HOME) 58 # Search for linker under TOOLCHAIN_HOME if it is defined 59 # to limit which linker to use, or else we would be using 60 # host tools. 61 set(LD_SEARCH_PATH PATHS ${TOOLCHAIN_HOME} NO_DEFAULT_PATH) 62 endif() 63 64 find_program(GNULD_LINKER ${CROSS_COMPILE}ld.bfd ${LD_SEARCH_PATH}) 65 if(GNULD_LINKER) 66 set(GNULD_LINKER_IS_BFD ON CACHE BOOL "Linker BFD compatibility (inferred from binary)" FORCE) 67 else() 68 find_program(GNULD_LINKER ${CROSS_COMPILE}ld ${LD_SEARCH_PATH}) 69 set(GNULD_LINKER_IS_BFD OFF CACHE BOOL "Linker BFD compatibility (inferred from binary)" FORCE) 70 endif() 71endif() 72 73if(GNULD_LINKER) 74 # Parse the 'ld.bfd --version' output to find the installed version. 75 execute_process( 76 COMMAND 77 ${GNULD_LINKER} --version 78 OUTPUT_VARIABLE gnuld_version_output 79 ERROR_VARIABLE gnuld_error_output 80 RESULT_VARIABLE gnuld_status 81 ) 82 83 if(${gnuld_status} EQUAL 0) 84 # Extract GNU ld version. Different distros have their 85 # own version scheme so we need to account for that. 86 # Examples: 87 # - "GNU ld (GNU Binutils for Ubuntu) 2.34" 88 # - "GNU ld (Zephyr SDK 0.15.2) 2.38" 89 # - "GNU ld (Gentoo 2.39 p5) 2.39.0" 90 string(REGEX MATCH 91 "GNU ld \\(.+\\) ([0-9]+[.][0-9]+[.]?[0-9]*).*" 92 out_var ${gnuld_version_output}) 93 set(GNULD_VERSION_STRING ${CMAKE_MATCH_1} CACHE STRING "GNU ld version" FORCE) 94 endif() 95endif() 96 97find_package_handle_standard_args(GnuLd 98 REQUIRED_VARS GNULD_LINKER 99 VERSION_VAR GNULD_VERSION_STRING 100) 101