Skip to content

Commit 5ad71d5

Browse files
committed
Fix duplicated swiftc flags when using custom sdks
- Fixes a bug which caused extraCLIFlags from an SDK's toolset.json files to be repeated multiple times in child process invocations. The repeated flags can cause issues with some downstream tools, such as repeated -segaddr flags to ld64 for the same segment.
1 parent dce5590 commit 5ad71d5

File tree

9 files changed

+243
-73
lines changed

9 files changed

+243
-73
lines changed

Sources/Build/BuildDescription/ClangTargetBuildDescription.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -235,12 +235,14 @@ public final class ClangTargetBuildDescription {
235235
args += ["-include", resourceAccessorHeaderFile.pathString]
236236
}
237237

238-
args += buildParameters.toolchain.extraFlags.cCompilerFlags
239-
// User arguments (from -Xcc and -Xcxx below) should follow generated arguments to allow user overrides
240-
args += buildParameters.flags.cCompilerFlags
238+
args += self.buildParameters.toolchain.extraFlags.cCompilerFlags
239+
// User arguments (from -Xcc) should follow generated arguments to allow user overrides
240+
args += self.buildParameters.flags.cCompilerFlags
241241

242242
// Add extra C++ flags if this target contains C++ files.
243-
if clangTarget.isCXX {
243+
if isCXX {
244+
args += self.buildParameters.toolchain.extraFlags.cxxCompilerFlags
245+
// User arguments (from -Xcxx) should follow generated arguments to allow user overrides
244246
args += self.buildParameters.flags.cxxCompilerFlags
245247
}
246248
return args

Sources/Build/BuildDescription/ProductBuildDescription.swift

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,11 @@ public final class ProductBuildDescription: SPMBuildCore.ProductBuildDescription
151151
args += self.buildParameters.sanitizers.linkSwiftFlags()
152152
args += self.additionalFlags
153153

154+
// pass `-v` during verbose builds.
155+
if self.buildParameters.verboseOutput {
156+
args += ["-v"]
157+
}
158+
154159
// Pass `-g` during a *release* build so the Swift driver emits a dSYM file for the binary.
155160
if self.buildParameters.configuration == .release {
156161
if self.buildParameters.triple.isWindows() {
@@ -304,9 +309,12 @@ public final class ProductBuildDescription: SPMBuildCore.ProductBuildDescription
304309
args += self.swiftASTs.flatMap { ["-Xlinker", "-add_ast_path", "-Xlinker", $0.pathString] }
305310

306311
args += self.buildParameters.toolchain.extraFlags.swiftCompilerFlags
307-
// User arguments (from -Xlinker and -Xswiftc) should follow generated arguments to allow user overrides
308-
args += self.buildParameters.linkerFlags
309-
args += self.stripInvalidArguments(self.buildParameters.swiftCompilerFlags)
312+
// User arguments (from -Xswiftc) should follow generated arguments to allow user overrides
313+
args += self.buildParameters.flags.swiftCompilerFlags
314+
315+
args += self.buildParameters.toolchain.extraFlags.linkerFlags.asSwiftcLinkerFlags()
316+
// User arguments (from -Xlinker) should follow generated arguments to allow user overrides
317+
args += self.buildParameters.flags.linkerFlags.asSwiftcLinkerFlags()
310318

311319
// Add toolchain's libdir at the very end (even after the user -Xlinker arguments).
312320
//
@@ -323,7 +331,7 @@ public final class ProductBuildDescription: SPMBuildCore.ProductBuildDescription
323331
}
324332
#endif
325333

326-
return args
334+
return self.stripInvalidArguments(args)
327335
}
328336

329337
/// Writes link filelist to the filesystem.

Sources/Build/BuildDescription/SwiftTargetBuildDescription.swift

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,11 @@ public final class SwiftTargetBuildDescription {
424424
args += try self.buildParameters.targetTripleArgs(for: self.target)
425425
args += ["-swift-version", self.swiftVersion.rawValue]
426426

427+
// pass `-v` during verbose builds.
428+
if self.buildParameters.verboseOutput {
429+
args += ["-v"]
430+
}
431+
427432
// Enable batch mode in debug mode.
428433
//
429434
// Technically, it should be enabled whenever WMO is off but we
@@ -506,7 +511,15 @@ public final class SwiftTargetBuildDescription {
506511

507512
args += self.buildParameters.toolchain.extraFlags.swiftCompilerFlags
508513
// User arguments (from -Xswiftc) should follow generated arguments to allow user overrides
509-
args += self.buildParameters.swiftCompilerFlags
514+
args += self.buildParameters.flags.swiftCompilerFlags
515+
516+
args += self.buildParameters.toolchain.extraFlags.cCompilerFlags.asSwiftcCCompilerFlags()
517+
// User arguments (from -Xcc) should follow generated arguments to allow user overrides
518+
args += self.buildParameters.flags.cCompilerFlags.asSwiftcCCompilerFlags()
519+
520+
args += self.buildParameters.toolchain.extraFlags.cxxCompilerFlags.asSwiftcCXXCompilerFlags()
521+
// User arguments (from -Xcxx) should follow generated arguments to allow user overrides
522+
args += self.buildParameters.flags.cxxCompilerFlags.asSwiftcCXXCompilerFlags()
510523

511524
// suppress warnings if the package is remote
512525
if self.package.isRemote {
@@ -621,6 +634,11 @@ public final class SwiftTargetBuildDescription {
621634
var result: [String] = []
622635
result.append(self.buildParameters.toolchain.swiftCompilerPath.pathString)
623636

637+
// pass `-v` during verbose builds.
638+
if self.buildParameters.verboseOutput {
639+
result += ["-v"]
640+
}
641+
624642
result.append("-module-name")
625643
result.append(self.target.c99name)
626644
result.append(contentsOf: packageNameArgumentIfSupported(with: self.package, packageAccess: self.target.packageAccess))
@@ -656,8 +674,19 @@ public final class SwiftTargetBuildDescription {
656674
result += self.buildParameters.sanitizers.compileSwiftFlags()
657675
result += ["-parseable-output"]
658676
result += try self.buildSettingsFlags()
677+
659678
result += self.buildParameters.toolchain.extraFlags.swiftCompilerFlags
660-
result += self.buildParameters.swiftCompilerFlags
679+
// User arguments (from -Xswiftc) should follow generated arguments to allow user overrides
680+
result += self.buildParameters.flags.swiftCompilerFlags
681+
682+
result += self.buildParameters.toolchain.extraFlags.cCompilerFlags.asSwiftcCCompilerFlags()
683+
// User arguments (from -Xcc) should follow generated arguments to allow user overrides
684+
result += self.buildParameters.flags.cCompilerFlags.asSwiftcCCompilerFlags()
685+
686+
result += self.buildParameters.toolchain.extraFlags.cxxCompilerFlags.asSwiftcCXXCompilerFlags()
687+
// User arguments (from -Xcxx) should follow generated arguments to allow user overrides
688+
result += self.buildParameters.flags.cxxCompilerFlags.asSwiftcCXXCompilerFlags()
689+
661690
result += try self.macroArguments()
662691
return result
663692
}

Sources/Build/BuildPlan.swift

Lines changed: 38 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -42,58 +42,70 @@ extension AbsolutePath {
4242
}
4343
}
4444

45-
extension BuildParameters {
46-
/// Returns the directory to be used for module cache.
47-
public var moduleCache: AbsolutePath {
48-
get throws {
49-
// FIXME: We use this hack to let swiftpm's functional test use shared
50-
// cache so it doesn't become painfully slow.
51-
if let path = ProcessEnv.vars["SWIFTPM_TESTS_MODULECACHE"] {
52-
return try AbsolutePath(validating: path)
53-
}
54-
return buildPath.appending("ModuleCache")
55-
}
45+
extension Array where Element == String {
46+
/// Converts a set of C compiler flags into an equivalent set to be
47+
/// indirected through the Swift compiler instead.
48+
func asSwiftcCCompilerFlags() -> Self {
49+
self.flatMap { ["-Xcc", $0] }
5650
}
5751

58-
/// Extra flags to pass to Swift compiler.
59-
public var swiftCompilerFlags: [String] {
60-
var flags = self.flags.cCompilerFlags.flatMap({ ["-Xcc", $0] })
61-
flags += self.flags.swiftCompilerFlags
62-
if self.verboseOutput {
63-
flags.append("-v")
64-
}
65-
return flags
52+
/// Converts a set of C++ compiler flags into an equivalent set to be
53+
/// indirected through the Swift compiler instead.
54+
func asSwiftcCXXCompilerFlags() -> Self {
55+
self.flatMap { ["-Xcc", $0] }
6656
}
6757

68-
/// Extra flags to pass to linker.
69-
public var linkerFlags: [String] {
58+
/// Converts a set of linker flags into an equivalent set to be indirected
59+
/// through the Swift compiler instead.
60+
///
61+
/// Some arguments can be passed directly to the Swift compiler. We omit
62+
/// prefixing these arguments (in both the "-option value" and
63+
/// "-option[=]value" forms) with "-Xlinker". All other arguments are
64+
/// prefixed with "-Xlinker".
65+
func asSwiftcLinkerFlags() -> Self {
7066
// Arguments that can be passed directly to the Swift compiler and
7167
// doesn't require -Xlinker prefix.
7268
//
7369
// We do this to avoid sending flags like linker search path at the end
7470
// of the search list.
75-
let directSwiftLinkerArgs = ["-L"]
71+
let directSwiftLinkerArgs = [
72+
"-L"
73+
]
7674

7775
var flags: [String] = []
78-
var it = self.flags.linkerFlags.makeIterator()
76+
var it = self.makeIterator()
7977
while let flag = it.next() {
8078
if directSwiftLinkerArgs.contains(flag) {
81-
// `-L <value>` variant.
79+
// `<option> <value>` variant.
8280
flags.append(flag)
8381
guard let nextFlag = it.next() else {
8482
// We expected a flag but don't have one.
8583
continue
8684
}
8785
flags.append(nextFlag)
8886
} else if directSwiftLinkerArgs.contains(where: { flag.hasPrefix($0) }) {
89-
// `-L<value>` variant.
87+
// `<option>[=]<value>` variant.
9088
flags.append(flag)
9189
} else {
9290
flags += ["-Xlinker", flag]
9391
}
9492
}
9593
return flags
9694
}
95+
}
96+
97+
extension BuildParameters {
98+
/// Returns the directory to be used for module cache.
99+
public var moduleCache: AbsolutePath {
100+
get throws {
101+
// FIXME: We use this hack to let swiftpm's functional test use shared
102+
// cache so it doesn't become painfully slow.
103+
if let path = ProcessEnv.vars["SWIFTPM_TESTS_MODULECACHE"] {
104+
return try AbsolutePath(validating: path)
105+
}
106+
return buildPath.appending("ModuleCache")
107+
}
108+
}
97109

98110
/// Returns the compiler arguments for the index store, if enabled.
99111
func indexStoreArguments(for target: ResolvedTarget) -> [String] {
@@ -147,7 +159,7 @@ extension BuildParameters {
147159
else {
148160
return nil
149161
}
150-
return args.flatMap { ["-Xlinker", $0] }
162+
return args.asSwiftcLinkerFlags()
151163
}
152164

153165
/// Returns the scoped view of build settings for a given target.

Sources/CoreCommands/SwiftTool.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -680,15 +680,13 @@ public final class SwiftTool {
680680
let dataPath = self.scratchDirectory.appending(
681681
component: destinationTriple.platformBuildPathComponent(buildSystem: options.build.buildSystem)
682682
)
683-
var buildFlags = options.build.buildFlags
684-
buildFlags.append(destinationToolchain.extraFlags)
685683

686684
return try BuildParameters(
687685
dataPath: dataPath,
688686
configuration: options.build.configuration,
689687
toolchain: destinationToolchain,
690688
destinationTriple: destinationTriple,
691-
flags: buildFlags,
689+
flags: options.build.buildFlags,
692690
pkgConfigDirectories: options.locations.pkgConfigDirectories,
693691
architectures: options.build.architectures,
694692
workers: options.build.jobs ?? UInt32(ProcessInfo.processInfo.activeProcessorCount),

Sources/PackageModel/BuildFlags.swift

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -40,20 +40,4 @@ public struct BuildFlags: Equatable, Encodable {
4040
self.linkerFlags = linkerFlags
4141
self.xcbuildFlags = xcbuildFlags
4242
}
43-
44-
/// Appends corresponding properties of a different `BuildFlags` value into `self`.
45-
/// - Parameter buildFlags: a `BuildFlags` value to merge flags from.
46-
public mutating func append(_ buildFlags: BuildFlags) {
47-
cCompilerFlags += buildFlags.cCompilerFlags
48-
cxxCompilerFlags += buildFlags.cxxCompilerFlags
49-
swiftCompilerFlags += buildFlags.swiftCompilerFlags
50-
linkerFlags += buildFlags.linkerFlags
51-
52-
if var xcbuildFlags, let newXcbuildFlags = buildFlags.xcbuildFlags {
53-
xcbuildFlags += newXcbuildFlags
54-
self.xcbuildFlags = xcbuildFlags
55-
} else if let xcbuildFlags = buildFlags.xcbuildFlags {
56-
self.xcbuildFlags = xcbuildFlags
57-
}
58-
}
5943
}

Sources/PackageModel/UserToolchain.swift

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -463,13 +463,15 @@ public final class UserToolchain: Toolchain {
463463
}
464464

465465
self.triple = triple
466-
self.extraFlags = BuildFlags()
467-
468-
self.extraFlags.swiftCompilerFlags = try Self.deriveSwiftCFlags(
469-
triple: triple,
470-
destination: destination,
471-
environment: environment
472-
)
466+
self.extraFlags = BuildFlags(
467+
cCompilerFlags: destination.toolset.knownTools[.cCompiler]?.extraCLIOptions ?? [],
468+
cxxCompilerFlags: destination.toolset.knownTools[.cxxCompiler]?.extraCLIOptions ?? [],
469+
swiftCompilerFlags: try Self.deriveSwiftCFlags(
470+
triple: triple,
471+
destination: destination,
472+
environment: environment),
473+
linkerFlags: destination.toolset.knownTools[.linker]?.extraCLIOptions ?? [],
474+
xcbuildFlags: destination.toolset.knownTools[.xcbuild]?.extraCLIOptions ?? [])
473475

474476
self.librarianPath = try UserToolchain.determineLibrarian(
475477
triple: triple,
@@ -481,14 +483,8 @@ public final class UserToolchain: Toolchain {
481483
)
482484

483485
if let sdkDir = destination.pathsConfiguration.sdkRootPath {
484-
self.extraFlags.cCompilerFlags = [
485-
triple.isDarwin() ? "-isysroot" : "--sysroot", sdkDir.pathString,
486-
] + (destination.toolset.knownTools[.cCompiler]?.extraCLIOptions ?? [])
487-
488-
self.extraFlags.cxxCompilerFlags = destination.toolset.knownTools[.cxxCompiler]?.extraCLIOptions ?? []
489-
} else {
490-
self.extraFlags.cCompilerFlags = (destination.toolset.knownTools[.cCompiler]?.extraCLIOptions ?? [])
491-
self.extraFlags.cxxCompilerFlags = (destination.toolset.knownTools[.cxxCompiler]?.extraCLIOptions ?? [])
486+
let sysrootFlags = [triple.isDarwin() ? "-isysroot" : "--sysroot", sdkDir.pathString]
487+
self.extraFlags.cCompilerFlags.insert(contentsOf: sysrootFlags, at: 0)
492488
}
493489

494490
if triple.isWindows() {

Sources/XCBuildSupport/XcodeBuildSystem.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,21 +193,22 @@ public final class XcodeBuildSystem: SPMBuildCore.BuildSystem {
193193
settings["LIBRARY_SEARCH_PATHS"] = "$(inherited) \(try buildParameters.toolchain.toolchainLibDir.pathString)"
194194
settings["OTHER_CFLAGS"] = (
195195
["$(inherited)"]
196-
+ buildParameters.toolchain.extraFlags.cCompilerFlags
196+
+ buildParameters.toolchain.extraFlags.cCompilerFlags.map { $0.spm_shellEscaped() }
197197
+ buildParameters.flags.cCompilerFlags.map { $0.spm_shellEscaped() }
198198
).joined(separator: " ")
199199
settings["OTHER_CPLUSPLUSFLAGS"] = (
200200
["$(inherited)"]
201-
+ buildParameters.toolchain.extraFlags.cxxCompilerFlags
201+
+ buildParameters.toolchain.extraFlags.cxxCompilerFlags.map { $0.spm_shellEscaped() }
202202
+ buildParameters.flags.cxxCompilerFlags.map { $0.spm_shellEscaped() }
203203
).joined(separator: " ")
204204
settings["OTHER_SWIFT_FLAGS"] = (
205205
["$(inherited)"]
206-
+ buildParameters.toolchain.extraFlags.swiftCompilerFlags
206+
+ buildParameters.toolchain.extraFlags.swiftCompilerFlags.map { $0.spm_shellEscaped() }
207207
+ buildParameters.flags.swiftCompilerFlags.map { $0.spm_shellEscaped() }
208208
).joined(separator: " ")
209209
settings["OTHER_LDFLAGS"] = (
210210
["$(inherited)"]
211+
+ buildParameters.toolchain.extraFlags.linkerFlags.map { $0.spm_shellEscaped() }
211212
+ buildParameters.flags.linkerFlags.map { $0.spm_shellEscaped() }
212213
).joined(separator: " ")
213214

0 commit comments

Comments
 (0)