Interop

Rust Backend

Build a checked Topaz package into a managed native product and run it without the Topaz source tree.

Choose the Rust path when the deliverable needs to be a native executable for the operating system and architecture of the build machine. Rust remains a build target. Rust tokens never become Topaz syntax.

Prerequisites

  • Complete the study-plan package from First Application.
  • Keep its topaz.toml, topaz.lock, src/plan.tpz, src/main.tpz, and selected test together.
  • Install a compatible Rust toolchain with Cargo on the build machine.
  • Run the following commands from the study-plan directory.

At runtime, the executable requires neither Topaz, Cargo, nor .tpz files. It remains specific to the OS and architecture for which it was built.

Shared checked package

The same two Topaz modules are used on the Python page. First, src/plan.tpz:

TOPAZ
export record StudyTask {
    title: string,
    minutes: int,
    done: bool = false,
}

function parseMinutes(text: string) -> Result<int, string> {
    match toInt(text) {
        case Some(value) if value > 0 => Ok(value)
        case _ => Err("minutes must be a positive integer")
    }
}

export function makeTask(
    title: string,
    minuteText: string,
    done: bool = false,
) -> Result<StudyTask, string> {
    let minutes = parseMinutes(minuteText)?
    Ok(StudyTask { title: title, minutes: minutes, done: done })
}

export function summarize(tasks: Array<StudyTask>) -> string {
    let mut remaining = 0
    for task in tasks {
        if !task.done {
            remaining = remaining + task.minutes
        }
    }
    "tasks={tasks.length}, remaining={remaining} minutes"
}

The package entry src/main.tpz:

TOPAZ
import src.plan { StudyTask, makeTask, summarize }

export function main(args: Array<string>, stdin: string) -> Result<int, string> {
    let tasks: Array<StudyTask> = [
        makeTask("Run first program", "10", true)?,
        makeTask("Build application", "25", false)?,
    ]
    print(summarize(tasks))
    Ok(0)
}

Verify the Topaz source

Check the package, run the selected test, and establish the reference output:

BASH
topaz check --root . --locked
topaz test tests/plan.tpz --root . --locked
topaz run --root . --locked

The test reports tests/plan.tpz: test-ok. The run prints:

Output
tasks=2, remaining=25 minutes

Emit for inspection, build for delivery

Use emit only when inspecting or integrating the generated Cargo source set:

BASH
topaz emit --target rust --root . --locked --out-dir ../dist/rust-source

Use build for the managed native product:

BASH
topaz build --target native --root . --locked --out-dir ../dist/native

build --target rust is not a valid command. rust designates an emit target, while native designates the deployable build target.

Inspect the managed product

A default debug build contains:

Output
dist/native/
├── GENERATED-OUTPUT-NOTICE.txt
├── LICENSE
├── NOTICE
├── target
│   └── debug
│       └── program[.exe]
└── topaz-artifact.json

topaz-artifact.json records the native target, OS and architecture runtime requirements, invocation details, and the size and SHA-256 hash of every managed file. Topaz writes the manifest last, rejecting modified managed files, unsafe collisions, or target mismatches in the same output directory.

Run after the Topaz source is unavailable

Because dist resides outside the package directory, move the source package aside and run only the product:

BASH
cd ..
mv study-plan source-unavailable
./dist/native/target/debug/program

On Windows, execute Rename-Item study-plan source-unavailable and run .\dist\native\target\debug\program.exe. The product exits with code 0 and prints the output shown above.

Target-specific recovery

  • A missing or incompatible Cargo toolchain indicates an issue on the build machine. Resolve the toolchain installation and rebuild.
  • Specifying --release produces target/release/program[.exe]. This flag changes the build profile without altering Topaz semantics.
  • Default lowering uses the boxed Rust runtime. Optional --backend native specializes proven regions while keeping unsupported shapes boxed rather than guessing.
  • Do not copy a native executable to another OS or architecture and treat it as a supported deployment.

Exact boundary

Generated Rust code and its runtime closure function as replaceable artifacts rather than a handwritten extension API or source-level Rust FFI. Treat a successful execution as evidence of the program's output and exit code on this target. Review any user-written wrapper under its own host-code contract.

If the package binds restricted Lispex rules, follow Run Lispex Rules before building. Only admitted native targets carry that application profile, and an unsupported route fails prior to artifact output.

Continue with Interop Boundaries, Python Backend, Interpreter & Backends, or Artifacts & Deployment.