Skip to content

Commit

Permalink
Implement no_std support
Browse files Browse the repository at this point in the history
  • Loading branch information
daxpedda committed Nov 27, 2024
1 parent f1fa50c commit 6747c5f
Show file tree
Hide file tree
Showing 37 changed files with 1,349 additions and 346 deletions.
2 changes: 1 addition & 1 deletion .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[target.wasm32-unknown-unknown]
[target.'cfg(target_family = "wasm")']
runner = "wasm-bindgen-test-runner"
4 changes: 3 additions & 1 deletion .config/topic.dic
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
23
25
1G
1M
1ns
allocator
APIs
Atomics
de
Expand All @@ -12,6 +13,7 @@ io
JS
MDN
MSRV
representable
Serde
Serde's
timestamps
Expand Down
13 changes: 7 additions & 6 deletions .github/workflows/coverage-documentation.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,11 @@ jobs:
- name: Checkout
uses: actions/checkout@v4
- name: Install `wasm-bindgen-cli`
uses: taiki-e/install-action@v2
uses: taiki-e/cache-cargo-install-action@v2
with:
tool: wasm-bindgen-cli
git: https://github.com/daxpedda/wasm-bindgen
rev: 480a246aef12c59b26c3335a716e6940b369aeb7
- name: Install Clang v19
run: |
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
Expand All @@ -58,10 +60,9 @@ jobs:
RUSTFLAGS:
-Cinstrument-coverage -Zcoverage-options=condition -Zno-profiler-runtime --emit=llvm-ir
--cfg=wasm_bindgen_unstable_test_coverage ${{ matrix.mt.flags }}
WASM_BINDGEN_UNSTABLE_TEST_PROFRAW_OUT: coverage-output
run: |
mkdir coverage-output
cargo test --all-features --target wasm32-unknown-unknown -Ztarget-applies-to-host -Zhost-config ${{ matrix.mt.args }} --tests
WASM_BINDGEN_UNSTABLE_TEST_PROFRAW_OUT=$(realpath coverage-output) cargo test --workspace --features serde --target wasm32-unknown-unknown -Ztarget-applies-to-host -Zhost-config ${{ matrix.mt.args }} --tests
- name: Prepare Object Files
env:
CFLAGS_wasm32_unknown_unknown: ${{ matrix.mt.cflags }}
Expand All @@ -74,7 +75,7 @@ jobs:
crate_name=web_time
IFS=$'\n'
for file in $(
cargo test --all-features --target wasm32-unknown-unknown -Ztarget-applies-to-host -Zhost-config ${{ matrix.mt.args }} --tests --no-run --message-format=json | \
cargo test --workspace --features serde --target wasm32-unknown-unknown -Ztarget-applies-to-host -Zhost-config ${{ matrix.mt.args }} --tests --no-run --message-format=json | \
jq -r "select(.reason == \"compiler-artifact\") | (select(.target.kind == [\"test\"]) // select(.target.name == \"$crate_name\")) | .filenames[0]"
)
do
Expand Down Expand Up @@ -130,7 +131,7 @@ jobs:
llvm-cov-19 show -show-instantiations=false -output-dir coverage-output -format=html -instr-profile=coverage-input/coverage.profdata ${objects[@]} -sources src
llvm-cov-19 export -format=text -summary-only -instr-profile=coverage-input/coverage.profdata ${objects[@]} -sources src | \
printf '{ "coverage": "%.2f%%" }' $(jq '.data[0].totals.functions.percent') > coverage-output/coverage.json
sed 's/<!doctype html>//' coverage-output/index.html | perl -p0e 's/<a[^>]*>((?!here).*?)<\/a>/$1/g' >> $GITHUB_STEP_SUMMARY
sed 's/<!doctype html>//' coverage-output/index.html | sed "s/<script src='control.js'><\/script>//" | perl -p0e 's/<a[^>]*>((?!here).*?)<\/a>/$1/g' >> $GITHUB_STEP_SUMMARY
- name: Upload Test Coverage Artifact
uses: actions/upload-artifact@v4
with:
Expand Down Expand Up @@ -158,7 +159,7 @@ jobs:
RUSTDOCFLAGS: --crate-version main --cfg=docsrs
run:
cargo doc --no-deps -Z rustdoc-map -Z rustdoc-scrape-examples --target
wasm32-unknown-unknown --all-features
wasm32-unknown-unknown --features serde
- name: Setup Pages
uses: actions/configure-pages@v5
- name: Fix permissions
Expand Down
41 changes: 31 additions & 10 deletions .github/workflows/lint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ env:
CARGO_TERM_COLOR: always

