-
Notifications
You must be signed in to change notification settings - Fork 1.4k
refactor toolchain SwiftPM libraries path #3660
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -689,21 +689,20 @@ public final class ManifestLoader: ManifestLoaderProtocol { | |
let moduleCachePath = (ProcessEnv.vars["SWIFTPM_MODULECACHE_OVERRIDE"] ?? ProcessEnv.vars["SWIFTPM_TESTS_MODULECACHE"]).flatMap{ AbsolutePath.init($0) } | ||
|
||
var cmd: [String] = [] | ||
cmd += [self.toolchain.swiftCompiler.pathString] | ||
cmd += [self.toolchain.swiftCompilerPath.pathString] | ||
cmd += verbosity.ccArgs | ||
|
||
let macOSPackageDescriptionPath: AbsolutePath | ||
// If we got the binDir that means we could be developing SwiftPM in Xcode | ||
// if runtimePath is set to "PackageFrameworks" that means we could be developing SwiftPM in Xcode | ||
// which produces a framework for dynamic package products. | ||
let packageFrameworkPath = runtimePath.appending(component: "PackageFrameworks") | ||
if self.toolchain.binDir != nil, localFileSystem.exists(packageFrameworkPath) { | ||
if runtimePath.extension == "framework" { | ||
cmd += [ | ||
"-F", packageFrameworkPath.pathString, | ||
"-F", runtimePath.parentDirectory.pathString, | ||
"-framework", "PackageDescription", | ||
"-Xlinker", "-rpath", "-Xlinker", packageFrameworkPath.pathString, | ||
"-Xlinker", "-rpath", "-Xlinker", runtimePath.parentDirectory.pathString, | ||
] | ||
|
||
macOSPackageDescriptionPath = packageFrameworkPath.appending(RelativePath("PackageDescription.framework/PackageDescription")) | ||
macOSPackageDescriptionPath = runtimePath.appending(component: "PackageDescription") | ||
} else { | ||
cmd += [ | ||
"-L", runtimePath.pathString, | ||
|
@@ -716,13 +715,13 @@ public final class ManifestLoader: ManifestLoaderProtocol { | |
#endif | ||
|
||
// note: this is not correct for all platforms, but we only actually use it on macOS. | ||
macOSPackageDescriptionPath = runtimePath.appending(RelativePath("libPackageDescription.dylib")) | ||
macOSPackageDescriptionPath = runtimePath.appending(component: "libPackageDescription.dylib") | ||
} | ||
|
||
// Use the same minimum deployment target as the PackageDescription library (with a fallback of 10.15). | ||
#if os(macOS) | ||
let triple = Self._hostTriple.memoize { | ||
Triple.getHostTriple(usingSwiftCompiler: self.toolchain.swiftCompiler) | ||
Triple.getHostTriple(usingSwiftCompiler: self.toolchain.swiftCompilerPath) | ||
} | ||
|
||
let version = try Self._packageDescriptionMinimumDeploymentTarget.memoize { | ||
|
@@ -853,9 +852,15 @@ public final class ManifestLoader: ManifestLoaderProtocol { | |
var cmd = [String]() | ||
let runtimePath = self.runtimePath(for: toolsVersion) | ||
cmd += ["-swift-version", toolsVersion.swiftLanguageVersion.rawValue] | ||
cmd += ["-I", runtimePath.pathString] | ||
// if runtimePath is set to "PackageFrameworks" that means we could be developing SwiftPM in Xcode | ||
// which produces a framework for dynamic package products. | ||
if runtimePath.extension == "framework" { | ||
cmd += ["-I", runtimePath.parentDirectory.parentDirectory.pathString] | ||
} else { | ||
cmd += ["-I", runtimePath.pathString] | ||
} | ||
#if os(macOS) | ||
if let sdkRoot = self.toolchain.sdkRoot ?? self.sdkRoot() { | ||
if let sdkRoot = self.toolchain.sdkRootPath ?? self.sdkRoot() { | ||
cmd += ["-sdk", sdkRoot.pathString] | ||
} | ||
#endif | ||
|
@@ -865,19 +870,14 @@ public final class ManifestLoader: ManifestLoaderProtocol { | |
|
||
/// Returns the runtime path given the manifest version and path to libDir. | ||
private func runtimePath(for version: ToolsVersion) -> AbsolutePath { | ||
// Bin dir will be set when developing swiftpm without building all of the runtimes. | ||
if let binDir = self.toolchain.binDir { | ||
return binDir | ||
} | ||
|
||
// Otherwise we use the standard location of the manifest API in the toolchain, if it exists. | ||
let manifestAPIDir = self.toolchain.libDir.appending(component: "ManifestAPI") | ||
let manifestAPIDir = self.toolchain.swiftPMLibrariesLocation.manifestAPI | ||
if localFileSystem.exists(manifestAPIDir) { | ||
return manifestAPIDir | ||
} | ||
|
||
// Otherwise, fall back on the old location (this would indicate that we're using an old toolchain). | ||
return self.toolchain.libDir.appending(version.runtimeSubpath) | ||
|
||
// FIXME: how do we test this? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @abertelrud do you know how I can test this? otherwise I was able to test all scenarios I was aware of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The only way I can think of would be to use a test fixture and then invoke |
||
// Fall back on the old location (this would indicate that we're using an old toolchain). | ||
return self.toolchain.swiftPMLibrariesLocation.manifestAPI.parentDirectory.appending(version.runtimeSubpath) | ||
} | ||
|
||
/// Returns path to the manifest database inside the given cache directory. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,37 +16,56 @@ import TSCBasic | |
/// using the package manager with alternate toolchains in the future. | ||
public struct ToolchainConfiguration { | ||
/// The path of the swift compiler. | ||
public var swiftCompiler: AbsolutePath | ||
public var swiftCompilerPath: AbsolutePath | ||
|
||
/// Extra arguments to pass the Swift compiler (defaults to the empty string). | ||
public var swiftCompilerFlags: [String] | ||
|
||
/// Environment to pass to the Swift compiler (defaults to the inherited environment). | ||
public var swiftCompilerEnvironment: [String: String] | ||
|
||
/// The path of the library resources. | ||
public var libDir: AbsolutePath | ||
|
||
/// The bin directory. | ||
public var binDir: AbsolutePath? | ||
/// SwiftPM library paths. | ||
public var swiftPMLibrariesLocation: SwiftPMLibrariesLocation | ||
|
||
/// The path to SDK root. | ||
/// | ||
/// If provided, it will be passed to the swift interpreter. | ||
public var sdkRoot: AbsolutePath? | ||
public var sdkRootPath: AbsolutePath? | ||
|
||
/// XCTest Location | ||
public var xctestLocation: AbsolutePath? | ||
public var xctestPath: AbsolutePath? | ||
|
||
/// Creates the set of manifest resources associated with a `swiftc` executable. | ||
/// | ||
/// - Parameters: | ||
/// - swiftCompiler: The absolute path of the associated `swiftc` executable. | ||
/// - swiftCompilerFlags: Extra flags to pass the Swift compiler.: Extra flags to pass the Swift compiler. | ||
/// - libDir: The path of the library resources. | ||
/// - binDir: The bin directory. | ||
/// - sdkRoot: The path to SDK root. | ||
/// - xctestLocation: XCTest Location | ||
/// - swiftCompilerPath: The absolute path of the associated swift compiler executable (`swiftc`). | ||
/// - swiftCompilerFlags: Extra flags to pass to the Swift compiler. | ||
/// - swiftCompilerEnvironment: Environment variables to pass to the Swift compiler. | ||
/// - swiftPMLibrariesRootPath: Custom path for SwiftPM libraries. Computed based on the compiler path by default. | ||
/// - sdkRootPath: Optional path to SDK root. | ||
/// - xctestPath: Optional path to XCTest. | ||
public init( | ||
swiftCompilerPath: AbsolutePath, | ||
swiftCompilerFlags: [String] = [], | ||
swiftCompilerEnvironment: [String: String] = ProcessEnv.vars, | ||
swiftPMLibrariesLocation: SwiftPMLibrariesLocation? = nil, | ||
sdkRootPath: AbsolutePath? = nil, | ||
xctestPath: AbsolutePath? = nil | ||
) { | ||
let swiftPMLibrariesLocation = swiftPMLibrariesLocation ?? { | ||
return .init(swiftCompilerPath: swiftCompilerPath) | ||
}() | ||
|
||
self.swiftCompilerPath = swiftCompilerPath | ||
self.swiftCompilerFlags = swiftCompilerFlags | ||
self.swiftCompilerEnvironment = swiftCompilerEnvironment | ||
self.swiftPMLibrariesLocation = swiftPMLibrariesLocation | ||
self.sdkRootPath = sdkRootPath | ||
self.xctestPath = xctestPath | ||
} | ||
|
||
// deprecated 8/2021 | ||
@available(*, deprecated, message: "use non-deprecated initializer instead") | ||
public init( | ||
swiftCompiler: AbsolutePath, | ||
swiftCompilerFlags: [String] = [], | ||
|
@@ -56,16 +75,37 @@ public struct ToolchainConfiguration { | |
sdkRoot: AbsolutePath? = nil, | ||
xctestLocation: AbsolutePath? = nil | ||
) { | ||
self.swiftCompiler = swiftCompiler | ||
self.swiftCompilerFlags = swiftCompilerFlags | ||
self.swiftCompilerEnvironment = swiftCompilerEnvironment | ||
self.libDir = libDir ?? Self.libDir(forBinDir: swiftCompiler.parentDirectory) | ||
self.binDir = binDir | ||
self.sdkRoot = sdkRoot | ||
self.xctestLocation = xctestLocation | ||
self.init( | ||
swiftCompilerPath: swiftCompiler, | ||
swiftCompilerFlags: swiftCompilerFlags, | ||
swiftCompilerEnvironment: swiftCompilerEnvironment, | ||
swiftPMLibrariesLocation: libDir.map { .init(root: $0) }, | ||
sdkRootPath: sdkRoot, | ||
xctestPath: xctestLocation | ||
) | ||
} | ||
} | ||
|
||
extension ToolchainConfiguration { | ||
public struct SwiftPMLibrariesLocation { | ||
public var manifestAPI: AbsolutePath | ||
public var pluginAPI: AbsolutePath | ||
|
||
public init(manifestAPI: AbsolutePath, pluginAPI: AbsolutePath) { | ||
self.manifestAPI = manifestAPI | ||
self.pluginAPI = pluginAPI | ||
} | ||
|
||
public init(root: AbsolutePath) { | ||
self.init( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a good convenience, I think. The idea was that if we add more of these, then the client (an IDE for example) should just be able to have a directory of support files, and then it's mostly SwiftPM's business what should be in that directory. So for a client to not have to enumerate these subdirectories in the default case is good. |
||
manifestAPI: root.appending(component: "ManifestAPI"), | ||
pluginAPI: root.appending(component: "PluginAPI") | ||
) | ||
} | ||
|
||
public static func libDir(forBinDir binDir: AbsolutePath) -> AbsolutePath { | ||
return binDir.parentDirectory.appending(components: "lib", "swift", "pm") | ||
public init(swiftCompilerPath: AbsolutePath) { | ||
let rootPath = swiftCompilerPath.parentDirectory.parentDirectory.appending(components: "lib", "swift", "pm") | ||
self.init(root: rootPath) | ||
} | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.