Skip to content
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

Fix some warnings with ProcessEnvironmentBlock #7364

Draft
wants to merge 8 commits into
base: main
Choose a base branch
from
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ let package = Package(
/** Support for building using Xcode's build system */
name: "XCBuildSupport",
dependencies: ["SPMBuildCore", "PackageGraph"],
exclude: ["CMakeLists.txt", "CODEOWNERS"]
exclude: ["CODEOWNERS"]
),
.target(
/** High level functionality */
Expand Down
2 changes: 1 addition & 1 deletion Sources/Basics/Concurrency/ConcurrencyHelpers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import func TSCBasic.tsc_await

public enum Concurrency {
public static var maxOperations: Int {
ProcessEnv.vars["SWIFTPM_MAX_CONCURRENT_OPERATIONS"].flatMap(Int.init) ?? ProcessInfo.processInfo
ProcessEnv.block["SWIFTPM_MAX_CONCURRENT_OPERATIONS"].flatMap(Int.init) ?? ProcessInfo.processInfo
.activeProcessorCount
}
}
Expand Down
22 changes: 10 additions & 12 deletions Sources/Basics/EnvironmentVariables.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,35 +11,38 @@
//===----------------------------------------------------------------------===//

import class Foundation.ProcessInfo
import typealias TSCBasic.ProcessEnvironmentBlock
import struct TSCBasic.ProcessEnvironmentKey
import enum TSCBasic.ProcessEnv

public typealias EnvironmentVariables = [String: String]
public typealias EnvironmentVariables = ProcessEnvironmentBlock
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to worry about this accidentally causing build issues?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we expose it anywhere outside of SwiftPM to any clients, at least not on purpose. IIUC corresponding TSC APIs were widely adopted instead. As soon as package support is merged in my other PR, I'll try using package visibility here to prevent any unintended adoption of this typealias in the future.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could use SPI in the meantime, would also make it easy to remember all the places we want package 😅

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And can now use package.


extension EnvironmentVariables {
public static func empty() -> EnvironmentVariables {
[:]
}

public static func process() -> EnvironmentVariables {
ProcessInfo.processInfo.environment
ProcessEnv.block
}

public mutating func prependPath(_ key: String, value: String) {
public mutating func prependPath(_ key: ProcessEnvironmentKey, value: String) {
var values = value.isEmpty ? [] : [value]
if let existing = self[key], !existing.isEmpty {
values.append(existing)
}
self.setPath(key, values)
}

public mutating func appendPath(_ key: String, value: String) {
public mutating func appendPath(_ key: ProcessEnvironmentKey, value: String) {
var values = value.isEmpty ? [] : [value]
if let existing = self[key], !existing.isEmpty {
values.insert(existing, at: 0)
}
self.setPath(key, values)
}

private mutating func setPath(_ key: String, _ values: [String]) {
private mutating func setPath(_ key: ProcessEnvironmentKey, _ values: [String]) {
#if os(Windows)
let delimiter = ";"
#else
Expand All @@ -50,12 +53,7 @@ extension EnvironmentVariables {

/// `PATH` variable in the process's environment (`Path` under Windows).
public var path: String? {
#if os(Windows)
let pathArg = "Path"
#else
let pathArg = "PATH"
#endif
return self[pathArg]
ProcessEnv.path
}
}

Expand All @@ -64,7 +62,7 @@ extension EnvironmentVariables {
// rdar://107029374
extension EnvironmentVariables {
// internal for testing
static let nonCachableKeys: Set<String> = [
static let nonCachableKeys: Set<ProcessEnvironmentKey> = [
"TERM",
"TERM_PROGRAM",
"TERM_PROGRAM_VERSION",
Expand Down
2 changes: 1 addition & 1 deletion Sources/Basics/ImportScanning.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public struct SwiftcImportScanner: ImportScanner {
filePathToScan.pathString,
"-scan-dependencies", "-Xfrontend", "-import-prescan"] + self.swiftCompilerFlags

let result = try await TSCBasic.Process.popen(arguments: cmd, environment: self.swiftCompilerEnvironment)
let result = try await TSCBasic.Process.popen(arguments: cmd, environmentBlock: self.swiftCompilerEnvironment)

let stdout = try result.utf8Output()
return try JSONDecoder.makeWithDefaults().decode(Imports.self, from: stdout).imports
Expand Down
2 changes: 1 addition & 1 deletion Sources/Build/BuildOperation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -759,7 +759,7 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
if !pluginConfiguration.disableSandbox {
commandLine = try Sandbox.apply(command: commandLine, fileSystem: self.fileSystem, strictness: .writableTemporaryDirectory, writableDirectories: [pluginResult.pluginOutputDirectory])
}
let processResult = try Process.popen(arguments: commandLine, environment: command.configuration.environment)
let processResult = try Process.popen(arguments: commandLine, environmentBlock: command.configuration.environment)
let output = try processResult.utf8Output() + processResult.utf8stderrOutput()
if processResult.exitStatus != .terminated(code: 0) {
throw StringError("failed: \(command)\n\n\(output)")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,7 @@ final class PackageStructureCommand: CustomLLBuildCommand {
var hash = Data()
hash += try! encoder.encode(self.context.productsBuildParameters)
hash += try! encoder.encode(self.context.toolsBuildParameters)
hash += try! encoder.encode(ProcessEnv.vars)
hash += try! encoder.encode(ProcessEnv.block)
return [UInt8](hash)
}

Expand Down
2 changes: 1 addition & 1 deletion Sources/Build/BuildPlan/BuildPlan.swift
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ extension BuildParameters {
get throws {
// FIXME: We use this hack to let swiftpm's functional test use shared
// cache so it doesn't become painfully slow.
if let path = ProcessEnv.vars["SWIFTPM_TESTS_MODULECACHE"] {
if let path = ProcessEnv.block["SWIFTPM_TESTS_MODULECACHE"] {
return try AbsolutePath(validating: path)
}
return buildPath.appending("ModuleCache")
Expand Down
3 changes: 2 additions & 1 deletion Sources/Commands/PackageTools/InstalledPackages.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//

import ArgumentParser
import typealias Basics.EnvironmentVariables
import CoreCommands
import Foundation
import PackageModel
Expand All @@ -32,7 +33,7 @@ extension SwiftPackageTool {
func run(_ tool: SwiftTool) throws {
let swiftpmBinDir = try tool.fileSystem.getOrCreateSwiftPMInstalledBinariesDirectory()

let env = ProcessInfo.processInfo.environment
let env = EnvironmentVariables.process()

if let path = env.path, !path.contains(swiftpmBinDir.pathString), !globalOptions.logging.quiet {
tool.observabilityScope.emit(
Expand Down
10 changes: 7 additions & 3 deletions Sources/Commands/SwiftTestTool.swift
Original file line number Diff line number Diff line change
Expand Up @@ -743,7 +743,7 @@ final class TestRunner {
// The toolchain to use.
private let toolchain: UserToolchain

private let testEnv: [String: String]
private let testEnv: EnvironmentVariables

/// ObservabilityScope to emit diagnostics.
private let observabilityScope: ObservabilityScope
Expand Down Expand Up @@ -777,7 +777,7 @@ final class TestRunner {
additionalArguments: [String],
cancellator: Cancellator,
toolchain: UserToolchain,
testEnv: [String: String],
testEnv: EnvironmentVariables,
observabilityScope: ObservabilityScope,
library: BuildParameters.Testing.Library
) {
Expand Down Expand Up @@ -835,7 +835,11 @@ final class TestRunner {
stdout: outputHandler,
stderr: outputHandler
)
let process = TSCBasic.Process(arguments: try args(forTestAt: path), environment: self.testEnv, outputRedirection: outputRedirection)
let process = TSCBasic.Process(
arguments: try args(forTestAt: path),
environmentBlock: self.testEnv,
outputRedirection: outputRedirection
)
guard let terminationKey = self.cancellator.register(process) else {
return false // terminating
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/Commands/Utilities/TestingSupport.swift
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ enum TestingSupport {
sanitizers: sanitizers
)

try TSCBasic.Process.checkNonZeroExit(arguments: args, environment: env)
try TSCBasic.Process.checkNonZeroExit(arguments: args, environmentBlock: env)
// Read the temporary file's content.
return try swiftTool.fileSystem.readFileContents(AbsolutePath(tempFile.path))
}
Expand Down
6 changes: 3 additions & 3 deletions Sources/DriverSupport/SPMSwiftDriverExecutor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@ public final class SPMSwiftDriverExecutor: DriverExecutor {

public let resolver: ArgsResolver
let fileSystem: FileSystem
let env: EnvironmentVariables
let env: [String: String]

public init(resolver: ArgsResolver,
fileSystem: FileSystem,
env: EnvironmentVariables) {
env: [String: String]) {
self.resolver = resolver
self.fileSystem = fileSystem
self.env = env
Expand Down
6 changes: 3 additions & 3 deletions Sources/LLBuildManifest/LLBuildManifestWriter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -184,12 +184,12 @@ public struct ManifestToolStream {
}
}

public subscript(key: String) -> [String: String] {
public subscript(key: String) -> EnvironmentVariables {
get { fatalError() }
set {
self.buffer += " \(key):\n"
for (key, value) in newValue.sorted(by: { $0.key < $1.key }) {
self.buffer += " \(key.asJSON): \(value.asJSON)\n"
for (key, value) in newValue.sorted(by: { $0.key.value < $1.key.value }) {
self.buffer += " \(key.value.asJSON): \(value.asJSON)\n"
}
}
}
Expand Down
20 changes: 13 additions & 7 deletions Sources/PackageLoading/ManifestLoader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -857,7 +857,9 @@ public final class ManifestLoader: ManifestLoaderProtocol {

// FIXME: Workaround for the module cache bug that's been haunting Swift CI
// <rdar://problem/48443680>
let moduleCachePath = try (ProcessEnv.vars["SWIFTPM_MODULECACHE_OVERRIDE"] ?? ProcessEnv.vars["SWIFTPM_TESTS_MODULECACHE"]).flatMap{ try AbsolutePath(validating: $0) }
let moduleCachePath = try (
ProcessEnv.block["SWIFTPM_MODULECACHE_OVERRIDE"] ?? ProcessEnv.block["SWIFTPM_TESTS_MODULECACHE"]
).flatMap { try AbsolutePath(validating: $0) }

var cmd: [String] = []
cmd += [self.toolchain.swiftCompilerPathForManifests.pathString]
Expand Down Expand Up @@ -955,7 +957,11 @@ public final class ManifestLoader: ManifestLoaderProtocol {
evaluationResult.compilerCommandLine = cmd

// Compile the manifest.
TSCBasic.Process.popen(arguments: cmd, environment: self.toolchain.swiftCompilerEnvironment, queue: callbackQueue) { result in
TSCBasic.Process.popen(
arguments: cmd,
environmentBlock: self.toolchain.swiftCompilerEnvironment,
queue: callbackQueue
) { result in
dispatchPrecondition(condition: .onQueue(callbackQueue))

var cleanupIfError = DelayableAction(target: tmpDir, action: cleanupTmpDir)
Expand Down Expand Up @@ -1047,14 +1053,14 @@ public final class ManifestLoader: ManifestLoaderProtocol {
)
}

var environment = ProcessEnv.vars
var environment = ProcessEnv.block
#if os(Windows)
let windowsPathComponent = runtimePath.pathString.replacingOccurrences(of: "/", with: "\\")
environment["Path"] = "\(windowsPathComponent);\(environment["Path"] ?? "")"
#endif

let cleanupAfterRunning = cleanupIfError.delay()
TSCBasic.Process.popen(arguments: cmd, environment: environment, queue: callbackQueue) { result in
TSCBasic.Process.popen(arguments: cmd, environmentBlock: environment, queue: callbackQueue) { result in
dispatchPrecondition(condition: .onQueue(callbackQueue))

defer { cleanupAfterRunning.perform() }
Expand Down Expand Up @@ -1236,8 +1242,8 @@ extension ManifestLoader {
stream.send(packageLocation)
stream.send(manifestContents)
stream.send(toolsVersion.description)
for (key, value) in env.sorted(by: { $0.key > $1.key }) {
stream.send(key).send(value)
for (key, value) in env.sorted(by: { $0.key.value > $1.key.value }) {
stream.send(key.value).send(value)
}
stream.send(swiftpmVersion)
return stream.bytes.sha256Checksum
Expand Down Expand Up @@ -1301,6 +1307,6 @@ extension ManifestLoader {

extension ProcessEnv {
fileprivate static var cachableVars: EnvironmentVariables {
Self.vars.cachable
Self.block.cachable
}
}
4 changes: 2 additions & 2 deletions Sources/PackageLoading/PkgConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ public struct PkgConfig {

private static var envSearchPaths: [AbsolutePath] {
get throws {
if let configPath = ProcessEnv.vars["PKG_CONFIG_PATH"] {
if let configPath = ProcessEnv.block["PKG_CONFIG_PATH"] {
#if os(Windows)
return try configPath.split(separator: ";").map({ try AbsolutePath(validating: String($0)) })
#else
Expand Down Expand Up @@ -183,7 +183,7 @@ internal struct PkgConfigParser {
variables["pcfiledir"] = pcFile.parentDirectory.pathString

// Add pc_sysrootdir variable. This is the path of the sysroot directory for pc files.
variables["pc_sysrootdir"] = ProcessEnv.vars["PKG_CONFIG_SYSROOT_DIR"] ?? AbsolutePath.root.pathString
variables["pc_sysrootdir"] = ProcessEnv.block["PKG_CONFIG_SYSROOT_DIR"] ?? AbsolutePath.root.pathString

let fileContents: String = try fileSystem.readFileContents(pcFile)
for line in fileContents.components(separatedBy: "\n") {
Expand Down
23 changes: 7 additions & 16 deletions Sources/PackageModel/SwiftSDKs/SwiftSDK.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import Foundation

import class TSCBasic.Process
import enum TSCBasic.ProcessEnv
import typealias TSCBasic.ProcessEnvironmentBlock

import struct TSCUtility.Version

Expand Down Expand Up @@ -446,29 +447,19 @@ public struct SwiftSDK: Equatable {
return try AbsolutePath(validating: CommandLine.arguments[0], relativeTo: cwd).parentDirectory
}

/// The Swift SDK describing the host platform.
@available(*, deprecated, renamed: "hostSwiftSDK")
public static func hostDestination(
_ binDir: AbsolutePath? = nil,
originalWorkingDirectory: AbsolutePath? = nil,
environment: [String: String] = ProcessEnv.vars
) throws -> SwiftSDK {
try self.hostSwiftSDK(binDir, originalWorkingDirectory: originalWorkingDirectory, environment: environment)
}

/// The Swift SDK for the host platform.
public static func hostSwiftSDK(
_ binDir: AbsolutePath? = nil,
originalWorkingDirectory: AbsolutePath? = nil,
environment: [String: String] = ProcessEnv.vars,
environment: ProcessEnvironmentBlock = ProcessEnv.block,
observabilityScope: ObservabilityScope? = nil
) throws -> SwiftSDK {
let originalWorkingDirectory = originalWorkingDirectory ?? localFileSystem.currentWorkingDirectory
// Select the correct binDir.
if ProcessEnv.vars["SWIFTPM_CUSTOM_BINDIR"] != nil {
if ProcessEnv.block["SWIFTPM_CUSTOM_BINDIR"] != nil {
print("SWIFTPM_CUSTOM_BINDIR was deprecated in favor of SWIFTPM_CUSTOM_BIN_DIR")
}
let customBinDir = (ProcessEnv.vars["SWIFTPM_CUSTOM_BIN_DIR"] ?? ProcessEnv.vars["SWIFTPM_CUSTOM_BINDIR"])
let customBinDir = (ProcessEnv.block["SWIFTPM_CUSTOM_BIN_DIR"] ?? ProcessEnv.block["SWIFTPM_CUSTOM_BINDIR"])
.flatMap { try? AbsolutePath(validating: $0) }
let binDir = try customBinDir ?? binDir ?? SwiftSDK.hostBinDir(
fileSystem: localFileSystem,
Expand All @@ -478,13 +469,13 @@ public struct SwiftSDK: Equatable {
let sdkPath: AbsolutePath?
#if os(macOS)
// Get the SDK.
if let value = ProcessEnv.vars["SDKROOT"] {
if let value = ProcessEnv.block["SDKROOT"] {
sdkPath = try AbsolutePath(validating: value)
} else {
// No value in env, so search for it.
let sdkPathStr = try TSCBasic.Process.checkNonZeroExit(
arguments: ["/usr/bin/xcrun", "--sdk", "macosx", "--show-sdk-path"],
environment: environment
environmentBlock: environment
).spm_chomp()
guard !sdkPathStr.isEmpty else {
throw SwiftSDKError.invalidInstallation("default SDK not found")
Expand Down Expand Up @@ -541,7 +532,7 @@ public struct SwiftSDK: Equatable {
}
let platformPath = try TSCBasic.Process.checkNonZeroExit(
arguments: ["/usr/bin/xcrun", "--sdk", "macosx", "--show-sdk-platform-path"],
environment: environment
environmentBlock: environment
).spm_chomp()

guard !platformPath.isEmpty else {
Expand Down
7 changes: 4 additions & 3 deletions Sources/PackageModel/UserToolchain.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import Basics
import Foundation

import class TSCBasic.Process
import struct TSCBasic.ProcessEnvironmentKey

#if os(Windows)
private let hostExecutableSuffix = ".exe"
Expand Down Expand Up @@ -117,7 +118,7 @@ public final class UserToolchain: Toolchain {
searchPaths: [AbsolutePath],
environment: EnvironmentVariables
) -> AbsolutePath? {
lookupExecutablePath(filename: environment[variable], searchPaths: searchPaths)
lookupExecutablePath(filename: environment[.init(variable)], searchPaths: searchPaths)
}

private static func getTool(_ name: String, binDirectories: [AbsolutePath]) throws -> AbsolutePath {
Expand Down Expand Up @@ -755,7 +756,7 @@ public final class UserToolchain: Toolchain {
private static func derivePluginServerPath(triple: Triple) throws -> AbsolutePath? {
if triple.isDarwin() {
let pluginServerPathFindArgs = ["/usr/bin/xcrun", "--find", "swift-plugin-server"]
if let path = try? TSCBasic.Process.checkNonZeroExit(arguments: pluginServerPathFindArgs, environment: [:])
if let path = try? TSCBasic.Process.checkNonZeroExit(arguments: pluginServerPathFindArgs, environmentBlock: [:])
.spm_chomp() {
return try AbsolutePath(validating: path)
}
Expand All @@ -772,7 +773,7 @@ public final class UserToolchain: Toolchain {
if triple.isDarwin() {
// XCTest is optional on macOS, for example when Xcode is not installed
let xctestFindArgs = ["/usr/bin/xcrun", "--sdk", "macosx", "--find", "xctest"]
if let path = try? TSCBasic.Process.checkNonZeroExit(arguments: xctestFindArgs, environment: environment)
if let path = try? TSCBasic.Process.checkNonZeroExit(arguments: xctestFindArgs, environmentBlock: environment)
.spm_chomp()
{
return try AbsolutePath(validating: path)
Expand Down
4 changes: 2 additions & 2 deletions Sources/SPMBuildCore/BuildSystem/BuildSystem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,8 @@ public enum BuildSystemUtilities {
/// Returns the build path from the environment, if present.
public static func getEnvBuildPath(workingDir: AbsolutePath) throws -> AbsolutePath? {
// Don't rely on build path from env for SwiftPM's own tests.
guard ProcessEnv.vars["SWIFTPM_TESTS_MODULECACHE"] == nil else { return nil }
guard let env = ProcessEnv.vars["SWIFTPM_BUILD_DIR"] else { return nil }
guard ProcessEnv.block["SWIFTPM_TESTS_MODULECACHE"] == nil else { return nil }
guard let env = ProcessEnv.block["SWIFTPM_BUILD_DIR"] else { return nil }
return try AbsolutePath(validating: env, relativeTo: workingDir)
}
}