Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
zpl-rs
A Rust library for rendering ZPL (Zebra Programming Language) labels to images.
This crate provides bindings to go-zpl, a native ZPL parser and renderer. Everything runs locally - no external services required.
Features
- Parse and render ZPL to PNG images
- Support for text, barcodes (Code 128, QR, DataMatrix, PDF417, etc.), and graphics
- Configurable DPI (203, 300, 600)
- Cross-platform: Linux, macOS, Windows (x64 and ARM64)
- Automatic library download at build time, or an offline build via
LIBZPL_PATH
Installation
Add to your Cargo.toml:
[]
= "0.1"
Quick Start
use render;
Advanced Usage
use ;
let zpl = "^XA^FO50,50^A0N,30,30^FDHello!^FS^XZ";
let options = new
.dpi
.size; // 4" x 6" at 300 DPI
let png_bytes = render_with_options.expect;
API
Functions
render(zpl: &str) -> Result<Vec<u8>>- Render ZPL with default settings (203 DPI)render_bytes(zpl: &[u8]) -> Result<Vec<u8>>- Render ZPL bytes (non-UTF8 safe)render_with_options(zpl: &str, options: &RenderOptions) -> Result<Vec<u8>>- Render with custom optionsrender_bytes_with_options(zpl: &[u8], options: &RenderOptions) -> Result<Vec<u8>>- Render bytes with options
Types
Dpi- Printer DPI:Dpi203,Dpi300,Dpi600RenderOptions- Configuration for rendering (DPI, width, height)Error- Error types:ParseError,RenderError,InternalError
Supported Platforms
| Platform | Architecture | Status |
|---|---|---|
| Linux | x86_64 | ✅ |
| Linux | aarch64 | ✅ |
| macOS | x86_64 | ✅ |
| macOS | aarch64 | ✅ |
| Windows | x86_64 | ✅ |
| Windows | aarch64 | ✅ |
Thread Safety
Important: The underlying Go library is not thread-safe for concurrent renders. If you need to render from multiple threads, use a mutex:
use Mutex;
use render;
static ZPL_MUTEX: = new;
How it works
At build time the crate stages the prebuilt libzpl shared library for the target into its OUT_DIR (downloaded from GitHub releases, or copied from LIBZPL_PATH) and links it dynamically (on Windows through raw-dylib, so no import library is needed). cargo run / cargo test in a downstream project need no extra setup: Cargo adds OUT_DIR library paths to the dynamic-library search path for those commands. Distributing the built binary is where it breaks: the library is not next to the binary, and the rpaths this crate sets do not apply to a downstream binary (Cargo applies a dependency's rustc-link-arg only to that dependency's own targets).
Environment variables
| Var | Effect |
|---|---|
LIBZPL_VERSION |
libzpl release to download (default: latest GitHub release). Changing it replaces the staged library on the next build. |
LIBZPL_PATH |
path to an already-built libzpl shared library for the target; staged instead of downloading (offline builds, a locally built cmd/libzpl, CI caches). Wins over LIBZPL_VERSION; no network access. |
LIBZPL_COPY_TO |
directory to also copy the staged library into (created if missing). Opt-in staging hook for bundlers; writes outside OUT_DIR on purpose. |
Build metadata for dependents
The crate declares links = "zpl", so the build script of a crate that depends on zpl-rs directly (Cargo passes metadata to immediate dependents only) gets:
| Variable | Value |
|---|---|
DEP_ZPL_LIB_DIR |
absolute directory that holds the staged library |
DEP_ZPL_LIB_PATH |
absolute path of the staged library file |
DEP_ZPL_LIB_NAME |
file name (libzpl.dylib / libzpl.so / zpl.dll) |
DEP_ZPL_VERSION |
the release version, or the literal file when LIBZPL_PATH was used |
This is the supported way to locate the library; never scan target/.
Bundling for distribution
Two things have to happen:
- The library file must end up where the OS loader looks at runtime — next to the executable, or a directory an rpath names.
- On macOS/Linux the binary needs rpaths that point there, and those must be emitted by your build script.
rpaths and staging from your own build.rs
cargo run / cargo test still work without this; it only matters for a relocated binary. This is a complete build.rs for the application crate. The first half sets the rpaths; the second half stages the library into lib/ next to your Cargo.toml for the bundler (drop it if you stage with LIBZPL_COPY_TO instead):
use env;
use fs;
use PathBuf;
Staging with LIBZPL_COPY_TO instead
If you would rather not copy from build.rs, set LIBZPL_COPY_TO and zpl-rs does the copy itself:
LIBZPL_COPY_TO=/lib
or in .cargo/config.toml:
[]
= { = "lib", = true }
Relative values resolve differently in the two forms: a raw environment value is taken relative to the zpl-rs package directory (the build script's working directory), while [env] with relative = true resolves against the directory that holds .cargo/ and reaches the build script as an absolute path. Prefer an absolute path or the [env] form.
The staging directory is the bundler's input, not "next to the binary": Cargo puts the binary under <target-dir>/[<target-triple>/]<profile>/, so for a bare binary locate the actual executable directory and copy the library beside it yourself (or point LIBZPL_COPY_TO at that directory with an absolute path).
Bundler notes
- Tauri:
bundle.macOS.frameworks: ["lib/libzpl.dylib"](relative tosrc-tauri/) puts the dylib inContents/Frameworks/— the@executable_path/../Frameworksrpath above is what makes that work. On Linux,LD_LIBRARY_PATHmust include the directory holdinglibzpl.sowhen runningtauri buildso linuxdeploy bundles it into the AppImage. On Windows use the object form ofbundle.resourcesso the DLL lands in the resource root next to the exe:"resources": { "lib/zpl.dll": "zpl.dll" }(the array form keeps thelib/subdirectory, which the Windows loader does not search). The staging step above is what produceslib/for these configs. - cargo-bundle / other: same idea — stage from
DEP_ZPL_LIB_PATHorLIBZPL_COPY_TO, tell the bundler about the file, set rpaths. - Bare binary: ship the library next to the executable and use the
$ORIGIN/@executable_pathrpaths.
License
MIT