[Build] Detect ld.gold version and prefer lld if gold is too old.

If we're on a system that has ld.gold 2.35 or earlier, we want to use
lld instead because otherwise we end up with duplicate sections in the
output.

rdar://123504095
This commit is contained in:
Alastair Houghton
2024-04-22 11:14:27 +01:00
parent f5b1ef77a6
commit a014bd2cc8
2 changed files with 31 additions and 1 deletions

View File

@@ -983,6 +983,8 @@ endif()
# Which default linker to use. Prefer LLVM_USE_LINKER if it set, otherwise use
# our own defaults. This should only be possible in a unified (not stand alone)
# build environment.
include(GoldVersion)
if(LLVM_USE_LINKER)
set(SWIFT_USE_LINKER_default "${LLVM_USE_LINKER}")
elseif(SWIFT_HOST_VARIANT_SDK STREQUAL "ANDROID")
@@ -994,7 +996,17 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
elseif(DISTRO_NAME STREQUAL "Amazon Linux 2023")
set(SWIFT_USE_LINKER_default "lld")
else()
set(SWIFT_USE_LINKER_default "gold")
get_gold_version(gold_version)
if(NOT gold_version)
message(STATUS "GNU Gold not found; using lld instead")
set(SWIFT_USE_LINKER_default "lld")
elseif(gold_version VERSION_LESS "2.36")
message(STATUS "GNU Gold is too old (${gold_version}); using lld instead")
set(SWIFT_USE_LINKER_default "lld")
else()
message(STATUS "Using GNU Gold ${gold_version}")
set(SWIFT_USE_LINKER_default "gold")
endif()
endif()
set(SWIFT_USE_LINKER ${SWIFT_USE_LINKER_default} CACHE STRING
"Build Swift with a non-default linker")

View File

@@ -0,0 +1,18 @@
# Find the version of ld.gold, if installed.
#
# Versions prior to 2.36 break Swift programs because they won't coalesce
# sections with different SHF_GNU_RETAIN flags.
function(get_gold_version result_var_name)
find_program(gold_executable "ld.gold")
if(gold_executable)
execute_process(
COMMAND "${gold_executable}" "--version"
COMMAND "head" "-n" "1"
COMMAND "sed" "-e" "s/^.* (\\([^)]*\\)).*$/\\1/g;s/.* \\([0-9][0-9]*\\(\\.[0-9][0-9]*\\)*\\).*/\\1/g"
OUTPUT_VARIABLE gold_version
OUTPUT_STRIP_TRAILING_WHITESPACE)
set("${result_var_name}" "${gold_version}" PARENT_SCOPE)
else()
set("${result_var_name}" "" PARENT_SCOPE)
endif()
endfunction()