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 -lm and -lpthread, both part of a
POSIX toolchain, 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.
Windows¶
Every release also carries doppler-<version>-windows-x86_64.zip, built with
clang-cl against the MSVC runtime. Your own code must be compiled with
clang-cl as well: doppler's headers use C99 _Complex, which MSVC's
cl.exe does not implement, and they stop a cl.exe build with an #error
saying so. From a Developer PowerShell for VS (x64), with the C++ Clang
tools for Windows component installed:
$v = "X.Y.Z" # the release to install
curl.exe -L -o doppler.zip `
"https://github.com/doppler-dsp/doppler/releases/download/v$v/doppler-$v-windows-x86_64.zip"
Expand-Archive doppler.zip -DestinationPath "$HOME\doppler"
cmake -B build -G Ninja -DCMAKE_C_COMPILER=clang-cl `
-DCMAKE_PREFIX_PATH="$HOME\doppler"
find_package(doppler) works exactly as below; pkg-config is not the Windows
path. doppler::doppler links the DLL — put $HOME\doppler\bin on PATH,
or copy doppler.dll beside your executable — and
doppler::doppler-static links doppler_static.lib with no DLL at all. The
NATS stream layer is not in the Windows build
(#1364).
With vcpkg¶
The repository carries its own vcpkg port and a clang-cl triplet, under
packaging/vcpkg/. The port is an overlay: it builds the checkout it lives
in, so you get the version you cloned, and it is not in the upstream
microsoft/vcpkg registry — whose default x64-windows triplet compiles
with cl.exe and therefore cannot build doppler.
$v = "X.Y.Z" # the release to install
git clone --depth 1 --branch "v$v" https://github.com/doppler-dsp/doppler
vcpkg install doppler:x64-windows-clangcl `
--overlay-ports=doppler/packaging/vcpkg/ports `
--overlay-triplets=doppler/packaging/vcpkg/triplets
cmake -B build -G Ninja -DCMAKE_C_COMPILER=clang-cl `
-DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_ROOT\scripts\buildsystems\vcpkg.cmake" `
-DVCPKG_TARGET_TRIPLET=x64-windows-clangcl
vcpkg's toolchain finds the package and copies doppler.dll beside your
executable, so there is no CMAKE_PREFIX_PATH and no PATH edit. vcpkg
builds in a scrubbed environment and looks for clang-cl under
%LLVMInstallDir%, then %ProgramFiles%\LLVM, then Visual Studio's Clang
component. Three things to know:
-
Use a full vcpkg checkout, not Visual Studio's. A Developer PowerShell sets
VCPKG_ROOTto the copy bundled with Visual Studio, which is manifest-only and answersvcpkg install <port>with "does not have a classic mode instance". Clonemicrosoft/vcpkg, run itsbootstrap-vcpkg.bat, and pointVCPKG_ROOTthere. (doppler's own CI hit exactly this.) -
Dynamic triplets only. The exported targets carry both linkages and refuse to load with one missing, so a static triplet (which must ship no DLL) is not expressible yet (#1405).
doppler::doppler-staticis still there to link against. -
Rebuild after updating the clone. vcpkg's binary cache is keyed on the port files, not on the sources an overlay port points at — after a
git pull, runvcpkg remove dopplerfirst or pass--binarysource=clear.
The same port installs on Linux and macOS with the stock *-dynamic
community triplets; CI exercises the Windows one on every pull request
(make vcpkg-smoke).
System packages (.deb / .rpm)¶
Every release carries native packages for x86_64 and aarch64, attached to the GitHub Release. Download the ones for your format and install them with your package manager, which resolves the dependencies:
# Debian / Ubuntu
sudo apt install ./libdoppler-dsp0.*_*.deb ./libdoppler-dsp-dev_*.deb
# Fedora / RHEL / AlmaLinux
sudo dnf install ./libdoppler-dsp-0.*.rpm ./libdoppler-dsp-devel-*.rpm
| Debian / Ubuntu | Fedora / RHEL | |
|---|---|---|
| shared libraries | libdoppler-dsp<X.Y> |
libdoppler-dsp |
headers, .a, CMake + pkg-config files |
libdoppler-dsp-dev |
libdoppler-dsp-devel |
the wfmgen CLI |
doppler-dsp-tools |
doppler-dsp-tools |
After that find_package(doppler) and pkg-config doppler resolve with no
path of yours on the command line. Three things to know:
- The name is
doppler-dsp, as on PyPI — an unrelateddopplerpackage (a secrets-manager CLI) is distributed from its vendor's own repository. The library itself is stilllibdoppler.so. - One package per architecture, for every distro at or above glibc 2.28
(Debian 10, Ubuntu 20.04, RHEL 8): they are built in the same
manylinux_2_28image as the tarballs, and CI installs them on AlmaLinux 8, the floor, on every pull request. The x86_64 build targetsx86-64-v2(SSE4.2), which is above the oldest CPUs those distros themselves still run on. - The Debian runtime package carries the ABI version in its name
(
libdoppler-dsp0.53for the 0.53 series), so two minors install side by side and a program built against one keeps running after you install the next.
These are release assets, not an apt or yum repository: upgrading means downloading the next release's files.
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 -lm and -lpthread
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
example-projects/consumer/.
pkg-config¶
# shared
gcc -o app main.c $(pkg-config --cflags --libs doppler)
# static — pure C, self-contained: -lm and -lpthread
gcc -o app main.c $(pkg-config --cflags doppler) \
"$(pkg-config --variable=libdir doppler)/libdoppler.a" -lm -lpthread
# 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 "doppler/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 -lpthread:
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 surface as the wfmgen binary,
including the NATS stream sink, which is not ported to Windows, so it is
not available there. See Build from Source for what
the Windows build includes.