Alien::Libduckdb — README
Alien::Libduckdb
Installs the DuckDB C library (libduckdb) and tells
Raku where the result lives, so that a NativeCall binding can just depend on
it instead of hunting for a pre-built binary.
Consumed by DB::DuckDB as its
depends entry (pinned to an exact version there, because the C API is not
ABI-stable across DuckDB majors).
Two install paths
| path | what happens | cost |
|---|---|---|
| prebuilt (default) | download duckdb-shared-libs-<os>-<arch>.tar.gz from the DuckDB release matching the pinned version, unpack it into a private prefix | seconds, no compiler |
| source (fallback) | git clone the pinned tag + CMake Release build, then harvest the shared object | 5-20 minutes, needs cmake/ninja/g++ |
The prebuilt path is tried first. It is abandoned - with a printed reason -
whenever the asset is missing for the platform, the download fails, or the
library does not actually load here (missing MSVC runtime, glibc/musl
mismatch, wrong CPU architecture). build-libduckdb then falls through to
the source build, so a bare zef install never leaves you without a library.
The fallback exists because the release assets are not portable enough for a distribution that has to work everywhere:
Linux tarballs ship
libduckdb.sowith noRUNPATH, so a binding either needsLD_LIBRARY_PATHor a system-wide install;Windows MinGW builds emit
libduckdb.dll, MSVC builds emitduckdb.dll, and both need the import library next to them for downstream linking;the headers must match the shared object exactly - mismatched
duckdb.his the classic source of silent memory corruption in NativeCall bindings.
Both paths land in the same private prefix with the same normalised layout,
so consumers cannot tell them apart; source-kind() reports which one was
used if you care.
Install
zef install Alien-LibduckdbA few seconds when a prebuilt archive exists for your platform, a few minutes when it does not. The result is cached per upstream version; reinstalling the module does not rebuild unless the version changed.
To install the module but put the library in place later:
zef install Alien-Libduckdb --/build # or ZEF_NO_BUILD=1and then, whenever you want the library:
use Alien::Libduckdb;
ensure-installed(); # idempotent, prebuilt first, source if neededForce a compile even when a prebuilt archive is available:
ALIEN_LIBDUCKDB_PREBUILT=0 zef install Alien-LibduckdbUsage
use Alien::Libduckdb;
say duckdb-version(); # 2.0.0 - upstream version we build
say prefix(); # .../Alien-Libduckdb/2.0.0
say installed(); # True once the build succeeded
say shared-lib().absolute; # .../bin/duckdb.dll or .../lib/libduckdb.so
# what a NativeCall binding should do
sub duckdb_library_version(--> Str) is native(Alien::Libduckdb::lib()) {*}lib() returns the absolute path when the library exists and falls back to the
bare name (duckdb) so the OS loader can still find a system install.
Exported API
| sub | meaning |
|---|---|
duckdb-version() | upstream DuckDB version this module installs |
prefix() | private install prefix (per version) |
lib-dir() | directory holding the shared library |
include-dir() | directory holding duckdb.h, duckdb_v2.h, ... |
shared-lib() | absolute path of the shared library, or an undefined IO::Path |
lib() | value to pass to is native(...) |
installed() | is an install matching version and platform present? |
source-kind() | 'prebuilt', 'source', or 'unknown' for an untagged older install |
prebuilt-asset() / prebuilt-url() | the release archive this platform maps to |
config() | Hash with all of the above |
cflags() / ldflags() | flags for building against this prefix |
ensure-installed(:force, :source-only) | install on demand: prebuilt first, source if needed |
install-prebuilt(:force) | prebuilt archive only; fails instead of compiling |
build-from-source(:force, :clean, :jobs) | always compile from the pinned tag |
How it works
build-libduckdb runs the two paths in order and never leaves a half-written
prefix behind (a failed attempt is wiped before the next one starts).
Prebuilt path
Resolve - map OS/arch to
duckdb-shared-libs-<os>-<arch>.tar.gzin thev<version>GitHub release; an asset that does not exist for this platform ends the path immediately.Fetch -
curl -fL(wgetas fallback) into<root>/prebuilt/<version>, with the HTTP status checked so a 404 is an error, not an HTML file on disk.Unpack -
tar xzfinto the version prefix, then normalise names (libduckdb.dll->duckdb.dll, headers intoinclude/).Verify - load it and call
duckdb_library_version(); only then write the.alientagmarker. A library that fails to load (no VC++ runtime, glibc/musl mismatch) falls through to the source path.
Source path
Fetch -
git clone --depth 1 --branch v<version>from the DuckDB repo (falls back to the release tarball whengitis unavailable). Submodules are initialised when the tag still has.gitmodules(1.x).Configure - CMake out-of-tree,
Release, shell/unittests/benchmarks off, PIC on. Ninja is preferred, Makefiles are the fallback.Compile -
<cores>parallel jobs (capped to keep memory sane).Harvest - copy the shared object into
<prefix>/bin(Windows) or<prefix>/lib(POSIX), normalisinglibduckdb.dll->duckdb.dllso consumers always load one canonical name; copy the headers and, on Windows, the import library.Verify - same smoke test as above, then the
.alientagmarker with version/platform/kind.installed()compares the marker against the current request, so a library installed for another DuckDB version or platform is never silently reused.
The source tree is deleted after a successful build (about 400 MB). Set
ALIEN_LIBDUCKDB_KEEP_SOURCE=1 to keep it, and the next build becomes a
near-instant incremental rebuild.
Platform notes
Linux / WSL
Prebuilt path needs only
curl(orwget) andtar.Source path additionally needs
cmake,ninja(ormake),g++(GCC 11+ works, Clang too) andgit.The prebuilt
libduckdb.sois built against a glibc baseline; on Alpine or any musl system it fails the load test and the source path takes over.The library is installed to
~/.local/share/Alien-Libduckdb/<version>/lib, honouringXDG_DATA_HOME.ldflags()adds-Wl,-rpath,<lib-dir>so binaries linked against the prefix do not needLD_LIBRARY_PATH.
Windows
Prebuilt path needs only
curl(orwget) andtar; the archive is an MSVC build, so it needs the VC++ runtime and falls back when that is absent.Source path needs CMake, Ninja, and a compiler. Both toolchains work:
MinGW-w64 (e.g.
D:\llvm-mingw-...\bin\gcc.exe) - emitslibduckdb.dll, which this module renames toduckdb.dllon install;MSVC - emits
duckdb.dllandduckdb.lib, both installed.
Default prefix:
%LOCALAPPDATA%\Alien-Libduckdb\<version>.Pathis looked up case-insensitively on Windows (%*ENV<PATH>is not always populated by Rakudo there), socmake/ninjafromPATHare found even when the environment block uses mixed case.
macOS
The layout follows ~/Library/Application Support and ldflags() omits
-rpath specifics beyond the standard flag; untested but no code path is
Windows- or Linux-only.
Environment variables
| variable | effect |
|---|---|
ALIEN_LIBDUCKDB_VERSION | target a different upstream tag (e.g. 1.4.1) |
ALIEN_LIBDUCKDB_ROOT | override the root that holds prebuilt/, src/, build/, <version>/ |
ALIEN_LIBDUCKDB_PREFIX | override the install prefix entirely |
ALIEN_LIBDUCKDB_PREBUILT | 0 disables the prebuilt path (always compile) |
ALIEN_LIBDUCKDB_PREBUILT_ONLY | 1 forbids the source fallback: fail instead of compiling |
ALIEN_LIBDUCKDB_SRC | use an existing DuckDB checkout instead of cloning |
ALIEN_LIBDUCKDB_JOBS | parallel compile jobs (default: CPU cores) |
ALIEN_LIBDUCKDB_CC / _CXX | force a specific compiler |
ALIEN_LIBDUCKDB_KEEP_SOURCE | keep the source tree after building |
Layout
<root>/ %LOCALAPPDATA%\Alien-Libduckdb or ~/.local/share/Alien-Libduckdb
├── prebuilt/duckdb-<ver>/ downloaded archive + staging area
├── src/duckdb-<version>/ source checkout (removed after success)
├── build/duckdb-<version>/ CMake build tree
└── <version>/ install prefix
├── bin/ duckdb.dll (Windows)
├── lib/ libduckdb.so (POSIX) + import libs
├── include/ duckdb.h, duckdb_v2.h, ...
├── logs/ download/clone/configure/build logs of the last attempt
└── .alientag marker: version, platform, kind, build idLicense
Artistic-2.0. DuckDB itself is MIT-licensed.