# transcribe-cpp-sys
Raw native FFI bindings for
[transcribe.cpp](https://github.com/handy-computer/transcribe.cpp), a C/C++
speech-to-text library built on ggml.
> **Status: in development (0.2.0).** This crate exposes the unsafe, generated
> FFI surface. Most users want the safe wrapper,
> [`transcribe-cpp`](https://crates.io/crates/transcribe-cpp).
Raw-FFI consumers upgrading from 0.1 should follow the
[0.2 migration guide](https://github.com/handy-computer/transcribe.cpp/blob/main/docs/migrating-to-0.2.md).
## What it does
`build.rs` compiles the vendored C++ tree from source via CMake (the crate
tarball carries the whole tree) and reconstructs the link line from the
installed `transcribe-link.json` manifest — no hardcoded per-platform link
lists. The committed bindgen output means **libclang is not needed** to build
this crate.
## Build prerequisites
A C++ toolchain and **CMake**. There is no external compression dependency —
the deflate codec (miniz) is vendored into the library, so no system zlib /
vcpkg setup is required on any platform. The static link is the default; the
`shared` feature links a shared library instead.
## Features
- `metal` (default on Apple), `vulkan`, `cuda`, `rocm`, `openmp` — each forwards
to the matching `TRANSCRIBE_*` CMake option (`rocm` enables `TRANSCRIBE_HIP`).
- `shared` — link a shared `libtranscribe` (`.so`/`.dylib`/`.dll`) loaded at
runtime instead of statically baking it in. The default is a self-contained
static link.
- `dynamic-backends` — additionally ship each compute backend (the per-ISA CPU
tiers, Vulkan, CUDA, ROCm, …) as a loadable module next to the library, selected at
runtime by `transcribe_init_backends_default()` when the modules sit next to
`libtranscribe`, or `transcribe_init_backends(dir)` for a custom provider
directory. Implies `shared`.
## ROCm builds
Install ROCm 6.1 or newer, then enable the first-class `rocm` feature:
```sh
cargo build --no-default-features --features rocm
```
The build detects the attached AMD GPU. To target a specific architecture, pass
it through CMake, for example
`TRANSCRIBE_CMAKE_ARGS="-DAMDGPU_TARGETS=gfx1201"`.
## Windows Vulkan builds
The `vulkan` feature requires the
[Vulkan SDK](https://vulkan.lunarg.com/sdk/home#windows) on Windows. Once the
SDK is installed and a new terminal sees `VULKAN_SDK`, build normally:
```powershell
cargo build --features vulkan
```
Windows' legacy path limit can otherwise break ggml's nested Vulkan shader
build. The build script handles this automatically by compiling through a
short, per-build NTFS junction under `%LOCALAPPDATA%\tcs`; installed artifacts
and Cargo metadata still use the durable `OUT_DIR` paths. Junction creation
does not require administrator rights.
If junction creation is blocked by filesystem or corporate policy, the build
prints a warning and falls back to the original `OUT_DIR`. Set a short Cargo
target directory to avoid `MAX_PATH` in that case:
```powershell
$env:CARGO_TARGET_DIR = "C:\tc-target"
cargo build --features vulkan
```
## Linking a prebuilt install
Set `TRANSCRIBE_DIR` (OPENSSL_DIR-style) to skip the source build and link an
existing install prefix instead:
```bash
cmake -B build -DTRANSCRIBE_INSTALL=ON [-DTRANSCRIBE_BUILD_SHARED=ON ...]
cmake --build build
cmake --install build --prefix /opt/transcribe
TRANSCRIBE_DIR=/opt/transcribe cargo build
```
The prefix must contain the installed `lib*/transcribe-link.json` manifest;
the link line is reconstructed from it exactly as in a source build. Cargo
features (`shared`, `vulkan`, ...) do not apply on this path — the prebuilt
already fixed its configuration, and the manifest records it (including
static vs shared). For a shared-library prefix, running consumer binaries
may additionally need the prefix's lib dir on the loader path (e.g.
`LD_LIBRARY_PATH=$TRANSCRIBE_DIR/lib`): the rpath the build emits does not
propagate to downstream binaries.
## Build-flag escape hatch
The features above cover the common, tested configurations. Anything else CMake
accepts can be forwarded via the `TRANSCRIBE_CMAKE_ARGS` (or `CMAKE_ARGS`) env
var — e.g. `TRANSCRIBE_CMAKE_ARGS="-DGGML_VULKAN=ON" cargo build`. These are
split on whitespace with simple double-quote handling, applied after the
feature-derived defines (so a user `-D` wins), and unsupported/untested by
design: they exist so a Cargo feature is never a hard ceiling on what you can
configure. The link line is still reconstructed from the generated manifest, so
whatever you turn on links correctly.
## ABI drift
The generated FFI is committed and CI-checked against `include/transcribe.abihash`
(`cargo xtask bindgen --check`): a public-header ABI change turns the check red
until the bindings are regenerated. Per-field layout checks are waived because
bindgen takes layout from a real compiler at generation time.
- Crate: `transcribe-cpp-sys` (raw FFI; the safe API is `transcribe-cpp`)
- License: MIT