Skip to content

Commit

Permalink
[6.0] Deprecate experimental Swift SDK CLI in favor of unprefixed c…
Browse files Browse the repository at this point in the history
…ounterparts (#7515)

Cherry-pick of #7512, #7507, and #7517.

**Explanation**: Since
[SE-0387](https://github.com/apple/swift-evolution/blob/main/proposals/0387-cross-compilation-destinations.md)
was accepted and available in Swift 5.9 and Swift 5.10, it's time to
deprecate relevant CLI with the `experimental` prefix. There are enough
users of this command and corresponding options on `swift build` in the
wild, which means those should be deprecated first before removing.
**Scope**: isolated to `swift sdk` command and 2 Swift SDK options on
`swift build`.
**Risk**: low, these commands options have no impact on `swift build`
outside of cross-compilation use cases.
**Testing**: added new end-to-end tests in `SDKCommandTests` in
#7517 cherry-picked
here.
**Issue**: N/A
**Reviewer**: @bnbarham
  • Loading branch information
MaxDesiatov committed May 1, 2024
1 parent 0b53c3c commit eb2d5b3
Show file tree
Hide file tree
Showing 16 changed files with 229 additions and 10 deletions.
19 changes: 18 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
Note: This is in reverse chronological order, so newer entries are added to the top.

Swift Next
Swift 6.0
-----------

* [#7507]

`swift experimental-sdk` command is deprecated with `swift sdk` command replacing it. `--experimental-swift-sdk` and
`--experimental-swift-sdks-path` options on `swift build` are deprecated with replacements that don't have the
`experimental` prefix.

* [#7202]

Package manifests can now access information about the Git repository the given package is in via the context object's
`gitInformation` property. This allows to determine the current tag (if any), the current commit and whether or not there are uncommited changes.

* [#7201]

`// swift-tools-version:` can now be specified on subsequent lines of `Package.swift`, for example when first few lines are required to contain a licensing comment header.

Swift 5.10
-----------
* [#7010]

On macOS, `swift build` and `swift run` now produce binaries that allow backtraces in debug builds. Pass `SWIFT_BACKTRACE=enable=yes` environment variable to enable backtraces on such binaries when running them.
Expand Down Expand Up @@ -387,4 +399,9 @@ Swift 3.0
[#6276]: https://github.com/apple/swift-package-manager/pull/6276
[#6540]: https://github.com/apple/swift-package-manager/pull/6540
[#6663]: https://github.com/apple/swift-package-manager/pull/6663
[#7010]: https://github.com/apple/swift-package-manager/pull/7010
[#7101]: https://github.com/apple/swift-package-manager/pull/7101
[#7118]: https://github.com/apple/swift-package-manager/pull/7118
[#7201]: https://github.com/apple/swift-package-manager/pull/7201
[#7202]: https://github.com/apple/swift-package-manager/pull/7202
[#7507]: https://github.com/apple/swift-package-manager/pull/7507
1 change: 1 addition & 0 deletions Fixtures/SwiftSDKs/Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// This empty file tells test fixture logic to copy this directory's content to the test case temp directory.
6 changes: 6 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,12 @@ let package = Package(
),
.executableTarget(
/** Interacts with Swift SDKs used for cross-compilation */
name: "swift-sdk",
dependencies: ["Commands", "SwiftSDKCommand"],
exclude: ["CMakeLists.txt"]
),
.executableTarget(
/** Deprecated command superseded by `swift-sdk` */
name: "swift-experimental-sdk",
dependencies: ["Commands", "SwiftSDKCommand"],
exclude: ["CMakeLists.txt"]
Expand Down
1 change: 1 addition & 0 deletions Sources/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ add_subdirectory(SPMSQLite3)
add_subdirectory(swift-bootstrap)
add_subdirectory(swift-build)
add_subdirectory(swift-experimental-sdk)
add_subdirectory(swift-sdk)
add_subdirectory(swift-package)
add_subdirectory(swift-run)
add_subdirectory(swift-test)
Expand Down
17 changes: 15 additions & 2 deletions Sources/CoreCommands/Options.swift
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,15 @@ package struct LocationOptions: ParsableArguments {
@Option(name: .customLong("destination"), help: .hidden, completion: .directory)
package var customCompileDestination: AbsolutePath?

/// Path to the directory containing installed Swift SDKs.
@Option(name: .customLong("experimental-swift-sdks-path"), help: .hidden, completion: .directory)
package var deprecatedSwiftSDKsDirectory: AbsolutePath?

/// Path to the directory containing installed Swift SDKs.
@Option(
name: .customLong("swift-sdks-path"),
help: "Path to the directory containing installed Swift SDKs",
completion: .directory
)
package var swiftSDKsDirectory: AbsolutePath?

@Option(
Expand Down Expand Up @@ -406,8 +413,14 @@ package struct BuildOptions: ParsableArguments {
)
package var architectures: [String] = []

/// Filter for selecting a specific Swift SDK to build with.
@Option(name: .customLong("experimental-swift-sdk"), help: .hidden)
package var deprecatedSwiftSDKSelector: String?

/// Filter for selecting a specific Swift SDK to build with.
@Option(
name: .customLong("swift-sdk"),
help: "Filter for selecting a specific Swift SDK to build with"
)
package var swiftSDKSelector: String?

/// Which compile-time sanitizers should be enabled.
Expand Down
15 changes: 13 additions & 2 deletions Sources/CoreCommands/SwiftCommandState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -350,8 +350,13 @@ package final class SwiftCommandState {
fileSystem: fileSystem
)
self.sharedCacheDirectory = try getSharedCacheDirectory(options: options, fileSystem: fileSystem)
if options.locations.deprecatedSwiftSDKsDirectory != nil {
self.observabilityScope.emit(
warning: "`--experimental-swift-sdks-path` is deprecated and will be removed in a future version of SwiftPM. Use `--swift-sdks-path` instead."
)
}
self.sharedSwiftSDKsDirectory = try fileSystem.getSharedSwiftSDKsDirectory(
explicitDirectory: options.locations.swiftSDKsDirectory
explicitDirectory: options.locations.swiftSDKsDirectory ?? options.locations.deprecatedSwiftSDKsDirectory
)

// set global process logging handler
Expand Down Expand Up @@ -821,14 +826,20 @@ package final class SwiftCommandState {
do {
let hostToolchain = try _hostToolchain.get()
hostSwiftSDK = hostToolchain.swiftSDK

if options.build.deprecatedSwiftSDKSelector != nil {
self.observabilityScope.emit(
warning: "`--experimental-swift-sdk` is deprecated and will be removed in a future version of SwiftPM. Use `--swift-sdk` instead."
)
}
swiftSDK = try SwiftSDK.deriveTargetSwiftSDK(
hostSwiftSDK: hostSwiftSDK,
hostTriple: hostToolchain.targetTriple,
customCompileDestination: options.locations.customCompileDestination,
customCompileTriple: options.build.customCompileTriple,
customCompileToolchain: options.build.customCompileToolchain,
customCompileSDK: options.build.customCompileSDK,
swiftSDKSelector: options.build.swiftSDKSelector,
swiftSDKSelector: options.build.swiftSDKSelector ?? options.build.deprecatedSwiftSDKSelector,
architectures: options.build.architectures,
store: store,
observabilityScope: self.observabilityScope,
Expand Down
2 changes: 1 addition & 1 deletion Sources/PackageModel/SwiftSDKs/SwiftSDKBundleStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public final class SwiftSDKBundleStore {
case let .noMatchingSwiftSDK(selector, hostTriple):
return """
No Swift SDK found matching query `\(selector)` and host triple \
`\(hostTriple.tripleString)`. Use `swift experimental-sdk list` command to see \
`\(hostTriple.tripleString)`. Use `swift sdk list` command to see \
available Swift SDKs.
"""
}
Expand Down
6 changes: 6 additions & 0 deletions Sources/SPMTestSupport/SwiftPMProduct.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ package enum SwiftPM {
case Registry
case Test
case Run
case experimentalSDK
case sdk
}

extension SwiftPM {
Expand All @@ -41,6 +43,10 @@ extension SwiftPM {
return "swift-test"
case .Run:
return "swift-run"
case .experimentalSDK:
return "swift-experimental-sdk"
case .sdk:
return "swift-sdk"
}
}

Expand Down
4 changes: 2 additions & 2 deletions Sources/SwiftSDKCommand/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Swift SDKs Tool
# Swift SDKs Command

This module implements `swift experimental-sdk` command and its subcommands, which allow managing artifact
This module implements `swift sdk` command and its subcommands, which allow managing artifact
bundles used as Swift SDKs, as specified in [SE-0387](https://github.com/apple/swift-evolution/blob/main/proposals/0387-cross-compilation-destinations.md).
2 changes: 1 addition & 1 deletion Sources/SwiftSDKCommand/SwiftSDKCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import Basics

package struct SwiftSDKCommand: AsyncParsableCommand {
package static let configuration = CommandConfiguration(
commandName: "experimental-sdk",
commandName: "sdk",
_superCommandName: "swift",
abstract: "Perform operations on Swift SDKs.",
version: SwiftVersion.current.completeDisplayString,
Expand Down
1 change: 1 addition & 0 deletions Sources/swift-experimental-sdk/Entrypoint.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import SwiftSDKCommand
@main
struct Entrypoint {
static func main() async {
print("warning: `swift experimental-sdk` command is deprecated and will be removed in a future version of SwiftPM. Use `swift sdk` instead.")
await SwiftSDKCommand.main()
}
}
3 changes: 3 additions & 0 deletions Sources/swift-package-manager/SwiftPM.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ struct SwiftPM {
case "swift-build":
await SwiftBuildCommand.main()
case "swift-experimental-sdk":
print("warning: `swift experimental-sdk` command is deprecated and will be removed in a future version of SwiftPM. Use `swift sdk` instead.")
fallthrough
case "swift-sdk":
await SwiftSDKCommand.main()
case "swift-test":
await SwiftTestCommand.main()
Expand Down
18 changes: 18 additions & 0 deletions Sources/swift-sdk/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# This source file is part of the Swift open source project
#
# Copyright (c) 2023 Apple Inc. and the Swift project authors
# Licensed under Apache License v2.0 with Runtime Library Exception
#
# See http://swift.org/LICENSE.txt for license information
# See http://swift.org/CONTRIBUTORS.txt for Swift project authors

add_executable(swift-sdk
Entrypoint.swift)
target_link_libraries(swift-sdk PRIVATE
SwiftSDKCommand)

target_compile_options(swift-sdk PRIVATE
-parse-as-library)

install(TARGETS swift-sdk
RUNTIME DESTINATION bin)
20 changes: 20 additions & 0 deletions Sources/swift-sdk/Entrypoint.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift open source project
//
// Copyright (c) 2023 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

import SwiftSDKCommand

@main
struct Entrypoint {
static func main() async {
await SwiftSDKCommand.main()
}
}
122 changes: 122 additions & 0 deletions Tests/CommandsTests/SDKCommandTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift open source project
//
// Copyright (c) 2014-2024 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

import Basics
import Commands
import SPMTestSupport
import XCTest

import class TSCBasic.Process
import enum TSCBasic.ProcessEnv

private let deprecationWarning = "warning: `swift experimental-sdk` command is deprecated and will be removed in a future version of SwiftPM. Use `swift sdk` instead."

final class SDKCommandTests: CommandsTestCase {
func testUsage() throws {
for command in [SwiftPM.sdk, SwiftPM.experimentalSDK] {
let stdout = try command.execute(["-help"]).stdout
XCTAssert(stdout.contains("USAGE: swift sdk <subcommand>") || stdout.contains("USAGE: swift sdk [<subcommand>]"), "got stdout:\n" + stdout)
}
}

func testVersion() throws {
for command in [SwiftPM.sdk, SwiftPM.experimentalSDK] {
let stdout = try command.execute(["--version"]).stdout
XCTAssert(stdout.contains("Swift Package Manager"), "got stdout:\n" + stdout)
}
}

func testInstallSDK() throws {
for command in [SwiftPM.sdk, SwiftPM.experimentalSDK] {
try fixture(name: "SwiftSDKs") { fixturePath in
for bundle in ["test-sdk.artifactbundle.tar.gz", "test-sdk.artifactbundle.zip"] {
var (stdout, stderr) = try command.execute(
[
"install",
"--swift-sdks-path", fixturePath.pathString,
fixturePath.appending(bundle).pathString
]
)

if command == .experimentalSDK {
XCTAssertMatch(stdout, .contains(deprecationWarning))
}

// We only expect tool's output on the stdout stream.
XCTAssertMatch(
stdout,
.contains("\(bundle)` successfully installed as test-sdk.artifactbundle.")
)

XCTAssertEqual(stderr.count, 0)

(stdout, stderr) = try command.execute(
["list", "--swift-sdks-path", fixturePath.pathString])

if command == .experimentalSDK {
XCTAssertMatch(stdout, .contains(deprecationWarning))
}

// We only expect tool's output on the stdout stream.
XCTAssertMatch(stdout, .contains("test-artifact"))
XCTAssertEqual(stderr.count, 0)

XCTAssertThrowsError(try command.execute(
[
"install",
"--swift-sdks-path", fixturePath.pathString,
fixturePath.appending(bundle).pathString
]
)) { error in
guard case SwiftPMError.executionFailure(_, _, let stderr) = error else {
XCTFail()
return
}

XCTAssertTrue(
stderr.contains(
"Error: Swift SDK bundle with name `test-sdk.artifactbundle` is already installed. Can't install a new bundle with the same name."
),
"got stderr: \(stderr)"
)
}

if command == .experimentalSDK {
XCTAssertMatch(stdout, .contains(deprecationWarning))
}

(stdout, stderr) = try command.execute(
["remove", "--swift-sdks-path", fixturePath.pathString, "test-artifact"])

if command == .experimentalSDK {
XCTAssertMatch(stdout, .contains(deprecationWarning))
}

// We only expect tool's output on the stdout stream.
XCTAssertMatch(stdout, .contains("test-sdk.artifactbundle` was successfully removed from the file system."))
XCTAssertEqual(stderr.count, 0)

(stdout, stderr) = try command.execute(
["list", "--swift-sdks-path", fixturePath.pathString])

if command == .experimentalSDK {
XCTAssertMatch(stdout, .contains(deprecationWarning))
}

// We only expect tool's output on the stdout stream.
XCTAssertNoMatch(stdout, .contains("test-artifact"))
XCTAssertEqual(stderr.count, 0)
}
}
}
}
}
2 changes: 1 addition & 1 deletion Utilities/bootstrap
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,7 @@ def install_swiftpm(prefix, args):
# Install the swift-package-manager tool and create symlinks to it.
cli_tool_dest = os.path.join(prefix, "bin")
install_binary(args, "swift-package-manager", os.path.join(cli_tool_dest, "swift-package"), destination_is_directory=False)
for tool in ["swift-build", "swift-test", "swift-run", "swift-package-collection", "swift-package-registry", "swift-experimental-sdk"]:
for tool in ["swift-build", "swift-test", "swift-run", "swift-package-collection", "swift-package-registry", "swift-sdk", "swift-experimental-sdk"]:
src = "swift-package"
dest = os.path.join(cli_tool_dest, tool)
note("Creating tool symlink from %s to %s" % (src, dest))
Expand Down

0 comments on commit eb2d5b3

Please sign in to comment.