# Alien-Libduckdb **Repository Path**: skyter10086/Alien-Libduckdb ## Basic Information - **Project Name**: Alien-Libduckdb - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-10-26 - **Last Updated**: 2026-10-26 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Alien::Libduckdb Installs the [DuckDB](https://duckdb.org) 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`](https://gitee.com/skyter10086/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--.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.so` with no `RUNPATH`, so a binding either needs `LD_LIBRARY_PATH` or a system-wide install; * Windows MinGW builds emit `libduckdb.dll`, MSVC builds emit `duckdb.dll`, and both need the import library next to them for downstream linking; * the headers must match the shared object exactly - mismatched `duckdb.h` is 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 ```sh 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: ```sh zef install Alien-Libduckdb --/build # or ZEF_NO_BUILD=1 ``` and then, whenever you want the library: ```raku use Alien::Libduckdb; ensure-installed(); # idempotent, prebuilt first, source if needed ``` Force a compile even when a prebuilt archive is available: ```sh ALIEN_LIBDUCKDB_PREBUILT=0 zef install Alien-Libduckdb ``` ## Usage ```raku 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** 1. **Resolve** - map OS/arch to `duckdb-shared-libs--.tar.gz` in the `v` GitHub release; an asset that does not exist for this platform ends the path immediately. 2. **Fetch** - `curl -fL` (`wget` as fallback) into `/prebuilt/`, 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` 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** - `` parallel jobs (capped to keep memory sane). 4. **Harvest** - copy the shared object into `/bin` (Windows) or `/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 * Prebuilt path needs only `curl` (or `wget`) and `tar`. * Source path additionally needs `cmake`, `ninja` (or `make`), `g++` (GCC 11+ works, Clang too) and `git`. * The prebuilt `libduckdb.so` is 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//lib`, honouring `XDG_DATA_HOME`. * `ldflags()` adds `-Wl,-rpath,` so binaries linked against the prefix do not need `LD_LIBRARY_PATH`. ### Windows * Prebuilt path needs only `curl` (or `wget`) and `tar`; 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`) - emits `libduckdb.dll`, which this module renames to `duckdb.dll` on install; * MSVC - emits `duckdb.dll` and `duckdb.lib`, both installed. * Default prefix: `%LOCALAPPDATA%\Alien-Libduckdb\`. * `Path` is looked up case-insensitively on Windows (`%*ENV` is not always populated by Rakudo there), so `cmake`/`ninja` from `PATH` are 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/`, `/` | | `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 ``` / %LOCALAPPDATA%\Alien-Libduckdb or ~/.local/share/Alien-Libduckdb ├── prebuilt/duckdb-/ downloaded archive + staging area ├── src/duckdb-/ source checkout (removed after success) ├── build/duckdb-/ CMake build tree └── / 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.