Skip to content

Commit 71b11e7

Browse files
committed
Correctly pass linker flags to Swift Build backend
These are expected to be prefixed with -Xlinker, like the native build system does. This solves linker failures with linker flags coming from toolset.json, especially for Swift Embedded workflows.
1 parent 5c2b398 commit 71b11e7

File tree

3 files changed

+55
-55
lines changed

3 files changed

+55
-55
lines changed

Sources/Build/BuildPlan/BuildPlan.swift

Lines changed: 0 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -36,59 +36,6 @@ extension String {
3636
}
3737
}
3838

39-
extension [String] {
40-
/// Converts a set of C compiler flags into an equivalent set to be
41-
/// indirected through the Swift compiler instead.
42-
func asSwiftcCCompilerFlags() -> Self {
43-
self.flatMap { ["-Xcc", $0] }
44-
}
45-
46-
/// Converts a set of C++ compiler flags into an equivalent set to be
47-
/// indirected through the Swift compiler instead.
48-
func asSwiftcCXXCompilerFlags() -> Self {
49-
_ = self.flatMap { ["-Xcxx", $0] }
50-
// TODO: Pass -Xcxx flags to swiftc (#6491)
51-
// Remove fatal error when downstream support arrives.
52-
fatalError("swiftc does support -Xcxx flags yet.")
53-
}
54-
55-
/// Converts a set of linker flags into an equivalent set to be indirected
56-
/// through the Swift compiler instead.
57-
///
58-
/// Some arguments can be passed directly to the Swift compiler. We omit
59-
/// prefixing these arguments (in both the "-option value" and
60-
/// "-option[=]value" forms) with "-Xlinker". All other arguments are
61-
/// prefixed with "-Xlinker".
62-
func asSwiftcLinkerFlags() -> Self {
63-
// Arguments that can be passed directly to the Swift compiler and
64-
// doesn't require -Xlinker prefix.
65-
//
66-
// We do this to avoid sending flags like linker search path at the end
67-
// of the search list.
68-
let directSwiftLinkerArgs = ["-L"]
69-
70-
var flags: [String] = []
71-
var it = self.makeIterator()
72-
while let flag = it.next() {
73-
if directSwiftLinkerArgs.contains(flag) {
74-
// `<option> <value>` variant.
75-
flags.append(flag)
76-
guard let nextFlag = it.next() else {
77-
// We expected a flag but don't have one.
78-
continue
79-
}
80-
flags.append(nextFlag)
81-
} else if directSwiftLinkerArgs.contains(where: { flag.hasPrefix($0) }) {
82-
// `<option>[=]<value>` variant.
83-
flags.append(flag)
84-
} else {
85-
flags += ["-Xlinker", flag]
86-
}
87-
}
88-
return flags
89-
}
90-
}
91-
9239
extension BuildParameters {
9340
/// Returns the directory to be used for module cache.
9441
public var moduleCache: Basics.AbsolutePath {

Sources/SPMBuildCore/BuildParameters/BuildParameters+Linking.swift

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,56 @@ extension BuildParameters {
6363
}
6464
}
6565
}
66+
67+
extension [String] {
68+
/// Converts a set of C compiler flags into an equivalent set to be
69+
/// indirected through the Swift compiler instead.
70+
public func asSwiftcCCompilerFlags() -> Self {
71+
self.flatMap { ["-Xcc", $0] }
72+
}
73+
74+
/// Converts a set of C++ compiler flags into an equivalent set to be
75+
/// indirected through the Swift compiler instead.
76+
public func asSwiftcCXXCompilerFlags() -> Self {
77+
_ = self.flatMap { ["-Xcxx", $0] }
78+
// TODO: Pass -Xcxx flags to swiftc (#6491)
79+
// Remove fatal error when downstream support arrives.
80+
fatalError("swiftc does support -Xcxx flags yet.")
81+
}
82+
83+
/// Converts a set of linker flags into an equivalent set to be indirected
84+
/// through the Swift compiler instead.
85+
///
86+
/// Some arguments can be passed directly to the Swift compiler. We omit
87+
/// prefixing these arguments (in both the "-option value" and
88+
/// "-option[=]value" forms) with "-Xlinker". All other arguments are
89+
/// prefixed with "-Xlinker".
90+
public func asSwiftcLinkerFlags() -> Self {
91+
// Arguments that can be passed directly to the Swift compiler and
92+
// doesn't require -Xlinker prefix.
93+
//
94+
// We do this to avoid sending flags like linker search path at the end
95+
// of the search list.
96+
let directSwiftLinkerArgs = ["-L"]
97+
98+
var flags: [String] = []
99+
var it = self.makeIterator()
100+
while let flag = it.next() {
101+
if directSwiftLinkerArgs.contains(flag) {
102+
// `<option> <value>` variant.
103+
flags.append(flag)
104+
guard let nextFlag = it.next() else {
105+
// We expected a flag but don't have one.
106+
continue
107+
}
108+
flags.append(nextFlag)
109+
} else if directSwiftLinkerArgs.contains(where: { flag.hasPrefix($0) }) {
110+
// `<option>[=]<value>` variant.
111+
flags.append(flag)
112+
} else {
113+
flags += ["-Xlinker", flag]
114+
}
115+
}
116+
return flags
117+
}
118+
}

Sources/SwiftBuildSupport/SwiftBuildSystem.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -686,8 +686,8 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem {
686686
settings["OTHER_LDFLAGS"] = (
687687
verboseFlag + // clang will be invoked to link so the verbose flag is valid for it
688688
["$(inherited)"]
689-
+ buildParameters.toolchain.extraFlags.linkerFlags.map { $0.shellEscaped() }
690-
+ buildParameters.flags.linkerFlags.map { $0.shellEscaped() }
689+
+ buildParameters.toolchain.extraFlags.linkerFlags.asSwiftcLinkerFlags().map { $0.shellEscaped() }
690+
+ buildParameters.flags.linkerFlags.asSwiftcLinkerFlags().map { $0.shellEscaped() }
691691
).joined(separator: " ")
692692

693693
// Optionally also set the list of architectures to build for.

0 commit comments

Comments
 (0)