Skip to content

Commit c5c6777

Browse files
committed
Don't link plugin dependencies to products
This fixes two issues with plugins and their dependencies: - we were traversing plugin products and including their targets as part of any product - since we are including plugin targets as dependencies as well, we could traverse plugin targets in a similarly incorrect way
1 parent 979dabc commit c5c6777

File tree

8 files changed

+71
-3
lines changed

8 files changed

+71
-3
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// swift-tools-version:5.8
2+
import PackageDescription
3+
4+
let package = Package(
5+
name: "111920845-sample",
6+
products: [
7+
.executable(name: "MyPluginExecutable", targets: ["MyPluginExecutable"]),
8+
.plugin(name: "MyPlugin", targets: ["MyPlugin"]),
9+
],
10+
targets: [
11+
.executableTarget(name: "MyPluginExecutable"),
12+
.plugin(name: "MyPlugin", capability: .buildTool, dependencies: ["MyPluginExecutable"]),
13+
14+
.target(name: "MyLibrary", plugins: ["MyPlugin"]),
15+
.executableTarget(name: "MyExecutable", dependencies: ["MyLibrary"]),
16+
.testTarget(name: "MyExecutableTests", dependencies: ["MyExecutable"]),
17+
]
18+
)
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import PackagePlugin
2+
3+
@main
4+
struct MyPlugin: BuildToolPlugin {
5+
func createBuildCommands(context: PluginContext, target: Target) async throws -> [Command] {
6+
return [.buildCommand(
7+
displayName: "Running MyPluginExecutable",
8+
executable: try context.tool(named: "MyPluginExecutable").path,
9+
arguments: [],
10+
environment: [:],
11+
inputFiles: [],
12+
outputFiles: []
13+
)]
14+
}
15+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import MyLibrary
2+
3+
@main
4+
struct MyExecutable {
5+
static func main() async throws {
6+
print("Hello from executable.")
7+
}
8+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
@main
2+
struct MyExecutable {
3+
static func main() async throws {
4+
print("Hello from plugin executable.")
5+
}
6+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import XCTest
2+
@testable import MyExecutable
3+
4+
final class MyExecutableTests: XCTestCase {
5+
func test() throws {
6+
XCTAssertTrue(true)
7+
}
8+
}

Sources/Build/BuildPlan.swift

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -702,19 +702,22 @@ public class BuildPlan: SPMBuildCore.BuildPlan {
702702
switch dependency {
703703
// Include all the dependencies of a target.
704704
case .target(let target, _):
705+
if [.macro, .plugin].contains(target.type) {
706+
return []
707+
}
705708
return target.dependencies.filter { $0.satisfies(self.buildEnvironment) }
706709

707710
// For a product dependency, we only include its content only if we
708-
// need to statically link it or if it's a plugin.
711+
// need to statically link it.
709712
case .product(let product, _):
710713
guard dependency.satisfies(self.buildEnvironment) else {
711714
return []
712715
}
713716

714717
switch product.type {
715-
case .library(.automatic), .library(.static), .plugin:
718+
case .library(.automatic), .library(.static):
716719
return product.targets.map { .target($0, conditions: []) }
717-
case .library(.dynamic), .test, .executable, .snippet, .macro:
720+
case .library(.dynamic), .test, .executable, .snippet, .macro, .plugin:
718721
return []
719722
}
720723
}

Tests/FunctionalTests/PluginTests.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -969,6 +969,15 @@ class PluginTests: XCTestCase {
969969
}
970970
}
971971

972+
func testIncorrectDependencies() throws {
973+
try XCTSkipIf(!UserToolchain.default.supportsSwiftConcurrency(), "skipping because test environment doesn't support concurrency")
974+
975+
try fixture(name: "Miscellaneous/Plugins") { path in
976+
let (stdout, stderr) = try executeSwiftBuild(path.appending("IncorrectDependencies"), extraArgs: ["--build-tests"])
977+
XCTAssert(stdout.contains("Build complete!"), "output:\n\(stderr)\n\(stdout)")
978+
}
979+
}
980+
972981
func testSandboxViolatingBuildToolPluginCommands() throws {
973982
#if !os(macOS)
974983
try XCTSkipIf(true, "sandboxing tests are only supported on macOS")

0 commit comments

Comments
 (0)