2020-06-04 04:42:44 +08:00
# carton 📦
2020-05-05 01:00:18 +08:00
2020-06-09 16:48:29 +08:00
## Watcher, bundler, and test runner for your [SwiftWasm](https://swiftwasm.org/) apps
The main goal of `carton` is to provide a smooth zero-config experience when developing for WebAssembly.
2020-06-18 07:15:53 +08:00
It is still in development, but it aims to support these features (🐥 means "ready to use"):
2020-06-04 04:41:21 +08:00
2020-06-09 04:17:27 +08:00
- 🥚 Creating basic package boilerplate for apps built with SwiftWasm with `carton init` .
2020-06-09 05:01:40 +08:00
- 🐥 Watching the app for source code changes and reloading it in your browser with `carton dev` .
2020-06-09 04:17:27 +08:00
- 🐣 Running your XCTest suite in the full JavaScript/DOM environment with `carton test` .
- 🥚 Optimizing and packaging the app for distribution with `carton bundle` .
2020-06-26 22:40:55 +08:00
- 🐥 Managing SwiftWasm toolchain and SDK installations with `carton sdk` .
2020-06-04 17:46:56 +08:00
2020-06-04 04:41:21 +08:00
It is currently work in progress, so watch the repository for imminent updates!
2020-06-06 06:07:07 +08:00
2020-06-20 03:21:07 +08:00
## Motivation
The main motivation for `carton` came after I had enough struggles with [webpack.js ](https://webpack.js.org ),
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`
2020-06-27 00:46:42 +08:00
you can avoid using `webpack` altogether. `carton` also simplifies a few other things in your SwiftWasm
development workflow such as toolchain and SDK installations.
2020-06-20 03:21:07 +08:00
2020-06-09 18:28:37 +08:00
## Requirements
2020-06-09 18:33:19 +08:00
- macOS 10.15 and Xcode 11.4 or later for macOS users.
2020-06-09 18:28:37 +08:00
- [Swift 5.2 or later ](https://swift.org/download/ ) for Linux users.
## Installation
On macOS `carton` can be installed with [Homebrew ](https://brew.sh/ ). Make sure you have Homebrew
installed and then run:
```sh
2020-06-26 22:53:46 +08:00
brew install swiftwasm/tap/carton
2020-06-09 18:28:37 +08:00
```
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.
2020-06-26 22:40:55 +08:00
`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` .
2020-06-20 03:21:07 +08:00
## How does it work?
2020-06-22 03:35:42 +08:00
`carton` bundles a [WASI ](https://wasi.dev ) polyfill, which is currently required to run any SwiftWasm code,
2020-06-26 22:40:55 +08:00
and the [JavaScriptKit ](https://github.com/kateinoigakukun/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
2020-06-21 17:59:03 +08:00
experience closer to Xcode live previews, which you may have previously used when developing SwiftUI apps.
2020-06-20 03:21:07 +08:00
`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 ](https://vapor.codes/ ), [SwiftNIO ](https://github.com/apple/swift-nio ),
[swift-tools-support-core ](https://github.com/apple/swift-tools-support-core ), and
[OpenCombine ](https://github.com/broadwaylamb/OpenCombine ), and supports both macOS and Linux. (Many
thanks to everyone supporting and maintaining those projects!)
2020-07-02 18:38:05 +08:00
### Providing a destination file to `carton dev`
2020-07-02 19:04:08 +08:00
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.
2020-07-02 18:38:05 +08:00
The specification of the `destination.json` can be found [here ](https://github.com/apple/swift-package-manager/blob/master/Sources/Workspace/Destination.swift ):
Below is a template allowing you to link to the right Foundation:
```json
{
"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"
]
}
```
2020-07-02 19:04:08 +08:00
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` ](https://github.com/kylef/swiftenv ).
2020-07-02 18:38:05 +08:00
2020-07-02 19:04:08 +08:00
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.
2020-07-02 18:38:05 +08:00
2020-07-02 19:04:08 +08:00
In the future, we'll make sure that this is taken care of by `carton` itself.
2020-07-02 18:38:05 +08:00
2020-06-20 03:21:07 +08:00
## 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 ](https://bugs.swift.org/browse/SR-8436 ),
2020-06-26 22:40:55 +08:00
which is now partially resolved with [a new argument available on
`XCTMain` ](https://github.com/apple/swift-corelibs-xctest/pull/306) and a custom [JSON test
reporter](https://github.com/MaxDesiatov/XCTestJSONObserver/). After [a few other
2020-06-20 03:21:07 +08:00
issues](https://github.com/swiftwasm/swift/pull/1233) 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
2020-06-27 04:47:30 +08:00
optimized production deployment bundle, SwiftPM resources support for bundled assets, and much more.
2020-06-20 03:21:07 +08:00
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.
2020-06-06 06:07:07 +08:00
## Contributing
### Sponsorship
If this tool saved you any amount of time or money, please consider [sponsoring
the work of its maintainer](https://github.com/sponsors/MaxDesiatov). 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 ](https://github.com/nicklockwood/SwiftFormat )
and [SwiftLint ](https://github.com/realm/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](https://github.com/nicklockwood/SwiftFormat#xcode-source-editor-extension),
[build phase ](https://github.com/nicklockwood/SwiftFormat#xcode-build-phase ) or
[git pre-commit
hook](https://github.com/nicklockwood/SwiftFormat#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 ](https://pre-commit.com/ ) 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 ](https://pre-commit.com/ ) 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
2020-06-14 05:51:53 +08:00
Conduct](https://github.com/swiftwasm/carton/blob/main/CODE_OF_CONDUCT.md).
2020-06-06 06:07:07 +08:00
By participating, you are expected to uphold this code. Please report
unacceptable behavior to conduct@carton.dev.