Skip to main content
CoreCrypto uses GNU Make as the top-level build orchestrator. Each platform has a dedicated Make target that compiles the Rust FFI library, generates language bindings, and assembles the final artifact.

General requirements

All platforms require the following baseline tools.
ToolVersionInstall
Rust1.94.0 (pinned in rust-toolchain.toml)rustup.rs
GNU Make≥ 4.3gnu.org/software/make
cargo-nextestlatestcargo install --locked cargo-nextest
The rust-toolchain.toml file at the repository root pins the exact toolchain version. Running any cargo or make command inside the repo will cause rustup to install 1.94.0 automatically if it is not already present.

Pre-commit hooks

1

Install the pre-commit framework

Follow the instructions at pre-commit.com for your OS.
2

Initialise the hooks

pre-commit install

Platforms

Prerequisites

1

Add the WASM Rust target

rustup target add wasm32-unknown-unknown
2

Install Node.js

The recommended way is via Volta. Any method that puts a recent node on your PATH works.
3

Install Bun

Follow the instructions on bun.sh.
4

Install wasm-bindgen-cli

The CLI version must exactly match the wasm-bindgen crate version recorded in Cargo.lock.
wasm_bindgen_version="$(
  cargo metadata --format-version 1 |
  jq -r '.packages[] | select (.name == "wasm-bindgen") | .version'
)"
cargo install wasm-bindgen-cli --version $wasm_bindgen_version
A version mismatch between wasm-bindgen-cli and the wasm-bindgen crate in Cargo.lock will cause test failures. Always derive the version from Cargo.lock as shown above.
5

Install chromedriver for tests

bunx @puppeteer/browsers install --path ~/bin chrome-headless-shell
bunx @puppeteer/browsers install --path ~/bin chromedriver

Build

make ts
This builds the WASM binary and the TypeScript wrapper for the browser target.

Test

make ts-test
Tests run via WebdriverIO against a headless Chrome instance, plus Bun’s built-in test runner for the native target.
Use the CC_TEST_LOG_LEVEL environment variable to control log verbosity during tests:
  • CC_TEST_LOG_LEVEL=1 — emit browser console logs
  • CC_TEST_LOG_LEVEL=2 — emit browser console logs and CoreCrypto internal logs
To run a specific test by name:
make ts-test TEST="<test name or regex>"

Interop testing

The interop test suite verifies that all binding layers can exchange MLS messages with each other. It is a superset of the per-platform test requirements.
1

Run all per-platform test suites

Complete the TypeScript, Kotlin/JVM, Android, and (on macOS) Swift/iOS test runs first. The interop test relies on the build artifacts produced by those steps.
2

Install Chrome and chromedriver

Follow the same chromedriver setup described in the TypeScript/WASM tab above.
3

Run the interop tests

make interop-test

End-to-end identity (E2EI) testing

E2EI tests verify the full OIDC certificate flow and require a running container runtime (Docker or Podman).

Prepare the container runtime

systemctl start docker.service

Choose the OIDC identity provider

Set the TEST_IDP environment variable before running tests:
# Use Keycloak
export TEST_IDP=keycloak

# Or use Authelia
export TEST_IDP=authelia

Run all E2EI tests

bash scripts/run-e2ei-tests.sh
The script starts the required containers, runs all tests, and cleans up containers and processes on exit.

Run specific E2EI tests

Arguments after the script name are forwarded to cargo nextest:
bash scripts/run-e2ei-tests.sh alg::p256

Manually invoke tests

For finer control, start test-wire-server manually:
1

Start test-wire-server

cargo run --locked --bin test-wire-server
Note the address printed on stdout, for example 127.0.0.1:20530.
2

Export the server address

export TEST_WIRE_SERVER_ADDR=127.0.0.1:20530
3

Run a specific test

cargo nextest run --locked --ignore-default-filter -p wire-e2e-identity alg::p256
4

Clean up containers

# If using Keycloak
docker kill keycloak && docker rm keycloak

# If using Authelia
docker kill authelia.local && docker rm authelia.local
Also terminate the test-wire-server process.

Formatting and linting

All languages are covered by top-level Make targets:
make fmt    # Format all files
make check  # Lint all files
Individual targets are available if you only need one language:
TargetLanguageTool
make rust-fmt / make rust-checkRustcargo +nightly fmt, cargo clippy
make swift-fmt / make swift-checkSwiftswift-format, swiftlint
make kotlin-fmt / make kotlin-checkKotlinktlint
make ts-fmt / make ts-checkTypeScripteslint, tsc

Per-language tool installation

Both tools are available via Homebrew:
brew install swift-format swiftlint

Build docs developers (and LLMs) love