jobs:
clippy-rustdoc:
clippy:
name:
Clippy ${{ matrix.target.description }} ${{ matrix.rust.description }} ${{
matrix.features.description }}
Expand All @@ -24,23 +24,38 @@ jobs:
fail-fast: false
matrix:
target:
- { target: wasm32-unknown-unknown, description: Web }
- { target: x86_64-unknown-linux-gnu, description: Native }
- { target: wasm32-unknown-unknown, description: Wasm }
- { target: wasm32v1-none, description: Wasm v1 }
rust:
- { version: stable }
- { version: stable, atomics: false }
- { version: nightly, atomics: false }
- {
version: nightly,
description: with Atomics,
atomics: true,
component: ",rust-src",
flags: "-Ctarget-feature=+atomics,+bulk-memory",
args: "-Zbuild-std=panic_abort,std",
build-std: true,
}
features:
- { features: "" }
- { features: --all-features, description: (all features) }
include:
- { features: "", no_std: false }
- { features: --features serde, no_std: false, description: (serde) }
- { features: --no-default-features, no_std: true, description: (`no_std`) }
- {
features: --no-default-features --features serde,
no_std: true,
description: "(`no_std`, serde)",
}
exclude:
- target: { target: x86_64-unknown-linux-gnu, description: Native }
rust: { version: nightly }
- target: { target: wasm32-unknown-unknown, description: Wasm }
rust: { version: nightly, atomics: false }
- target: { target: wasm32v1-none, description: Wasm v1 }
rust: { version: stable }
features: { features: "" }
- target: { target: wasm32v1-none, description: Wasm v1 }
features: { no_std: false }

steps:
- name: Checkout
Expand All @@ -49,12 +64,18 @@ jobs:
run: |
rustup toolchain install ${{ matrix.rust.version }} --profile minimal --component clippy${{ matrix.rust.component }} --allow-downgrade --target ${{ matrix.target.target }}
rustup default ${{ matrix.rust.version }}
- name: Set `build-std` components
if: matrix.rust.build-std == true && matrix.features.no_std == false
run: echo "BUILD_STD_COMPONENTS=-Zbuild-std=panic_abort,std" >> $GITHUB_ENV
- name: Set `build-std` `no_std` components
if: matrix.rust.build-std == true && matrix.features.no_std == true
run: echo "BUILD_STD_COMPONENTS=-Zbuild-std=core,alloc" >> $GITHUB_ENV
- name: Run Clippy
env:
RUSTFLAGS: ${{ matrix.rust.flags }}
run:
cargo clippy --all-targets ${{ matrix.features.features }} --target ${{
matrix.target.target }} ${{ matrix.rust.args }} -- -D warnings
cargo clippy --workspace --all-targets ${{ matrix.features.features }} --target ${{
matrix.target.target }} $BUILD_STD_COMPONENTS -- -D warnings

rustdoc:
name:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ jobs:
with:
tool: wasm-bindgen-cli
git: https://github.com/daxpedda/wasm-bindgen
rev: 6a5e62b1d89c9e927747700b5908b257761c9280
rev: 480a246aef12c59b26c3335a716e6940b369aeb7
- name: Install Rust
run: |
rustup toolchain install ${{ matrix.rust.version }} --profile minimal ${{ matrix.rust.component }} --target ${{ matrix.target.target }}
Expand Down
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added

- Add [`no_std`] support through a `std` crate feature.
- Add support for the [`wasm32v1-none`] target.

[`no_std`]: https://doc.rust-lang.org/1.82.0/reference/names/preludes.html#the-no_std-attribute
[`wasm32v1-none`]: https://doc.rust-lang.org/nightly/rustc/platform-support/wasm32v1-none.html

## [1.1.0] - 2024-03-01

### Added
Expand Down
108 changes: 99 additions & 9 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,33 @@

Thank you for contributing!

## [`no_std`]

