Go to file
Max Desiatov 947ecb1322
Remove `platforms` stanza from `Template.swift`
2020-07-21 21:52:06 +01:00
.github Update update-deps.yml 2020-07-12 22:14:20 +01:00
.vscode Add `list` flag and `testCases` argument to `test` (#52) 2020-07-15 19:12:28 +01:00
Sources Remove `platforms` stanza from `Template.swift` 2020-07-21 21:52:06 +01:00
TestApp Update static.zip, automate its release process (#60) 2020-07-19 21:53:04 +01:00
Tests Fix Linux build: rename cartonTests to CartonTests 2020-06-06 10:52:12 +01:00
entrypoint Update static.zip, automate its release process (#60) 2020-07-19 21:53:04 +01:00
.gitignore Update static.zip, automate its release process (#60) 2020-07-19 21:53:04 +01:00
.pre-commit-config.yaml Add empty package with basic dependencies 2020-05-04 18:00:18 +01:00
.swift-version Basic parsing of package info on carton dev 2020-06-04 10:38:51 +01:00
.swiftformat Specify operators in .swiftformat 2020-05-04 18:08:00 +01:00
.swiftlint.yml Add empty package with basic dependencies 2020-05-04 18:00:18 +01:00
Brewfile Start implementing checkDevDependencies function 2020-06-05 17:55:10 +01:00
CHANGELOG.md Fix typo in CHANGELOG.md 2020-07-08 17:31:30 +01:00
CODE_OF_CONDUCT.md Update CODE_OF_CONDUCT.md 2020-06-05 23:05:04 +01:00
Dangerfile.swift Create Dangerfile.swift 2020-06-17 17:49:10 +01:00
LICENSE Update LICENSE 2020-05-04 18:01:52 +01:00
Package.resolved Update dependencies (#62) 2020-07-21 08:10:50 +01:00
Package.swift Update static.zip, automate its release process (#60) 2020-07-19 21:53:04 +01:00
Package@swift-5.2.swift Update static.zip, automate its release process (#60) 2020-07-19 21:53:04 +01:00
README.md Add a --release flag to the carton dev command (#19) 2020-07-02 13:49:46 +01:00
package-lock.json Update static.zip, automate its release process (#60) 2020-07-19 21:53:04 +01:00
package.json Upgrade JavaScriptKit (#59) 2020-07-18 12:42:38 -04:00
webpack.config.js Update static.zip, automate its release process (#60) 2020-07-19 21:53:04 +01:00

README.md

carton 📦

Watcher, bundler, and test runner for your SwiftWasm apps

The main goal of carton is to provide a smooth zero-config experience when developing for WebAssembly. It is still in development, but it aims to support these features (🐥 means "ready to use"):

  • 🥚 Creating basic package boilerplate for apps built with SwiftWasm with carton init.
  • 🐥 Watching the app for source code changes and reloading it in your browser with carton dev.
  • 🐣 Running your XCTest suite in the full JavaScript/DOM environment with carton test.
  • 🥚 Optimizing and packaging the app for distribution with carton bundle.
  • 🐥 Managing SwiftWasm toolchain and SDK installations with carton sdk.

It is currently work in progress, so watch the repository for imminent updates!

Motivation

The main motivation for carton came after I had enough struggles with webpack.js, trying to make its config file work, looking for appropriate plugins. I'm convinced that the required use of webpack in SwiftWasm projects could limit the wider adoption of SwiftWasm itself. Hopefully, with carton you can avoid using webpack altogether. carton also simplifies a few other things in your SwiftWasm development workflow such as toolchain and SDK installations.

Requirements

  • macOS 10.15 and Xcode 11.4 or later for macOS users.
  • Swift 5.2 or later for Linux users.

Installation

On macOS carton can be installed with Homebrew. Make sure you have Homebrew installed and then run:

brew install swiftwasm/tap/carton

You'll have to build carton from sources on Linux. Clone the repository and run swift build -c release, the carton binary will be located in the .build/release/carton directory after that.

carton automatically installs the required SwiftWasm toolchain and SDK when you build your project with carton dev. You can however install SwiftWasm separately if needed, either by passing an archive URL to carton sdk install directly, or just specifying the snapshot version, like carton sdk install wasm-DEVELOPMENT-SNAPSHOT-2020-06-07-a. carton dev can also detect existing installations of swiftenv, so if you already have SwiftWasm installed via swiftenv, you don't have to do anything on top of that to start using carton.

How does it work?

carton bundles a WASI polyfill, which is currently required to run any SwiftWasm code, and the JavaScriptKit runtime for convenience. carton also embeds an HTTP server for previewing your SwiftWasm app directly in a browser. The development version of the polyfill establishes a helper WebSocket connection to the server, so that it can reload development browser tabs when rebuilt binary is available. This brings the development experience closer to Xcode live previews, which you may have previously used when developing SwiftUI apps.

carton does not require any config files for these basic development scenarios, while some configuration may be supported in the future, for example for complex asset pipelines if needed. The only requirement is that your Package.swift contains at least a single executable product, which then will be compiled for WebAssembly and served when you start carton dev in the directory where Package.swift is located.

carton is built with Vapor, SwiftNIO, swift-tools-support-core, and OpenCombine, and supports both macOS and Linux. (Many thanks to everyone supporting and maintaining those projects!)

Running carton dev with the release configuration

By default carton dev will compile in the debug configuration. Add the --release flag to compile in the release configuration.

Providing a destination file to carton dev

The carton dev command can be passed an optional destination.json file to the swift build command it calls. Currently, this is required to be able to use Foundation in your code.

The specification of the destination.json can be found here:

Below is a template allowing you to link to the right Foundation:

{
  "version": 1,
  "sdk": "${PATH_TO_TOOLCHAIN}/usr/share/wasi-sysroot",
  "toolchain-bin-dir": "${PATH_TO_TOOLCHAIN}/usr/bin",
  "target": "wasm32-unknown-wasi",
  "extra-cc-flags": [
    ""
  ],
  "extra-cpp-flags": [
    ""
  ],
  "extra-swiftc-flags": [
    "-I", "${PATH_TO_TOOLCHAIN}/usr/lib/swift/wasi/wasm32",
    "-Xlinker", "-lCoreFoundation",
    "-Xlinker", "-lBlocksRuntime",
    "-Xlinker", "-licui18n",
    "-Xlinker", "-luuid"
  ]
}

When using carton on MacOS, ${PATH_TO_TOOLCHAIN} will usually be of the following format: /Users/me/.carton/sdk/wasm-DEVELOPMENT-SNAPSHOT-2020-06-12-a/ or /Users/me/.swiftenv/versions/wasm-DEVELOPMENT-SNAPSHOT-2020-06-12-a/ if you installed the SDK with swiftenv.

Note that this path should really be consistent with the toolchain used by carton. So when you do not use a swiftenv based toolchain, you need to take care of specifying the correct one.

In the future, we'll make sure that this is taken care of by carton itself.

Roadmap

Since a subset of Foundation and XCTest already work and are supplied in the latest snapshots of SwiftWasm SDK, the next top priority for carton is to allow running your XCTest suites directly in browsers and receiving test results back to the HTTP server, so that test results can be reported in CLI. This was blocked by XCTest not allowing customized test report formats, which is now partially resolved with a new argument available on XCTMain and a custom JSON test reporter. After a few other issues are resolved with the SwiftWasm toolchain, I'll get carton test fully working with XCTest.

There are a few more commands on the roadmap to be implemented, such as carton init for initializing basic SwiftWasm projects (potentially with configurable templates), carton bundle to produce an optimized production deployment bundle, SwiftPM resources support for bundled assets, and much more.

As cross-compiling to WebAssembly and running apps and tests remotely is not too dissimilar to Android development, or even development on macOS for Linux through Docker, carton could potentially become a generic tool for cross-platform Swift developers. I'm not developing any Android apps currently, but if there are interested Swift for Android developers, I'd be very happy to review and merge their contributions enabling that.

Contributing

Sponsorship

If this tool saved you any amount of time or money, please consider sponsoring the work of its maintainer. While some of the sponsorship tiers give you priority support or even consulting time, any amount is appreciated and helps in maintaining the project.

Coding Style

This project uses SwiftFormat and SwiftLint to enforce formatting and coding style. We encourage you to run SwiftFormat within a local clone of the repository in whatever way works best for you either manually or automatically via an Xcode extension, build phase or git pre-commit hook etc.

To guarantee that these tools run before you commit your changes on macOS, you're encouraged to run this once to set up the pre-commit hook:

brew bundle # installs SwiftLint, SwiftFormat and pre-commit
pre-commit install # installs pre-commit hook to run checks before you commit

Refer to the pre-commit documentation page for more details and installation instructions for other platforms.

SwiftFormat and SwiftLint also run on CI for every PR and thus a CI build can fail with incosistent formatting or style. We require CI builds to pass for all PRs before merging.

Code of Conduct

This project adheres to the Contributor Covenant Code of Conduct. By participating, you are expected to uphold this code. Please report unacceptable behavior to conduct@carton.dev.