Rand Stats

Alien::Libduckdb

zef:skyter10086

Alien::Libduckdb

Builds the DuckDB C library (libduckdb) from source 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.

Why build it ourselves

The DuckDB release assets are convenient but not portable enough for a Raku distribution that has to work on both Linux and Windows:

Building from a pinned upstream tag once, into a private prefix, removes all three problems. DuckDB 2.x vendors every third-party dependency in-tree, so a plain git clone + CMake is enough - no submodules, no vcpkg.

Install

zef install Alien-Libduckdb

This compiles DuckDB and therefore takes a few minutes (~5 min on 10 cores). The result is cached per upstream version; reinstalling the module does not rebuild unless the version changed.

To install the module but build later:

zef install Alien-Libduckdb --/build   # or ZEF_NO_BUILD=1

and then, whenever you want the library:

use Alien::Libduckdb;
ensure-installed();     # idempotent, builds only when missing

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 builds
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 a build matching version and platform present?
config()Hash with all of the above
cflags() / ldflags()flags for building against this prefix
ensure-installed()build on demand
build-from-source(:force, :clean, :jobs)explicit control

How it works

  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 - load the library and call duckdb_library_version(); write a .alientag marker with version/platform/build-id. installed() compares the marker against the current request, so a library built 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_VERSIONbuild a different upstream tag (e.g. 1.4.1)
ALIEN_LIBDUCKDB_ROOToverride the root that holds src/, build/, <version>/
ALIEN_LIBDUCKDB_PREFIXoverride the install prefix entirely
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
├── 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/               clone/configure/build logs of the last attempt
    └── .alientag           marker: version, platform, build id

License

Artistic-2.0. DuckDB itself is MIT-licensed.