100 lines
3.2 KiB
CMake
100 lines
3.2 KiB
CMake
# 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}")
|
|
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
|
|
)
|