Skip to content

[5.5] Allow a custom manifest loader to provide custom environment variables when compiling the manifest #3667

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions Sources/PackageLoading/ManifestLoader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,11 @@ public protocol ManifestResourceProvider {
/// The bin directory.
var binDir: AbsolutePath? { get }

/// Extra flags to pass the Swift compiler.
/// Extra flags to pass the Swift compiler (if not specified, no additional arguments are passed).
var swiftCompilerFlags: [String] { get }

/// Custom environment to pass to the Swift compiler (if not specified, the inherited environment is passed).
var swiftCompilerEnvironment: [String: String] { get }

/// XCTest Location
var xctestLocation: AbsolutePath? { get }
Expand All @@ -63,6 +66,10 @@ public extension ManifestResourceProvider {
var swiftCompilerFlags: [String] {
return []
}

var swiftCompilerEnvironment: [String: String] {
return ProcessEnv.vars
}

var xctestLocation: AbsolutePath? {
return nil
Expand Down Expand Up @@ -666,8 +673,8 @@ public final class ManifestLoader: ManifestLoaderProtocol {
stream <<< packageIdentity
stream <<< manifestContents
stream <<< toolsVersion.description
for key in env.keys.sorted(by: >) {
stream <<< key <<< env[key]! // forced unwrap safe
for (key, value) in env.sorted(by: { $0.key > $1.key }) {
stream <<< key <<< value
}
stream <<< swiftpmVersion
return stream.bytes.sha256Checksum
Expand Down Expand Up @@ -807,9 +814,11 @@ public final class ManifestLoader: ManifestLoaderProtocol {
#endif
let compiledManifestFile = tmpDir.appending(component: "\(packageIdentity)-manifest\(executableSuffix)")
cmd += ["-o", compiledManifestFile.pathString]

let compilerEnv = resources.swiftCompilerEnvironment

// Compile the manifest.
let compilerResult = try Process.popen(arguments: cmd)
let compilerResult = try Process.popen(arguments: cmd, environment: compilerEnv)
let compilerOutput = try (compilerResult.utf8Output() + compilerResult.utf8stderrOutput()).spm_chuzzle()
manifestParseResult.compilerOutput = compilerOutput

Expand Down
4 changes: 3 additions & 1 deletion Sources/Workspace/DefaultPluginScriptRunner.swift
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,10 @@ public struct DefaultPluginScriptRunner: PluginScriptRunner {
command += sources.paths.map { $0.pathString }
let compiledExec = cacheDir.appending(component: "compiled-plugin")
command += ["-o", compiledExec.pathString]

let compilerEnv = resources.swiftCompilerEnvironment

let result = try Process.popen(arguments: command)
let result = try Process.popen(arguments: command, environment: compilerEnv)
let output = try (result.utf8Output() + result.utf8stderrOutput()).spm_chuzzle() ?? ""
if result.exitStatus != .terminated(code: 0) {
// TODO: Make this a proper error.
Expand Down
64 changes: 64 additions & 0 deletions Tests/PackageLoadingTests/PD5_0LoadingTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -547,4 +547,68 @@ class PackageDescription5_0LoadingTests: PackageDescriptionLoadingTests {
XCTAssertEqual(manifest.dependencies, [])
}
}

func testManifestLoaderEnvironment() throws {
try testWithTemporaryDirectory { path in
let fs = localFileSystem

struct CustomManifestResources: ManifestResourceProvider {
var swiftCompiler: AbsolutePath
var libDir: AbsolutePath
var binDir: AbsolutePath?
var sdkRoot: AbsolutePath?
var swiftCompilerEnvironment: [String: String]
}

let packagePath = path.appending(component: "pkg")
let manifestPath = packagePath.appending(component: "Package.swift")
try fs.writeFileContents(manifestPath) { stream in
stream <<< """
// swift-tools-version:5
import PackageDescription

let package = Package(
name: "Trivial",
targets: [
.target(
name: "foo",
dependencies: []),
]
)
"""
}

let moduleTraceFilePath = path.appending(component: "swift-module-trace")
var customManifestCompilerEnv = ProcessEnv.vars
customManifestCompilerEnv["SWIFT_LOADED_MODULE_TRACE_FILE"] = moduleTraceFilePath.pathString
let customResources = CustomManifestResources(
swiftCompiler: Resources.default.swiftCompiler,
libDir: Resources.default.libDir,
binDir: Resources.default.binDir,
sdkRoot: Resources.default.sdkRoot,
swiftCompilerEnvironment: customManifestCompilerEnv)
let manifestLoader = ManifestLoader(
manifestResources: customResources,
serializedDiagnostics: true,
isManifestSandboxEnabled: false,
cacheDir: nil)

let diagnostics = DiagnosticsEngine()
let manifest = try manifestLoader.load(
at: manifestPath.parentDirectory,
packageKind: .local,
packageLocation: manifestPath.pathString,
toolsVersion: .v5,
fileSystem: fs,
diagnostics: diagnostics
)

XCTAssertTrue(diagnostics.diagnostics.isEmpty)
XCTAssertEqual(manifest.name, "Trivial")

if let moduleTraceJSON = try? localFileSystem.readFileContents(moduleTraceFilePath).validDescription {
XCTAssert(moduleTraceJSON.contains("PackageDescription"))
}
}
}
}