
duckdb-extensions
Building DuckDB loadable extensions with CMake, FetchContent, and proper metadata handling
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 POST_BUILD command running
${duckdb_SOURCE_DIR}/scripts/append_metadata.cmake, andadd_dependencies(${TARGET_NAME} duckdb_platform)— theduckdb_platformtarget generates theduckdb_platform_outfile the metadata step reads. -
Const bind_data (DuckDB 1.1+):
bind_datais const during execution ("increment of member in read-only object"). Put mutable state in aGlobalTableFunctionStatesubclass, register aninit_global, and access it viainput.global_state. -
Platform ABI mismatch: "built for platform 'linux_amd64', but we can only load extensions built for platform 'linux_amd64_gcc4'" 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
POSITION_INDEPENDENT_CODE ON.
Deployment
- Auto-discovery install path:
~/.duckdb/extensions/v{version}/{platform}/(e.g.~/.duckdb/extensions/v1.2.1/linux_amd64/myextension.duckdb_extension). - 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