Contributing

May 22, 2026 · View on GitHub

Glad your are interested in this project. Here I'll share how I develop this library, hopefully it will be helpfull for you to get start.

Background

This repo has two crates: duckdb and libduckdb-sys, which libduckdb-sys is the original binding for duckdb-c-api and duckdb is an ergonomic wrapper on libduckdb-sys.

Most user should use duckdb, but our development may happen in both of these components.

Prerequisites

Required for buildtime_bindgen feature

When using the buildtime_bindgen feature, you need to have libclang installed on your system, as it's required by the bindgen crate to generate Rust bindings from C headers.

Linux (Debian/Ubuntu):

sudo apt-get update
sudo apt-get install -y libclang-dev

macOS:

brew install llvm

Windows: Install LLVM from llvm.org or use the installer, and ensure the binaries are in your PATH.

DuckDB Library and Header Setup

When using DUCKDB_LIB_DIR and DUCKDB_INCLUDE_DIR environment variables, ensure the following folder structure:

~/duckdb-lib/
├── duckdb.h          # Header file (must be directly in the directory, not in a subdirectory)
└── libduckdb.so      # Library file (or .dylib on macOS, .dll on Windows)

Important: The header file duckdb.h must be placed directly in the directory specified by DUCKDB_INCLUDE_DIR, not in a duckdb/ subdirectory. The build system expects the header at {DUCKDB_INCLUDE_DIR}/duckdb.h.

Development

duckdb-c-api

Some features are still not implemented in the c api, so we may need pull request in the duckdb repo.

# build duckdb
cd ~/github/
git clone git@github.com:duckdb/duckdb.git
cd duckdb
GEN=ninja make debug

Related logics:

After make the change, we can build the repo and use it in duckdb-rs by:

# export library and header file
cd ~/github/duckdb
mkdir ~/duckdb-lib

# Copy header and library to the same directory
# Note: duckdb.h must be directly in ~/duckdb-lib/, not in a subdirectory

# macOS:
cp src/include/duckdb.h build/debug/src/libduckdb.dylib ~/duckdb-lib/

# Linux:
cp src/include/duckdb.h build/debug/src/libduckdb.so ~/duckdb-lib/

# Windows:
cp src/include/duckdb.h build/debug/src/duckdb.dll ~/duckdb-lib/

# set lib dir
export DUCKDB_LIB_DIR=~/duckdb-lib

# set header dir (can be the same as LIB_DIR)
export DUCKDB_INCLUDE_DIR=~/duckdb-lib

libduckdb-sys

Use the exported library and header:

# Ensure environment variables are set
export DUCKDB_LIB_DIR=~/duckdb-lib
export DUCKDB_INCLUDE_DIR=~/duckdb-lib

cd ~/github/duckdb-rs/crates/libduckdb-sys
cargo test --features buildtime_bindgen

Note: Make sure libclang is installed (see Prerequisites section above) when using the buildtime_bindgen feature.

Use the bundled header file:

cd ~/github/duckdb-rs/crates/libduckdb-sys
cargo test --features bundled

Currently in github actions, we always use the bundled file for testing. So if you change the header in duckdb-cpp repo, you need to make the PR merged and updated the duckdb-sources submodule. You can generated the amalgamated file by:

cd ~/github/duckdb
mkdir -p build/amaldebug
python scripts/amalgamation.py
cp src/amalgamation/duckdb.cpp src/include/duckdb.h src/amalgamation/duckdb.hpp ../duckdb-rs/crates/libduckdb-sys/duckdb-sources/

duckdb-rs

Use the exported library and header:

# Ensure environment variables are set
export DUCKDB_LIB_DIR=~/duckdb-lib
export DUCKDB_INCLUDE_DIR=~/duckdb-lib

cd ~/github/duckdb-rs/
cargo test --features buildtime_bindgen -- --nocapture

Note: Make sure libclang is installed (see Prerequisites section above) when using the buildtime_bindgen feature.

Use the bundled header file:

cd ~/github/duckdb-rs
cargo test --features bundled -- --nocapture

Detect memory leaks:

cd ~/github/duckdb-rs
ASAN_OPTIONS=detect_leaks=1 ASAN_SYMBOLIZER_PATH=/usr/local/opt/llvm/bin/llvm-symbolizer cargo test --features bundled -- --nocapture

Update to a new version

When DuckDB releases a new version, duckdb-rs needs a matching release.

Use the top-level upgrade script for DuckDB version updates:

./upgrade.sh

This updates the workspace crate version, the exact workspace dependency pins that keep sibling crates in lockstep, README Cargo.toml examples, and DuckDB version references such as workflow tags and README download URLs. It then calls ./crates/libduckdb-sys/upgrade.sh to regenerate bindings.

DuckDB's C API may occasionally have breaking changes, so version updates may also require code fixes.

For a duckdb-rs patch release that does not change the bundled DuckDB version:

./upgrade.sh --patch

Patch releases only update crate versions, exact workspace dependency pins, README Cargo.toml examples, and Cargo.lock. They do not update the DuckDB submodule, generated bindings, or DuckDB download tags.