Skip to content

Commit 4a6660a

Browse files
authored
Align swift sdk configuration subcommand with proposal text (#7535)
Per [the proposal text](https://github.com/apple/swift-evolution/blob/main/proposals/0387-cross-compilation-destinations.md#swift-sdk-installation-and-configuration): > `swift sdk configure <identifier> <target-triple>`, which allows users to provide additional search paths and toolsets to be used subsequently when building with a given Swift SDK. Specifically, multiple `--swift-resources-path`, `--include-search-path`, `--library-search-path`, and `--toolset` options with corresponding paths can be provided, which then will be stored as configuration for this Swift SDK. `swift sdk configure <identifier> --show-configuration` will print currently set paths, while `swift sdk configure <identifier> --reset` will reset all of those at once.
1 parent 8b12909 commit 4a6660a

19 files changed

+554
-149
lines changed

CHANGELOG.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ Swift 6.0
1515
`--experimental-swift-sdks-path` options on `swift build` are deprecated with replacements that don't have the
1616
`experimental` prefix.
1717

18+
* [#7535] The `swift sdk configuration` subcommand is deprecated with a replacement named `configure` that has options that exactly match
19+
[SE-0387 proposal text].
20+
1821
* [#7202]
1922

2023
Package manifests can now access information about the Git repository the given package is in via the context object's
@@ -366,6 +369,7 @@ Swift 3.0
366369
[SE-0386]: https://github.com/apple/swift-evolution/blob/main/proposals/0386-package-access-modifier.md
367370
[SE-0387]: https://github.com/apple/swift-evolution/blob/main/proposals/0387-cross-compilation-destinations.md
368371
[SE-0391]: https://github.com/apple/swift-evolution/blob/main/proposals/0391-package-registry-publish.md
372+
[SE-0387 proposal text]: https://github.com/apple/swift-evolution/blob/main/proposals/0387-cross-compilation-destinations.md#swift-sdk-installation-and-configuration
369373

370374
[SR-5918]: https://bugs.swift.org/browse/SR-5918
371375
[SR-6978]: https://bugs.swift.org/browse/SR-6978
@@ -415,4 +419,5 @@ Swift 3.0
415419
[#7118]: https://github.com/apple/swift-package-manager/pull/7118
416420
[#7201]: https://github.com/apple/swift-package-manager/pull/7201
417421
[#7202]: https://github.com/apple/swift-package-manager/pull/7202
418-
[#7505]: https://github.com/apple/swift-package-manager/pull/7507
422+
[#7507]: https://github.com/apple/swift-package-manager/pull/7507
423+
[#7535]: https://github.com/apple/swift-package-manager/pull/7535
376 Bytes
Binary file not shown.
-42 Bytes
Binary file not shown.

Sources/PackageModel/SwiftSDKs/SwiftSDKBundle.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,16 +53,18 @@ extension [SwiftSDKBundle] {
5353
/// - hostTriple: triple of the machine on which the Swift SDK is building.
5454
/// - targetTriple: triple of the machine for which the Swift SDK is building.
5555
/// - Returns: ``SwiftSDK`` value with a given artifact ID, `nil` if none found.
56-
public func selectSwiftSDK(id: String, hostTriple: Triple, targetTriple: Triple) -> SwiftSDK? {
56+
public func selectSwiftSDK(id: String, hostTriple: Triple?, targetTriple: Triple) -> SwiftSDK? {
5757
for bundle in self {
5858
for (artifactID, variants) in bundle.artifacts {
5959
guard artifactID == id else {
6060
continue
6161
}
6262

6363
for variant in variants {
64-
guard variant.isSupporting(hostTriple: hostTriple) else {
65-
continue
64+
if let hostTriple {
65+
guard variant.isSupporting(hostTriple: hostTriple) else {
66+
continue
67+
}
6668
}
6769

6870
return variant.swiftSDKs.first { $0.targetTriple == targetTriple }

Sources/PackageModel/SwiftSDKs/SwiftSDKBundleStore.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -239,9 +239,10 @@ public final class SwiftSDKBundleStore {
239239

240240
try await archiver.extract(from: bundlePath, to: extractionResultsDirectory)
241241

242-
guard let bundleName = try fileSystem.getDirectoryContents(extractionResultsDirectory).first,
243-
bundleName.hasSuffix(".\(artifactBundleExtension)")
244-
else {
242+
guard let bundleName = try fileSystem.getDirectoryContents(extractionResultsDirectory).first(where: {
243+
$0.hasSuffix(".\(artifactBundleExtension)") &&
244+
fileSystem.isDirectory(extractionResultsDirectory.appending($0))
245+
}) else {
245246
throw SwiftSDKError.invalidBundleArchive(bundlePath)
246247
}
247248

Sources/PackageModel/SwiftSDKs/SwiftSDKConfigurationStore.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ public final class SwiftSDKConfigurationStore {
9797

9898
guard var swiftSDK = swiftSDKs.selectSwiftSDK(
9999
id: sdkID,
100-
hostTriple: hostTriple,
100+
hostTriple: nil,
101101
targetTriple: targetTriple
102102
) else {
103103
return nil

Sources/SwiftSDKCommand/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@
88

99
add_library(SwiftSDKCommand
1010
Configuration/ConfigurationSubcommand.swift
11-
Configuration/ConfigureSwiftSDK.swift
11+
Configuration/DeprecatedSwiftSDKConfigurationCommand.swift
1212
Configuration/ResetConfiguration.swift
1313
Configuration/SetConfiguration.swift
1414
Configuration/ShowConfiguration.swift
15+
ConfigureSwiftSDK.swift
1516
SwiftSDKSubcommand.swift
1617
InstallSwiftSDK.swift
1718
ListSwiftSDKs.swift

Sources/SwiftSDKCommand/Configuration/ConfigurationSubcommand.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
import ArgumentParser
1414
import Basics
15+
import Foundation
1516
import PackageModel
1617

1718
protocol ConfigurationSubcommand: SwiftSDKSubcommand {
@@ -47,6 +48,8 @@ extension ConfigurationSubcommand {
4748
_ swiftSDKsDirectory: AbsolutePath,
4849
_ observabilityScope: ObservabilityScope
4950
) throws {
51+
fputs("warning: `swift sdk configuration` command is deprecated and will be removed in a future version of SwiftPM. Use `swift sdk configure` instead.\n", stderr)
52+
5053
let bundleStore = SwiftSDKBundleStore(
5154
swiftSDKsDirectory: swiftSDKsDirectory,
5255
fileSystem: self.fileSystem,

Sources/SwiftSDKCommand/Configuration/ConfigureSwiftSDK.swift renamed to Sources/SwiftSDKCommand/Configuration/DeprecatedSwiftSDKConfigurationCommand.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,15 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
import ArgumentParser
14+
import Basics
15+
import PackageModel
1416

15-
package struct ConfigureSwiftSDK: ParsableCommand {
16-
package static let configuration = CommandConfiguration(
17+
struct DeprecatedSwiftSDKConfigurationCommand: ParsableCommand {
18+
static let configuration = CommandConfiguration(
1719
commandName: "configuration",
1820
abstract: """
21+
Deprecated: use `swift sdk configure` instead.
22+
1923
Manages configuration options for installed Swift SDKs.
2024
""",
2125
subcommands: [
@@ -24,6 +28,4 @@ package struct ConfigureSwiftSDK: ParsableCommand {
2428
ShowConfiguration.self,
2529
]
2630
)
27-
28-
package init() {}
2931
}
Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift open source project
4+
//
5+
// Copyright (c) 2023 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import ArgumentParser
14+
import Basics
15+
import CoreCommands
16+
import Dispatch
17+
import PackageModel
18+
19+
import var TSCBasic.stdoutStream
20+
21+
struct ConfigureSwiftSDK: AsyncParsableCommand {
22+
static let configuration = CommandConfiguration(
23+
commandName: "configure",
24+
abstract: """
25+
Manages configuration options for installed Swift SDKs.
26+
"""
27+
)
28+
29+
@OptionGroup(visibility: .hidden)
30+
var locations: LocationOptions
31+
32+
@Option(help: "A path to a directory containing the SDK root.")
33+
var sdkRootPath: String? = nil
34+
35+
@Option(help: "A path to a directory containing Swift resources for dynamic linking.")
36+
var swiftResourcesPath: String? = nil
37+
38+
@Option(help: "A path to a directory containing Swift resources for static linking.")
39+
var swiftStaticResourcesPath: String? = nil
40+
41+
@Option(
42+
parsing: .singleValue,
43+
help: """
44+
A path to a directory containing headers. Multiple paths can be specified by providing this option multiple \
45+
times to the command.
46+
"""
47+
)
48+
var includeSearchPath: [String] = []
49+
50+
@Option(
51+
parsing: .singleValue,
52+
help: """
53+
"A path to a directory containing libraries. Multiple paths can be specified by providing this option multiple \
54+
times to the command.
55+
"""
56+
)
57+
var librarySearchPath: [String] = []
58+
59+
@Option(
60+
parsing: .singleValue,
61+
help: """
62+
"A path to a toolset file. Multiple paths can be specified by providing this option multiple times to the command.
63+
"""
64+
)
65+
var toolsetPath: [String] = []
66+
67+
@Flag(
68+
name: .customLong("reset"),
69+
help: """
70+
Resets configuration properties currently applied to a given Swift SDK and target triple. If no specific \
71+
property is specified, all of them are reset for the Swift SDK.
72+
"""
73+
)
74+
var shouldReset: Bool = false
75+
76+
@Flag(
77+
name: .customLong("show-configuration"),
78+
help: """
79+
Prints all configuration properties currently applied to a given Swift SDK and target triple.
80+
"""
81+
)
82+
var shouldShowConfiguration: Bool = false
83+
84+
@Argument(
85+
help: """
86+
An identifier of an already installed Swift SDK. Use the `list` subcommand to see all available \
87+
identifiers.
88+
"""
89+
)
90+
var sdkID: String
91+
92+
@Argument(help: "The target triple of the Swift SDK to configure.")
93+
var targetTriple: String
94+
95+
/// The file system used by default by this command.
96+
private var fileSystem: FileSystem { localFileSystem }
97+
98+
/// Parses Swift SDKs directory option if provided or uses the default path for Swift SDKs
99+
/// on the file system. A new directory at this path is created if one doesn't exist already.
100+
/// - Returns: existing or a newly created directory at the computed location.
101+
private func getOrCreateSwiftSDKsDirectory() throws -> AbsolutePath {
102+
var swiftSDKsDirectory = try fileSystem.getSharedSwiftSDKsDirectory(
103+
explicitDirectory: locations.swiftSDKsDirectory
104+
)
105+
106+
if !self.fileSystem.exists(swiftSDKsDirectory) {
107+
swiftSDKsDirectory = try self.fileSystem.getOrCreateSwiftPMSwiftSDKsDirectory()
108+
}
109+
110+
return swiftSDKsDirectory
111+
}
112+
113+
func run() async throws {
114+
let observabilityHandler = SwiftCommandObservabilityHandler(outputStream: stdoutStream, logLevel: .info)
115+
let observabilitySystem = ObservabilitySystem(observabilityHandler)
116+
let observabilityScope = observabilitySystem.topScope
117+
let swiftSDKsDirectory = try self.getOrCreateSwiftSDKsDirectory()
118+
119+
let hostToolchain = try UserToolchain(swiftSDK: SwiftSDK.hostSwiftSDK())
120+
let triple = try Triple.getHostTriple(usingSwiftCompiler: hostToolchain.swiftCompilerPath)
121+
122+
var commandError: Error? = nil
123+
do {
124+
let bundleStore = SwiftSDKBundleStore(
125+
swiftSDKsDirectory: swiftSDKsDirectory,
126+
fileSystem: self.fileSystem,
127+
observabilityScope: observabilityScope,
128+
outputHandler: { print($0) }
129+
)
130+
let configurationStore = try SwiftSDKConfigurationStore(
131+
hostTimeTriple: triple,
132+
swiftSDKBundleStore: bundleStore
133+
)
134+
let targetTriple = try Triple(self.targetTriple)
135+
136+
guard let swiftSDK = try configurationStore.readConfiguration(
137+
sdkID: sdkID,
138+
targetTriple: targetTriple
139+
) else {
140+
throw SwiftSDKError.swiftSDKNotFound(
141+
artifactID: sdkID,
142+
hostTriple: triple,
143+
targetTriple: targetTriple
144+
)
145+
}
146+
147+
if self.shouldShowConfiguration {
148+
print(swiftSDK.pathsConfiguration)
149+
return
150+
}
151+
152+
var configuration = swiftSDK.pathsConfiguration
153+
if self.shouldReset {
154+
if try !configurationStore.resetConfiguration(sdkID: sdkID, targetTriple: targetTriple) {
155+
observabilityScope.emit(
156+
warning: "No configuration for Swift SDK `\(sdkID)`"
157+
)
158+
} else {
159+
observabilityScope.emit(
160+
info: """
161+
All configuration properties of Swift SDK `\(sdkID)` for target triple \
162+
`\(targetTriple)` were successfully reset.
163+
"""
164+
)
165+
}
166+
} else {
167+
var updatedProperties = [String]()
168+
169+
let currentWorkingDirectory: AbsolutePath? = fileSystem.currentWorkingDirectory
170+
171+
if let sdkRootPath {
172+
configuration.sdkRootPath = try AbsolutePath(validating: sdkRootPath, relativeTo: currentWorkingDirectory)
173+
updatedProperties.append(CodingKeys.sdkRootPath.stringValue)
174+
}
175+
176+
if let swiftResourcesPath {
177+
configuration.swiftResourcesPath =
178+
try AbsolutePath(validating: swiftResourcesPath, relativeTo: currentWorkingDirectory)
179+
updatedProperties.append(CodingKeys.swiftResourcesPath.stringValue)
180+
}
181+
182+
if let swiftStaticResourcesPath {
183+
configuration.swiftResourcesPath =
184+
try AbsolutePath(validating: swiftStaticResourcesPath, relativeTo: currentWorkingDirectory)
185+
updatedProperties.append(CodingKeys.swiftStaticResourcesPath.stringValue)
186+
}
187+
188+
if !includeSearchPath.isEmpty {
189+
configuration.includeSearchPaths =
190+
try includeSearchPath.map { try AbsolutePath(validating: $0, relativeTo: currentWorkingDirectory) }
191+
updatedProperties.append(CodingKeys.includeSearchPath.stringValue)
192+
}
193+
194+
if !librarySearchPath.isEmpty {
195+
configuration.librarySearchPaths =
196+
try librarySearchPath.map { try AbsolutePath(validating: $0, relativeTo: currentWorkingDirectory) }
197+
updatedProperties.append(CodingKeys.librarySearchPath.stringValue)
198+
}
199+
200+
if !toolsetPath.isEmpty {
201+
configuration.toolsetPaths =
202+
try toolsetPath.map { try AbsolutePath(validating: $0, relativeTo: currentWorkingDirectory) }
203+
updatedProperties.append(CodingKeys.toolsetPath.stringValue)
204+
}
205+
206+
guard !updatedProperties.isEmpty else {
207+
observabilityScope.emit(
208+
error: """
209+
No properties of Swift SDK `\(sdkID)` for target triple `\(targetTriple)` were updated \
210+
since none were specified. Pass `--help` flag to see the list of all available properties.
211+
"""
212+
)
213+
return
214+
}
215+
216+
var swiftSDK = swiftSDK
217+
swiftSDK.pathsConfiguration = configuration
218+
try configurationStore.updateConfiguration(sdkID: sdkID, swiftSDK: swiftSDK)
219+
220+
observabilityScope.emit(
221+
info: """
222+
These properties of Swift SDK `\(sdkID)` for target triple \
223+
`\(targetTriple)` were successfully updated: \(updatedProperties.joined(separator: ", ")).
224+
"""
225+
)
226+
}
227+
228+
if observabilityScope.errorsReported {
229+
throw ExitCode.failure
230+
}
231+
} catch {
232+
commandError = error
233+
}
234+
235+
// wait for all observability items to process
236+
observabilityHandler.wait(timeout: .now() + 5)
237+
238+
if let commandError {
239+
throw commandError
240+
}
241+
}
242+
}
243+
244+
extension AbsolutePath {
245+
fileprivate init(validating string: String, relativeTo basePath: AbsolutePath?) throws {
246+
if let basePath {
247+
try self.init(validating: string, relativeTo: basePath)
248+
} else {
249+
try self.init(validating: string)
250+
}
251+
}
252+
}

Sources/SwiftSDKCommand/InstallSwiftSDK.swift

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ import PackageModel
1818

1919
import var TSCBasic.stdoutStream
2020

21-
package struct InstallSwiftSDK: SwiftSDKSubcommand {
22-
package static let configuration = CommandConfiguration(
21+
struct InstallSwiftSDK: SwiftSDKSubcommand {
22+
static let configuration = CommandConfiguration(
2323
commandName: "install",
2424
abstract: """
2525
Installs a given Swift SDK bundle to a location discoverable by SwiftPM. If the artifact bundle \
@@ -33,8 +33,6 @@ package struct InstallSwiftSDK: SwiftSDKSubcommand {
3333
@Argument(help: "A local filesystem path or a URL of a Swift SDK bundle to install.")
3434
var bundlePathOrURL: String
3535

36-
package init() {}
37-
3836
func run(
3937
hostTriple: Triple,
4038
_ swiftSDKsDirectory: AbsolutePath,

0 commit comments

Comments
 (0)