From 9c502ddeccc7c860b4047e48a5b4b51b5b77abd3 Mon Sep 17 00:00:00 2001 From: Evan Wilde Date: Fri, 22 Sep 2023 10:16:21 -0700 Subject: [PATCH] Distro-overridable default Unix linker Being able to specify various defaults that the driver should assume is necessary for building specialized distributions of the toolchain. This mostly affects the non-Darwin Unix environment, where folks may be using a whole smorgasbord of different linkers in their toolchain. The original experience made it impossible to generally build the driver to default to a specific linker without editing source, which isn't great. Swift has the challenge of not allowing values assigned to macro definitions though, and neither does SwiftPM. Unless you have some fun with the clang importer, of course :). So we introduce a new DriverDefaults module that really just contains strings that were set as defaults. It seems that that clang importer was unable to import macros directly if they involved more than the literal, so I was unable to use `SWIFT_DEFAULT_LINKER` directly since I want to quote it, but instead have to assign it to an actual value. To configure the default linker while building with SwiftPM, `swift build -Xcc -DSWIFT_DEFAULT_LINKER=lld`, and you will end up with a Swift driver that will default to using lld on Linux. --- Package.swift | 5 +++++ Sources/DriverDefaults/constants.c | 6 ++++++ Sources/DriverDefaults/include/constants.h | 16 ++++++++++++++++ Sources/DriverDefaults/include/module.modulemap | 4 ++++ .../GenericUnixToolchain+LinkerSupport.swift | 7 +++++++ 5 files changed, 38 insertions(+) create mode 100644 Sources/DriverDefaults/constants.c create mode 100644 Sources/DriverDefaults/include/constants.h create mode 100644 Sources/DriverDefaults/include/module.modulemap diff --git a/Package.swift b/Package.swift index 16d72b8bb..3d7e43d5e 100644 --- a/Package.swift +++ b/Package.swift @@ -46,6 +46,10 @@ let package = Package( .target(name: "CSwiftScan", exclude: [ "CMakeLists.txt" ]), + /// Header containing distribution-configurable defaults. + .target(name: "DriverDefaults", + exclude: [ "CMakeLists.txt" ]), + /// The driver library. .target( name: "SwiftDriver", @@ -53,6 +57,7 @@ let package = Package( "SwiftOptions", .product(name: "SwiftToolsSupport-auto", package: "swift-tools-support-core"), "CSwiftScan", + "DriverDefaults", .product(name: "Yams", package: "yams"), ], exclude: ["CMakeLists.txt"]), diff --git a/Sources/DriverDefaults/constants.c b/Sources/DriverDefaults/constants.c new file mode 100644 index 000000000..7be5ce7a6 --- /dev/null +++ b/Sources/DriverDefaults/constants.c @@ -0,0 +1,6 @@ +#include "constants.h" + +#define Q(X) #X +#define QUOTE(X) Q(X) + +const char * defaultLinker = QUOTE(SWIFT_DEFAULT_LINKER); diff --git a/Sources/DriverDefaults/include/constants.h b/Sources/DriverDefaults/include/constants.h new file mode 100644 index 000000000..83fc1cd8f --- /dev/null +++ b/Sources/DriverDefaults/include/constants.h @@ -0,0 +1,16 @@ +#ifndef DRIVER_DEFAULTS_CONSTANTS_H +#define DRIVER_DEFAULTS_CONSTANTS_H + +/// Default Linker +/// +/// This macro allows configuring the Swift driver build to specify a default +/// linker, overriding the existing heuristic. +/// +/// NOTE: Darwin and Windows use clang as the linker. This does not affect the +/// linker that the clang linker selects. +#ifndef SWIFT_DEFAULT_LINKER +#define SWIFT_DEFAULT_LINKER +#endif +const char *defaultLinker; + +#endif // DRIVER_DEFAULTS_CONSTANTS_H diff --git a/Sources/DriverDefaults/include/module.modulemap b/Sources/DriverDefaults/include/module.modulemap new file mode 100644 index 000000000..dc253e231 --- /dev/null +++ b/Sources/DriverDefaults/include/module.modulemap @@ -0,0 +1,4 @@ +module DriverDefaults { + header "constants.h" + export * +} diff --git a/Sources/SwiftDriver/Jobs/GenericUnixToolchain+LinkerSupport.swift b/Sources/SwiftDriver/Jobs/GenericUnixToolchain+LinkerSupport.swift index 8030f9035..bda0644a1 100644 --- a/Sources/SwiftDriver/Jobs/GenericUnixToolchain+LinkerSupport.swift +++ b/Sources/SwiftDriver/Jobs/GenericUnixToolchain+LinkerSupport.swift @@ -11,12 +11,19 @@ //===----------------------------------------------------------------------===// import SwiftOptions +import DriverDefaults import func TSCBasic.lookupExecutablePath import struct TSCBasic.AbsolutePath extension GenericUnixToolchain { private func defaultLinker(for targetTriple: Triple) -> String? { + let constantDefaultLinker = String(cString: DriverDefaults.defaultLinker) + if !constantDefaultLinker.isEmpty { + print("Using linker: \(constantDefaultLinker)") + return constantDefaultLinker + } + if targetTriple.os == .openbsd || targetTriple.os == .freeBSD || targetTriple.environment == .android { return "lld"