Rand Stats

Alien::Libduckdb

zef:skyter10086

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

pathwhat happenscost
prebuilt (default)download duckdb-shared-libs-<os>-<arch>.tar.gz from the DuckDB release matching the pinned version, unpack it into a private prefixseconds, no compiler
source (fallback)git clone the pinned tag + CMake Release build, then harvest the shared object5-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:

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

A 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=1

and then, whenever you want the library:

use Alien::Libduckdb;
ensure-installed();     # idempotent, prebuilt first, source if needed

Force a compile even when a prebuilt archive is available:

ALIEN_LIBDUCKDB_PREBUILT=0 zef install Alien-Libduckdb

Usage

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

submeaning
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

  1. Resolve - map OS/arch to duckdb-shared-libs-<os>-<arch>.tar.gz in the v<version> GitHub release; an asset that does not exist for this platform ends the path immediately.
  2. Fetch - curl -fL (wget as fallback) into <root>/prebuilt/<version>, with the HTTP status checked so a 404 is an error, not an HTML file on disk.
  3. Unpack - tar xzf into the version prefix, then normalise names (libduckdb.dll -> duckdb.dll, headers into include/).
  4. Verify - load it and call duckdb_library_version(); only then write the .alientag marker. A library that fails to load (no VC++ runtime, glibc/musl mismatch) falls through to the source path.

Source path

  1. Fetch - git clone --depth 1 --branch v<version> from the DuckDB repo (falls back to the release tarball when git is unavailable). Submodules are initialised when the tag still has .gitmodules (1.x).
  2. Configure - CMake out-of-tree, Release, shell/unittests/benchmarks off, PIC on. Ninja is preferred, Makefiles are the fallback.
  3. Compile - <cores> parallel jobs (capped to keep memory sane).
  4. Harvest - copy the shared object into <prefix>/bin (Windows) or <prefix>/lib (POSIX), normalising libduckdb.dll -> duckdb.dll so consumers always load one canonical name; copy the headers and, on Windows, the import library.
  5. Verify - same smoke test as above, then the .alientag marker 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

Windows

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

variableeffect
ALIEN_LIBDUCKDB_VERSIONtarget a different upstream tag (e.g. 1.4.1)
ALIEN_LIBDUCKDB_ROOToverride the root that holds prebuilt/, src/, build/, <version>/
ALIEN_LIBDUCKDB_PREFIXoverride the install prefix entirely
ALIEN_LIBDUCKDB_PREBUILT0 disables the prebuilt path (always compile)
ALIEN_LIBDUCKDB_PREBUILT_ONLY1 forbids the source fallback: fail instead of compiling
ALIEN_LIBDUCKDB_SRCuse an existing DuckDB checkout instead of cloning
ALIEN_LIBDUCKDB_JOBSparallel compile jobs (default: CPU cores)
ALIEN_LIBDUCKDB_CC / _CXXforce a specific compiler
ALIEN_LIBDUCKDB_KEEP_SOURCEkeep 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 id

License

Artistic-2.0. DuckDB itself is MIT-licensed.