diff --git a/CHANGELOG.md b/CHANGELOG.md index fe5ed046fe5..b732193691d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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. @@ -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 diff --git a/Fixtures/SwiftSDKs/Package.swift b/Fixtures/SwiftSDKs/Package.swift new file mode 100644 index 00000000000..fc9bc8d91c8 --- /dev/null +++ b/Fixtures/SwiftSDKs/Package.swift @@ -0,0 +1 @@ +// This empty file tells test fixture logic to copy this directory's content to the test case temp directory. diff --git a/Package.swift b/Package.swift index d074af13fd8..c74f42d9c9b 100644 --- a/Package.swift +++ b/Package.swift @@ -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"] diff --git a/Sources/CMakeLists.txt b/Sources/CMakeLists.txt index 1f4226f88e6..279084bb5c0 100644 --- a/Sources/CMakeLists.txt +++ b/Sources/CMakeLists.txt @@ -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) diff --git a/Sources/CoreCommands/Options.swift b/Sources/CoreCommands/Options.swift index bcb60853c23..59def60256d 100644 --- a/Sources/CoreCommands/Options.swift +++ b/Sources/CoreCommands/Options.swift @@ -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( @@ -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. diff --git a/Sources/CoreCommands/SwiftCommandState.swift b/Sources/CoreCommands/SwiftCommandState.swift index 38c190ec386..34ab25d2d93 100644 --- a/Sources/CoreCommands/SwiftCommandState.swift +++ b/Sources/CoreCommands/SwiftCommandState.swift @@ -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 @@ -821,6 +826,12 @@ 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, @@ -828,7 +839,7 @@ package final class SwiftCommandState { 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, diff --git a/Sources/PackageModel/SwiftSDKs/SwiftSDKBundleStore.swift b/Sources/PackageModel/SwiftSDKs/SwiftSDKBundleStore.swift index f5e40bb2083..13d3b55b966 100644 --- a/Sources/PackageModel/SwiftSDKs/SwiftSDKBundleStore.swift +++ b/Sources/PackageModel/SwiftSDKs/SwiftSDKBundleStore.swift @@ -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. """ } diff --git a/Sources/SPMTestSupport/SwiftPMProduct.swift b/Sources/SPMTestSupport/SwiftPMProduct.swift index 3338b295be0..93bd49e4857 100644 --- a/Sources/SPMTestSupport/SwiftPMProduct.swift +++ b/Sources/SPMTestSupport/SwiftPMProduct.swift @@ -25,6 +25,8 @@ package enum SwiftPM { case Registry case Test case Run + case experimentalSDK + case sdk } extension SwiftPM { @@ -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" } } diff --git a/Sources/SwiftSDKCommand/README.md b/Sources/SwiftSDKCommand/README.md index 15fb0924c16..94180372b7a 100644 --- a/Sources/SwiftSDKCommand/README.md +++ b/Sources/SwiftSDKCommand/README.md @@ -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). diff --git a/Sources/SwiftSDKCommand/SwiftSDKCommand.swift b/Sources/SwiftSDKCommand/SwiftSDKCommand.swift index dc0cf4fe933..e39740d4796 100644 --- a/Sources/SwiftSDKCommand/SwiftSDKCommand.swift +++ b/Sources/SwiftSDKCommand/SwiftSDKCommand.swift @@ -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, diff --git a/Sources/swift-experimental-sdk/Entrypoint.swift b/Sources/swift-experimental-sdk/Entrypoint.swift index 71d84e8443d..f908ff3ff10 100644 --- a/Sources/swift-experimental-sdk/Entrypoint.swift +++ b/Sources/swift-experimental-sdk/Entrypoint.swift @@ -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() } } diff --git a/Sources/swift-package-manager/SwiftPM.swift b/Sources/swift-package-manager/SwiftPM.swift index 84ea0f28baa..fa6fc156023 100644 --- a/Sources/swift-package-manager/SwiftPM.swift +++ b/Sources/swift-package-manager/SwiftPM.swift @@ -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() diff --git a/Sources/swift-sdk/CMakeLists.txt b/Sources/swift-sdk/CMakeLists.txt new file mode 100644 index 00000000000..ee3be128bae --- /dev/null +++ b/Sources/swift-sdk/CMakeLists.txt @@ -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) diff --git a/Sources/swift-sdk/Entrypoint.swift b/Sources/swift-sdk/Entrypoint.swift new file mode 100644 index 00000000000..71d84e8443d --- /dev/null +++ b/Sources/swift-sdk/Entrypoint.swift @@ -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() + } +} diff --git a/Tests/CommandsTests/SDKCommandTests.swift b/Tests/CommandsTests/SDKCommandTests.swift new file mode 100644 index 00000000000..0c74126d8ba --- /dev/null +++ b/Tests/CommandsTests/SDKCommandTests.swift @@ -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 ") || stdout.contains("USAGE: swift sdk []"), "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) + } + } + } + } +} diff --git a/Utilities/bootstrap b/Utilities/bootstrap index ba146d46e2a..a328c6b1860 100755 --- a/Utilities/bootstrap +++ b/Utilities/bootstrap @@ -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))