Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Getting started

We generally recommend building Crux apps from inside out, starting with the Core.

This part will first take you through setting up the tools and building the Core, and writing tests to make sure everything works as expected. Finally, once we're confident we have a working core, we'll set up the necessary bindings for the shell and build the UI for your chosen platform.

But first, we need to make sure we have all the necessary tools

Install the tools

This is an example of a rust-toolchain.toml file, which you can add at the root of your repo. It should ensure that the correct rust channel and compile targets are installed automatically for you when you use any rust tooling within the repo.

You may not need all the targets if you're not planning to build a fully cross platform app.

[toolchain]
channel = "stable"
components = ["rustfmt", "rustc-dev"]
targets = [
    "aarch64-apple-darwin",
    "aarch64-apple-ios",
    "aarch64-apple-ios-sim",
    "aarch64-linux-android",
    "wasm32-unknown-unknown",
    "x86_64-apple-ios",
]
profile = "minimal"

For testing, we also recommend to install cargo-nextest, the test runner we'll be using in the examples.

cargo install cargo-nextest

Create the core crate

We need a crate to hold our application's core, but since one of our shell options later will be rust based, we'll set up a cargo workspace to have some isolation between the core and the other Rust based modules

The workspace and library manifests

First, create a workspace and start with a /Cargo.toml file, at the monorepo root, to add the new library to our workspace.

It should look something like this:

# /Cargo.toml
[workspace]
resolver = "3"
members = ["shared"]

[workspace.package]
edition = "2024"
rust-version = "1.88"

[workspace.dependencies]
anyhow = "1.0.100"
crux_core = "0.17.0"
serde = "1.0.228"

The shared library

The first library to create is the one that will be shared across all platforms, containing the behavior of the app. You can call it whatever you like, but we have chosen the name shared here. You can create the shared rust library, like this:

cargo new --lib shared

The library's manifest, at /shared/Cargo.toml, should look something like the following,

# /shared/Cargo.toml
[package]
name = "shared"
version = "0.1.0"
edition.workspace = true
rust-version.workspace = true

[lib]
crate-type = ["cdylib", "lib", "staticlib"]
name = "shared"

[dependencies]
crux_core.workspace = true
serde = { workspace = true, features = ["derive"] }

Note the crate-type in the [lib] section. This is in preparation for linking with the shells:

  • lib is the default rust library when linking into a rust binary
  • staticlib is a static library (libshared.a) for use with iOS apps
  • cdylib is a C-ABI dynamic library (libshared.so) for use with JNA in an Android app

The basic files

The only missing part now is your src/lib.rs file. This will eventually contain a fair bit of configuration for the shell interface, so we tend to recommend reserving it to this job and creating a a src/app.rs module for your app code.

For now, the lib.rs file looks as follows:

#![allow(unused)]
fn main() {
// src/lib.rs
pub mod app;
}

and app.rs can be empty, but let's put our app's main type in it, call it Counter:

#![allow(unused)]
fn main() {
// src/app.rs

#[derive(Default)]
pub struct Counter;
}

Running

cargo build

should build your Core. Let's make it do something now.