Skip to content

Commit bb7f039

Browse files
MaxDesiatovgrynspanbnbarhamkateinoigakukunxedin
authored
[6.0] Support macros when cross-compiling (#7640)
**Explanation**: Macros cross-compiled by SwiftPM with Swift SDKs should be correctly built, loaded, and evaluated for the host triple. **Scope**: isolated to modules dependency resolution and llbuild, does not impact code related to XCBuild. **Risk**: medium, known issues were addressed on `main` and are cherry-picked here, with no new issues reported for a few weeks now. **Testing**: added unit tests, manual end-to-end testing done with existing Swift SDKs. **Issue**: rdar://105991372 **Reviewers**: @bnbarham @xedin @neonichu (cherry picked from commit cb3b085, #7353) ``` # Conflicts: # CHANGELOG.md # Sources/Build/BuildDescription/SwiftTargetBuildDescription.swift # Sources/Build/BuildManifest/LLBuildManifestBuilder.swift # Sources/Build/BuildPlan/BuildPlan.swift # Sources/Commands/SwiftTestCommand.swift # Sources/Commands/Utilities/PluginDelegate.swift # Sources/Commands/Utilities/TestingSupport.swift # Sources/PackageGraph/ModulesGraph+Loading.swift # Sources/PackageGraph/ModulesGraph.swift # Sources/SPMTestSupport/MockBuildTestHelper.swift # Sources/SPMTestSupport/MockPackageGraphs.swift # Sources/SPMTestSupport/PackageGraphTester.swift # Sources/SPMTestSupport/ResolvedTarget+Mock.swift # Tests/BuildTests/ClangTargetBuildDescriptionTests.swift # Tests/BuildTests/CrossCompilationBuildPlanTests.swift # Tests/SourceKitLSPAPITests/SourceKitLSPAPITests.swift ``` (cherry picked from commit b9eb3c1, #7493) ``` # Conflicts: # Sources/PackageGraph/ModulesGraph+Loading.swift # Sources/PackageGraph/Resolution/ResolvedPackage.swift ``` (cherry picked from commit 5a4c024, #7508) ``` # Conflicts: # Sources/Commands/SwiftBuildCommand.swift # Sources/Commands/SwiftTestCommand.swift # Sources/Commands/Utilities/TestingSupport.swift ``` (cherry picked from commit 8db2401, #7519) ``` # Conflicts: # Tests/BuildTests/CrossCompilationBuildPlanTests.swift ``` --------- Co-authored-by: Jonathan Grynspan <[email protected]> Co-authored-by: Ben Barham <[email protected]> Co-authored-by: Yuta Saito <[email protected]> Co-authored-by: Pavel Yaskevich <[email protected]>
1 parent 9afe748 commit bb7f039

File tree

66 files changed

+2383
-951
lines changed

Some content is hidden

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

66 files changed

+2383
-951
lines changed

CHANGELOG.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,18 @@ Swift 6.0
2727

2828
`// swift-tools-version:` can now be specified on subsequent lines of `Package.swift`, for example when first few lines are required to contain a licensing comment header.
2929

30+
* [#7118]
31+
32+
Macros cross-compiled by SwiftPM with Swift SDKs are now correctly built, loaded, and evaluated for the host triple.
33+
3034
Swift 5.10
3135
-----------
36+
3237
* [#7010]
3338

3439
On macOS, `swift build` and `swift run` now produce binaries that allow backtraces in debug builds. Pass `SWIFT_BACKTRACE=enable=yes` environment variable to enable backtraces on such binaries when running them.
3540

36-
* [7101]
41+
* [#7101]
3742

3843
Binary artifacts are now cached along side repository checkouts so they do not need to be re-downloaded across projects.
3944

Sources/Basics/Collections/IdentifiableSet.swift

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,22 @@ public struct IdentifiableSet<Element: Identifiable>: Collection {
4747
}
4848

4949
public subscript(id: Element.ID) -> Element? {
50-
self.storage[id]
50+
get {
51+
self.storage[id]
52+
}
53+
set {
54+
self.storage[id] = newValue
55+
}
5156
}
5257

5358
public func index(after i: Index) -> Index {
5459
Index(storageIndex: self.storage.elements.index(after: i.storageIndex))
5560
}
5661

62+
public mutating func insert(_ element: Element) {
63+
self.storage[element.id] = element
64+
}
65+
5766
public func union(_ otherSequence: some Sequence<Element>) -> Self {
5867
var result = self
5968
for element in otherSequence {

Sources/Basics/Errors.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@ public struct InternalError: Error {
2121
private let description: String
2222
public init(_ description: String) {
2323
assertionFailure(description)
24-
self
25-
.description =
24+
self.description =
2625
"Internal error. Please file a bug at https://github.com/apple/swift-package-manager/issues with this info. \(description)"
2726
}
2827
}

Sources/Build/BuildDescription/ClangTargetBuildDescription.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public final class ClangTargetBuildDescription {
5353

5454
/// Path to the bundle generated for this module (if any).
5555
var bundlePath: AbsolutePath? {
56-
guard !resources.isEmpty else {
56+
guard !self.resources.isEmpty else {
5757
return .none
5858
}
5959

@@ -133,7 +133,7 @@ public final class ClangTargetBuildDescription {
133133
self.target = target
134134
self.toolsVersion = toolsVersion
135135
self.buildParameters = buildParameters
136-
self.tempsPath = buildParameters.buildPath.appending(component: target.c99name + ".build")
136+
self.tempsPath = target.tempsPath(buildParameters)
137137
self.derivedSources = Sources(paths: [], root: tempsPath.appending("DerivedSources"))
138138

139139
// We did not use to apply package plugins to C-family targets in prior tools-versions, this preserves the behavior.
@@ -225,7 +225,7 @@ public final class ClangTargetBuildDescription {
225225
if self.buildParameters.triple.isDarwin() {
226226
args += ["-fobjc-arc"]
227227
}
228-
args += try buildParameters.targetTripleArgs(for: target)
228+
args += try self.buildParameters.tripleArgs(for: target)
229229

230230
args += optimizationArguments
231231
args += activeCompilationConditions

Sources/Build/BuildDescription/PluginDescription.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ public final class PluginDescription: Codable {
2929
/// the plugin).
3030
public let targetName: String
3131

32+
/// The language-level target name.
33+
public let targetC99Name: String
34+
3235
/// The names of any plugin products in that package that vend the plugin
3336
/// to other packages.
3437
public let productNames: [String]
@@ -56,6 +59,7 @@ public final class PluginDescription: Codable {
5659

5760
self.package = package.identity
5861
self.targetName = target.name
62+
self.targetC99Name = target.c99name
5963
self.productNames = products.map(\.name)
6064
self.toolsVersion = toolsVersion
6165
self.sources = target.sources

Sources/Build/BuildDescription/ProductBuildDescription.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ public final class ProductBuildDescription: SPMBuildCore.ProductBuildDescription
322322
// setting is the package-level right now. We might need to figure out a better
323323
// answer for libraries if/when we support specifying deployment target at the
324324
// target-level.
325-
args += try self.buildParameters.targetTripleArgs(for: self.product.targets[self.product.targets.startIndex])
325+
args += try self.buildParameters.tripleArgs(for: self.product.targets[self.product.targets.startIndex])
326326

327327
// Add arguments from declared build settings.
328328
args += self.buildSettingsFlags
@@ -357,7 +357,7 @@ public final class ProductBuildDescription: SPMBuildCore.ProductBuildDescription
357357
// Library search path for the toolchain's copy of SwiftSyntax.
358358
#if BUILD_MACROS_AS_DYLIBS
359359
if product.type == .macro {
360-
args += try ["-L", buildParameters.toolchain.hostLibDir.pathString]
360+
args += try ["-L", defaultBuildParameters.toolchain.hostLibDir.pathString]
361361
}
362362
#endif
363363

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift open source project
4+
//
5+
// Copyright (c) 2015-2023 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import struct Basics.AbsolutePath
14+
import struct PackageGraph.ResolvedModule
15+
16+
import SPMBuildCore
17+
18+
extension ResolvedModule {
19+
func tempsPath(_ buildParameters: BuildParameters) -> AbsolutePath {
20+
let suffix = buildParameters.suffix
21+
return buildParameters.buildPath.appending(component: "\(self.c99name)\(suffix).build")
22+
}
23+
}

Sources/Build/BuildDescription/SwiftTargetBuildDescription.swift

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public final class SwiftTargetBuildDescription {
4343
/// a target is built.
4444
public let toolsVersion: ToolsVersion
4545

46-
/// The build parameters.
46+
/// The build parameters for this target.
4747
let buildParameters: BuildParameters
4848

4949
/// Path to the temporary directory for this target.
@@ -63,9 +63,10 @@ public final class SwiftTargetBuildDescription {
6363
/// Path to the bundle generated for this module (if any).
6464
var bundlePath: AbsolutePath? {
6565
if let bundleName = target.underlying.potentialBundleName, needsResourceBundle {
66-
return self.buildParameters.bundlePath(named: bundleName)
66+
let suffix = self.buildParameters.suffix
67+
return self.buildParameters.bundlePath(named: bundleName + suffix)
6768
} else {
68-
return .none
69+
return nil
6970
}
7071
}
7172

@@ -112,7 +113,8 @@ public final class SwiftTargetBuildDescription {
112113
}
113114

114115
var modulesPath: AbsolutePath {
115-
return self.buildParameters.buildPath.appending(component: "Modules")
116+
let suffix = self.buildParameters.suffix
117+
return self.buildParameters.buildPath.appending(component: "Modules\(suffix)")
116118
}
117119

118120
/// The path to the swiftmodule file after compilation.
@@ -121,7 +123,7 @@ public final class SwiftTargetBuildDescription {
121123
let triple = buildParameters.triple
122124
let allowLinkingAgainstExecutables = (triple.isDarwin() || triple.isLinux() || triple.isWindows()) && self.toolsVersion >= .v5_5
123125
let dirPath = (target.type == .executable && !allowLinkingAgainstExecutables) ? self.tempsPath : self.modulesPath
124-
return dirPath.appending(component: self.target.c99name + ".swiftmodule")
126+
return dirPath.appending(component: "\(self.target.c99name).swiftmodule")
125127
}
126128

127129
/// The path to the wrapped swift module which is created using the modulewrap tool. This is required
@@ -131,7 +133,7 @@ public final class SwiftTargetBuildDescription {
131133
self.tempsPath.appending(component: self.target.c99name + ".swiftmodule.o")
132134
}
133135

134-
/// The path to the swifinterface file after compilation.
136+
/// The path to the swiftinterface file after compilation.
135137
var parseableModuleInterfaceOutputPath: AbsolutePath {
136138
self.modulesPath.appending(component: self.target.c99name + ".swiftinterface")
137139
}
@@ -233,7 +235,7 @@ public final class SwiftTargetBuildDescription {
233235
public let prebuildCommandResults: [PrebuildCommandResult]
234236

235237
/// Any macro products that this target requires to build.
236-
public let requiredMacroProducts: [ResolvedProduct]
238+
public let requiredMacroProducts: [ProductBuildDescription]
237239

238240
/// ObservabilityScope with which to emit diagnostics
239241
private let observabilityScope: ObservabilityScope
@@ -242,7 +244,7 @@ public final class SwiftTargetBuildDescription {
242244
private let shouldGenerateTestObservation: Bool
243245

244246
/// Whether to disable sandboxing (e.g. for macros).
245-
private let disableSandbox: Bool
247+
private let shouldDisableSandbox: Bool
246248

247249
/// Create a new target description with target and build parameters.
248250
init(
@@ -253,10 +255,10 @@ public final class SwiftTargetBuildDescription {
253255
buildParameters: BuildParameters,
254256
buildToolPluginInvocationResults: [BuildToolPluginInvocationResult] = [],
255257
prebuildCommandResults: [PrebuildCommandResult] = [],
256-
requiredMacroProducts: [ResolvedProduct] = [],
258+
requiredMacroProducts: [ProductBuildDescription] = [],
257259
testTargetRole: TestTargetRole? = nil,
258260
shouldGenerateTestObservation: Bool = false,
259-
disableSandbox: Bool,
261+
shouldDisableSandbox: Bool,
260262
fileSystem: FileSystem,
261263
observabilityScope: ObservabilityScope
262264
) throws {
@@ -269,6 +271,7 @@ public final class SwiftTargetBuildDescription {
269271
self.target = target
270272
self.toolsVersion = toolsVersion
271273
self.buildParameters = buildParameters
274+
272275
// Unless mentioned explicitly, use the target type to determine if this is a test target.
273276
if let testTargetRole {
274277
self.testTargetRole = testTargetRole
@@ -278,21 +281,21 @@ public final class SwiftTargetBuildDescription {
278281
self.testTargetRole = nil
279282
}
280283

281-
self.tempsPath = buildParameters.buildPath.appending(component: target.c99name + ".build")
284+
self.tempsPath = target.tempsPath(self.buildParameters)
282285
self.derivedSources = Sources(paths: [], root: self.tempsPath.appending("DerivedSources"))
283286
self.buildToolPluginInvocationResults = buildToolPluginInvocationResults
284287
self.prebuildCommandResults = prebuildCommandResults
285288
self.requiredMacroProducts = requiredMacroProducts
286289
self.shouldGenerateTestObservation = shouldGenerateTestObservation
287-
self.disableSandbox = disableSandbox
290+
self.shouldDisableSandbox = shouldDisableSandbox
288291
self.fileSystem = fileSystem
289292
self.observabilityScope = observabilityScope
290293

291294
(self.pluginDerivedSources, self.pluginDerivedResources) = ModulesGraph.computePluginGeneratedFiles(
292295
target: target,
293296
toolsVersion: toolsVersion,
294297
additionalFileRules: additionalFileRules,
295-
buildParameters: buildParameters,
298+
buildParameters: self.buildParameters,
296299
buildToolPluginInvocationResults: buildToolPluginInvocationResults,
297300
prebuildCommandResults: prebuildCommandResults,
298301
observabilityScope: observabilityScope
@@ -332,7 +335,10 @@ public final class SwiftTargetBuildDescription {
332335
return
333336
}
334337

335-
guard self.buildParameters.triple.isDarwin(), self.buildParameters.testingParameters.experimentalTestOutput else {
338+
guard
339+
self.buildParameters.triple.isDarwin() &&
340+
self.buildParameters.testingParameters.experimentalTestOutput
341+
else {
336342
return
337343
}
338344

@@ -412,21 +418,25 @@ public final class SwiftTargetBuildDescription {
412418

413419
#if BUILD_MACROS_AS_DYLIBS
414420
self.requiredMacroProducts.forEach { macro in
415-
args += ["-Xfrontend", "-load-plugin-library", "-Xfrontend", self.buildParameters.binaryPath(for: macro).pathString]
421+
args += ["-Xfrontend", "-load-plugin-library", "-Xfrontend", macro.binaryPath.pathString]
416422
}
417423
#else
418424
try self.requiredMacroProducts.forEach { macro in
419-
if let macroTarget = macro.targets.first {
420-
let executablePath = try self.buildParameters.binaryPath(for: macro).pathString
425+
if let macroTarget = macro.product.targets.first {
426+
let executablePath = try macro.binaryPath.pathString
421427
args += ["-Xfrontend", "-load-plugin-executable", "-Xfrontend", "\(executablePath)#\(macroTarget.c99name)"]
422428
} else {
423-
throw InternalError("macro product \(macro.name) has no targets") // earlier validation should normally catch this
429+
throw InternalError("macro product \(macro.product.name) has no targets") // earlier validation should normally catch this
424430
}
425431
}
426432
#endif
427433

428-
if self.disableSandbox {
429-
let toolchainSupportsDisablingSandbox = DriverSupport.checkSupportedFrontendFlags(flags: ["-disable-sandbox"], toolchain: self.buildParameters.toolchain, fileSystem: fileSystem)
434+
if self.shouldDisableSandbox {
435+
let toolchainSupportsDisablingSandbox = DriverSupport.checkSupportedFrontendFlags(
436+
flags: ["-disable-sandbox"],
437+
toolchain: self.buildParameters.toolchain,
438+
fileSystem: fileSystem
439+
)
430440
if toolchainSupportsDisablingSandbox {
431441
args += ["-disable-sandbox"]
432442
} else {
@@ -443,7 +453,7 @@ public final class SwiftTargetBuildDescription {
443453
/// The arguments needed to compile this target.
444454
public func compileArguments() throws -> [String] {
445455
var args = [String]()
446-
args += try self.buildParameters.targetTripleArgs(for: self.target)
456+
args += try self.buildParameters.tripleArgs(for: self.target)
447457

448458
// pass `-v` during verbose builds.
449459
if self.buildParameters.outputParameters.isVerbose {
@@ -818,7 +828,7 @@ public final class SwiftTargetBuildDescription {
818828
// Include path for the toolchain's copy of SwiftSyntax.
819829
#if BUILD_MACROS_AS_DYLIBS
820830
if target.type == .macro {
821-
flags += try ["-I", self.buildParameters.toolchain.hostLibDir.pathString]
831+
flags += try ["-I", self.defaultBuildParameters.toolchain.hostLibDir.pathString]
822832
}
823833
#endif
824834

Sources/Build/BuildManifest/LLBuildManifestBuilder+Clang.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ extension LLBuildManifestBuilder {
9393
let additionalInputs = try addBuildToolPlugins(.clang(target))
9494

9595
// Create a phony node to represent the entire target.
96-
let targetName = target.target.getLLBuildTargetName(config: target.buildParameters.buildConfig)
96+
let targetName = target.llbuildTargetName
9797
let output: Node = .virtual(targetName)
9898

9999
self.manifest.addNode(output, toTarget: targetName)

0 commit comments

Comments
 (0)