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-12-04 19:41:20 +08:00
It currently supports these features with separate commands:
2020-06-04 04:41:21 +08:00
2020-12-04 19:41:20 +08:00
- 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` .
2020-06-04 17:46:56 +08:00
2020-06-20 03:21:07 +08:00
## Motivation
2020-12-04 21:05:55 +08:00
The main motivation for `carton` came after having enough struggles with
[webpack.js ](https://webpack.js.org ), trying to make its config file work, looking for appropriate
plugins. At some point the maintainers became 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
2020-06-27 00:46:42 +08:00
development workflow such as toolchain and SDK installations.
2020-06-20 03:21:07 +08:00
2020-08-20 18:35:58 +08:00
## Getting started
2020-06-09 18:28:37 +08:00
2020-08-20 18:35:58 +08:00
### Requirements
2022-01-17 17:04:44 +08:00
- macOS 11 and Xcode 13.2.1 or later. macOS 10.15 may work, but is untested.
- [Swift 5.5 or later ](https://swift.org/download/ ) and Ubuntu 18.04 or 20.04 for Linux users.
2020-06-09 18:28:37 +08:00
2020-08-20 18:35:58 +08:00
### Installation
2020-06-09 18:28:37 +08:00
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
```
2023-01-10 18:22:07 +08:00
> **Note**
> If you can't install the latest carton via `brew upgrade swiftwasm/tap/carton`, please try `rm -rf $(brew --prefix)/Library/Taps/swiftwasm/homebrew-tap/ && brew tap swiftwasm/tap` and retry again. The `master` branch was renamed to `main`, so you need to update your local tap repo.
2020-10-22 17:58:16 +08:00
`carton` is also available as a Docker image for Linux. You can pull it with this command:
```
docker pull ghcr.io/swiftwasm/carton:latest
```
2021-05-29 05:00:38 +08:00
If Docker images are not suitable for you, you'll have to build `carton` from sources on Ubuntu.
Clone the repository and run `./install_ubuntu_deps.sh` in the root directory of the clone. After
that completes successfully, run `swift build -c release` , the `carton` binary will be located in
the `.build/release` directory after that. Unfortunately, other Linux distributions are currently
not supported.
2020-06-09 18:28:37 +08:00
2022-05-11 22:36:47 +08:00
### Version compatibility
2022-05-20 22:27:53 +08:00
`carton` previously embedded runtime parts of [the JavaScriptKit library ](https://github.com/swiftwasm/JavaScriptKit ).
This runtime allows Swift and JavaScript code to interoperate in Node.js and browser environments. Because of how
JavaScriptKit runtime was embedded, older versions of JavaScriptKit were incompatible with different versions of
`carton` and vice versa. This incompatibility between different versions was resolved starting with JavaScriptKit 0.15
2022-05-20 22:29:43 +08:00
and `carton` 0.15. All version combinations of `carton` and JavaScriptKit higher than those are compatible with each
2022-05-20 22:27:53 +08:00
other.
You still have to keep in mind that older versions of SwiftWasm may be incompatible with newer `carton` . You can follow
the compatibility matrix if you need to use older verions:
2022-05-11 22:36:47 +08:00
| `carton` version | SwiftWasm version | JavaScriptKit version | Tokamak version |
| ---------------- | ----------------- | --------------------- | --------------- |
2022-06-15 22:08:43 +08:00
| 0.15+ | 5.6 | 0.15+ | 0.10.1+ |
2022-05-20 22:27:53 +08:00
| 0.14 | 5.6 | 0.14 | 0.10 |
| 0.13 | 5.5 | 0.13 | 0.9.1 |
| 0.12.2 | 5.5 | 0.12 | 0.9.1 |
| 0.12.0 | 5.5 | 0.11 | 0.9.0 |
| 0.11.0 | 5.4 | 0.10.1 | 0.8.0 |
2022-05-11 22:36:47 +08:00
2020-08-20 18:35:58 +08:00
### Usage
2021-05-29 05:00:38 +08:00
The `carton init` command initializes a new SwiftWasm project for you (similarly to
`swift package init` ) with multiple templates available at your choice. `carton init --template tokamak`
creates a new [Tokamak ](https://tokamak.dev/ ) project, while `carton init --template basic` (equivalent
to `carton init` ) creates an empty SwiftWasm project with no dependencies. Also, `carton init list-templates`
provides a complete list of templates (with only `basic` and `tokamak` available currently).
2020-08-20 18:35:58 +08:00
The `carton dev` command builds your project with the SwiftWasm toolchain and starts an HTTP server
2020-10-22 23:38:51 +08:00
that hosts your WebAssembly executable and a corresponding JavaScript entrypoint that loads it. The
app, reachable at [http://127.0.0.1:8080/ ](http://127.0.0.1:8080/ ), will automatically open in your
default web browser. The port that the development server uses can also be controlled with the
`--port` option (or `-p` for short). You can edit the app source code in your favorite editor and
save it, `carton` will immediately rebuild the app and reload all browser tabs that have the app
open. You can also pass a `--verbose` flag to keep the build process output available, otherwise
stale output is cleaned up from your terminal screen by default. If you have a custom `index.html`
page you'd like to use when serving, pass a path to it with a `--custom-index-page` option.
2020-08-20 18:35:58 +08:00
2022-05-11 21:52:44 +08:00
The `carton test` command runs your test suite in [`wasmer` ](https://wasmer.io/ ), [`node` ](https://nodejs.org/en/ )
or using your default browser. You can switch between these with the `--environment` option, passing
2022-05-11 22:40:15 +08:00
either: `wasmer` , `node` or `defaultBrowser` . Code that depends on
[JavaScriptKit ](https://github.com/swiftwasm/JavaScriptKit ) should pass either `--environment node` or
`--environment defaultBrowser` options, depending on whether it needs Web APIs to work. Otherwise
the test run will not succeed, since JavaScript environment is not available with `--environment wasmer` .
2022-06-11 00:42:20 +08:00
If you want to run your test suite on CI or without GUI but on browser, you can pass `--headless` flag.
It enables [WebDriver ](https://w3c.github.io/webdriver/ )-based headless browser testing. Note that you
need to install a WebDriver executable in `PATH` before running tests.
2022-05-31 00:59:14 +08:00
You can use the command with a prebuilt test bundle binary instead of building it in carton by passing
`--prebuilt-test-bundle-path <your binary path>` .
2020-08-20 18:35:58 +08:00
The `carton sdk` command and its subcommands allow you to manage installed SwiftWasm toolchains, but
2020-09-29 04:30:26 +08:00
is rarely needed, as `carton dev` installs the recommended version of SwiftWasm automatically.
2020-08-20 18:35:58 +08:00
`carton sdk versions` lists all installed versions, and `carton sdk local` prints the version
specified for the current project in the `.swift-version` file. You can however install SwiftWasm
separately if needed, either by passing an archive URL to `carton sdk install` directly, or just
2020-09-29 04:30:26 +08:00
specifying the snapshot version, like `carton sdk install wasm-5.3-SNAPSHOT-2020-09-25-a` .
2020-08-20 18:35:58 +08:00
`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-08-31 23:29:47 +08:00
The `carton bundle` command builds your project using the `release` configuration (although you can
pass the `--debug` flag to it to change that), and copies all required assets to the `Bundle`
directory. You can then use a static file hosting (e.g. [GitHub Pages ](https://pages.github.com/ ))
or any other server with support for static files to deploy your application. All resulting bundle
files except `index.html` are named by their content hashes to enable [cache
2020-09-01 01:37:43 +08:00
busting](https://www.keycdn.com/support/what-is-cache-busting). As with `carton dev` , a custom
2022-04-03 01:28:53 +08:00
`index.html` page can be provided through the `--custom-index-page` option. You can also pass
`--debug-info` flag to preserve `names` and DWARF sections in the resulting `.wasm` file, as these
2022-06-03 01:40:00 +08:00
are stripped in the `release` configuration by default. By default, `carton bundle` will run `wasm-opt`
on the resulting .wasm binary in order to reduce its file size. That behaviour can be disabled (in order
to speed up the build) by appending the `--wasm-optimizations none` option.
2020-08-31 23:29:47 +08:00
2020-09-29 04:37:34 +08:00
The `carton package` command proxies its subcommands to `swift package` invocations on the
currently-installed toolchain. This may be useful in situations where you'd like to generate an
Xcode project file for your app with something like `carton package generate-xcodeproj` . It would be
equivalent to `swift package generate-xcodeproj` , but invoked with the SwiftWasm toolchain instead
of the toolchain supplied by Xcode.
2022-04-03 01:28:53 +08:00
All commands that delegate to `swift build` and `swiftc` (namely, `dev` , `test` , and `bundle` )
can be passed `-Xswiftc` arguments, which is equivalent to `-Xswiftc` in `swift build` . All
`-Xswiftc` arguments are propagated to `swiftc` itself unmodified.
2020-08-20 18:35:58 +08:00
All of these commands and subcommands can be passed a `--help` flag that prints usage info and
information about all available options.
2020-06-26 22:40:55 +08:00
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 ),
2022-01-17 17:04:44 +08:00
[swift-tools-support-core ](https://github.com/apple/swift-tools-support-core ), and supports both
macOS and Linux. (Many thanks to everyone supporting and maintaining those projects!)
2020-06-20 03:21:07 +08:00
2020-07-02 20:49:46 +08:00
### Running `carton dev` with the `release` configuration
2020-08-19 01:02:34 +08:00
2020-07-02 20:49:46 +08:00
By default `carton dev` will compile in the `debug` configuration. Add the `--release` flag to compile in the `release` configuration.
2020-06-06 06:07:07 +08:00
## Contributing
### Sponsorship
2021-01-10 04:15:19 +08:00
If this tool saved you any amount of time or money, please consider [sponsoring
the SwiftWasm organization](https://github.com/sponsors/swiftwasm). Or you can sponsor some of our
maintainers directly on their personal sponsorship pages:
2020-10-10 18:42:15 +08:00
[@carson-katri ](https://github.com/sponsors/carson-katri ),
[@kateinoigakukun ](https://github.com/sponsors/kateinoigakukun ), and
[@MaxDesiatov ](https://github.com/sponsors/MaxDesiatov ). While some of the
2020-06-06 06:07:07 +08:00
sponsorship tiers give you priority support or even consulting time, any amount is
appreciated and helps in maintaining the project.
2023-07-21 09:04:48 +08:00
[Become a gold or platinum sponsor ](https://github.com/sponsors/swiftwasm/ ) and contact maintainers to add your logo on our README on Github with a link to your site.
< a href = "https://www.emergetools.com/" >
2023-07-23 09:14:13 +08:00
< img src = "https://github.com/swiftwasm/swift/raw/swiftwasm-distribution/assets/sponsors/emergetools.png" width = "30%" >
2023-07-21 09:04:48 +08:00
< / a >
2020-06-06 06:07:07 +08:00
### 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
2022-05-11 02:10:54 +08:00
Conduct](https://github.com/swiftwasm/.github/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
2022-05-11 02:10:54 +08:00
unacceptable behavior to hello@swiftwasm.org.