diff --git a/Sources/SWBTestSupport/RunDestinationTestSupport.swift b/Sources/SWBTestSupport/RunDestinationTestSupport.swift index 247397b7..69b83184 100644 --- a/Sources/SWBTestSupport/RunDestinationTestSupport.swift +++ b/Sources/SWBTestSupport/RunDestinationTestSupport.swift @@ -316,6 +316,26 @@ extension RunDestinationInfo { return .elf } } + + /// An `Environment` object with `PATH` or `LD_LIBRARY_PATH` set appropriately pointing into the toolchain to be able to run a built Swift binary in tests. + /// + /// - note: On macOS, the OS provided Swift runtime is used, so `DYLD_LIBRARY_PATH` is never set for Mach-O destinations. + package func hostRuntimeEnvironment(_ core: Core, initialEnvironment: Environment = Environment()) -> Environment { + var environment = initialEnvironment + guard let toolchain = core.toolchainRegistry.defaultToolchain else { + return environment + } + switch imageFormat(core) { + case .elf: + environment.prependPath(key: "LD_LIBRARY_PATH", value: toolchain.path.join("usr/lib/swift/\(platform)").str) + case .pe: + environment.prependPath(key: .path, value: core.developerPath.path.join("Runtimes").join(toolchain.version.description).join("usr/bin").str) + case .macho: + // Fall back to the OS provided Swift runtime + break + } + return environment + } } extension _RunDestinationInfo { diff --git a/Tests/SWBBuildSystemTests/BuildOperationTests.swift b/Tests/SWBBuildSystemTests/BuildOperationTests.swift index ac9faf34..d6806ebc 100644 --- a/Tests/SWBBuildSystemTests/BuildOperationTests.swift +++ b/Tests/SWBBuildSystemTests/BuildOperationTests.swift @@ -145,15 +145,7 @@ fileprivate struct BuildOperationTests: CoreBasedTests { try await tester.checkBuild(runDestination: destination, signableTargets: Set(provisioningInputs.keys), signableTargetInputs: provisioningInputs) { results in results.checkNoErrors() - let toolchain = try #require(core.toolchainRegistry.defaultToolchain) - let environment: Environment - if destination.imageFormat(core) == .elf { - environment = ["LD_LIBRARY_PATH": toolchain.path.join("usr/lib/swift/\(destination.platform)").str] - } else { - environment = .init() - } - - let executionResult = try await Process.getOutput(url: URL(fileURLWithPath: projectDir.join("build").join("Debug\(destination.builtProductsDirSuffix)").join(core.hostOperatingSystem.imageFormat.executableName(basename: "tool")).str), arguments: [], environment: environment) + let executionResult = try await Process.getOutput(url: URL(fileURLWithPath: projectDir.join("build").join("Debug\(destination.builtProductsDirSuffix)").join(core.hostOperatingSystem.imageFormat.executableName(basename: "tool")).str), arguments: [], environment: destination.hostRuntimeEnvironment(core)) #expect(executionResult.exitStatus == .exit(0)) if core.hostOperatingSystem == .windows { #expect(String(decoding: executionResult.stdout, as: UTF8.self) == "Hello world\r\n") @@ -378,15 +370,7 @@ fileprivate struct BuildOperationTests: CoreBasedTests { } } - let toolchain = try #require(try await getCore().toolchainRegistry.defaultToolchain) - let environment: Environment - if destination.platform == "linux" { - environment = ["LD_LIBRARY_PATH": toolchain.path.join("usr/lib/swift/linux").str] - } else { - environment = .init() - } - - let executionResult = try await Process.getOutput(url: URL(fileURLWithPath: projectDir.join("build").join("Debug\(destination.builtProductsDirSuffix)").join(core.hostOperatingSystem.imageFormat.executableName(basename: "tool")).str), arguments: [], environment: environment) + let executionResult = try await Process.getOutput(url: URL(fileURLWithPath: projectDir.join("build").join("Debug\(destination.builtProductsDirSuffix)").join(core.hostOperatingSystem.imageFormat.executableName(basename: "tool")).str), arguments: [], environment: destination.hostRuntimeEnvironment(core)) #expect(executionResult.exitStatus == .exit(0)) if core.hostOperatingSystem == .windows { #expect(String(decoding: executionResult.stdout, as: UTF8.self) == "Hello world\r\n") @@ -508,13 +492,7 @@ fileprivate struct BuildOperationTests: CoreBasedTests { try await tester.checkBuild(runDestination: destination, persistent: true) { results in results.checkNoErrors() - let toolchain = try #require(try await getCore().toolchainRegistry.defaultToolchain) - let environment: Environment - if destination.platform == "linux" { - environment = ["LD_LIBRARY_PATH": "\(toolchain.path.join("usr/lib/swift/linux").str):\(projectDir.join("build").join("Debug\(destination.builtProductsDirSuffix)"))"] - } else { - environment = .init() - } + let environment = destination.hostRuntimeEnvironment(core) do { let executionResult = try await Process.getOutput(url: URL(fileURLWithPath: projectDir.join("build").join("Debug\(destination.builtProductsDirSuffix)").join(core.hostOperatingSystem.imageFormat.executableName(basename: "UnitTestRunner")).str), arguments: [], environment: environment) diff --git a/Tests/SWBBuildSystemTests/CustomTaskBuildOperationTests.swift b/Tests/SWBBuildSystemTests/CustomTaskBuildOperationTests.swift index f94d48ac..763d508a 100644 --- a/Tests/SWBBuildSystemTests/CustomTaskBuildOperationTests.swift +++ b/Tests/SWBBuildSystemTests/CustomTaskBuildOperationTests.swift @@ -30,12 +30,7 @@ fileprivate struct CustomTaskBuildOperationTests: CoreBasedTests { let destination: RunDestinationInfo = .host let core = try await getCore() let toolchain = try #require(core.toolchainRegistry.defaultToolchain) - let environment: [String: String] - if destination.imageFormat(core) == .elf { - environment = ["LD_LIBRARY_PATH": toolchain.path.join("usr/lib/swift/\(destination.platform)").str] - } else { - environment = ProcessInfo.processInfo.environment.filter { $0.key.uppercased() == "PATH" } // important to allow swift to be looked up in PATH on Windows/Linux - } + let environment = destination.hostRuntimeEnvironment(core) let testProject = TestProject( "aProject", @@ -69,7 +64,7 @@ fileprivate struct CustomTaskBuildOperationTests: CoreBasedTests { customTasks: [ TestCustomTask( commandLine: ["$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/tool\(destination == .windows ? ".exe" : "")"], - environment: environment, + environment: .init(environment), workingDirectory: tmpDir.str, executionDescription: "My Custom Task", inputs: ["$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/tool\(destination == .windows ? ".exe" : "")"],