Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

jiff: add robust WASM support #58

Merged
merged 1 commit into from
Jul 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
163 changes: 101 additions & 62 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,6 @@ permissions:

jobs:
test:
env:
# For some builds, we use cross to test on 32-bit and big-endian
# systems.
CARGO: cargo
# When CARGO is set to CROSS, TARGET is set to `--target matrix.target`.
# Note that we only use cross on Linux, so setting a target on a
# different OS will just use normal cargo.
TARGET:
# Bump this as appropriate. We pin to a version to make sure CI
# continues to work as cross releases in the past have broken things
# in subtle ways.
CROSS_VERSION: v0.2.5
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
Expand All @@ -49,22 +37,6 @@ jobs:
- build: stable
os: ubuntu-latest
rust: stable
- build: stable-x86
os: ubuntu-latest
rust: stable
target: i686-unknown-linux-gnu
- build: stable-aarch64
os: ubuntu-latest
rust: stable
target: aarch64-unknown-linux-gnu
- build: stable-powerpc64
os: ubuntu-latest
rust: stable
target: powerpc64-unknown-linux-gnu
- build: stable-s390x
os: ubuntu-latest
rust: stable
target: s390x-unknown-linux-gnu
- build: beta
os: ubuntu-latest
rust: beta
Expand All @@ -87,38 +59,12 @@ jobs:
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.rust }}
- name: Install and configure Cross
if: matrix.os == 'ubuntu-latest' && matrix.target != ''
run: |
# In the past, new releases of 'cross' have broken CI. So for now, we
# pin it. We also use their pre-compiled binary releases because cross
# has over 100 dependencies and takes a bit to compile.
dir="$RUNNER_TEMP/cross-download"
mkdir "$dir"
echo "$dir" >> $GITHUB_PATH
cd "$dir"
curl -LO "https://github.com/cross-rs/cross/releases/download/$CROSS_VERSION/cross-x86_64-unknown-linux-musl.tar.gz"
tar xf cross-x86_64-unknown-linux-musl.tar.gz
# We used to install 'cross' from master, but it kept failing. So now
# we build from a known-good version until 'cross' becomes more stable
# or we find an alternative. Notably, between v0.2.1 and current
# master (2022-06-14), the number of Cross's dependencies has doubled.
echo "CARGO=cross" >> $GITHUB_ENV
echo "TARGET=--target ${{ matrix.target }}" >> $GITHUB_ENV
- name: Show command used for Cargo
run: |
echo "cargo command is: ${{ env.CARGO }}"
echo "target flag is: ${{ env.TARGET }}"
- run: ${{ env.CARGO }} build --verbose $TARGET
- run: ${{ env.CARGO }} doc --verbose $TARGET
- if: matrix.build == 'pinned'
run: ${{ env.CARGO }} test
- if: matrix.build != 'pinned'
run: ${{ env.CARGO }} test --all --verbose $TARGET
- if: matrix.build != 'pinned'
run: ${{ env.CARGO }} test -p jiff-cli --verbose $TARGET
- if: matrix.target == ''
- run: cargo build --verbose
- run: cargo doc --verbose
- run: cargo test --verbose --all
- run: cargo test --verbose -p jiff-cli
# Skip on Windows because it takes freaking forever.
- if: matrix.build != 'win-msvc' && matrix.build != 'win-gnu'
run: ./test

# This job runs a stripped down version of CI to test the MSRV. The specific
Expand Down Expand Up @@ -150,8 +96,44 @@ jobs:
- name: Run integration tests
run: cargo test --test integration

# Setup and run tests on the wasm32-wasi target via wasmtime.
wasm:
# Generic testing for most cross targets. Some get special treatment in
# other jobs.
cross:
env:
# Bump this as appropriate. We pin to a version to make sure CI
# continues to work as cross releases in the past have broken things
# in subtle ways.
CROSS_VERSION: v0.2.5
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
target:
- i686-unknown-linux-gnu
- aarch64-unknown-linux-gnu
- powerpc-unknown-linux-gnu
- powerpc64-unknown-linux-gnu
- s390x-unknown-linux-gnu
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install and configure Cross
run: |
# In the past, new releases of 'cross' have broken CI. So for now, we
# pin it. We also use their pre-compiled binary releases because cross
# has over 100 dependencies and takes a bit to compile.
dir="$RUNNER_TEMP/cross-download"
mkdir "$dir"
echo "$dir" >> $GITHUB_PATH
cd "$dir"
curl -LO "https://github.com/cross-rs/cross/releases/download/$CROSS_VERSION/cross-x86_64-unknown-linux-musl.tar.gz"
tar xf cross-x86_64-unknown-linux-musl.tar.gz
- run: cross build --verbose --target ${{ matrix.target }}
- run: cross test --verbose --target ${{ matrix.target }} --all
- run: cross test --verbose --target ${{ matrix.target }} -p jiff-cli

# Test the wasm32-wasip1 target via wasmtime.
wasm32-wasip1:
runs-on: ubuntu-latest
env:
# The version of wasmtime to download and install.
Expand Down Expand Up @@ -185,6 +167,62 @@ jobs:
- name: Run integration tests
run: cargo test --test integration -- --nocapture