This crate has some code paths that depend on [`no_std`], which can be compiled with Cargo by using
`--no-default-features`. Additionally, its best to use the `wasm32v1-none` target to ensure the
standard library isn't included in any dependency.

Example usage:

```sh
cargo +nightly build --target wasm32v1-none --no-default-features
```

### Rust Analyzer

To get proper diagnostics for [`no_std`] it can be helpful to configure Rust Analyzer to support
that.

Here is an example configuration for Visual Studio Code:

```json
"rust-analyzer.cargo.target": "wasm32v1-none",
"rust-analyzer.cargo.noDefaultFeatures": true,
"rust-analyzer.cargo.extraEnv": {
"RUSTUP_TOOLCHAIN": "nightly",
},
```

## Wasm Atomics

This crate has some code paths that depend on Wasm Atomics, which has some prerequisites to compile:
Expand All @@ -17,9 +44,13 @@ Example usage:
# Installing Rust nightly and necessary components:
rustup toolchain install nightly --target wasm32-unknown-unknown --component rust-src
# Example `cargo build` usage:
RUSTFLAGS=-Ctarget-feature=+atomics,+bulk-memory cargo +nightly build -Zbuild-std=panic_abort,std --target wasm32-unknown-unknown
RUSTFLAGS=-Ctarget-feature=+atomics,+bulk-memory cargo +nightly build --target wasm32-unknown-unknown -Zbuild-std=panic_abort,std
# Example `no_std` `cargo build` usage:
RUSTFLAGS=-Ctarget-feature=+atomics,+bulk-memory cargo +nightly build --target wasm32v1-none -Zbuild-std=core,alloc --no-default-features
```

[`build-std`]: https://doc.rust-lang.org/1.73.0/cargo/reference/unstable.html#build-std

### Rust Analyzer

To get proper diagnostics for Rust Atomics it can be helpful to configure Rust Analyzer to support
Expand All @@ -38,30 +69,87 @@ Here is an example configuration for Visual Studio Code:
},
```

Or with [`no_std`]:

```json
"rust-analyzer.cargo.target": "wasm32v1-none",
"rust-analyzer.cargo.noDefaultFeatures": true,
"rust-analyzer.cargo.extraArgs": [
"-Zbuild-std=core,alloc"
],
"rust-analyzer.cargo.extraEnv": {
"RUSTUP_TOOLCHAIN": "nightly",
"RUSTFLAGS": "-Ctarget-feature=+atomics,+bulk-memory"
},
```

## Testing

Tests are run as usual, but tests that require Wasm Atomics can be run like this:
Tests are run as usual. But integration tests have a special setup to support [`no_std`].

### Run

To run integration tests just use `--workspace`:

```sh
RUSTFLAGS=-Ctarget-feature=+atomics,+bulk-memory cargo +nightly test -Zbuild-std=panic_abort,std --target wasm32-unknown-unknown
# Run tests for native.
cargo test --workspace
# Run tests for Wasm.
cargo test --workspace --target wasm32-unknown-unknown
# Run tests for `no_std`.
cargo +nightly test --workspace --target wasm32v1-none --no-default-features
# Run tests for Wasm atomics.
RUSTFLAGS=-Ctarget-feature=+atomics,+bulk-memory cargo +nightly test --workspace --target wasm32-unknown-unknown -Zbuild-std=panic_abort,std
```

Make sure not to use `--all-features`.

### Implement

To implement integration tests, you have to understand the setup. [`no_std`] support requires the
[test harness] has to be disabled. However, to keep the [test harness] enabled for native tests, the
same tests are split into two [test targets]. These are defined in the `tests-native` and
`tests-web` crate for each target respectively. The [test targets] are then enabled, depending on
the target, via the `run` crate feature.

So to add a new integration test the following [test targets] have to be added:

`tests-web/Cargo.toml`:

```toml
[[test]]
harness = false
name = "web_new_test"
path = "../tests/new_test.rs"
required-features = ["run"]
```

`tests-native/Cargo.toml`:

```toml
[[test]]
name = "native_new_test"
path = "../tests/new_test.rs"
required-features = ["run"]
```

Additionally, keep in mind that usage of [`#[should_panic]`](`should_panic`) is known to cause
browsers to get stuck because of the lack of unwinding support.

The current workaround is to split tests using `await` into separate test targets.
The current workaround is to split tests using `await` into separate [test targets].

