SKILL.md
DuckDB Extensions
Building .duckdb_extension files with CMake + FetchContent. The gotchas below all cost real debugging time.
Critical gotchas
- Exact version match: the extension MUST be built against the exact DuckDB version that will load it. Use FetchContent with a specific git tag (e.g.
v1.2.1), nevermain. Version strings need thevprefix (v1.2.1, not1.2.1) or loading fails with a version mismatch.
- Metadata append is REQUIRED: DuckDB rejects extensions without appended metadata ("The file is not a DuckDB extension. The metadata at the end of the file is invalid"). Add a POSTBUILD command running
${duckdbSOURCEDIR}/scripts/appendmetadata.cmake, andadddependencies(${TARGETNAME} duckdbplatform)— theduckdbplatformtarget generates theduckdbplatformoutfile the metadata step reads.
- Const binddata (DuckDB 1.1+):
binddatais const during execution ("increment of member in read-only object"). Put mutable state in aGlobalTableFunctionStatesubclass, register aninitglobal, and access it viainput.globalstate.
- Platform ABI mismatch: "built for platform 'linuxamd64', but we can only load extensions built for platform 'linuxamd64gcc4'" means the system DuckDB has a different ABI. Easiest fix: use the DuckDB binary from your own build at
build/release/deps/duckdb-build/duckdb.
- PIC: any static library linked into the shared extension needs
POSITIONINDEPENDENTCODE ON.
Deployment
- Auto-discovery install path:
~/.duckdb/extensions/v{version}/{platform}/(e.g.~/.duckdb/extensions/v1.2.1/linuxamd64/myextension.duckdbextension). - In
~/.duckdbrc,LOADmust come BEFORE anySETof extension-registered settings — the settings don't exist until the extension loads. - Unsigned (dev) extensions need
duckdb -unsigned. Use a wrapper script so it's never forgotten:
#!/bin/bash
# ~/.local/bin/duckdb (ahead of the real duckdb in PATH)
exec /path/to/actual/duckdb -unsigned "$@"
References
- Full CMakeLists template (static linking, metadata POST_BUILD, PIC/relocation troubleshooting):
reference-cmake.md - Entry-point and table-function C++ boilerplate, custom settings registration:
reference-cpp-patterns.md