Skip to content

Commit fef96a3

Browse files
committed
Fix issues with excluding macros/plugins from dependency computation
While fixing this, I also noticed the original issue also exists for executable targets, so this gets fixed here as well. There's one unfortunate nuance here for test targets since using a macro/plugin is indistinguishable from needing to link it because it is being tested. We err on the side of caution here and will always link. (sidenote: theoretically, plugins *do* distinguish between linkage and use in the package manifest, but this distinction is not carried forward into the actual model) Partially fixes https://github.com/apple/swift/issues/67371 since the underlying project also does not declare a dependency on the macro that is being tested.
1 parent 0e50b63 commit fef96a3

File tree

2 files changed

+32
-8
lines changed

2 files changed

+32
-8
lines changed

Fixtures/Miscellaneous/Plugins/MySourceGenPlugin/Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// swift-tools-version: 5.6
1+
// swift-tools-version: 5.9
22
import PackageDescription
33

44
let package = Package(

Sources/Build/BuildPlan.swift

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -695,13 +695,28 @@ public class BuildPlan: SPMBuildCore.BuildPlan {
695695
libraryBinaryPaths: Set<AbsolutePath>,
696696
availableTools: [String: AbsolutePath]
697697
) {
698-
/* Prior to tools-version 5.9, we used to errorneously recursively traverse plugin dependencies and statically include their
698+
/* Prior to tools-version 5.9, we used to errorneously recursively traverse executable/plugin dependencies and statically include their
699699
targets. For compatibility reasons, we preserve that behavior for older tools-versions. */
700-
let shouldExcludePlugins: Bool
700+
let shouldExcludeExecutablesAndPlugins: Bool
701701
if let toolsVersion = self.graph.package(for: product)?.manifest.toolsVersion {
702-
shouldExcludePlugins = toolsVersion >= .v5_9
702+
shouldExcludeExecutablesAndPlugins = toolsVersion >= .v5_9
703703
} else {
704-
shouldExcludePlugins = false
704+
shouldExcludeExecutablesAndPlugins = false
705+
}
706+
707+
// For test targets, we need to consider the first level of transitive dependencies since the first level is always test targets.
708+
let topLevelDependencies: [PackageModel.Target]
709+
if product.type == .test {
710+
topLevelDependencies = product.targets.flatMap { $0.underlyingTarget.dependencies }.compactMap {
711+
switch $0 {
712+
case .product:
713+
return nil
714+
case .target(let target, _):
715+
return target
716+
}
717+
}
718+
} else {
719+
topLevelDependencies = []
705720
}
706721

707722
// Sort the product targets in topological order.
@@ -710,10 +725,19 @@ public class BuildPlan: SPMBuildCore.BuildPlan {
710725
switch dependency {
711726
// Include all the dependencies of a target.
712727
case .target(let target, _):
713-
if target.type == .macro {
728+
let isTopLevel = topLevelDependencies.contains(target.underlyingTarget) || product.targets.contains(target)
729+
let topLevelIsExecutable = isTopLevel && product.type == .executable
730+
let topLevelIsMacro = isTopLevel && product.type == .macro
731+
let topLevelIsPlugin = isTopLevel && product.type == .plugin
732+
let topLevelIsTest = isTopLevel && product.type == .test
733+
734+
if !topLevelIsMacro && !topLevelIsTest && target.type == .macro {
735+
return []
736+
}
737+
if shouldExcludeExecutablesAndPlugins, !topLevelIsPlugin && !topLevelIsTest && target.type == .plugin {
714738
return []
715739
}
716-
if shouldExcludePlugins, target.type == .plugin {
740+
if shouldExcludeExecutablesAndPlugins, !topLevelIsExecutable && topLevelIsTest && target.type == .executable {
717741
return []
718742
}
719743
return target.dependencies.filter { $0.satisfies(self.buildEnvironment) }
@@ -730,7 +754,7 @@ public class BuildPlan: SPMBuildCore.BuildPlan {
730754
case .library(.automatic), .library(.static):
731755
return productDependencies
732756
case .plugin:
733-
return shouldExcludePlugins ? [] : productDependencies
757+
return shouldExcludeExecutablesAndPlugins ? [] : productDependencies
734758
case .library(.dynamic), .test, .executable, .snippet, .macro:
735759
return []
736760
}

0 commit comments

Comments
 (0)