Skip to content

Commit 2c18196

Browse files
authored
Build direct dependencies of tests for target triple (#7350)
`assertMacroExpansion` requires macros to be compiled for target platform and evaluated in-process. We can't handle the case of indirect macro dependencies cleanly, those will be still compiled for the host. Supersedes #7349. This doesn't contain tests to expedite the fix and unblock broken CI jobs, but I've verified locally that test products of the `Examples` package in `apple/swift-syntax` repo can be built successfully and these tests all pass.
1 parent 9c6493f commit 2c18196

File tree

8 files changed

+64
-14
lines changed

8 files changed

+64
-14
lines changed

Sources/Build/BuildDescription/SwiftTargetBuildDescription.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ public final class SwiftTargetBuildDescription {
130130
self.tempsPath.appending(component: self.target.c99name + ".swiftmodule.o")
131131
}
132132

133-
/// The path to the swifinterface file after compilation.
133+
/// The path to the swiftinterface file after compilation.
134134
var parseableModuleInterfaceOutputPath: AbsolutePath {
135135
self.modulesPath.appending(component: self.target.c99name + ".swiftinterface")
136136
}

Sources/Build/BuildPlan/BuildPlan+Product.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,13 @@ extension BuildPlan {
9292

9393
buildProduct.staticTargets = dependencies.staticTargets
9494
buildProduct.dylibs = try dependencies.dylibs.map {
95-
guard let product = productMap[$0.id] else {
95+
guard let product = self.productMap[$0.id] else {
9696
throw InternalError("unknown product \($0)")
9797
}
9898
return product
9999
}
100100
buildProduct.objects += try dependencies.staticTargets.flatMap { targetName -> [AbsolutePath] in
101-
guard let target = targetMap[targetName.id] else {
101+
guard let target = self.targetMap[targetName.id] else {
102102
throw InternalError("unknown target \(targetName)")
103103
}
104104
return try target.objects

Sources/PackageGraph/PackageGraph+Loading.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,10 @@ private func createResolvedPackages(
280280

281281
// Resolve module aliases, if specified, for targets and their dependencies
282282
// across packages. Aliasing will result in target renaming.
283-
let moduleAliasingUsed = try resolveModuleAliases(packageBuilders: packageBuilders, observabilityScope: observabilityScope)
283+
let moduleAliasingUsed = try resolveModuleAliases(
284+
packageBuilders: packageBuilders,
285+
observabilityScope: observabilityScope
286+
)
284287

285288
// Scan and validate the dependencies
286289
for packageBuilder in packageBuilders {

Sources/PackageGraph/PackageGraph.swift

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,14 @@ public struct PackageGraph {
7979
/// Returns true if a given target is present in root packages and is not excluded for the given build environment.
8080
public func isInRootPackages(_ target: ResolvedTarget, satisfying buildEnvironment: BuildEnvironment) -> Bool {
8181
// FIXME: This can be easily cached.
82-
return rootPackages.reduce(into: IdentifiableSet<ResolvedTarget>()) { (accumulator: inout IdentifiableSet<ResolvedTarget>, package: ResolvedPackage) in
82+
return rootPackages.reduce(
83+
into: IdentifiableSet<ResolvedTarget>()
84+
) { (accumulator: inout IdentifiableSet<ResolvedTarget>, package: ResolvedPackage) in
8385
let allDependencies = package.targets.flatMap { $0.dependencies }
8486
let unsatisfiedDependencies = allDependencies.filter { !$0.satisfies(buildEnvironment) }
85-
let unsatisfiedDependencyTargets = unsatisfiedDependencies.compactMap { (dep: ResolvedTarget.Dependency) -> ResolvedTarget? in
87+
let unsatisfiedDependencyTargets = unsatisfiedDependencies.compactMap { (
88+
dep: ResolvedTarget.Dependency
89+
) -> ResolvedTarget? in
8690
switch dep {
8791
case .target(let target, _):
8892
return target
@@ -152,7 +156,7 @@ public struct PackageGraph {
152156
for package in self.packages {
153157
let targetsToInclude: [ResolvedTarget]
154158
if rootPackages.contains(id: package.id) {
155-
targetsToInclude = package.targets
159+
targetsToInclude = Array(package.targets)
156160
} else {
157161
// Don't include tests targets from non-root packages so swift-test doesn't
158162
// try to run them.

Sources/PackageGraph/Resolution/ResolvedPackage.swift

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
import Basics
14+
15+
import struct OrderedCollections.OrderedDictionary
16+
1417
import PackageModel
1518

1619
/// A fully resolved package. Contains resolved targets, products and dependencies of the package.
@@ -64,8 +67,43 @@ public struct ResolvedPackage {
6467
platformVersionProvider: PlatformVersionProvider
6568
) {
6669
self.underlying = underlying
67-
self.targets = targets
68-
self.products = products
70+
71+
var processedTargets = OrderedDictionary<ResolvedTarget.ID, ResolvedTarget>(
72+
uniqueKeysWithValues: targets.map { ($0.id, $0) }
73+
)
74+
var processedProducts = [ResolvedProduct]()
75+
// Make sure that direct macro dependencies of test products are also built for the target triple.
76+
// Without this workaround, `assertMacroExpansion` in tests can't be built, as it requires macros
77+
// and SwiftSyntax to be built for the target triple: https://github.com/apple/swift-package-manager/pull/7349
78+
for var product in products {
79+
if product.type == .test {
80+
var targets = IdentifiableSet<ResolvedTarget>()
81+
for var target in product.targets {
82+
var dependencies = [ResolvedTarget.Dependency]()
83+
for dependency in target.dependencies {
84+
switch dependency {
85+
case .target(var target, let conditions) where target.type == .macro:
86+
target.buildTriple = .destination
87+
dependencies.append(.target(target, conditions: conditions))
88+
processedTargets[target.id] = target
89+
case .product(var product, let conditions) where product.type == .macro:
90+
product.buildTriple = .destination
91+
dependencies.append(.product(product, conditions: conditions))
92+
default:
93+
dependencies.append(dependency)
94+
}
95+
}
96+
target.dependencies = dependencies
97+
targets.insert(target)
98+
}
99+
product.targets = targets
100+
}
101+
102+
processedProducts.append(product)
103+
}
104+
105+
self.products = processedProducts
106+
self.targets = Array(processedTargets.values)
69107
self.dependencies = dependencies
70108
self.defaultLocalization = defaultLocalization
71109
self.supportedPlatforms = supportedPlatforms

Sources/PackageGraph/Resolution/ResolvedProduct.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public struct ResolvedProduct {
3030
public let underlying: Product
3131

3232
/// The top level targets contained in this product.
33-
public private(set) var targets: IdentifiableSet<ResolvedTarget>
33+
public internal(set) var targets: IdentifiableSet<ResolvedTarget>
3434

3535
/// Executable target for test entry point file.
3636
public let testEntryPointTarget: ResolvedTarget?

Sources/PackageGraph/Resolution/ResolvedTarget.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ public struct ResolvedTarget {
133133
public let underlying: Target
134134

135135
/// The dependencies of this target.
136-
public private(set) var dependencies: [Dependency]
136+
public internal(set) var dependencies: [Dependency]
137137

138138
/// The default localization for resources.
139139
public let defaultLocalization: String?

Tests/BuildTests/CrossCompilationBuildTests.swift

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,17 @@ final class CrossCompilationBuildPlanTests: XCTestCase {
7070
let macroProduct = try XCTUnwrap(macroProducts.first)
7171
XCTAssertEqual(macroProduct.buildParameters.triple, toolsTriple)
7272

73-
// FIXME: check for *toolsTriple*
73+
// FIXME: check for *toolsTriple*
7474
let mmioTarget = try XCTUnwrap(plan.targets.first { try $0.swiftTarget().target.name == "MMIO" }?.swiftTarget())
75-
let compileArguments = try mmioTarget.compileArguments()
75+
let compileArguments = try mmioTarget.emitCommandLine()
7676
XCTAssertMatch(
7777
compileArguments,
78-
["-Xfrontend", "-load-plugin-executable", "-Xfrontend", .contains(toolsTriple.tripleString)]
78+
[
79+
"-I", .equal(mmioTarget.moduleOutputPath.parentDirectory.pathString),
80+
.anySequence,
81+
"-Xfrontend", "-load-plugin-executable",
82+
"-Xfrontend", .contains(toolsTriple.tripleString)
83+
]
7984
)
8085
}
8186
}

0 commit comments

Comments
 (0)