Skip to content

Commit d0ae07b

Browse files
committed
refactor toolchain SwiftPM libraries path
motivation: improve logic in how Manifest and Plugin APIs locations are derived changes: * rename fields on ToolchainConfiguration to better articulate their meaning * change logic in UserToolchain to derive the SwiftPM libraries path more clearly and reliably * adjust call-sites and test
1 parent 7cb50e4 commit d0ae07b

File tree

10 files changed

+229
-141
lines changed

10 files changed

+229
-141
lines changed

Sources/Commands/SwiftRunTool.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ public struct SwiftRunTool: SwiftCommand {
136136
let arguments = buildOp.buildPlan!.createREPLArguments()
137137
print("Launching Swift REPL with arguments: \(arguments.joined(separator: " "))")
138138
try run(
139-
swiftTool.getToolchain().swiftInterpreter,
139+
swiftTool.getToolchain().swiftInterpreterPath,
140140
originalWorkingDirectory: swiftTool.originalWorkingDirectory,
141141
arguments: arguments)
142142

@@ -171,7 +171,7 @@ public struct SwiftRunTool: SwiftCommand {
171171
if let executable = options.executable, isValidSwiftFilePath(executable) {
172172
swiftTool.diagnostics.emit(.runFileDeprecation)
173173
// Redirect execution to the toolchain's swift executable.
174-
let swiftInterpreterPath = try swiftTool.getToolchain().swiftInterpreter
174+
let swiftInterpreterPath = try swiftTool.getToolchain().swiftInterpreterPath
175175
// Prepend the script to interpret to the arguments.
176176
let arguments = [executable] + options.arguments
177177
try run(

Sources/PackageLoading/ManifestLoader.swift

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -689,21 +689,20 @@ public final class ManifestLoader: ManifestLoaderProtocol {
689689
let moduleCachePath = (ProcessEnv.vars["SWIFTPM_MODULECACHE_OVERRIDE"] ?? ProcessEnv.vars["SWIFTPM_TESTS_MODULECACHE"]).flatMap{ AbsolutePath.init($0) }
690690

691691
var cmd: [String] = []
692-
cmd += [self.toolchain.swiftCompiler.pathString]
692+
cmd += [self.toolchain.swiftCompilerPath.pathString]
693693
cmd += verbosity.ccArgs
694694

695695
let macOSPackageDescriptionPath: AbsolutePath
696-
// If we got the binDir that means we could be developing SwiftPM in Xcode
696+
// if runtimePath is set to "PackageFrameworks" that means we could be developing SwiftPM in Xcode
697697
// which produces a framework for dynamic package products.
698-
let packageFrameworkPath = runtimePath.appending(component: "PackageFrameworks")
699-
if self.toolchain.binDir != nil, localFileSystem.exists(packageFrameworkPath) {
698+
if runtimePath.basename == "PackageFrameworks" {
700699
cmd += [
701-
"-F", packageFrameworkPath.pathString,
700+
"-F", runtimePath.pathString,
702701
"-framework", "PackageDescription",
703-
"-Xlinker", "-rpath", "-Xlinker", packageFrameworkPath.pathString,
702+
"-Xlinker", "-rpath", "-Xlinker", runtimePath.pathString,
704703
]
705704

706-
macOSPackageDescriptionPath = packageFrameworkPath.appending(RelativePath("PackageDescription.framework/PackageDescription"))
705+
macOSPackageDescriptionPath = runtimePath.appending(RelativePath("PackageDescription.framework/PackageDescription"))
707706
} else {
708707
cmd += [
709708
"-L", runtimePath.pathString,
@@ -722,7 +721,7 @@ public final class ManifestLoader: ManifestLoaderProtocol {
722721
// Use the same minimum deployment target as the PackageDescription library (with a fallback of 10.15).
723722
#if os(macOS)
724723
let triple = Self._hostTriple.memoize {
725-
Triple.getHostTriple(usingSwiftCompiler: self.toolchain.swiftCompiler)
724+
Triple.getHostTriple(usingSwiftCompiler: self.toolchain.swiftCompilerPath)
726725
}
727726

728727
let version = try Self._packageDescriptionMinimumDeploymentTarget.memoize {
@@ -853,9 +852,15 @@ public final class ManifestLoader: ManifestLoaderProtocol {
853852
var cmd = [String]()
854853
let runtimePath = self.runtimePath(for: toolsVersion)
855854
cmd += ["-swift-version", toolsVersion.swiftLanguageVersion.rawValue]
856-
cmd += ["-I", runtimePath.pathString]
855+
// if runtimePath is set to "PackageFrameworks" that means we could be developing SwiftPM in Xcode
856+
// which produces a framework for dynamic package products.
857+
if runtimePath.basename == "PackageFrameworks" {
858+
cmd += ["-I", runtimePath.parentDirectory.pathString]
859+
} else {
860+
cmd += ["-I", runtimePath.pathString]
861+
}
857862
#if os(macOS)
858-
if let sdkRoot = self.toolchain.sdkRoot ?? self.sdkRoot() {
863+
if let sdkRoot = self.toolchain.sdkRootPath ?? self.sdkRoot() {
859864
cmd += ["-sdk", sdkRoot.pathString]
860865
}
861866
#endif
@@ -865,19 +870,14 @@ public final class ManifestLoader: ManifestLoaderProtocol {
865870

866871
/// Returns the runtime path given the manifest version and path to libDir.
867872
private func runtimePath(for version: ToolsVersion) -> AbsolutePath {
868-
// Bin dir will be set when developing swiftpm without building all of the runtimes.
869-
if let binDir = self.toolchain.binDir {
870-
return binDir
871-
}
872-
873-
// Otherwise we use the standard location of the manifest API in the toolchain, if it exists.
874-
let manifestAPIDir = self.toolchain.libDir.appending(component: "ManifestAPI")
873+
let manifestAPIDir = self.toolchain.swiftPMLibrariesLocation.manifestAPI
875874
if localFileSystem.exists(manifestAPIDir) {
876875
return manifestAPIDir
877876
}
878-
879-
// Otherwise, fall back on the old location (this would indicate that we're using an old toolchain).
880-
return self.toolchain.libDir.appending(version.runtimeSubpath)
877+
878+
// FIXME: how do we test this?
879+
// Fall back on the old location (this would indicate that we're using an old toolchain).
880+
return self.toolchain.swiftPMLibrariesLocation.manifestAPI.parentDirectory.appending(version.runtimeSubpath)
881881
}
882882

883883
/// Returns path to the manifest database inside the given cache directory.

Sources/PackageModel/ToolchainConfiguration.swift

Lines changed: 58 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,34 +16,50 @@ import TSCBasic
1616
/// using the package manager with alternate toolchains in the future.
1717
public struct ToolchainConfiguration {
1818
/// The path of the swift compiler.
19-
public let swiftCompiler: AbsolutePath
19+
public let swiftCompilerPath: AbsolutePath
2020

2121
/// Extra flags to pass the Swift compiler.
2222
public let swiftCompilerFlags: [String]
2323

24-
/// The path of the library resources.
25-
public let libDir: AbsolutePath
26-
27-
/// The bin directory.
28-
public let binDir: AbsolutePath?
24+
/// SwiftPM library paths.
25+
public let swiftPMLibrariesLocation: SwiftPMLibrariesLocation
2926

3027
/// The path to SDK root.
3128
///
3229
/// If provided, it will be passed to the swift interpreter.
33-
public let sdkRoot: AbsolutePath?
30+
public let sdkRootPath: AbsolutePath?
3431

3532
/// XCTest Location
36-
public let xctestLocation: AbsolutePath?
33+
public let xctestPath: AbsolutePath?
3734

3835
/// Creates the set of manifest resources associated with a `swiftc` executable.
3936
///
4037
/// - Parameters:
41-
/// - swiftCompiler: The absolute path of the associated `swiftc` executable.
38+
/// - swiftCompilerPath: The absolute path of the associated `swiftc` executable.
4239
/// - swiftCompilerFlags: Extra flags to pass the Swift compiler.: Extra flags to pass the Swift compiler.
43-
/// - libDir: The path of the library resources.
44-
/// - binDir: The bin directory.
45-
/// - sdkRoot: The path to SDK root.
46-
/// - xctestLocation: XCTest Location
40+
/// - swiftPMLibrariesRootPath: Custom path for SwiftPM libraries.
41+
/// - sdkRootPath: The path to SDK root.
42+
/// - xctestPath: XCTest Location
43+
public init(
44+
swiftCompilerPath: AbsolutePath,
45+
swiftCompilerFlags: [String] = [],
46+
swiftPMLibrariesLocation: SwiftPMLibrariesLocation? = nil,
47+
sdkRootPath: AbsolutePath? = nil,
48+
xctestPath: AbsolutePath? = nil
49+
) {
50+
let swiftPMLibrariesLocation = swiftPMLibrariesLocation ?? {
51+
return .init(swiftCompilerPath: swiftCompilerPath)
52+
}()
53+
54+
self.swiftCompilerPath = swiftCompilerPath
55+
self.swiftCompilerFlags = swiftCompilerFlags
56+
self.swiftPMLibrariesLocation = swiftPMLibrariesLocation
57+
self.sdkRootPath = sdkRootPath
58+
self.xctestPath = xctestPath
59+
}
60+
61+
// deprecated 8/2021
62+
@available(*, deprecated, message: "use non-deprecated initializer instead")
4763
public init(
4864
swiftCompiler: AbsolutePath,
4965
swiftCompilerFlags: [String] = [],
@@ -52,15 +68,36 @@ public struct ToolchainConfiguration {
5268
sdkRoot: AbsolutePath? = nil,
5369
xctestLocation: AbsolutePath? = nil
5470
) {
55-
self.swiftCompiler = swiftCompiler
56-
self.swiftCompilerFlags = swiftCompilerFlags
57-
self.libDir = libDir ?? Self.libDir(forBinDir: swiftCompiler.parentDirectory)
58-
self.binDir = binDir
59-
self.sdkRoot = sdkRoot
60-
self.xctestLocation = xctestLocation
71+
self.init(
72+
swiftCompilerPath: swiftCompiler,
73+
swiftCompilerFlags: swiftCompilerFlags,
74+
swiftPMLibrariesLocation: libDir.map { .init(root: $0) },
75+
sdkRootPath: sdkRoot,
76+
xctestPath: xctestLocation
77+
)
6178
}
79+
}
80+
81+
extension ToolchainConfiguration {
82+
public struct SwiftPMLibrariesLocation {
83+
public var manifestAPI: AbsolutePath
84+
public var pluginAPI: AbsolutePath
85+
86+
public init(manifestAPI: AbsolutePath, pluginAPI: AbsolutePath) {
87+
self.manifestAPI = manifestAPI
88+
self.pluginAPI = pluginAPI
89+
}
90+
91+
public init(root: AbsolutePath) {
92+
self.init(
93+
manifestAPI: root.appending(component: "ManifestAPI"),
94+
pluginAPI: root.appending(component: "PluginAPI")
95+
)
96+
}
6297

63-
public static func libDir(forBinDir binDir: AbsolutePath) -> AbsolutePath {
64-
return binDir.parentDirectory.appending(components: "lib", "swift", "pm")
98+
fileprivate init(swiftCompilerPath: AbsolutePath) {
99+
let rootPath = swiftCompilerPath.parentDirectory.parentDirectory.appending(components: "lib", "swift", "pm")
100+
self.init(root: rootPath)
101+
}
65102
}
66103
}

Sources/SPMTestSupport/Toolchain.swift

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,9 @@ extension ToolchainConfiguration {
3535
get {
3636
let toolchain = UserToolchain.default
3737
return .init(
38-
swiftCompiler: toolchain.configuration.swiftCompiler,
38+
swiftCompilerPath: toolchain.configuration.swiftCompilerPath,
3939
swiftCompilerFlags: [],
40-
libDir: toolchain.configuration.libDir,
41-
binDir: toolchain.configuration.binDir
40+
swiftPMLibrariesLocation: toolchain.configuration.swiftPMLibrariesLocation
4241
)
4342
}
4443
}

Sources/Workspace/DefaultPluginScriptRunner.swift

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -40,36 +40,33 @@ public struct DefaultPluginScriptRunner: PluginScriptRunner {
4040

4141
public var hostTriple: Triple {
4242
return Self._hostTriple.memoize {
43-
Triple.getHostTriple(usingSwiftCompiler: self.toolchain.swiftCompiler)
43+
Triple.getHostTriple(usingSwiftCompiler: self.toolchain.swiftCompilerPath)
4444
}
4545
}
4646

4747
/// Helper function that compiles a plugin script as an executable and returns the path to it.
4848
fileprivate func compile(sources: Sources, toolsVersion: ToolsVersion, cacheDir: AbsolutePath) throws -> AbsolutePath {
4949
// FIXME: Much of this is copied from the ManifestLoader and should be consolidated.
5050

51-
// Bin dir will be set when developing swiftpm without building all of the runtimes.
52-
let runtimePath = self.toolchain.binDir ?? self.toolchain.libDir.appending(component: "PluginAPI")
51+
let runtimePath = self.toolchain.swiftPMLibrariesLocation.pluginAPI
5352

5453
// Compile the package plugin script.
55-
var command = [self.toolchain.swiftCompiler.pathString]
54+
var command = [self.toolchain.swiftCompilerPath.pathString]
5655

5756
// FIXME: Workaround for the module cache bug that's been haunting Swift CI
5857
// <rdar://problem/48443680>
5958
let moduleCachePath = ProcessEnv.vars["SWIFTPM_MODULECACHE_OVERRIDE"] ?? ProcessEnv.vars["SWIFTPM_TESTS_MODULECACHE"]
6059

61-
// If we got the binDir that means we could be developing SwiftPM in Xcode
62-
// which produces a framework for dynamic package products.
63-
let packageFrameworkPath = runtimePath.appending(component: "PackageFrameworks")
64-
6560
let macOSPackageDescriptionPath: AbsolutePath
66-
if self.toolchain.binDir != nil, localFileSystem.exists(packageFrameworkPath) {
61+
// if runtimePath is set to "PackageFrameworks" that means we could be developing SwiftPM in Xcode
62+
// which produces a framework for dynamic package products.
63+
if runtimePath.basename == "PackageFrameworks" {
6764
command += [
68-
"-F", packageFrameworkPath.pathString,
65+
"-F", runtimePath.pathString,
6966
"-framework", "PackagePlugin",
70-
"-Xlinker", "-rpath", "-Xlinker", packageFrameworkPath.pathString,
67+
"-Xlinker", "-rpath", "-Xlinker", runtimePath.pathString,
7168
]
72-
macOSPackageDescriptionPath = packageFrameworkPath.appending(RelativePath("PackagePlugin.framework/PackagePlugin"))
69+
macOSPackageDescriptionPath = runtimePath.appending(RelativePath("PackagePlugin.framework/PackagePlugin"))
7370
} else {
7471
command += [
7572
"-L", runtimePath.pathString,
@@ -99,9 +96,15 @@ public struct DefaultPluginScriptRunner: PluginScriptRunner {
9996
command += self.toolchain.swiftCompilerFlags
10097

10198
command += ["-swift-version", toolsVersion.swiftLanguageVersion.rawValue]
102-
command += ["-I", runtimePath.pathString]
99+
// if runtimePath is set to "PackageFrameworks" that means we could be developing SwiftPM in Xcode
100+
// which produces a framework for dynamic package products.
101+
if runtimePath.basename == "PackageFrameworks" {
102+
command += ["-I", runtimePath.parentDirectory.pathString]
103+
} else {
104+
command += ["-I", runtimePath.pathString]
105+
}
103106
#if os(macOS)
104-
if let sdkRoot = self.toolchain.sdkRoot ?? self.sdkRoot() {
107+
if let sdkRoot = self.toolchain.sdkRootPath ?? self.sdkRoot() {
105108
command += ["-sdk", sdkRoot.pathString]
106109
}
107110
#endif

0 commit comments

Comments
 (0)