Add separate Builder class, use WasmTransformer (#131)
Resolves #127. * Add separate Builder class, use WasmTransformer * Don't apply the transformer in non-browser environments * Fix macOS Swift 5.2 build failure * Fix Package.swift errors * Fix cyclic dependency in `Package.swift` * Bump WasmTransformer requirement to 0.0.1 * Rename `case wasmer` to `case other`
This commit is contained in:
parent
703078dd83
commit
08956baf1d
|
@ -33,6 +33,11 @@
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "swift build && cd TestApp && ../.build/debug/carton dev"
|
"command": "swift build && cd TestApp && ../.build/debug/carton dev"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"label": "build release and run dev",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "swift build -c release && cd TestApp && ../.build/release/carton dev"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"label": "build and run dev on 9090 port",
|
"label": "build and run dev on 9090 port",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
|
|
|
@ -163,6 +163,15 @@
|
||||||
"version": "4.32.0"
|
"version": "4.32.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"package": "WasmTransformer",
|
||||||
|
"repositoryURL": "https://github.com/swiftwasm/WasmTransformer",
|
||||||
|
"state": {
|
||||||
|
"branch": null,
|
||||||
|
"revision": "c7cb17309372e57c9f75f7abd5c7323d667eaddc",
|
||||||
|
"version": "0.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"package": "websocket-kit",
|
"package": "websocket-kit",
|
||||||
"repositoryURL": "https://github.com/vapor/websocket-kit.git",
|
"repositoryURL": "https://github.com/vapor/websocket-kit.git",
|
||||||
|
|
|
@ -26,6 +26,7 @@ let package = Package(
|
||||||
.package(url: "https://github.com/vapor/vapor.git", from: "4.29.3"),
|
.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/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.14.0"),
|
||||||
|
.package(url: "https://github.com/swiftwasm/WasmTransformer", .upToNextMinor(from: "0.0.1")),
|
||||||
],
|
],
|
||||||
targets: [
|
targets: [
|
||||||
// Targets are the basic building blocks of a package. A target can define a module
|
// Targets are the basic building blocks of a package. A target can define a module
|
||||||
|
@ -51,6 +52,7 @@ let package = Package(
|
||||||
.product(name: "SwiftToolsSupport-auto", package: "swift-tools-support-core"),
|
.product(name: "SwiftToolsSupport-auto", package: "swift-tools-support-core"),
|
||||||
"CartonHelpers",
|
"CartonHelpers",
|
||||||
openCombineProduct,
|
openCombineProduct,
|
||||||
|
"WasmTransformer",
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
.target(
|
.target(
|
||||||
|
|
|
@ -20,6 +20,7 @@ let package = Package(
|
||||||
.package(url: "https://github.com/vapor/vapor.git", from: "4.29.3"),
|
.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/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.14.0"),
|
||||||
|
.package(url: "https://github.com/swiftwasm/WasmTransformer", .upToNextMinor(from: "0.0.1")),
|
||||||
],
|
],
|
||||||
targets: [
|
targets: [
|
||||||
// Targets are the basic building blocks of a package. A target can define a module
|
// Targets are the basic building blocks of a package. A target can define a module
|
||||||
|
@ -45,6 +46,7 @@ let package = Package(
|
||||||
.product(name: "SwiftToolsSupport-auto", package: "swift-tools-support-core"),
|
.product(name: "SwiftToolsSupport-auto", package: "swift-tools-support-core"),
|
||||||
"CartonHelpers",
|
"CartonHelpers",
|
||||||
"OpenCombine",
|
"OpenCombine",
|
||||||
|
"WasmTransformer",
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
.target(
|
.target(
|
||||||
|
|
|
@ -21,7 +21,7 @@ import OpenCombine
|
||||||
#endif
|
#endif
|
||||||
import TSCBasic
|
import TSCBasic
|
||||||
|
|
||||||
extension Subscribers.Completion {
|
public extension Subscribers.Completion {
|
||||||
var result: Result<(), Failure> {
|
var result: Result<(), Failure> {
|
||||||
switch self {
|
switch self {
|
||||||
case let .failure(error):
|
case let .failure(error):
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
// Copyright 2020 Carton contributors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
import CartonHelpers
|
||||||
|
#if canImport(Combine)
|
||||||
|
import Combine
|
||||||
|
#else
|
||||||
|
import OpenCombine
|
||||||
|
#endif
|
||||||
|
import Foundation
|
||||||
|
import TSCBasic
|
||||||
|
import WasmTransformer
|
||||||
|
|
||||||
|
public final class Builder {
|
||||||
|
public enum Environment {
|
||||||
|
case other
|
||||||
|
case browser
|
||||||
|
}
|
||||||
|
|
||||||
|
public let mainWasmPath: AbsolutePath
|
||||||
|
|
||||||
|
private var currentProcess: ProcessRunner?
|
||||||
|
private let arguments: [String]
|
||||||
|
private let environment: Environment
|
||||||
|
private let terminal: InteractiveWriter
|
||||||
|
private let fileSystem: FileSystem
|
||||||
|
private var subscription: AnyCancellable?
|
||||||
|
|
||||||
|
public init(
|
||||||
|
arguments: [String],
|
||||||
|
mainWasmPath: AbsolutePath,
|
||||||
|
environment: Environment = .browser,
|
||||||
|
_ fileSystem: FileSystem,
|
||||||
|
_ terminal: InteractiveWriter
|
||||||
|
) {
|
||||||
|
self.arguments = arguments
|
||||||
|
self.mainWasmPath = mainWasmPath
|
||||||
|
self.environment = environment
|
||||||
|
self.terminal = terminal
|
||||||
|
self.fileSystem = fileSystem
|
||||||
|
}
|
||||||
|
|
||||||
|
public func run() -> AnyPublisher<String, Error> {
|
||||||
|
let buildStarted = Date()
|
||||||
|
let process = ProcessRunner(arguments, loadingMessage: "Compiling...", terminal)
|
||||||
|
currentProcess = process
|
||||||
|
|
||||||
|
return process
|
||||||
|
.publisher
|
||||||
|
.handleEvents(receiveCompletion: { [weak self] in
|
||||||
|
guard case .finished = $0, let self = self else { return }
|
||||||
|
|
||||||
|
self.terminal.logLookup(
|
||||||
|
"`swift build` completed in ",
|
||||||
|
String(format: "%.2f seconds", abs(buildStarted.timeIntervalSinceNow))
|
||||||
|
)
|
||||||
|
|
||||||
|
guard self.environment == .browser else { return }
|
||||||
|
|
||||||
|
// FIXME: errors from these `try` expressions should be recoverable, not sure how to
|
||||||
|
// do that in `handleEvents`, and `flatMap` doesnt' fit here as we need to track
|
||||||
|
// publisher completion.
|
||||||
|
// swiftlint:disable force_try
|
||||||
|
let binary = try! self.fileSystem.readFileContents(self.mainWasmPath)
|
||||||
|
|
||||||
|
let loweringStarted = Date()
|
||||||
|
let loweredBinary = try! lowerI64Imports(binary.contents)
|
||||||
|
|
||||||
|
self.terminal.logLookup(
|
||||||
|
"Binary transformation for Safari compatibility completed in ",
|
||||||
|
String(format: "%.2f seconds", abs(loweringStarted.timeIntervalSinceNow))
|
||||||
|
)
|
||||||
|
|
||||||
|
try! self.fileSystem.writeFileContents(self.mainWasmPath, bytes: .init(loweredBinary))
|
||||||
|
// swiftlint:enable force_try
|
||||||
|
})
|
||||||
|
.eraseToAnyPublisher()
|
||||||
|
}
|
||||||
|
|
||||||
|
public func runAndWaitUntilFinished() throws {
|
||||||
|
try await { completion in
|
||||||
|
subscription = run()
|
||||||
|
.sink(
|
||||||
|
receiveCompletion: { completion($0.result) },
|
||||||
|
receiveValue: { _ in }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -225,10 +225,10 @@ public final class Toolchain {
|
||||||
"--enable-test-discovery", "--destination", destination ?? inferDestinationPath().pathString,
|
"--enable-test-discovery", "--destination", destination ?? inferDestinationPath().pathString,
|
||||||
]
|
]
|
||||||
|
|
||||||
try ProcessRunner(builderArguments, loadingMessage: "Compiling...", terminal)
|
try Builder(arguments: builderArguments, mainWasmPath: mainWasmPath, fileSystem, terminal)
|
||||||
.waitUntilFinished()
|
.runAndWaitUntilFinished()
|
||||||
|
|
||||||
guard localFileSystem.exists(mainWasmPath) else {
|
guard fileSystem.exists(mainWasmPath) else {
|
||||||
terminal.write(
|
terminal.write(
|
||||||
"Failed to build the main executable binary, fix the build errors and restart\n",
|
"Failed to build the main executable binary, fix the build errors and restart\n",
|
||||||
inColor: .red
|
inColor: .red
|
||||||
|
@ -257,9 +257,16 @@ public final class Toolchain {
|
||||||
"-Xswiftc", "-color-diagnostics",
|
"-Xswiftc", "-color-diagnostics",
|
||||||
]
|
]
|
||||||
|
|
||||||
try ProcessRunner(builderArguments, terminal).waitUntilFinished()
|
try Builder(
|
||||||
|
arguments: builderArguments,
|
||||||
|
mainWasmPath: testBundlePath,
|
||||||
|
environment: .other,
|
||||||
|
fileSystem,
|
||||||
|
terminal
|
||||||
|
)
|
||||||
|
.runAndWaitUntilFinished()
|
||||||
|
|
||||||
guard localFileSystem.exists(testBundlePath) else {
|
guard fileSystem.exists(testBundlePath) else {
|
||||||
terminal.write(
|
terminal.write(
|
||||||
"Failed to build the test bundle, fix the build errors and restart\n",
|
"Failed to build the test bundle, fix the build errors and restart\n",
|
||||||
inColor: .red
|
inColor: .red
|
||||||
|
|
|
@ -84,9 +84,8 @@ struct Dev: ParsableCommand {
|
||||||
let sources = try paths.flatMap { try localFileSystem.traverseRecursively($0) }
|
let sources = try paths.flatMap { try localFileSystem.traverseRecursively($0) }
|
||||||
|
|
||||||
try Server(
|
try Server(
|
||||||
builderArguments: arguments,
|
builder: Builder(arguments: arguments, mainWasmPath: mainWasmPath, localFileSystem, terminal),
|
||||||
pathsToWatch: sources,
|
pathsToWatch: sources,
|
||||||
mainWasmPath: mainWasmPath,
|
|
||||||
customIndexContent: HTML.readCustomIndexPage(at: customIndexPage, on: localFileSystem),
|
customIndexContent: HTML.readCustomIndexPage(at: customIndexPage, on: localFileSystem),
|
||||||
// swiftlint:disable:next force_try
|
// swiftlint:disable:next force_try
|
||||||
package: try! toolchain.package.get(),
|
package: try! toolchain.package.get(),
|
||||||
|
|
|
@ -37,15 +37,13 @@ final class Server {
|
||||||
private var connections = Set<WebSocket>()
|
private var connections = Set<WebSocket>()
|
||||||
private var subscriptions = [AnyCancellable]()
|
private var subscriptions = [AnyCancellable]()
|
||||||
private let watcher: Watcher
|
private let watcher: Watcher
|
||||||
private var builder: ProcessRunner?
|
|
||||||
private let app: Application
|
private let app: Application
|
||||||
private let localURL: String
|
private let localURL: String
|
||||||
private let skipAutoOpen: Bool
|
private let skipAutoOpen: Bool
|
||||||
|
|
||||||
init(
|
init(
|
||||||
builderArguments: [String],
|
builder: Builder,
|
||||||
pathsToWatch: [AbsolutePath],
|
pathsToWatch: [AbsolutePath],
|
||||||
mainWasmPath: AbsolutePath,
|
|
||||||
customIndexContent: String?,
|
customIndexContent: String?,
|
||||||
package: SwiftToolchain.Package,
|
package: SwiftToolchain.Package,
|
||||||
verbose: Bool,
|
verbose: Bool,
|
||||||
|
@ -63,7 +61,7 @@ final class Server {
|
||||||
app = Application(env)
|
app = Application(env)
|
||||||
app.configure(
|
app.configure(
|
||||||
port: port,
|
port: port,
|
||||||
mainWasmPath: mainWasmPath,
|
mainWasmPath: builder.mainWasmPath,
|
||||||
customIndexContent: customIndexContent,
|
customIndexContent: customIndexContent,
|
||||||
package: package,
|
package: package,
|
||||||
onWebSocketOpen: { [weak self] in
|
onWebSocketOpen: { [weak self] in
|
||||||
|
@ -85,8 +83,8 @@ final class Server {
|
||||||
for change in changes.map(\.pathString) {
|
for change in changes.map(\.pathString) {
|
||||||
terminal.write("- \(change)\n", inColor: .cyan)
|
terminal.write("- \(change)\n", inColor: .cyan)
|
||||||
}
|
}
|
||||||
return ProcessRunner(builderArguments, terminal)
|
return builder
|
||||||
.publisher
|
.run()
|
||||||
.handleEvents(receiveCompletion: { [weak self] in
|
.handleEvents(receiveCompletion: { [weak self] in
|
||||||
guard case .finished = $0, let self = self else { return }
|
guard case .finished = $0, let self = self else { return }
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue