Build for your target architecture
Compile dotlottie-rs into a shared or static library for Android, Apple, Linux, or Windows architectures and generate the dotlottie_player.h C header.
A build produces two artifacts: a native library for one target architecture, and the dotlottie_player.h C header that declares the API. You need one library per architecture you ship, but the header is identical for all of them.
The repository provides a make target for every supported architecture. Use those unless you need a target the makefiles don't cover, in which case call cargo rustc yourself.
The crate declares crate-type = ["rlib"], so a plain cargo build produces only a Rust archive — no .so,
.dylib, .dll, or .a, and no header. Every build must override the crate type on the command line with cargo
rustc --crate-type cdylib (or --crate-type staticlib). The make targets already do this.
Build for the machine you're on
To get a library for your own architecture with the software renderer, run:
make nativeThis compiles with the features tvg,tvg-cpu,c_api and writes:
release/native/dotlottie-player/
├── include/dotlottie_player.h
└── lib/libdotlottie_player.dylib # .so on Linux, .dll on WindowsTwo variants swap the renderer for a GPU backend:
make native-opengl # OpenGL / OpenGL ES backend
make native-webgpu # WebGPU backendmake native reports its artifacts as being in release/native/lib and release/native/include. Those directories
are never created — the real output is under release/native/dotlottie-player/ as shown above.
Build for a specific architecture
Each platform has one make target per architecture. Building a single architecture is much faster than building the whole platform, so target only what you need.
Set ANDROID_NDK_HOME first, then build the architectures you need.
| Target | Android ABI | Rust target triple |
make android-aarch64 | arm64-v8a | aarch64-linux-android |
make android-armv7 | armeabi-v7a | armv7-linux-androideabi |
make android-x86_64 | x86_64 | x86_64-linux-android |
make android-x86 | x86 | i686-linux-android |
export ANDROID_NDK_HOME=/path/to/android-ndk-r28b
make android-aarch64Each target writes into a shared jniLibs tree, so you can build several architectures in sequence and they accumulate:
release/android/
├── include/dotlottie_player.h # added by `make android`
└── jniLibs/
└── arm64-v8a/
├── libdotlottie_player.so
└── libc++_shared.soBuild all four architectures and copy the header in one step with make android.
Android builds enable both the software and OpenGL ES renderers (tvg-cpu,tvg-gl) and target API level 21.
:::warning[Ship libc++_shared.so alongside the player]
ThorVG is C++, so the library depends on the NDK's shared C++ runtime. Each make android-* target copies the matching libc++_shared.so next to the player. Package both files in your APK or your app will fail to load the library at runtime.
:::
Choose your features
The runtime is heavily feature-gated so you only compile the codecs and renderers you actually use. The crate's default features are dotlottie, state-machines, and theming — deliberately no renderer and no C API. Every platform target passes --no-default-features and lists what it wants explicitly.
| Feature | Enables |
c_api | The C API and header generation. Required |
tvg | The ThorVG renderer core. Required |
tvg-cpu | Software rendering into a pixel buffer |
tvg-gl | OpenGL and OpenGL ES rendering |
tvg-wg | WebGPU rendering |
dotlottie | .lottie archive support, manifests, and multi-animation files |
theming | Runtime theming. Implies dotlottie |
state-machines | Interactive state machines. Implies dotlottie |
tvg-png | PNG image assets |
tvg-jpg | JPEG image assets |
tvg-webp | WebP image assets |
tvg-ttf | TrueType font rendering |
tvg-otf | OpenType font rendering |
tvg-lottie-expressions | Lottie expressions |
tvg-threads | Multithreaded rendering |
audio | Audio playback for animations with embedded audio |
Header generation runs from the renderer branch of the build script, so --features c_api on its own produces no
dotlottie_player.h at all — and no error explaining why. Always pass a renderer feature alongside it, for example
--features tvg,tvg-cpu,c_api.
The Android, Apple, Linux, and Windows targets accept a FEATURES variable to add features on top of their defaults:
FEATURES=tvg-png,tvg-jpg,tvg-ttf,tvg-threads make android-aarch64Build with cargo directly
Use cargo rustc when you need a target the makefiles don't cover, or when you want full control over features and flags. The shape of the command is always the same:
cargo rustc \
--manifest-path dotlottie-rs/Cargo.toml \
--target aarch64-unknown-linux-gnu \
--crate-type cdylib \
--features tvg,tvg-cpu,c_api \
--releaseSwap --crate-type cdylib for --crate-type staticlib to get a static archive, or pass both to get each in one build. Omit --target to build for your host.
Cross-compiling this way means setting the toolchain environment yourself, because the repository's Cargo config contains no linker settings — the makefiles export them inline. At minimum you need CC, CXX, AR, RANLIB, and CARGO_TARGET_<TRIPLE>_LINKER, plus BINDGEN_EXTRA_CLANG_ARGS pointing at the target sysroot so bindgen can parse ThorVG's headers against the right platform.
Output from a direct cargo rustc build is not packaged into release/. Look for it here instead:
| Artifact | Path |
| Header | dotlottie-rs/build/dotlottie_player.h |
| Library | dotlottie-rs/target/<triple>/release/libdotlottie_rs.{so,dylib,a} |
When you build for your host without --target, the library lands in dotlottie-rs/target/release/ instead.
dotlottie_player.h is git-ignored and absent from a fresh clone. It appears only after a successful build with
c_api and tvg enabled. Regenerate it whenever you change features, since the declarations it contains depend on
which features are on.
Verify the build
Confirm the header exists and the library exports the API:
ls dotlottie-rs/build/dotlottie_player.h
nm -gU release/native/dotlottie-player/lib/libdotlottie_player.dylib | grep dotlottie_new_playerOn Linux use nm -D --defined-only, and on Windows use dumpbin /exports.
Troubleshooting
You ran cargo build instead of cargo rustc --crate-type cdylib. The crate declares only rlib, so the crate type has to be overridden on the command line. Use a make target, or add --crate-type cdylib to your cargo rustc invocation.
The header is generated only when both c_api and tvg are enabled. Rebuild with --features tvg,tvg-cpu,c_api. Note that the file is git-ignored, so it is also missing in a fresh clone until you build.
Usually a missing ThorVG submodule. Run git submodule update --init --recursive, then confirm with git submodule status. If the submodule is present, check that libclang is installed and that LIBCLANG_PATH is set on Windows.
The WebGPU backend links against prebuilt wgpu-native binaries, which the build script downloads on demand. Artifacts exist only for macOS, iOS, Linux, and Android — there is none for any Windows target, and none for macCatalyst, tvOS, visionOS, or watchOS. Use tvg-cpu or tvg-gl on those platforms.
Because the download happens at build time, a tvg-wg build needs network access. On an air-gapped machine, set WGPU_NATIVE_INCLUDE and WGPU_NATIVE_LIB to a local copy instead.
macCatalyst, visionOS, tvOS, and watchOS are compiled with -Z build-std, which needs the Rust source component on the nightly toolchain:
rustup toolchain install nightly
rustup component add rust-src --toolchain nightlyNext steps
Link the runtime into your project — compiler and linker flags for your build system
Render your first animation — a complete C program