[`build-std`]: https://doc.rust-lang.org/1.73.0/cargo/reference/unstable.html#build-std
[`should_panic`]:
https://doc.rust-lang.org/1.73.0/reference/attributes/testing.html#the-should_panic-attribute
[test harness]: https://doc.rust-lang.org/test
[test targets]: https://doc.rust-lang.org/1.82.0/cargo/reference/cargo-targets.html#tests

## Benchmark

The only benchmark is marked as an example target because of the lack of Wasm support. To run it you
can use the following command:

```sh
cargo build --example benchmark --target wasm32-unknown-unknown --profile bench
cargo build --workspace --example benchmark --target wasm32-unknown-unknown --profile bench
wasm-bindgen --out-dir benches --target web --no-typescript target/wasm32-unknown-unknown/release/examples/benchmark.wasm
```

Expand Down Expand Up @@ -89,12 +177,12 @@ If you want to generate test coverage locally, here is an example shell script t
```sh
# Single-threaded test run.
st () {
CARGO_HOST_RUSTFLAGS=--cfg=wasm_bindgen_unstable_test_coverage RUSTFLAGS="-Cinstrument-coverage -Zcoverage-options=condition -Zno-profiler-runtime --emit=llvm-ir --cfg=wasm_bindgen_unstable_test_coverage" cargo +nightly test --all-features --target wasm32-unknown-unknown -Ztarget-applies-to-host -Zhost-config --tests $@
CARGO_HOST_RUSTFLAGS=--cfg=wasm_bindgen_unstable_test_coverage RUSTFLAGS="-Cinstrument-coverage -Zcoverage-options=condition -Zno-profiler-runtime --emit=llvm-ir --cfg=wasm_bindgen_unstable_test_coverage" cargo +nightly test --workspace --features serde --target wasm32-unknown-unknown -Ztarget-applies-to-host -Zhost-config --tests $@
}

# Multi-threaded test run.
mt () {
CFLAGS_wasm32_unknown_unknown="-matomics -mbulk-memory" CARGO_HOST_RUSTFLAGS=--cfg=wasm_bindgen_unstable_test_coverage RUSTFLAGS="-Cinstrument-coverage -Zcoverage-options=condition -Zno-profiler-runtime --emit=llvm-ir --cfg=wasm_bindgen_unstable_test_coverage -Ctarget-feature=+atomics,+bulk-memory" cargo +nightly test --all-features --target wasm32-unknown-unknown -Ztarget-applies-to-host -Zhost-config -Zbuild-std=panic_abort,std --tests $@
CFLAGS_wasm32_unknown_unknown="-matomics -mbulk-memory" CARGO_HOST_RUSTFLAGS=--cfg=wasm_bindgen_unstable_test_coverage RUSTFLAGS="-Cinstrument-coverage -Zcoverage-options=condition -Zno-profiler-runtime --emit=llvm-ir --cfg=wasm_bindgen_unstable_test_coverage -Ctarget-feature=+atomics,+bulk-memory" cargo +nightly test --workspace --features serde --target wasm32-unknown-unknown -Ztarget-applies-to-host -Zhost-config -Zbuild-std=panic_abort,std --tests $@
}

# To collect object files.
Expand All @@ -107,7 +195,7 @@ test () {

# Run tests.
mkdir -p coverage-input/$path
CHROMEDRIVER=chromedriver WASM_BINDGEN_UNSTABLE_TEST_PROFRAW_OUT=coverage-input/$path $command
CHROMEDRIVER=chromedriver WASM_BINDGEN_UNSTABLE_TEST_PROFRAW_OUT=$(realpath coverage-input/$path) $command

local crate_name=web_time
local IFS=$'\n'
Expand Down Expand Up @@ -142,3 +230,5 @@ llvm-profdata-19 merge -sparse coverage-input/*/*.profraw -o coverage-input/cove
# Finally generate coverage information.
llvm-cov-19 show -show-instantiations=false -output-dir coverage-output -format=html -instr-profile=coverage-input/coverage.profdata ${objects[@]} -sources src
```

[`no_std`]: https://doc.rust-lang.org/1.82.0/reference/names/preludes.html#the-no_std-attribute
Loading

0 comments on commit 6747c5f

Please sign in to comment.