diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml index 56968775..38b7802e 100644 --- a/.github/workflows/swift.yml +++ b/.github/workflows/swift.yml @@ -11,22 +11,16 @@ jobs: strategy: matrix: include: - - os: macos-10.15 - swift_version: 5.2 - xcode: /Applications/Xcode_11.7.app/Contents/Developer - - os: macos-10.15 - swift_version: 5.3 - xcode: /Applications/Xcode_12.app/Contents/Developer - os: macos-11 swift_version: 5.4 - xcode: /Applications/Xcode_12.5.app/Contents/Developer -# - os: macos-11 -# swift_version: 5.5 -# xcode: /Applications/Xcode_13.0.app/Contents/Developer + xcode: /Applications/Xcode_12.5.1.app/Contents/Developer + - os: macos-11 + swift_version: 5.5 + xcode: /Applications/Xcode_13.1.app/Contents/Developer - os: ubuntu-18.04 - swift_version: 5.4 + swift_version: 5.5 - os: ubuntu-20.04 - swift_version: 5.4 + swift_version: 5.5 name: Build on ${{ matrix.os }} with Swift ${{ matrix.swift_version }} runs-on: ${{ matrix.os }} @@ -34,8 +28,8 @@ jobs: - uses: actions/checkout@v2 - name: Select Xcode version - run: sudo xcode-select --switch ${{ matrix.xcode }} if: startsWith(matrix.os, 'macos') + run: sudo xcode-select --switch ${{ matrix.xcode }} - name: Cleanup pre-installed SwiftLint run: rm -f '/usr/local/bin/swiftlint' @@ -45,10 +39,10 @@ jobs: if: startsWith(matrix.os, 'macos') - name: Install dependencies for Ubuntu + if: startsWith(matrix.os, 'ubuntu') run: | sudo ./install_ubuntu_deps.sh curl https://get.wasmer.io -sSfL | sh - if: startsWith(matrix.os, 'ubuntu') - name: Build the project run: swift build diff --git a/Package.resolved b/Package.resolved index 6fe2c524..a5cb69e4 100644 --- a/Package.resolved +++ b/Package.resolved @@ -6,8 +6,8 @@ "repositoryURL": "https://github.com/swift-server/async-http-client.git", "state": { "branch": null, - "revision": "8fa7f082b155ea325bcf7b2dbffaf81d4eea1ae4", - "version": "1.5.1" + "revision": "1081b0b0541f535ca088acdb56f5ca5598bc6247", + "version": "1.6.3" } }, { @@ -69,8 +69,8 @@ "repositoryURL": "https://github.com/apple/swift-argument-parser.git", "state": { "branch": null, - "revision": "9564d61b08a5335ae0a36f789a7d71493eacadfc", - "version": "0.3.2" + "revision": "83b23d940471b313427da226196661856f6ba3e0", + "version": "0.4.4" } }, { @@ -95,8 +95,8 @@ "package": "swift-driver", "repositoryURL": "https://github.com/apple/swift-driver.git", "state": { - "branch": "release/5.4", - "revision": "93e8b927225a62b963ebe13ab11e04192fa8a67b", + "branch": "release/5.5", + "revision": "b1ffa4985d4691c8a83db35412f05507c1be3f29", "version": null } }, @@ -104,8 +104,8 @@ "package": "llbuild", "repositoryURL": "https://github.com/apple/swift-llbuild.git", "state": { - "branch": "release/5.4", - "revision": "eb56a00ed9dfd62c2ce4ec86183ff0bc0afda997", + "branch": "release/5.5", + "revision": "b5d9b4a9995c05688ae5f3b87a0d7ac0dc45c6c6", "version": null } }, @@ -176,8 +176,8 @@ "package": "SwiftPM", "repositoryURL": "https://github.com/apple/swift-package-manager.git", "state": { - "branch": "release/5.4", - "revision": "374cdb42d7b146837de70489a04c5df956092685", + "branch": "release/5.5", + "revision": "96c347b1419e513291f07c988f3e995363d400ed", "version": null } }, @@ -185,8 +185,8 @@ "package": "swift-tools-support-core", "repositoryURL": "https://github.com/apple/swift-tools-support-core.git", "state": { - "branch": "release/5.4", - "revision": "d7bd4375c26e7dab2c17791cfa06f9b981d02339", + "branch": "release/5.5", + "revision": "1b21e2ce36891ed4f458421a83b5d9e886acd4cd", "version": null } }, @@ -195,8 +195,8 @@ "repositoryURL": "https://github.com/vapor/vapor.git", "state": { "branch": null, - "revision": "f9f68e5f417ef1de56222a80079a72605fbfde8d", - "version": "4.48.8" + "revision": "27119271502bf266be293be5325f0fb72435e8fd", + "version": "4.49.2" } }, { diff --git a/Package.swift b/Package.swift index 8df164b9..440f1a0c 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:5.3 +// swift-tools-version:5.4 // The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription @@ -21,24 +21,25 @@ let package = Package( .executable(name: "carton-release", targets: ["carton-release"]), ], dependencies: [ - .package(url: "https://github.com/swift-server/async-http-client.git", from: "1.2.2"), + .package(url: "https://github.com/swift-server/async-http-client.git", from: "1.6.3"), .package( url: "https://github.com/apple/swift-argument-parser.git", - .upToNextMinor(from: "0.3.0") + from: "0.4.3" ), + .package(url: "https://github.com/apple/swift-nio.git", from: "2.33.0"), .package( name: "SwiftPM", url: "https://github.com/apple/swift-package-manager.git", - .branch("release/5.4") + .branch("release/5.5") ), .package( url: "https://github.com/apple/swift-tools-support-core.git", - .branch("release/5.4") + .branch("release/5.5") ), .package(url: "https://github.com/OpenCombine/OpenCombine.git", from: "0.12.0"), - .package(url: "https://github.com/vapor/vapor.git", from: "4.29.3"), + .package(url: "https://github.com/vapor/vapor.git", from: "4.49.2"), .package(url: "https://github.com/apple/swift-crypto.git", from: "1.1.0"), - .package(url: "https://github.com/JohnSundell/Splash.git", from: "0.14.0"), + .package(url: "https://github.com/JohnSundell/Splash.git", from: "0.16.0"), .package( url: "https://github.com/swiftwasm/WasmTransformer", .upToNextMinor(from: "0.0.3") @@ -48,7 +49,7 @@ let package = Package( // Targets are the basic building blocks of a package. A target can define a module // or a test suite. Targets can depend on other targets in this package, and on // products in packages which this package depends on. - .target( + .executableTarget( name: "Carton", dependencies: [ "CartonCLI", @@ -74,6 +75,7 @@ let package = Package( name: "SwiftToolchain", dependencies: [ .product(name: "AsyncHTTPClient", package: "async-http-client"), + .product(name: "NIOFoundationCompat", package: "swift-nio"), .product(name: "SwiftPMDataModel", package: "SwiftPM"), "CartonHelpers", openCombineProduct, @@ -91,7 +93,7 @@ let package = Package( ), // This target is used only for release automation tasks and // should not be installed by `carton` users. - .target( + .executableTarget( name: "carton-release", dependencies: [ .product(name: "ArgumentParser", package: "swift-argument-parser"), diff --git a/Package@swift-5.2.swift b/Package@swift-5.2.swift deleted file mode 100644 index 7ea09493..00000000 --- a/Package@swift-5.2.swift +++ /dev/null @@ -1,113 +0,0 @@ -// swift-tools-version:5.2 -// The swift-tools-version declares the minimum version of Swift required to build this package. - -import PackageDescription - -let package = Package( - name: "carton", - platforms: [.macOS(.v10_15)], - products: [ - .library(name: "SwiftToolchain", targets: ["SwiftToolchain"]), - .library(name: "CartonHelpers", targets: ["CartonHelpers"]), - .library(name: "CartonKit", targets: ["CartonKit"]), - .library(name: "CartonCLI", targets: ["CartonCLI"]), - .executable(name: "carton", targets: ["Carton"]), - .executable(name: "carton-release", targets: ["carton-release"]), - ], - dependencies: [ - .package(url: "https://github.com/swift-server/async-http-client.git", from: "1.2.2"), - .package( - url: "https://github.com/apple/swift-argument-parser.git", - .upToNextMinor(from: "0.3.0") - ), - .package( - name: "SwiftPM", - url: "https://github.com/apple/swift-package-manager.git", - .branch("release/5.4") - ), - .package( - url: "https://github.com/apple/swift-tools-support-core.git", - .branch("release/5.4") - ), - .package(url: "https://github.com/OpenCombine/OpenCombine.git", from: "0.12.0"), - .package(url: "https://github.com/vapor/vapor.git", from: "4.29.3"), - .package(url: "https://github.com/apple/swift-crypto.git", from: "1.1.0"), - .package(url: "https://github.com/JohnSundell/Splash.git", from: "0.14.0"), - .package(url: "https://github.com/swiftwasm/WasmTransformer", .upToNextMinor(from: "0.0.3")), - ], - targets: [ - // Targets are the basic building blocks of a package. A target can define a module - // or a test suite. Targets can depend on other targets in this package, and on - // products in packages which this package depends on. - .target( - name: "Carton", - dependencies: [ - "CartonCLI", - ] - ), - .target( - name: "CartonCLI", - dependencies: ["CartonKit"] - ), - .target( - name: "CartonKit", - dependencies: [ - .product(name: "ArgumentParser", package: "swift-argument-parser"), - .product(name: "AsyncHTTPClient", package: "async-http-client"), - .product(name: "Crypto", package: "swift-crypto"), - .product(name: "Vapor", package: "vapor"), - "CartonHelpers", - "OpenCombine", - "SwiftToolchain", - ] - ), - .target( - name: "SwiftToolchain", - dependencies: [ - .product(name: "AsyncHTTPClient", package: "async-http-client"), - .product(name: "SwiftPMDataModel", package: "SwiftPM"), - .product(name: "SwiftToolsSupport-auto", package: "swift-tools-support-core"), - "CartonHelpers", - "OpenCombine", - "WasmTransformer", - ] - ), - .target( - name: "CartonHelpers", - dependencies: [ - .product(name: "AsyncHTTPClient", package: "async-http-client"), - .product(name: "SwiftToolsSupport-auto", package: "swift-tools-support-core"), - "OpenCombine", - "Splash", - "WasmTransformer", - ] - ), - // This target is used only for release automation tasks and - // should not be installed by `carton` users. - .target( - name: "carton-release", - dependencies: [ - .product(name: "ArgumentParser", package: "swift-argument-parser"), - .product(name: "AsyncHTTPClient", package: "async-http-client"), - "CartonHelpers", - ] - ), - .testTarget( - name: "CartonTests", - dependencies: [ - "Carton", - "CartonHelpers", - .product(name: "SwiftToolsSupport-auto", package: "swift-tools-support-core"), - .product(name: "ArgumentParser", package: "swift-argument-parser"), - ] - ), - .testTarget( - name: "CartonCommandTests", - dependencies: [ - "CartonCLI", - .product(name: "ArgumentParser", package: "swift-argument-parser"), - .product(name: "AsyncHTTPClient", package: "async-http-client"), - ] - ), - ] -) diff --git a/README.md b/README.md index eee0288e..a6ec447b 100644 --- a/README.md +++ b/README.md @@ -24,8 +24,8 @@ development workflow such as toolchain and SDK installations. ### Requirements -- macOS 10.15 and Xcode 11.4 or later. -- [Swift 5.2 or later](https://swift.org/download/) and Ubuntu 18.04 or 20.04 for Linux users. +- macOS 11 and Xcode 12.5.1 or later. macOS 10.15 may work, but is untested. +- [Swift 5.4 or later](https://swift.org/download/) and Ubuntu 18.04 or 20.04 for Linux users. ### Installation diff --git a/Sources/CartonHelpers/DefaultToolchain.swift b/Sources/CartonHelpers/DefaultToolchain.swift index 1e389b2f..0920e1f5 100644 --- a/Sources/CartonHelpers/DefaultToolchain.swift +++ b/Sources/CartonHelpers/DefaultToolchain.swift @@ -12,4 +12,4 @@ // See the License for the specific language governing permissions and // limitations under the License. -public let defaultToolchainVersion = "wasm-5.4.0-RELEASE" +public let defaultToolchainVersion = "wasm-5.5-SNAPSHOT-2021-11-16-a" diff --git a/Sources/SwiftToolchain/Manifest.swift b/Sources/SwiftToolchain/Manifest.swift index b451ca6a..1472e60b 100644 --- a/Sources/SwiftToolchain/Manifest.swift +++ b/Sources/SwiftToolchain/Manifest.swift @@ -48,34 +48,6 @@ public enum PackageType: String { // MARK: Custom Decodable Wrappers -// TODO: Remove this struct when we move to `Swift 5.4` -/// A temprary wrapper for decoding `PackageDependencyDescription` since -/// `productFilter` is not available in dumped JSON with pre-5.4 compilers. -struct DumpedPackageDependencyDescription: Decodable { - var dependendy: PackageDependencyDescription - - private enum CodingKeys: CodingKey { - case name, url, requirement, productFilter - } - - init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - let name = try container.decode(String.self, forKey: .name) - let url = try container.decode(String.self, forKey: .url) - let requirement = try container.decode( - PackageDependencyDescription.Requirement.self, - forKey: .requirement - ) - let productFilter = try? container.decode(ProductFilter.self, forKey: .productFilter) - dependendy = PackageDependencyDescription( - name: name, - url: url, - requirement: requirement, - productFilter: productFilter ?? .nothing - ) - } -} - /// A wrapper around `Manifest` needed for decoding from `dump-package` output, /// since when encoding several (required for initialization) keys are skipped. /// When decoding this wrapper, callers must provide an `unencodedKey` in the @@ -122,31 +94,29 @@ struct DumpedManifest: Decodable { [SwiftLanguageVersion]?.self, forKey: .swiftLanguageVersions ) - // TODO: Change to `PackageDependencyDescription` when we move to `Swift 5.4` let dependencies = try container.decode( - [DumpedPackageDependencyDescription].self, + [PackageDependencyDescription].self, forKey: .dependencies ) let products = try container.decode([ProductDescription].self, forKey: .products) let targets = try container.decode([TargetDescription].self, forKey: .targets) let platforms = try container.decode([PlatformDescription].self, forKey: .platforms) - // TODO: Change to non-optional when we move to `Swift 5.4` - // `packageKind` is not available in dumped JSON with pre-5.4 compilers. - let packageKind = try? container.decode(PackageReference.Kind.self, forKey: .packageKind) + let packageKind = try container.decode(PackageReference.Kind.self, forKey: .packageKind) + manifest = Manifest( name: name, - platforms: platforms, path: unencoded.path, - url: unencoded.url, + packageKind: packageKind, + packageLocation: unencoded.path.parentDirectory.pathString, + platforms: platforms, version: unencoded.version, toolsVersion: toolsVersion, - packageKind: packageKind ?? .root, pkgConfig: pkgConfig, providers: providers, cLanguageStandard: cLanguageStandard, cxxLanguageStandard: cxxLanguageStandard, swiftLanguageVersions: swiftLanguageVersions, - dependencies: dependencies.map(\.dependendy), + dependencies: dependencies, products: products, targets: targets ) diff --git a/Sources/SwiftToolchain/Toolchain.swift b/Sources/SwiftToolchain/Toolchain.swift index c97ffd19..2d9efa79 100644 --- a/Sources/SwiftToolchain/Toolchain.swift +++ b/Sources/SwiftToolchain/Toolchain.swift @@ -76,8 +76,6 @@ extension PackageDependencyDescription.Requirement { return version == compatibleJSKitVersion case let .range(range): return range.upperBound >= compatibleJSKitVersion - case .localPackage: - return true default: return false } @@ -192,7 +190,7 @@ public final class Toolchain { switch target.type { case .regular: return RelativePath("Sources").appending(component: target.name).pathString - case .test, .system, .executable, .binary: + case .test, .system, .executable, .binary, .plugin: return nil } } @@ -214,21 +212,39 @@ public final class Toolchain { else { throw ToolchainError.noExecutableProduct } let manifest = try self.manifest.get() - if let jsKit = manifest.dependencies.first(where: { $0.name == "JavaScriptKit" }), - !jsKit.requirement.isJavaScriptKitCompatible - { + let jsKit = manifest.dependencies.first { + $0.nameForTargetDependencyResolutionOnly == "JavaScriptKit" + } + + switch jsKit { + case let .scm(jsKit) where !jsKit.requirement.isJavaScriptKitCompatible: let versionDescription = jsKit.requirement.versionDescription terminal.write( """ - This version of JavaScriptKit \(versionDescription) is not known to be compatible with \ - carton \(cartonVersion). Please specify a JavaScriptKit dependency on version \ + JavaScriptKit \(versionDescription), which is present in your dependency tree is not \ + known to be compatible with carton \(cartonVersion). Please specify a JavaScriptKit \ + dependency on version \(compatibleJSKitVersion) in your `Package.swift`.\n + + """, + inColor: .red + ) + + case .local: + terminal.write( + """ + + The version of JavaScriptKit found in your dependency tree is not known to be compatible \ + with carton \(cartonVersion). Please specify a JavaScriptKit dependency on version \ \(compatibleJSKitVersion) in your `Package.swift`.\n """, inColor: .red ) + + case nil, .scm: + break } let binPath = try inferBinPath(isRelease: flavor.isRelease) @@ -286,7 +302,9 @@ public final class Toolchain { var builderArguments = [ swiftPath.pathString, "build", "-c", flavor.isRelease ? "release" : "debug", "--product", testProductName, "--triple", "wasm32-unknown-wasi", - "-Xswiftc", "-color-diagnostics", + "-Xswiftc", "-color-diagnostics", + // workaround for 5.5 linking issues, see https://github.com/swiftwasm/swift/issues/3891 + "-Xlinker", "-licuuc", "-Xlinker", "-licui18n" ] // Versions later than 5.3.x have test discovery enabled by default and the explicit flag diff --git a/Sources/SwiftToolchain/ToolchainManagement.swift b/Sources/SwiftToolchain/ToolchainManagement.swift index 08c989af..163ae7a9 100644 --- a/Sources/SwiftToolchain/ToolchainManagement.swift +++ b/Sources/SwiftToolchain/ToolchainManagement.swift @@ -15,6 +15,7 @@ import AsyncHTTPClient import CartonHelpers import Foundation +import NIOFoundationCompat import TSCBasic import TSCUtility @@ -166,6 +167,12 @@ public class ToolchainSystem { }.whenComplete($0) } + #if arch(x86_64) + let archSuffix = "x86_64" + #elseif arch(arm64) + let archSuffix = "arm64" + #endif + #if os(macOS) let platformSuffixes = ["osx", "catalina", "macos"] #elseif os(Linux) @@ -191,8 +198,9 @@ public class ToolchainSystem { "Response succesfully parsed, choosing from this number of assets: ", release.assets.count ) + let nameSuffixes = platformSuffixes.map { "\($0)_\(archSuffix)" } return release.assets.map(\.url).filter { url in - platformSuffixes.contains { url.absoluteString.contains($0) } + nameSuffixes.contains { url.absoluteString.contains($0) } }.first } diff --git a/Tests/CartonCommandTests/CommandTestHelper.swift b/Tests/CartonCommandTests/CommandTestHelper.swift index 89b33b97..f18f03b6 100644 --- a/Tests/CartonCommandTests/CommandTestHelper.swift +++ b/Tests/CartonCommandTests/CommandTestHelper.swift @@ -204,7 +204,7 @@ public extension XCTest { func executeCommand( command: String, shouldPrintOutput: Bool = false, - cwd: URL? = nil, // To allow for testing of file based output + cwd: URL? = nil, // To allow for testing of file-based output file: StaticString = #file, line: UInt = #line ) -> Process? { let splitCommand = command.split(separator: " ") diff --git a/Tests/CartonCommandTests/DevCommandTests.swift b/Tests/CartonCommandTests/DevCommandTests.swift index 1f022074..7f8922c2 100644 --- a/Tests/CartonCommandTests/DevCommandTests.swift +++ b/Tests/CartonCommandTests/DevCommandTests.swift @@ -124,6 +124,12 @@ final class DevCommandTests: XCTestCase { // give the server some time to start repeat { + // Don't wait for anything if the process is dead. + guard process?.isRunning == true else { + process = nil + break + } + sleep(delay) response = try? client?.get(url: url).wait() count += 1 diff --git a/Tests/CartonCommandTests/TestCommandTests.swift b/Tests/CartonCommandTests/TestCommandTests.swift index ca8e7020..ebe7d529 100644 --- a/Tests/CartonCommandTests/TestCommandTests.swift +++ b/Tests/CartonCommandTests/TestCommandTests.swift @@ -39,7 +39,8 @@ final class TestCommandTests: XCTestCase { AssertExecuteCommand( command: "carton test", - cwd: packageDirectory.url + cwd: packageDirectory.url, + debug: true ) // finally, clean up