Edit source

Rust projects and output

Generated Cargo crate

Without projectFile, Tsonic emits a complete Cargo project:

out/rust/
├── Cargo.toml
└── src/
    ├── lib.rs or main.rs
    └── <source-owned Rust modules>
{
  "targets": [{
    "id": "rust",
    "options": {
      "crateName": "example_app",
      "edition": "2024",
      "foundation": "std",
      "outputType": "bin"
    }
  }]
}

Generated manifests contain only closed dependencies contributed by the selected target, source surface, and activated capabilities. An installed but unused capability contributes no crate.

Tsonic formats every generated .rs artifact with the selected edition’s rustfmt before it publishes the output set. This includes generated source for a user-owned Cargo project, but never changes Rust source authored by the user. A missing formatter or a formatting failure rejects publication.

outputType: "bin" requires an exported entry function:

export function main(): void {
  // application startup
}

This may also be async function main(): Promise<void>. A fallible entry is emitted as a native Result path. outputType: "lib" instead exposes supported TypeScript exports as Rust library declarations.

Foundation

FoundationGenerated crateAvailable semantic layer
core#![no_std] librarycore only
alloc#![no_std], extern crate alloc librarycore + allocator-backed carriers
stdhosted library or binarycore + alloc + std

Tsonic does not invent panic handlers, allocators, entrypoints, link scripts, or target triples. Therefore core and alloc generated outputs are libraries; a native project owns executable startup.

User-owned Cargo project

{
  "targets": [{
    "id": "rust",
    "options": {
      "projectFile": "native/Cargo.toml",
      "foundation": "std"
    }
  }]
}

The manifest must exist outside generated output. Tsonic emits source artifacts only and never creates or mutates the manifest. The user project owns dependencies, features, profiles, target triples, build scripts, linking, startup, and inclusion of generated source.

A hosted library project has this basic shape:

[package]
name = "example_native"
version = "0.1.0"
edition = "2024"

[lib]
path = "../out/rust/src/lib.rs"

[dependencies]
tsonic_rust_runtime = {
  path = "../node_modules/@tsonic/rust-runtime/crates/tsonic_rust_runtime",
  default-features = false,
  features = ["std"],
}

Adjust both paths for the actual layout. Add every capability/runtime crate and every @tsonic/rust/crates/* dependency directly. Tsonic validates the configured Cargo graph but does not edit it.

Select the runtime feature that matches the target foundation:

FoundationRuntime dependency
coredefault-features = false with no feature
allocdefault-features = false, features = ["alloc"]
stddefault-features = false, features = ["std"]

What each setting controls

NeedPut it here
generated crate name, edition, library/binary shapeRust target options
maximum core/alloc/std semantic layerfoundation
target triple, profiles, features, linker, build scriptCargo
third-party native cratedirect Cargo dependency plus @tsonic/rust/crates/* import
allocator, panic handler, startup, image formatuser-owned native project

There is no generic “Cargo overrides” object. Cargo owns Cargo configuration; Tsonic owns the source and target semantic contract.

Native build

npx --no-install tsonic build -p tsonic.json
cargo build --manifest-path out/rust/Cargo.toml

Tsonic’s toolchain stage reports the formatted generated artifact set; Cargo performs the native compile, test, run, and publish operations.

After the first Cargo command creates Cargo.lock, commands against that generated tree can add --locked:

cargo test --manifest-path out/rust/Cargo.toml --locked

A later tsonic build atomically replaces compiler-owned outDir, including that generated lockfile. Run an unlocked Cargo command after regeneration. Keep a durable, committed lockfile in a user-owned Cargo project.