Skip to content

Commit cf727a8

Browse files
authored
Keep separate build parameters for host and target (#7164)
Unblocks support for macros in cross-compilation implemented in #7118. ### Motivation: So far we used a single `BuildParameters` value for the whole build graph, which explicitly mentioned both host and target triples, but assumed you can use the same toolchain for both, which is not true. Additionally, it would assume that all other build parameters can be shared between the host and target, like debug info format, build configuration, sanitizers etc. That's not true either, one would use CodeView for build tools on Windows when cross-compiling products with DWARF for Linux, or build macros in release mode for performance while cross-compiling code that uses debug build configuration. ### Modifications: Removed `hostTriple` and `targetTriple` from `BuildParameters`, keeping only a single `triple` property of `Triple` type in it. In `SwiftTool` and `BuildPlan` we'll use two separate `destinationBuildParameters` and `toolsBuildParameters` instead. The latter will pick one of the two `BuildParameters` values for specific target and product build descriptions. ### Result: We can compile build tools for the host, while cross-compiling end products for the target, in the same build graph. This also removes one of big roadblocks in folding build tool and package plugins into the build graph, instead of building and invoking them separately outside of the build graph.
1 parent 20b86fe commit cf727a8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1024
-500
lines changed

Sources/Build/BuildDescription/ClangTargetBuildDescription.swift

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ public final class ClangTargetBuildDescription {
216216

217217
var args = [String]()
218218
// Only enable ARC on macOS.
219-
if buildParameters.targetTriple.isDarwin() {
219+
if self.buildParameters.triple.isDarwin() {
220220
args += ["-fobjc-arc"]
221221
}
222222
args += try buildParameters.targetTripleArgs(for: target)
@@ -225,32 +225,33 @@ public final class ClangTargetBuildDescription {
225225
args += activeCompilationConditions
226226
args += ["-fblocks"]
227227

228+
let buildTriple = self.buildParameters.triple
228229
// Enable index store, if appropriate.
229230
//
230231
// This feature is not widely available in OSS clang. So, we only enable
231232
// index store for Apple's clang or if explicitly asked to.
232233
if ProcessEnv.vars.keys.contains("SWIFTPM_ENABLE_CLANG_INDEX_STORE") {
233-
args += buildParameters.indexStoreArguments(for: target)
234-
} else if buildParameters.targetTriple.isDarwin(),
235-
(try? buildParameters.toolchain._isClangCompilerVendorApple()) == true
234+
args += self.buildParameters.indexStoreArguments(for: target)
235+
} else if buildTriple.isDarwin(),
236+
(try? self.buildParameters.toolchain._isClangCompilerVendorApple()) == true
236237
{
237-
args += buildParameters.indexStoreArguments(for: target)
238+
args += self.buildParameters.indexStoreArguments(for: target)
238239
}
239240

240241
// Enable Clang module flags, if appropriate.
241242
let enableModules: Bool
243+
let triple = self.buildParameters.triple
242244
if toolsVersion < .v5_8 {
243245
// For version < 5.8, we enable them except in these cases:
244246
// 1. on Darwin when compiling for C++, because C++ modules are disabled on Apple-built Clang releases
245247
// 2. on Windows when compiling for any language, because of issues with the Windows SDK
246248
// 3. on Android when compiling for any language, because of issues with the Android SDK
247-
enableModules = !(buildParameters.targetTriple.isDarwin() && isCXX) && !buildParameters.targetTriple
248-
.isWindows() && !buildParameters.targetTriple.isAndroid()
249+
enableModules = !(triple.isDarwin() && isCXX) && !triple.isWindows() && !triple.isAndroid()
249250
} else {
250251
// For version >= 5.8, we disable them when compiling for C++ regardless of platforms, see:
251252
// https://github.com/llvm/llvm-project/issues/55980 for clang frontend crash when module
252253
// enabled for C++ on c++17 standard and above.
253-
enableModules = !isCXX && !buildParameters.targetTriple.isWindows() && !buildParameters.targetTriple.isAndroid()
254+
enableModules = !isCXX && !triple.isWindows() && !triple.isAndroid()
254255
}
255256

256257
if enableModules {

Sources/Build/BuildDescription/ProductBuildDescription.swift

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -110,15 +110,16 @@ public final class ProductBuildDescription: SPMBuildCore.ProductBuildDescription
110110
return []
111111
}
112112

113+
let triple = self.buildParameters.triple
113114
switch self.buildParameters.configuration {
114115
case .debug:
115116
return []
116117
case .release:
117-
if self.buildParameters.targetTriple.isApple() {
118+
if triple.isApple() {
118119
return ["-Xlinker", "-dead_strip"]
119-
} else if self.buildParameters.targetTriple.isWindows() {
120+
} else if triple.isWindows() {
120121
return ["-Xlinker", "/OPT:REF"]
121-
} else if self.buildParameters.targetTriple.arch == .wasm32 {
122+
} else if triple.arch == .wasm32 {
122123
// FIXME: wasm-ld strips data segments referenced through __start/__stop symbols
123124
// during GC, and it removes Swift metadata sections like swift5_protocols
124125
// We should add support of SHF_GNU_RETAIN-like flag for __attribute__((retain))
@@ -136,7 +137,7 @@ public final class ProductBuildDescription: SPMBuildCore.ProductBuildDescription
136137
/// The arguments to the librarian to create a static library.
137138
public func archiveArguments() throws -> [String] {
138139
let librarian = self.buildParameters.toolchain.librarianPath.pathString
139-
let triple = self.buildParameters.targetTriple
140+
let triple = self.buildParameters.triple
140141
if triple.isWindows(), librarian.hasSuffix("link") || librarian.hasSuffix("link.exe") {
141142
return try [librarian, "/LIB", "/OUT:\(binaryPath.pathString)", "@\(self.linkFileListPath.pathString)"]
142143
}
@@ -187,6 +188,7 @@ public final class ProductBuildDescription: SPMBuildCore.ProductBuildDescription
187188
}
188189

189190
var isLinkingStaticStdlib = false
191+
let triple = self.buildParameters.triple
190192
switch derivedProductType {
191193
case .macro:
192194
throw InternalError("macro not supported") // should never be reached
@@ -206,7 +208,7 @@ public final class ProductBuildDescription: SPMBuildCore.ProductBuildDescription
206208
args += self.deadStripArguments
207209
case .library(.dynamic):
208210
args += ["-emit-library"]
209-
if self.buildParameters.targetTriple.isDarwin() {
211+
if triple.isDarwin() {
210212
let relativePath = try "@rpath/\(buildParameters.binaryRelativePath(for: self.product).pathString)"
211213
args += ["-Xlinker", "-install_name", "-Xlinker", relativePath]
212214
}
@@ -215,9 +217,9 @@ public final class ProductBuildDescription: SPMBuildCore.ProductBuildDescription
215217
// Link the Swift stdlib statically, if requested.
216218
// TODO: unify this logic with SwiftTargetBuildDescription.stdlibArguments
217219
if self.buildParameters.linkingParameters.shouldLinkStaticSwiftStdlib {
218-
if self.buildParameters.targetTriple.isDarwin() {
220+
if triple.isDarwin() {
219221
self.observabilityScope.emit(.swiftBackDeployError)
220-
} else if self.buildParameters.targetTriple.isSupportingStaticStdlib {
222+
} else if triple.isSupportingStaticStdlib {
221223
args += ["-static-stdlib"]
222224
isLinkingStaticStdlib = true
223225
}
@@ -260,9 +262,9 @@ public final class ProductBuildDescription: SPMBuildCore.ProductBuildDescription
260262
// Set rpath such that dynamic libraries are looked up
261263
// adjacent to the product, unless overridden.
262264
if !self.buildParameters.linkingParameters.shouldDisableLocalRpath {
263-
if self.buildParameters.targetTriple.isLinux() {
265+
if triple.isLinux() {
264266
args += ["-Xlinker", "-rpath=$ORIGIN"]
265-
} else if self.buildParameters.targetTriple.isDarwin() {
267+
} else if triple.isDarwin() {
266268
let rpath = self.product.type == .test ? "@loader_path/../../../" : "@loader_path"
267269
args += ["-Xlinker", "-rpath", "-Xlinker", rpath]
268270
}
@@ -283,7 +285,7 @@ public final class ProductBuildDescription: SPMBuildCore.ProductBuildDescription
283285

284286
// When deploying to macOS prior to macOS 12, add an rpath to the
285287
// back-deployed concurrency libraries.
286-
if useStdlibRpath, self.buildParameters.targetTriple.isMacOSX {
288+
if useStdlibRpath, triple.isMacOSX {
287289
let macOSSupportedPlatform = self.package.platforms.getDerived(for: .macOS, usingXCTest: product.isLinkingXCTest)
288290
if macOSSupportedPlatform.version.major < 12 {
289291
let backDeployedStdlib = try buildParameters.toolchain.macosSwiftStdlib
@@ -361,7 +363,7 @@ public final class ProductBuildDescription: SPMBuildCore.ProductBuildDescription
361363
flags += libraries.map { "-l" + $0 }
362364

363365
// Linked frameworks.
364-
if self.buildParameters.targetTriple.supportsFrameworks {
366+
if self.buildParameters.triple.supportsFrameworks {
365367
let frameworks = OrderedSet(self.staticTargets.reduce([]) {
366368
$0 + self.buildParameters.createScope(for: $1).evaluate(.LINK_FRAMEWORKS)
367369
})

Sources/Build/BuildDescription/SwiftTargetBuildDescription.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,8 @@ public final class SwiftTargetBuildDescription {
110110
/// The path to the swiftmodule file after compilation.
111111
public var moduleOutputPath: AbsolutePath { // note: needs to be public because of sourcekit-lsp
112112
// If we're an executable and we're not allowing test targets to link against us, we hide the module.
113-
let allowLinkingAgainstExecutables = (buildParameters.targetTriple.isDarwin() || self.buildParameters.targetTriple
114-
.isLinux() || self.buildParameters.targetTriple.isWindows()) && self.toolsVersion >= .v5_5
113+
let triple = buildParameters.triple
114+
let allowLinkingAgainstExecutables = (triple.isDarwin() || triple.isLinux() || triple.isWindows()) && self.toolsVersion >= .v5_5
115115
let dirPath = (target.type == .executable && !allowLinkingAgainstExecutables) ? self.tempsPath : self.modulesPath
116116
return dirPath.appending(component: self.target.c99name + ".swiftmodule")
117117
}
@@ -320,7 +320,7 @@ public final class SwiftTargetBuildDescription {
320320
return
321321
}
322322

323-
guard buildParameters.targetTriple.isDarwin(), buildParameters.testingParameters.experimentalTestOutput else {
323+
guard self.buildParameters.triple.isDarwin(), self.buildParameters.testingParameters.experimentalTestOutput else {
324324
return
325325
}
326326

@@ -364,7 +364,7 @@ public final class SwiftTargetBuildDescription {
364364
guard let bundlePath else { return }
365365

366366
let mainPathSubstitution: String
367-
if self.buildParameters.targetTriple.isWASI() {
367+
if self.buildParameters.triple.isWASI() {
368368
// We prefer compile-time evaluation of the bundle path here for WASI. There's no benefit in evaluating this
369369
// at runtime, especially as `Bundle` support in WASI Foundation is partial. We expect all resource paths to
370370
// evaluate to `/\(resourceBundleName)/\(resourcePath)`, which allows us to pass this path to JS APIs like
@@ -649,7 +649,7 @@ public final class SwiftTargetBuildDescription {
649649

650650
/// Returns true if ObjC compatibility header should be emitted.
651651
private var shouldEmitObjCCompatibilityHeader: Bool {
652-
self.buildParameters.targetTriple.isDarwin() && self.target.type == .library
652+
self.buildParameters.triple.isDarwin() && self.target.type == .library
653653
}
654654

655655
func writeOutputFileMap() throws -> AbsolutePath {
@@ -852,7 +852,7 @@ public final class SwiftTargetBuildDescription {
852852
var arguments: [String] = []
853853

854854
let isLinkingStaticStdlib = self.buildParameters.linkingParameters.shouldLinkStaticSwiftStdlib
855-
&& self.buildParameters.targetTriple.isSupportingStaticStdlib
855+
&& self.buildParameters.triple.isSupportingStaticStdlib
856856
if isLinkingStaticStdlib {
857857
arguments += ["-static-stdlib"]
858858
}

Sources/Build/BuildDescription/TargetBuildDescription.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
import Basics
14+
import struct SPMBuildCore.BuildParameters
1415
import class PackageGraph.ResolvedTarget
1516
import struct PackageModel.Resource
1617
import struct SPMBuildCore.BuildToolPluginInvocationResult
@@ -91,4 +92,13 @@ public enum TargetBuildDescription {
9192
return target.buildToolPluginInvocationResults
9293
}
9394
}
95+
96+
var buildParameters: BuildParameters {
97+
switch self {
98+
case .swift(let swiftTargetBuildDescription):
99+
return swiftTargetBuildDescription.buildParameters
100+
case .clang(let clangTargetBuildDescription):
101+
return clangTargetBuildDescription.buildParameters
102+
}
103+
}
94104
}

Sources/Build/BuildManifest/LLBuildManifestBuilder+Clang.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ extension LLBuildManifestBuilder {
4242
}
4343
}
4444

45-
for dependency in target.target.dependencies(satisfying: self.buildEnvironment) {
45+
for dependency in target.target.dependencies(satisfying: target.buildEnvironment) {
4646
switch dependency {
4747
case .target(let target, _):
4848
addStaticTargetInputs(target)
@@ -68,7 +68,7 @@ extension LLBuildManifestBuilder {
6868
}
6969

7070
for binaryPath in target.libraryBinaryPaths {
71-
let path = destinationPath(forBinaryAt: binaryPath)
71+
let path = target.buildParameters.destinationPath(forBinaryAt: binaryPath)
7272
if self.fileSystem.isDirectory(binaryPath) {
7373
inputs.append(directory: path)
7474
} else {
@@ -97,7 +97,7 @@ extension LLBuildManifestBuilder {
9797

9898
args += ["-c", path.source.pathString, "-o", path.object.pathString]
9999

100-
let clangCompiler = try buildParameters.toolchain.getClangCompiler().pathString
100+
let clangCompiler = try target.buildParameters.toolchain.getClangCompiler().pathString
101101
args.insert(clangCompiler, at: 0)
102102

103103
let objectFileNode: Node = .file(path.object)
@@ -116,7 +116,7 @@ extension LLBuildManifestBuilder {
116116
try addBuildToolPlugins(.clang(target))
117117

118118
// Create a phony node to represent the entire target.
119-
let targetName = target.target.getLLBuildTargetName(config: self.buildConfig)
119+
let targetName = target.target.getLLBuildTargetName(config: target.buildParameters.buildConfig)
120120
let output: Node = .virtual(targetName)
121121

122122
self.manifest.addNode(output, toTarget: targetName)
@@ -126,7 +126,7 @@ extension LLBuildManifestBuilder {
126126
outputs: [output]
127127
)
128128

129-
if self.plan.graph.isInRootPackages(target.target, satisfying: self.buildEnvironment) {
129+
if self.plan.graph.isInRootPackages(target.target, satisfying: target.buildParameters.buildEnvironment) {
130130
if !target.isTestTarget {
131131
self.addNode(output, toTarget: .main)
132132
}

Sources/Build/BuildManifest/LLBuildManifestBuilder+Product.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ import struct LLBuildManifest.Node
1515

1616
extension LLBuildManifestBuilder {
1717
func createProductCommand(_ buildProduct: ProductBuildDescription) throws {
18-
let cmdName = try buildProduct.product.getCommandName(config: self.buildConfig)
18+
let cmdName = try buildProduct.product.getCommandName(config: buildProduct.buildParameters.buildConfig)
1919

2020
// Add dependency on Info.plist generation on Darwin platforms.
2121
let testInputs: [AbsolutePath]
2222
if buildProduct.product.type == .test
23-
&& buildProduct.buildParameters.targetTriple.isDarwin()
23+
&& buildProduct.buildParameters.triple.isDarwin()
2424
&& buildProduct.buildParameters.testingParameters.experimentalTestOutput {
2525
let testBundleInfoPlistPath = try buildProduct.binaryPath.parentDirectory.parentDirectory.appending(component: "Info.plist")
2626
testInputs = [testBundleInfoPlistPath]
@@ -34,7 +34,7 @@ extension LLBuildManifestBuilder {
3434
}
3535

3636
// Create a phony node to represent the entire target.
37-
let targetName = try buildProduct.product.getLLBuildTargetName(config: self.buildConfig)
37+
let targetName = try buildProduct.product.getLLBuildTargetName(config: buildProduct.buildParameters.buildConfig)
3838
let output: Node = .virtual(targetName)
3939

4040
let finalProductNode: Node
@@ -59,8 +59,8 @@ extension LLBuildManifestBuilder {
5959
let linkedBinaryNode: Node
6060
let linkedBinaryPath = try buildProduct.binaryPath
6161
if case .executable = buildProduct.product.type,
62-
buildParameters.targetTriple.isMacOSX,
63-
buildParameters.debuggingParameters.shouldEnableDebuggingEntitlement {
62+
buildProduct.buildParameters.triple.isMacOSX,
63+
buildProduct.buildParameters.debuggingParameters.shouldEnableDebuggingEntitlement {
6464
shouldCodeSign = true
6565
linkedBinaryNode = try .file(buildProduct.binaryPath, isMutated: true)
6666
} else {
@@ -85,7 +85,7 @@ extension LLBuildManifestBuilder {
8585
outputPath: plistPath
8686
)
8787

88-
let cmdName = try buildProduct.product.getCommandName(config: self.buildConfig)
88+
let cmdName = try buildProduct.product.getCommandName(config: buildProduct.buildParameters.buildConfig)
8989
let codeSigningOutput = Node.virtual(targetName + "-CodeSigning")
9090
try self.manifest.addShellCmd(
9191
name: "\(cmdName)-entitlements",

Sources/Build/BuildManifest/LLBuildManifestBuilder+Resources.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ extension LLBuildManifestBuilder {
4545
outputs.append(output)
4646
}
4747

48-
let cmdName = target.target.getLLBuildResourcesCmdName(config: self.buildConfig)
48+
let cmdName = target.target.getLLBuildResourcesCmdName(config: target.buildParameters.buildConfig)
4949
self.manifest.addPhonyCmd(name: cmdName, inputs: outputs, outputs: [.virtual(cmdName)])
5050

5151
return .virtual(cmdName)

0 commit comments

Comments
 (0)