C Library¶
Get the C library one of two ways — a pre-built release tarball (no build)
or building from source — then choose an integration method
below. Either way you get the headers plus a shared (libdoppler.so) and a
self-contained static (libdoppler.a) library.
Install from a release tarball¶
Every GitHub release ships a pre-built C library for Linux (x86_64, aarch64) and macOS (arm64) — no toolchain or build step.
One-liner via jbx
jbx get-doppler # extracts to $HOME/.local/doppler
jbx get-doppler --prefix /opt/doppler # or a custom prefix
jbx get-doppler --version 0.33.1 # pin a specific release
jbx get-doppler --restore # roll back to the prior install
Resolves the latest release, downloads the platform-appropriate tarball,
and extracts it — the manual steps below, in one command. A previous
install at the same prefix is moved aside first, restored automatically
if the new one fails a sanity check, and restorable any time with
--restore. Needs
jbx (make install-deps bootstraps
it, or by hand: . <(curl -sSL https://just-buildit.github.io/get-jb.sh)).
Source: scripts/get-doppler.sh.
Or by hand:
# Resolve the latest release tag (or set VERSION=x.y.z to pin a specific one):
VERSION=$(curl -fsSL https://api.github.com/repos/doppler-dsp/doppler/releases/latest \
| sed -n 's/.*"tag_name": *"v\([^"]*\)".*/\1/p')
# Linux x86_64 — for Linux aarch64 swap the suffix for `linux-aarch64`,
# for macOS arm64 swap it for `macos-arm64`:
curl -L -o doppler.tar.gz \
"https://github.com/doppler-dsp/doppler/releases/download/v${VERSION}/doppler-${VERSION}-linux-x86_64.tar.gz"
mkdir -p "$HOME/.local/doppler" && tar -xzf doppler.tar.gz -C "$HOME/.local/doppler"
Point your build at the extracted prefix — CMake via CMAKE_PREFIX_PATH, or
pkg-config via PKG_CONFIG_PATH — then use the find_package or
pkg-config method shown below:
cmake -B build -DCMAKE_PREFIX_PATH="$HOME/.local/doppler" # for find_package(doppler)
export PKG_CONFIG_PATH="$HOME/.local/doppler/lib/pkgconfig" # for pkg-config doppler
The core library is pure C and links only -lm, so there is no external
runtime dependency to install. The optional stream component
(libdoppler_stream, for the NATS wire layer) embeds the vendored nats.c
statically, so it too needs no external runtime NATS client library — just a
running nats-server to connect to. See the
static vs. dynamic linking design notes
for why static vendoring was chosen over a system client-library dependency.
System install¶
Install headers and libraries to a system prefix (default /usr/local)
so find_package/pkg-config resolve with no per-project paths.
From a release tarball (no toolchain, no build) — point
jbx get-doppler at the prefix. The sudo env "PATH=$PATH" form keeps
jbx findable under sudo's restricted PATH:
From a source build — only if you already
built from source (a build/ tree exists):
Either way, verify the install is visible to your toolchain:
CMake — find_package¶
The package provides two link targets — pick the one matching your linking policy:
find_package(doppler REQUIRED)
# shared: links -ldoppler; smallest binary
target_link_libraries(my_app PRIVATE doppler::doppler)
# static: pure C, self-contained — links only -lm
target_link_libraries(my_app PRIVATE doppler::doppler-static)
# optional: the NATS stream layer (dp_pub_*/dp_sub_*, wfmgen --output nats://).
# Pure C (vendored nats.c, folded in). Link only if needed.
target_link_libraries(my_app PRIVATE doppler::stream-static)
A complete, buildable consumer that exercises both targets lives in
examples/consumer/.
pkg-config¶
# shared
gcc -o app main.c $(pkg-config --cflags --libs doppler)
# static — pure C, self-contained: only -lm
gcc -o app main.c $(pkg-config --cflags doppler) \
"$(pkg-config --variable=libdir doppler)/libdoppler.a" -lm
# the optional NATS stream layer has its own module — one name gives
# the whole line (shared; Requires: doppler)
gcc -o app main.c $(pkg-config --cflags --libs doppler_stream) -lm
# static + stream: name the archives explicitly
gcc -o app main.c $(pkg-config --cflags doppler) \
"$(pkg-config --variable=libdir doppler)/libdoppler_stream.a" \
"$(pkg-config --variable=libdir doppler)/libdoppler.a" \
-lpthread -lm
Custom install prefix
Link from the build tree (no install)¶
Useful during development — no cmake --install required.
Shared library:
rpath on Linux
The -Wl,-rpath flag bakes the build path into the binary. If you
move the binary or the build tree, set LD_LIBRARY_PATH or re-link.
Static library (no runtime .so dependency):
CMake — add_subdirectory:
Embedding the wfmgen generator¶
The wfmgen composer CLI is archived into the library as a plain callable, so
a C program can drive the full generator in-process — same flags, same output
as the command line — without spawning a subprocess. Include wfm/wfmgen.h
and call doppler_wfmgen(argc, argv):
#include <stddef.h>
#include "wfm/wfmgen.h"
int main(void)
{
/* identical to: wfmgen --type qpsk --count 4096 --output out.cf32 */
char *av[] = { "wfmgen", "--type", "qpsk", "--count", "4096",
"--output", "out.cf32", NULL };
return doppler_wfmgen(7, av); /* 0 on success; writes out.cf32 */
}
It is the exact code path the wfmgen binary runs (which is itself a one-line
main shim over doppler_wfmgen), so the output is byte-identical. wfmgen
lives in the pure-C core, so the file/raw/csv/BLUE/SigMF output paths link
with just libdoppler.a -lm:
The --output nats://… PUB-sink path additionally needs the optional stream
component (it carries the vendored nats.c, pure C). Link
libdoppler_stream.a alongside the core; nats.c is statically embedded, so
there is still no runtime client-library dependency — just a running
nats-server to connect to:
gcc -o app app.c -I "$PREFIX/include" \
"$PREFIX/lib/libdoppler.a" "$PREFIX/lib/libdoppler_stream.a" \
-lpthread -lm
Without the stream component, doppler_wfmgen() still builds and runs; only the
nats:// path is unavailable (it reports a clear "requires the stream component"
error via the weak wfm_stream_sink_* seam).
The shared library is even simpler — -ldoppler alone is sufficient.
POSIX only
doppler_wfmgen is built on the same POSIX surface as the wfmgen binary
(the stream sink and --realtime pacing), so it is not available on Windows.