Skip to content

Commit

Permalink
Merge pull request #154 from dmhts/bugfix/sdk-environment-fixes
Browse files Browse the repository at this point in the history
Follow-up / Making Scipio environment-configurable
  • Loading branch information
giginet authored Nov 18, 2024
2 parents 10490f9 + 4614bdd commit 8bab62a
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 19 deletions.
17 changes: 13 additions & 4 deletions Sources/ScipioKit/DescriptionPackage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,21 @@ struct DescriptionPackage: PackageLocator {
/// Then, use package versions only from existing Package.resolved.
/// If it is `true`, Package.resolved never be updated.
/// Instead, the resolving will fail if the Package.resolved is mis-matched with the workspace.
init(packageDirectory: ScipioAbsolutePath, mode: Runner.Mode, onlyUseVersionsFromResolvedFile: Bool) throws {
init(
packageDirectory: ScipioAbsolutePath,
mode: Runner.Mode,
onlyUseVersionsFromResolvedFile: Bool,
toolchainEnvironment: ToolchainEnvironment? = nil
) throws {
self.packageDirectory = packageDirectory
self.mode = mode

let toolchain = try UserToolchain(swiftSDK: try .hostSwiftSDK())
self.toolchain = toolchain
self.toolchain = try UserToolchain(
swiftSDK: try .hostSwiftSDK(
toolchainEnvironment?.toolchainBinPath,
environment: toolchainEnvironment?.asSwiftPMEnvironment ?? .current
),
environment: toolchainEnvironment?.asSwiftPMEnvironment ?? .current
)

let workspace = try Self.makeWorkspace(toolchain: toolchain, packagePath: packageDirectory)
let scope = makeObservabilitySystem().topScope
Expand Down
7 changes: 4 additions & 3 deletions Sources/ScipioKit/Producer/FrameworkProducer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ struct FrameworkProducer {
private let overwrite: Bool
private let outputDir: URL
private let fileSystem: any FileSystem
private let toolchainEnvironment: [String: String]?
private let toolchainEnvironment: ToolchainEnvironment?

private var cacheStorage: (any CacheStorage)? {
switch cacheMode {
Expand Down Expand Up @@ -52,7 +52,7 @@ struct FrameworkProducer {
cacheMode: Runner.Options.CacheMode,
overwrite: Bool,
outputDir: URL,
toolchainEnvironment: [String: String]? = nil,
toolchainEnvironment: ToolchainEnvironment? = nil,
fileSystem: any FileSystem = localFileSystem
) {
self.descriptionPackage = descriptionPackage
Expand Down Expand Up @@ -280,7 +280,8 @@ struct FrameworkProducer {
let compiler = PIFCompiler(
descriptionPackage: descriptionPackage,
buildOptions: buildOptions,
buildOptionsMatrix: buildOptionsMatrix
buildOptionsMatrix: buildOptionsMatrix,
toolchainEnvironment: toolchainEnvironment
)
try await compiler.createXCFramework(buildProduct: product,
outputDirectory: outputDir,
Expand Down
4 changes: 2 additions & 2 deletions Sources/ScipioKit/Producer/PIF/PIFCompiler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ struct PIFCompiler: Compiler {
private let fileSystem: any FileSystem
private let executor: any Executor
private let buildOptionsMatrix: [String: BuildOptions]
private let toolchainEnvironment: [String: String]?
private let toolchainEnvironment: ToolchainEnvironment?

private let buildParametersGenerator: BuildParametersGenerator

init(
descriptionPackage: DescriptionPackage,
buildOptions: BuildOptions,
buildOptionsMatrix: [String: BuildOptions],
toolchainEnvironment: [String: String]? = nil,
toolchainEnvironment: ToolchainEnvironment? = nil,
fileSystem: any FileSystem = TSCBasic.localFileSystem,
executor: any Executor = ProcessExecutor()
) {
Expand Down
47 changes: 41 additions & 6 deletions Sources/ScipioKit/Producer/PIF/ToolchainGenerator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ struct ToolchainGenerator {
let destination: SwiftSDK = try await makeDestination(sdk: sdk)
return try UserToolchain(
swiftSDK: destination,
environment: environment.map(Environment.init) ?? .current
environment: environment?.asSwiftPMEnvironment ?? .current
)
}

Expand All @@ -44,11 +44,11 @@ struct ToolchainGenerator {
// Compute common arguments for clang and swift.
var extraCCFlags: [String] = []
var extraSwiftCFlags: [String] = []
let sdkPaths = try SwiftSDK.sdkPlatformFrameworkPaths(environment: [:])
extraCCFlags += ["-F", sdkPaths.fwk.pathString]
extraSwiftCFlags += ["-F", sdkPaths.fwk.pathString]
extraSwiftCFlags += ["-I", sdkPaths.lib.pathString]
extraSwiftCFlags += ["-L", sdkPaths.lib.pathString]
let macosSDKPlatformPaths = try await resolveSDKPlatformFrameworkPaths()
extraCCFlags += ["-F", macosSDKPlatformPaths.frameworkPath.pathString]
extraSwiftCFlags += ["-F", macosSDKPlatformPaths.frameworkPath.pathString]
extraSwiftCFlags += ["-I", macosSDKPlatformPaths.libPath.pathString]
extraSwiftCFlags += ["-L", macosSDKPlatformPaths.libPath.pathString]

let buildFlags = BuildFlags(cCompilerFlags: extraCCFlags, swiftCompilerFlags: extraSwiftCFlags)
return SwiftSDK(
Expand All @@ -60,3 +60,38 @@ struct ToolchainGenerator {
)
}
}

extension ToolchainGenerator {

/// A non-caching environment-aware implementation of `SwiftSDK.sdkPlatformFrameworkPaths`
/// This implementation is based on the original SwiftPM
/// https://github.com/swiftlang/swift-package-manager/blob/release/6.0/Sources/PackageModel/SwiftSDKs/SwiftSDK.swift#L592-L595
/// Returns `macosx` sdk platform framework path.
fileprivate func resolveSDKPlatformFrameworkPaths() async throws -> (frameworkPath: AbsolutePath, libPath: AbsolutePath) {
let platformPath = try await executor.execute(
"/usr/bin/xcrun",
"--sdk",
"macosx",
"--show-sdk-platform-path"
)
.unwrapOutput()
.spm_chomp()

guard !platformPath.isEmpty else {
throw StringError("could not determine SDK platform path")
}

// For XCTest framework.
let frameworkPath = try AbsolutePath(validating: platformPath).appending(
components: "Developer", "Library", "Frameworks"
)

// For XCTest Swift library.
let libPath = try AbsolutePath(validating: platformPath).appending(
components: "Developer", "usr", "lib"
)

return (frameworkPath, libPath)
}

}
10 changes: 6 additions & 4 deletions Sources/ScipioKit/Runner.swift
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ public struct Runner {
descriptionPackage = try DescriptionPackage(
packageDirectory: packagePath,
mode: mode,
onlyUseVersionsFromResolvedFile: false
onlyUseVersionsFromResolvedFile: false,
toolchainEnvironment: options.toolchainEnvironment
)
} catch {
throw Error.invalidPackage(packageDirectory)
Expand All @@ -99,7 +100,8 @@ public struct Runner {
buildOptionsMatrix: buildOptionsMatrix,
cacheMode: options.cacheMode,
overwrite: options.overwrite,
outputDir: outputDir
outputDir: outputDir,
toolchainEnvironment: options.toolchainEnvironment
)
do {
try await producer.produce()
Expand Down Expand Up @@ -240,7 +242,7 @@ extension Runner {
public var cacheMode: CacheMode
public var overwrite: Bool
public var verbose: Bool
public var toolchainEnvironment: [String: String]?
public var toolchainEnvironment: ToolchainEnvironment?

public init(
baseBuildOptions: BuildOptions = .init(),
Expand All @@ -249,7 +251,7 @@ extension Runner {
cacheMode: CacheMode = .project,
overwrite: Bool = false,
verbose: Bool = false,
toolchainEnvironment: [String: String]? = nil
toolchainEnvironment: ToolchainEnvironment? = nil
) {
self.buildOptionsContainer = BuildOptionsContainer(
baseBuildOptions: baseBuildOptions,
Expand Down
19 changes: 19 additions & 0 deletions Sources/ScipioKit/ToolchainEnvironment.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import struct Basics.AbsolutePath
@_spi(SwiftPMInternal) import struct Basics.Environment

public typealias ToolchainEnvironment = [String: String]

extension ToolchainEnvironment {
var developerDirPath: String? { self["DEVELOPER_DIR"] }
var toolchainBinPath: Basics.AbsolutePath? {
if let developerDirPath {
return try? AbsolutePath(validating: developerDirPath)
.appending(components: "Toolchains", "XcodeDefault.xctoolchain", "usr", "bin")
}
return nil
}
}

extension ToolchainEnvironment {
var asSwiftPMEnvironment: Environment { Environment(self) }
}
19 changes: 19 additions & 0 deletions Tests/ScipioKitTests/ToolchainEnvironmentTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import XCTest
@testable import ScipioKit
@_spi(SwiftPMInternal) import struct Basics.Environment

final class ToolchainEnvironmentTests: XCTestCase {

func testBasics() {
let environment = [
"DEVELOPER_DIR": "/Applications/Xcode.app/Contents/Developer",
]

XCTAssertEqual(environment.developerDirPath, "/Applications/Xcode.app/Contents/Developer")
XCTAssertEqual(
environment.toolchainBinPath?.pathString,
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin"
)
}

}

0 comments on commit 8bab62a

Please sign in to comment.