From c7e01fcf60a7b09075ccfe5cf0024e0644624563 Mon Sep 17 00:00:00 2001 From: Chris McGee Date: Wed, 4 Jun 2025 15:36:46 -0400 Subject: [PATCH 1/5] Provide library paths to plugin tools when run as custom tasks --- Sources/SwiftBuildSupport/PIFBuilder.swift | 29 ++++++++++++++++++++ Tests/FunctionalTests/PluginTests.swift | 31 +++------------------- 2 files changed, 32 insertions(+), 28 deletions(-) diff --git a/Sources/SwiftBuildSupport/PIFBuilder.swift b/Sources/SwiftBuildSupport/PIFBuilder.swift index 1274f17d129..a6da4c1e041 100644 --- a/Sources/SwiftBuildSupport/PIFBuilder.swift +++ b/Sources/SwiftBuildSupport/PIFBuilder.swift @@ -362,6 +362,35 @@ public final class PIFBuilder { env[key.rawValue] = value } + if let libDir = try? buildParameters.toolchain.toolchainLibDir { + var libPathVar: String? = nil + var libPathEntry: String? = nil + var libPathSeparator: String? = nil +#if os(macOS) + libPathVar = "DYLD_LIBRARY_PATH" + libPathEntry = libDir.appending("swift").appending("macosx").pathString + libPathSeparator = ":" +#elseif os(Linux) + libPathVar = "LD_LIBRARY_PATH" + libPathEntry = libDir.appending("swift").appending("linux").pathString + libPathSeparator = ":" +#elseif os(Windows) + libPathVar = "PATH" + libPathEntry = libDir.pathString + libPathSeparator = ";" +#endif + + if let libPathVar, let libPathEntry, let libPathSeparator { + let existingEntry = env[libPathVar] ?? "" + if case var parts = existingEntry.split(separator: libPathSeparator).map({ String($0) }), !parts.contains(libPathEntry) { + parts.append(libPathEntry) + env[libPathVar] = parts.joined(separator: libPathSeparator) + } + } else { + observabilityScope.emit(warning: "Unable to set the library path for this platform. Some plugin build tools may not run without this.") + } + } + let workingDir = buildCommand.configuration.workingDirectory let writableDirectories: [AbsolutePath] = buildCommand.outputFiles diff --git a/Tests/FunctionalTests/PluginTests.swift b/Tests/FunctionalTests/PluginTests.swift index 35f7e5b170b..6a22a540fc4 100644 --- a/Tests/FunctionalTests/PluginTests.swift +++ b/Tests/FunctionalTests/PluginTests.swift @@ -70,13 +70,11 @@ final class PluginTests: XCTestCase { XCTAssert(stdout.contains("Build of product 'MyTool' complete!"), "stdout:\n\(stdout)") } -#if os(macOS) // See https://github.com/swiftlang/swift-package-manager/issues/8416 for errors running build tools on Linux // Try again with the Swift Build build system try await fixture(name: "Miscellaneous/Plugins") { fixturePath in let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("MySourceGenClient"), configuration: .Debug, extraArgs: ["--build-system", "swiftbuild", "--product", "MyTool"]) XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)") } -#endif } func testUseOfPrebuildPluginTargetByExecutableAcrossPackages() async throws { @@ -92,12 +90,10 @@ final class PluginTests: XCTestCase { XCTAssert(stdout.contains("Build of product 'MyOtherLocalTool' complete!"), "stdout:\n\(stdout)") } -#if os(macOS) // See https://github.com/swiftlang/swift-package-manager/issues/8416 for errors running build tools on Linux try await fixture(name: "Miscellaneous/Plugins") { fixturePath in let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("MySourceGenPlugin"), configuration: .Debug, extraArgs: ["--build-system", "swiftbuild", "--product", "MyOtherLocalTool"]) XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)") } -#endif } func testUseOfPluginWithInternalExecutable() async throws { @@ -115,13 +111,11 @@ final class PluginTests: XCTestCase { XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)") } -#if os(macOS) // See https://github.com/swiftlang/swift-package-manager/issues/8416 for errors running build tools on Linux // Try again with the Swift Build build system try await fixture(name: "Miscellaneous/Plugins") { fixturePath in let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("ClientOfPluginWithInternalExecutable"), extraArgs: ["--build-system", "swiftbuild"]) XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)") } -#endif } func testInternalExecutableAvailableOnlyToPlugin() async throws { @@ -136,13 +130,11 @@ final class PluginTests: XCTestCase { } } -#if os(macOS) // See https://github.com/swiftlang/swift-package-manager/issues/8416 for errors running build tools on Linux try await fixture(name: "Miscellaneous/Plugins") { fixturePath in await XCTAssertThrowsCommandExecutionError(try await executeSwiftBuild(fixturePath.appending("InvalidUseOfInternalPluginExecutable")), "Illegally used internal executable" ) { error in } } -#endif } func testLocalBuildToolPluginUsingRemoteExecutable() async throws { @@ -159,13 +151,11 @@ final class PluginTests: XCTestCase { XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)") } -#if os(macOS) // See https://github.com/swiftlang/swift-package-manager/issues/8416 for errors running build tools on Linux // Try again with the Swift Build build system try await fixture(name: "Miscellaneous/Plugins") { fixturePath in let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("LibraryWithLocalBuildToolPluginUsingRemoteTool"), extraArgs: ["--build-system", "swiftbuild"]) XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)") } -#endif } func testBuildToolPluginDependencies() async throws { @@ -182,7 +172,7 @@ final class PluginTests: XCTestCase { XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)") } -#if os(macOS) // See https://github.com/swiftlang/swift-package-manager/issues/8416 for errors running build tools on Linux +#if os(macOS) // Try again with the Swift Build build system try await fixture(name: "Miscellaneous/Plugins") { fixturePath in let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("MyBuildToolPluginDependencies"), extraArgs: ["--build-system", "swiftbuild"]) @@ -204,12 +194,10 @@ final class PluginTests: XCTestCase { XCTAssert(stdout.contains("Build of product 'MyLocalTool' complete!"), "stdout:\n\(stdout)") } -#if os(macOS) // See https://github.com/swiftlang/swift-package-manager/issues/8416 for errors running build tools on Linux try await fixture(name: "Miscellaneous/Plugins") { fixturePath in let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("ContrivedTestPlugin"), configuration: .Debug, extraArgs: ["--build-system", "swiftbuild", "--product", "MyLocalTool", "--disable-sandbox"]) XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)") } -#endif } func testPluginScriptSandbox() async throws { @@ -1158,13 +1146,11 @@ final class PluginTests: XCTestCase { XCTAssert(stdout.contains("type of snippet target: snippet"), "output:\n\(stderr)\n\(stdout)") } -#if os(macOS) // See https://github.com/swiftlang/swift-package-manager/issues/8416 for errors running build tools on Linux // Try again with the Swift Build build system try await fixture(name: "Miscellaneous/Plugins") { path in let (stdout, stderr) = try await executeSwiftPackage(path.appending("PluginsAndSnippets"), configuration: .Debug, extraArgs: ["--build-system", "swiftbuild", "do-something"]) XCTAssert(stdout.contains("type of snippet target: snippet"), "output:\n\(stderr)\n\(stdout)") } -#endif } func testIncorrectDependencies() async throws { @@ -1175,13 +1161,11 @@ final class PluginTests: XCTestCase { XCTAssert(stdout.contains("Build complete!"), "output:\n\(stderr)\n\(stdout)") } -#if os(macOS) // See https://github.com/swiftlang/swift-package-manager/issues/8416 for errors running build tools on Linux // Try again with the Swift Build build system try await fixture(name: "Miscellaneous/Plugins") { path in let (stdout, stderr) = try await executeSwiftBuild(path.appending("IncorrectDependencies"), extraArgs: ["--build-system", "swiftbuild", "--build-tests"]) XCTAssert(stdout.contains("Build complete!"), "output:\n\(stderr)\n\(stdout)") } -#endif } func testSandboxViolatingBuildToolPluginCommands() async throws { @@ -1219,13 +1203,11 @@ final class PluginTests: XCTestCase { XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)") } -#if os(macOS) // See https://github.com/swiftlang/swift-package-manager/issues/8416 for errors running build tools on Linux // Try again with Swift Build build system try await fixture(name: "Miscellaneous/Plugins") { fixturePath in let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("TransitivePluginOnlyDependency"), extraArgs: ["--build-system", "swiftbuild"]) XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)") } -#endif } func testMissingPlugin() async throws { @@ -1240,7 +1222,6 @@ final class PluginTests: XCTestCase { } } -#if os(macOS) // See https://github.com/swiftlang/swift-package-manager/issues/8416 for errors running build tools on Linux try await fixture(name: "Miscellaneous/Plugins") { fixturePath in do { try await executeSwiftBuild(fixturePath.appending("MissingPlugin"), extraArgs: ["--build-system", "swiftbuild"]) @@ -1248,7 +1229,6 @@ final class PluginTests: XCTestCase { XCTAssert(stderr.contains("error: 'missingplugin': no plugin named 'NonExistingPlugin' found"), "stderr:\n\(stderr)") } } -#endif } func testPluginCanBeReferencedByProductName() async throws { @@ -1262,13 +1242,11 @@ final class PluginTests: XCTestCase { XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)") } -#if os(macOS) // See https://github.com/swiftlang/swift-package-manager/issues/8416 for errors running build tools on Linux // Try again with the Swift Build build system try await fixture(name: "Miscellaneous/Plugins") { fixturePath in let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("PluginCanBeReferencedByProductName"), extraArgs: ["--build-system", "swiftbuild"]) XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)") } -#endif } func testPluginCanBeAffectedByXBuildToolsParameters() async throws { @@ -1292,7 +1270,7 @@ final class PluginTests: XCTestCase { XCTAssert(stdout.contains("Build of product 'MyLocalTool' complete!"), "stdout:\n\(stdout)") } -#if os(macOS) // See https://github.com/swiftlang/swift-package-manager/issues/8416 for errors running build tools on Linux +#if os(macOS) try await fixture(name: "Miscellaneous/Plugins") { fixturePath in let (stdout, stderr) = try await executeSwiftBuild( fixturePath.appending(component: "MySourceGenPlugin"), @@ -1315,8 +1293,7 @@ final class PluginTests: XCTestCase { let (stdout, _) = try await executeSwiftBuild(fixturePath, configuration: .Debug) XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)") } - -#if os(macOS) // See https://github.com/swiftlang/swift-package-manager/issues/8416 for errors running build tools on Linux +#if os(macOS) // Try again with the Swift Build build system try await fixture(name: "Miscellaneous/Plugins/MySourceGenPluginUsingURLBasedAPI") { fixturePath in let (stdout, _) = try await executeSwiftBuild(fixturePath, configuration: .Debug, extraArgs: ["--build-system", "swiftbuild"]) @@ -1333,11 +1310,9 @@ final class PluginTests: XCTestCase { XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)") } -#if os(macOS) // See https://github.com/swiftlang/swift-package-manager/issues/8416 for errors running build tools on Linux try await fixture(name: "Miscellaneous/Plugins/DependentPlugins") { fixturePath in let (stdout, _) = try await executeSwiftBuild(fixturePath, extraArgs: ["--build-system", "swiftbuild"]) XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)") } -#endif } } From de4550916bcf3d42d3ff9906c55feca10344220b Mon Sep 17 00:00:00 2001 From: Chris McGee Date: Thu, 5 Jun 2025 09:40:34 -0400 Subject: [PATCH 2/5] Abstract the runtime library detection into UserToolchain Use path handling logic from Environment --- .../Basics/Environment/EnvironmentKey.swift | 10 +++++ Sources/PackageModel/Toolchain.swift | 3 ++ Sources/PackageModel/UserToolchain.swift | 24 ++++++++++++ Sources/SwiftBuildSupport/PIFBuilder.swift | 38 +++---------------- .../MockBuildTestHelper.swift | 1 + 5 files changed, 44 insertions(+), 32 deletions(-) diff --git a/Sources/Basics/Environment/EnvironmentKey.swift b/Sources/Basics/Environment/EnvironmentKey.swift index 82c8dc6bd3d..8d31fcc4ab7 100644 --- a/Sources/Basics/Environment/EnvironmentKey.swift +++ b/Sources/Basics/Environment/EnvironmentKey.swift @@ -24,6 +24,16 @@ public struct EnvironmentKey { extension EnvironmentKey { package static let path: Self = "PATH" + package static var libraryPath: Self { + #if os(Windows) + path + #elseif canImport(Darwin) + "DYLD_LIBRARY_PATH" + #else + "LD_LIBRARY_PATH" + #endif + } + /// A set of known keys which should not be included in cache keys. package static let nonCachable: Set = [ "TERM", diff --git a/Sources/PackageModel/Toolchain.swift b/Sources/PackageModel/Toolchain.swift index 3e3b8ef433f..562a83622ce 100644 --- a/Sources/PackageModel/Toolchain.swift +++ b/Sources/PackageModel/Toolchain.swift @@ -35,6 +35,9 @@ public protocol Toolchain { /// An array of paths to search for libraries at link time. var librarySearchPaths: [AbsolutePath] { get } + /// An array of paths to use with binaries produced by this toolchain at run time. + var runtimeLibraryPaths: [AbsolutePath] { get } + /// Configuration from the used toolchain. var installedSwiftPMConfiguration: InstalledSwiftPMConfiguration { get } diff --git a/Sources/PackageModel/UserToolchain.swift b/Sources/PackageModel/UserToolchain.swift index 1ff61309ddd..2bddc8e78a5 100644 --- a/Sources/PackageModel/UserToolchain.swift +++ b/Sources/PackageModel/UserToolchain.swift @@ -42,6 +42,9 @@ public final class UserToolchain: Toolchain { /// An array of paths to search for libraries at link time. public let librarySearchPaths: [AbsolutePath] + /// An array of paths to use with binaries produced by this toolchain at run time. + public let runtimeLibraryPaths: [AbsolutePath] + /// Path containing Swift resources for dynamic linking. public var swiftResourcesPath: AbsolutePath? { swiftSDK.pathsConfiguration.swiftResourcesPath @@ -206,6 +209,24 @@ public final class UserToolchain: Toolchain { } } + private static func computeRuntimeLibraryPaths(targetInfo: JSON) throws -> [AbsolutePath] { + var libraryPaths: [AbsolutePath] = [] + + for runtimeLibPath in try targetInfo.get("paths").getArray("runtimeLibraryPaths") { + guard case .string(let value) = runtimeLibPath else { + continue + } + + guard let path = try? AbsolutePath(validating: value) else { + continue + } + + libraryPaths.append(path) + } + + return libraryPaths + } + private static func computeSwiftCompilerVersion(targetInfo: JSON) -> String? { // Get the compiler version from the target info let compilerVersion: String @@ -692,6 +713,9 @@ public final class UserToolchain: Toolchain { // Get compiler version information from target info self.swiftCompilerVersion = Self.computeSwiftCompilerVersion(targetInfo: targetInfo) + // Get the list of runtime libraries from the target info + self.runtimeLibraryPaths = try Self.computeRuntimeLibraryPaths(targetInfo: targetInfo) + // Use the triple from Swift SDK or compute the host triple from the target info var triple = try swiftSDK.targetTriple ?? Self.getHostTriple(targetInfo: targetInfo) diff --git a/Sources/SwiftBuildSupport/PIFBuilder.swift b/Sources/SwiftBuildSupport/PIFBuilder.swift index a6da4c1e041..fe72c05016a 100644 --- a/Sources/SwiftBuildSupport/PIFBuilder.swift +++ b/Sources/SwiftBuildSupport/PIFBuilder.swift @@ -10,7 +10,7 @@ // //===----------------------------------------------------------------------===// -import Basics +@_spi(SwiftPMInternal) import Basics import Foundation import PackageGraph import PackageLoading @@ -357,37 +357,11 @@ public final class PIFBuilder { let result2 = PackagePIFBuilder.BuildToolPluginInvocationResult( prebuildCommandOutputPaths: result.prebuildCommands.map( { $0.outputFilesDirectory } ), buildCommands: result.buildCommands.map( { buildCommand in - var env: [String: String] = [:] - for (key, value) in buildCommand.configuration.environment { - env[key.rawValue] = value - } + var newEnv: Environment = buildCommand.configuration.environment - if let libDir = try? buildParameters.toolchain.toolchainLibDir { - var libPathVar: String? = nil - var libPathEntry: String? = nil - var libPathSeparator: String? = nil -#if os(macOS) - libPathVar = "DYLD_LIBRARY_PATH" - libPathEntry = libDir.appending("swift").appending("macosx").pathString - libPathSeparator = ":" -#elseif os(Linux) - libPathVar = "LD_LIBRARY_PATH" - libPathEntry = libDir.appending("swift").appending("linux").pathString - libPathSeparator = ":" -#elseif os(Windows) - libPathVar = "PATH" - libPathEntry = libDir.pathString - libPathSeparator = ";" -#endif - - if let libPathVar, let libPathEntry, let libPathSeparator { - let existingEntry = env[libPathVar] ?? "" - if case var parts = existingEntry.split(separator: libPathSeparator).map({ String($0) }), !parts.contains(libPathEntry) { - parts.append(libPathEntry) - env[libPathVar] = parts.joined(separator: libPathSeparator) - } - } else { - observabilityScope.emit(warning: "Unable to set the library path for this platform. Some plugin build tools may not run without this.") + if let runtimeLibPaths = try? buildParameters.toolchain.runtimeLibraryPaths { + for libPath in runtimeLibPaths { + newEnv.appendPath(key: .libraryPath, value: libPath.pathString) } } @@ -399,7 +373,7 @@ public final class PIFBuilder { displayName: buildCommand.configuration.displayName, executable: buildCommand.configuration.executable.pathString, arguments: buildCommand.configuration.arguments, - environment: env, + environment: .init(newEnv), workingDir: workingDir, inputPaths: buildCommand.inputFiles, outputPaths: buildCommand.outputFiles.map(\.pathString), diff --git a/Sources/_InternalTestSupport/MockBuildTestHelper.swift b/Sources/_InternalTestSupport/MockBuildTestHelper.swift index 5a29ebadf33..3246247f99d 100644 --- a/Sources/_InternalTestSupport/MockBuildTestHelper.swift +++ b/Sources/_InternalTestSupport/MockBuildTestHelper.swift @@ -31,6 +31,7 @@ public struct MockToolchain: PackageModel.Toolchain { public let swiftCompilerPath = AbsolutePath("/fake/path/to/swiftc") public let includeSearchPaths = [AbsolutePath]() public let librarySearchPaths = [AbsolutePath]() + public let runtimeLibraryPaths: [AbsolutePath] = [AbsolutePath]() public let swiftResourcesPath: AbsolutePath? public let swiftStaticResourcesPath: AbsolutePath? = nil public let sdkRootPath: AbsolutePath? = nil From e9b532aec49e102ece9fb38b3b0f08e62f9fb3c1 Mon Sep 17 00:00:00 2001 From: Chris McGee Date: Thu, 5 Jun 2025 10:16:09 -0400 Subject: [PATCH 3/5] Defend against malformed JSON target information that prevents detection of runtime library paths --- Sources/PackageModel/UserToolchain.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/PackageModel/UserToolchain.swift b/Sources/PackageModel/UserToolchain.swift index 2bddc8e78a5..8adabeb9f8c 100644 --- a/Sources/PackageModel/UserToolchain.swift +++ b/Sources/PackageModel/UserToolchain.swift @@ -212,7 +212,7 @@ public final class UserToolchain: Toolchain { private static func computeRuntimeLibraryPaths(targetInfo: JSON) throws -> [AbsolutePath] { var libraryPaths: [AbsolutePath] = [] - for runtimeLibPath in try targetInfo.get("paths").getArray("runtimeLibraryPaths") { + for runtimeLibPath in (try? (try? targetInfo.get("paths"))?.getArray("runtimeLibraryPaths")) ?? [] { guard case .string(let value) = runtimeLibPath else { continue } From 45e384127f3333d381aced69d30d6f1f6aa85ea4 Mon Sep 17 00:00:00 2001 From: Chris McGee Date: Fri, 6 Jun 2025 08:41:29 -0400 Subject: [PATCH 4/5] Skip tests on Windows because of a filesystem error --- Tests/FunctionalTests/PluginTests.swift | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Tests/FunctionalTests/PluginTests.swift b/Tests/FunctionalTests/PluginTests.swift index 6a22a540fc4..d5f3c22585f 100644 --- a/Tests/FunctionalTests/PluginTests.swift +++ b/Tests/FunctionalTests/PluginTests.swift @@ -70,11 +70,13 @@ final class PluginTests: XCTestCase { XCTAssert(stdout.contains("Build of product 'MyTool' complete!"), "stdout:\n\(stdout)") } +#if !os(Windows) // https://github.com/swiftlang/swift-package-manager/issues/8774 // Try again with the Swift Build build system try await fixture(name: "Miscellaneous/Plugins") { fixturePath in let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("MySourceGenClient"), configuration: .Debug, extraArgs: ["--build-system", "swiftbuild", "--product", "MyTool"]) XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)") } +#endif } func testUseOfPrebuildPluginTargetByExecutableAcrossPackages() async throws { @@ -90,10 +92,12 @@ final class PluginTests: XCTestCase { XCTAssert(stdout.contains("Build of product 'MyOtherLocalTool' complete!"), "stdout:\n\(stdout)") } +#if !os(Windows) // https://github.com/swiftlang/swift-package-manager/issues/8774 try await fixture(name: "Miscellaneous/Plugins") { fixturePath in let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("MySourceGenPlugin"), configuration: .Debug, extraArgs: ["--build-system", "swiftbuild", "--product", "MyOtherLocalTool"]) XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)") } +#endif } func testUseOfPluginWithInternalExecutable() async throws { @@ -111,11 +115,13 @@ final class PluginTests: XCTestCase { XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)") } +#if !os(Windows) // https://github.com/swiftlang/swift-package-manager/issues/8774 // Try again with the Swift Build build system try await fixture(name: "Miscellaneous/Plugins") { fixturePath in let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("ClientOfPluginWithInternalExecutable"), extraArgs: ["--build-system", "swiftbuild"]) XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)") } +#endif } func testInternalExecutableAvailableOnlyToPlugin() async throws { @@ -151,11 +157,13 @@ final class PluginTests: XCTestCase { XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)") } +#if !os(Windows) // https://github.com/swiftlang/swift-package-manager/issues/8774 // Try again with the Swift Build build system try await fixture(name: "Miscellaneous/Plugins") { fixturePath in let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("LibraryWithLocalBuildToolPluginUsingRemoteTool"), extraArgs: ["--build-system", "swiftbuild"]) XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)") } +#endif } func testBuildToolPluginDependencies() async throws { @@ -194,10 +202,12 @@ final class PluginTests: XCTestCase { XCTAssert(stdout.contains("Build of product 'MyLocalTool' complete!"), "stdout:\n\(stdout)") } +#if !os(Windows) // https://github.com/swiftlang/swift-package-manager/issues/8774 try await fixture(name: "Miscellaneous/Plugins") { fixturePath in let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("ContrivedTestPlugin"), configuration: .Debug, extraArgs: ["--build-system", "swiftbuild", "--product", "MyLocalTool", "--disable-sandbox"]) XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)") } +#endif } func testPluginScriptSandbox() async throws { @@ -1146,11 +1156,13 @@ final class PluginTests: XCTestCase { XCTAssert(stdout.contains("type of snippet target: snippet"), "output:\n\(stderr)\n\(stdout)") } +#if !os(Windows) // https://github.com/swiftlang/swift-package-manager/issues/8774 // Try again with the Swift Build build system try await fixture(name: "Miscellaneous/Plugins") { path in let (stdout, stderr) = try await executeSwiftPackage(path.appending("PluginsAndSnippets"), configuration: .Debug, extraArgs: ["--build-system", "swiftbuild", "do-something"]) XCTAssert(stdout.contains("type of snippet target: snippet"), "output:\n\(stderr)\n\(stdout)") } +#endif } func testIncorrectDependencies() async throws { @@ -1161,11 +1173,13 @@ final class PluginTests: XCTestCase { XCTAssert(stdout.contains("Build complete!"), "output:\n\(stderr)\n\(stdout)") } +#if !os(Windows) // https://github.com/swiftlang/swift-package-manager/issues/8774 // Try again with the Swift Build build system try await fixture(name: "Miscellaneous/Plugins") { path in let (stdout, stderr) = try await executeSwiftBuild(path.appending("IncorrectDependencies"), extraArgs: ["--build-system", "swiftbuild", "--build-tests"]) XCTAssert(stdout.contains("Build complete!"), "output:\n\(stderr)\n\(stdout)") } +#endif } func testSandboxViolatingBuildToolPluginCommands() async throws { @@ -1203,11 +1217,13 @@ final class PluginTests: XCTestCase { XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)") } +#if !os(Windows) // https://github.com/swiftlang/swift-package-manager/issues/8774 // Try again with Swift Build build system try await fixture(name: "Miscellaneous/Plugins") { fixturePath in let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("TransitivePluginOnlyDependency"), extraArgs: ["--build-system", "swiftbuild"]) XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)") } +#endif } func testMissingPlugin() async throws { @@ -1222,6 +1238,7 @@ final class PluginTests: XCTestCase { } } +#if !os(Windows) // https://github.com/swiftlang/swift-package-manager/issues/8774 try await fixture(name: "Miscellaneous/Plugins") { fixturePath in do { try await executeSwiftBuild(fixturePath.appending("MissingPlugin"), extraArgs: ["--build-system", "swiftbuild"]) @@ -1229,6 +1246,7 @@ final class PluginTests: XCTestCase { XCTAssert(stderr.contains("error: 'missingplugin': no plugin named 'NonExistingPlugin' found"), "stderr:\n\(stderr)") } } +#endif } func testPluginCanBeReferencedByProductName() async throws { @@ -1242,11 +1260,13 @@ final class PluginTests: XCTestCase { XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)") } +#if !os(Windows) // https://github.com/swiftlang/swift-package-manager/issues/8774 // Try again with the Swift Build build system try await fixture(name: "Miscellaneous/Plugins") { fixturePath in let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("PluginCanBeReferencedByProductName"), extraArgs: ["--build-system", "swiftbuild"]) XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)") } +#endif } func testPluginCanBeAffectedByXBuildToolsParameters() async throws { @@ -1310,9 +1330,11 @@ final class PluginTests: XCTestCase { XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)") } +#if !os(Windows) // https://github.com/swiftlang/swift-package-manager/issues/8774 try await fixture(name: "Miscellaneous/Plugins/DependentPlugins") { fixturePath in let (stdout, _) = try await executeSwiftBuild(fixturePath, extraArgs: ["--build-system", "swiftbuild"]) XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)") } +#endif } } From 4b4b96f25362e343273d8bd45242d6c596f73162 Mon Sep 17 00:00:00 2001 From: Chris McGee Date: Fri, 6 Jun 2025 11:57:52 -0400 Subject: [PATCH 5/5] Give stderr on failing sdk install test case for Windows --- Tests/CommandsTests/SwiftSDKCommandTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/CommandsTests/SwiftSDKCommandTests.swift b/Tests/CommandsTests/SwiftSDKCommandTests.swift index 5f0ad97665d..aba11289047 100644 --- a/Tests/CommandsTests/SwiftSDKCommandTests.swift +++ b/Tests/CommandsTests/SwiftSDKCommandTests.swift @@ -66,7 +66,7 @@ final class SwiftSDKCommandTests: CommandsTestCase { // We only expect tool's output on the stdout stream. XCTAssertMatch( - stdout, + stdout + "\nstderr:\n" + stderr, .contains("\(bundle)` successfully installed as test-sdk.artifactbundle.") )