# Test the wasm32-unknown-emscripten target.
#
# Regretably, `insta` doesn't work on emscripten, so we just do a basic
# sanity check here.
wasm32-unknown-emscripten:
runs-on: ubuntu-latest
env:
# Bump this as appropriate. We pin to a version to make sure CI
# continues to work as cross releases in the past have broken things
# in subtle ways.
CROSS_VERSION: v0.2.5
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@master
with:
toolchain: stable
- name: Install and configure Cross
run: |
dir="$RUNNER_TEMP/cross-download"
mkdir "$dir"
echo "$dir" >> $GITHUB_PATH
cd "$dir"
curl -LO "https://github.com/cross-rs/cross/releases/download/$CROSS_VERSION/cross-x86_64-unknown-linux-musl.tar.gz"
tar xf cross-x86_64-unknown-linux-musl.tar.gz
- name: Build jiff
run: cross build --verbose --target wasm32-unknown-emscripten -p jiff
- name: Build jiff-tzdb
run: cargo build --verbose --target wasm32-unknown-emscripten -p jiff-tzdb
- name: Build jiff-tzdb-platform
run: cargo build --verbose --target wasm32-unknown-emscripten -p jiff-tzdb-platform
- name: Run library tests
run: cross test --verbose --target wasm32-unknown-emscripten --features logging --lib now_works -- --nocapture

# Tests wasm32-unknown-unknown integration via wasm-pack.
wasm32-unknown-uknown:
runs-on: ubuntu-latest
env:
# Set the time zone to something so that there's some kind of interesting
# output to scrutinize. The test below doesn't actually assert anything
# about the time zone, but we can at least visually inspect it in the CI
# logs.
TZ: America/New_York
steps:
- uses: dtolnay/rust-toolchain@stable
- uses: actions/checkout@v4
- name: Install wasm-pack
run: |
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
- name: Test wasm-pack project
run: |
cd jiff-wasm
wasm-pack test --node
# Run benchmarks as tests.
testbench:
runs-on: ubuntu-latest
steps:
Expand All @@ -198,6 +236,7 @@ jobs:
run: |
cargo bench --manifest-path bench/Cargo.toml -- --test
# Check that all files are formatted properly.
rustfmt:
runs-on: ubuntu-latest
steps:
Expand Down
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
0.1.3 (2024-07-30)
==================
This release features support for `wasm32-unknown-unknown`. That is, when
Jiff's new `js` crate feature is enabled, Jiff will automatically use
JavaScript APIs to determine the current time and time zone.

Enhancements:

* [#58](https://github.com/BurntSushi/jiff/pull/58):
Add WASM support and a new `PLATFORM.md` guide.


0.1.2 (2024-07-28)
==================
This release features a few new APIs that a need for arose while experimenting
Expand Down
33 changes: 28 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,26 @@ tzdb-bundle-always = ["dep:jiff-tzdb", "alloc"]
# database that is typically found at /usr/share/zoneinfo on macOS and Linux.
tzdb-zoneinfo = ["std"]

# This enables bindings to web browser APIs for retrieving the current time
# and configured time zone. This ONLY applies on wasm32-unknown-unknown and
# wasm64-unknown-unknown targets. Specifically, *not* on wasm32-wasi or
# wasm32-unknown-emscripten targets.
#
# This is an "ecosystem" compromise due to the fact that there is no general
# way to determine at compile time whether a wasm target is intended for use
# on the "web." In practice, only wasm{32,64}-unknown-unknown targets are used
# on the web, but wasm{32,64}-unknown-unknown targets can be used in non-web
# contexts as well. Thus, the `js` feature should be enabled only by binaries,
# tests or benchmarks when it is *known* that the application will be used in a
# web context.
#
# Libraries that depend on Jiff should not need to define their own `js`
# feature just to forward it to Jiff. Instead, application authors can depend
# on Jiff directly and enable the `js` feature themselves.
#
# (This is the same dependency setup that the `getrandom` crate uses.)
js = ["wasm-bindgen", "js-sys"]

[dependencies]
jiff-tzdb = { version = "0.1.0", path = "jiff-tzdb", optional = true }
log = { version = "0.4.21", optional = true }
Expand All @@ -62,8 +82,8 @@ serde = { version = "1.0.203", optional = true }
# Note that the `cfg` gate for the `tzdb-bundle-platform` must repeat the
# target gate on this dependency. The intent is that `tzdb-bundle-platform`
# is enabled by default, but that the `tzdb-bundle-platform` crate is only
# actually used on platforms without a system tzdb (i.e., Windows).
[target.'cfg(windows)'.dependencies]
# actually used on platforms without a system tzdb (i.e., Windows and wasm).
[target.'cfg(any(windows, target_family = "wasm"))'.dependencies]
jiff-tzdb-platform = { version = "0.1.0", path = "jiff-tzdb-platform", optional = true }

[target.'cfg(windows)'.dependencies.windows-sys]
Expand All @@ -72,6 +92,10 @@ default-features = false
features = ["Win32_Foundation", "Win32_System_Time"]
optional = true

[target.'cfg(all(any(target_arch = "wasm32", target_arch = "wasm64"), target_os = "unknown"))'.dependencies]
js-sys = { version = "0.3.50", optional = true }
wasm-bindgen = { version = "0.2.70", optional = true }

[dev-dependencies]
anyhow = "1.0.81"
chrono = { version = "0.4.38", features = ["serde"] }
Expand All @@ -88,9 +112,8 @@ time = { version = "0.3.36", features = ["local-offset", "macros", "parsing"] }
tzfile = "0.1.3"
walkdir = "2.5.0"

# hifitime doesn't build on wasm32-wasip1 for some reason, so only
# depend on it on Unix or Windows.
[target.'cfg(any(unix, windows))'.dev-dependencies.hifitime]
# hifitime doesn't build on wasm for some reason, so exclude it there.
[target.'cfg(not(target_family = "wasm"))'.dev-dependencies.hifitime]
version = "3.9.0"

[[test]]
Expand Down
6 changes: 6 additions & 0 deletions Cross.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[build.env]
passthrough = [
"TZ",
"RUST_LOG",
"RUST_BACKTRACE",
]
Loading