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.

cargo build does not produce a linkable library

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 native

This 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 Windows

Two variants swap the renderer for a GPU backend:

make native-opengl    # OpenGL / OpenGL ES backend
make native-webgpu    # WebGPU backend
The terminal output prints the wrong path

make 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.

TargetAndroid ABIRust target triple
make android-aarch64arm64-v8aaarch64-linux-android
make android-armv7armeabi-v7aarmv7-linux-androideabi
make android-x86_64x86_64x86_64-linux-android
make android-x86x86i686-linux-android
export ANDROID_NDK_HOME=/path/to/android-ndk-r28b
make android-aarch64

Each 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.so

Build 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.

FeatureEnables
c_apiThe C API and header generation. Required
tvgThe ThorVG renderer core. Required
tvg-cpuSoftware rendering into a pixel buffer
tvg-glOpenGL and OpenGL ES rendering
tvg-wgWebGPU rendering
dotlottie.lottie archive support, manifests, and multi-animation files
themingRuntime theming. Implies dotlottie
state-machinesInteractive state machines. Implies dotlottie
tvg-pngPNG image assets
tvg-jpgJPEG image assets
tvg-webpWebP image assets
tvg-ttfTrueType font rendering
tvg-otfOpenType font rendering
tvg-lottie-expressionsLottie expressions
tvg-threadsMultithreaded rendering
audioAudio playback for animations with embedded audio
The header needs both the c_api and tvg features

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-aarch64

Build 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 \
  --release

Swap --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:

ArtifactPath
Headerdotlottie-rs/build/dotlottie_player.h
Librarydotlottie-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.

The header is generated, not checked in

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_player

On 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 nightly

Next steps

Last updated: August 13, 2026 at 9:17 AMEdit this page