-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
db4569a
commit 4891496
Showing
9 changed files
with
198 additions
and
46 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,29 +1,33 @@ | ||
cmake_minimum_required(VERSION 3.5...3.29) | ||
cmake_minimum_required(VERSION 2.8) | ||
|
||
set(CMAKE_CXX_STANDARD "11" CACHE STRING "C++ standard to enforce") | ||
|
||
### | ||
# Configuration | ||
### | ||
if(NOT DEFINED MINIMUM_DUCKDB_VERSION_MAJOR OR | ||
NOT DEFINED MINIMUM_DUCKDB_VERSION_MINOR OR | ||
NOT DEFINED MINIMUM_DUCKDB_VERSION_PATCH) | ||
message(FATAL_ERROR "DuckDB minimum version is required") | ||
Check failure on line 11 in CMakeLists.txt
|
||
endif() | ||
|
||
if(NOT DEFINED EXTENSION_NAME) | ||
message(FATAL_ERROR "DuckDB extension name is required") | ||
endif() | ||
|
||
project(${EXTENSION_NAME}) | ||
|
||
#message(FATAL_ERROR "-DDUCKDB_EXTENSION_API_VERSION_MAJOR=${MINIMUM_DUCKDB_VERSION_MINOR}") | ||
add_definitions(-DDUCKDB_EXTENSION_API_VERSION_MAJOR=${MINIMUM_DUCKDB_VERSION_MAJOR}) | ||
add_definitions(-DDUCKDB_EXTENSION_API_VERSION_MINOR=${MINIMUM_DUCKDB_VERSION_MINOR}) | ||
add_definitions(-DDUCKDB_EXTENSION_API_VERSION_PATCH=${MINIMUM_DUCKDB_VERSION_PATCH}) | ||
add_definitions(-DDUCKDB_EXTENSION_NAME=${EXTENSION_NAME}) | ||
|
||
### | ||
# Build | ||
### | ||
project(${EXTENSION_NAME}) | ||
|
||
set(EXTENSION_SOURCES | ||
src/add_numbers.cpp | ||
src/capi_quack.cpp | ||
) | ||
|
||
add_library(${EXTENSION_NAME} SHARED ${EXTENSION_SOURCES}) | ||
target_include_directories(${EXTENSION_NAME} PRIVATE src/include) | ||
target_include_directories(${EXTENSION_NAME} PRIVATE src/include) | ||
target_include_directories(${EXTENSION_NAME} PRIVATE duckdb_capi) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
# DuckDB C/C++ extension template | ||
This is an **experimental** template for C or C++ based extensions based on the C Extension API of DuckDB. Note that this | ||
is a different template from | ||
|
||
Features: | ||
- No DuckDB build required | ||
- CI/CD chain preconfigured | ||
- (Coming soon) Works with community extensions | ||
|
||
## Cloning | ||
Clone the repo with submodules | ||
|
||
```shell | ||
git clone --recurse-submodules <repo> | ||
``` | ||
|
||
## Dependencies | ||
In principle, compiling this template only requires a C/C++ toolchain. However, this template relies on some additional | ||
tooling to make life a little easier and to be able to share CI/CD infrastructure with extension templates for other languages: | ||
|
||
- Python3 | ||
- Python3-venv | ||
- [Make](https://www.gnu.org/software/make) | ||
- CMake | ||
- Git | ||
|
||
Installing these dependencies will vary per platform: | ||
- For Linux, these come generally pre-installed or are available through the distro-specific package manager. | ||
- For MacOS, [homebrew](https://formulae.brew.sh/). | ||
- For Windows, [chocolatey](https://community.chocolatey.org/). | ||
|
||
## Building | ||
After installing the dependencies, building is a two-step process. Firstly run: | ||
```shell | ||
make configure | ||
``` | ||
This will ensure a Python venv is set up with DuckDB and DuckDB's test runner installed. Additionally, depending on configuration, | ||
DuckDB will be used to determine the correct platform for which you are compiling. | ||
|
||
Then, to build the extension run: | ||
```shell | ||
make debug | ||
``` | ||
This delegates the build process to cargo, which will produce a shared library in `target/debug/<shared_lib_name>`. After this step, | ||
a script is run to transform the shared library into a loadable extension by appending a binary footer. The resulting extension is written | ||
to the `build/debug` directory. | ||
|
||
To create optimized release binaries, simply run `make release` instead. | ||
|
||
## Testing | ||
This extension uses the DuckDB Python client for testing. This should be automatically installed in the `make configure` step. | ||
The tests themselves are written in the SQLLogicTest format, just like most of DuckDB's tests. A sample test can be found in | ||
`test/sql/<extension_name>.test`. To run the tests using the *debug* build: | ||
|
||
```shell | ||
make test_debug | ||
``` | ||
|
||
or for the *release* build: | ||
```shell | ||
make test_release | ||
``` | ||
|
||
### Version switching | ||
Testing with different DuckDB versions is really simple: | ||
|
||
First, run | ||
``` | ||
make clean_all | ||
``` | ||
to ensure the previous `make configure` step is deleted. | ||
|
||
Then, run | ||
``` | ||
DUCKDB_TEST_VERSION=v1.1.2 make configure | ||
``` | ||
to select a different duckdb version to test with | ||
|
||
Finally, build and test with | ||
``` | ||
make debug | ||
make test_debug | ||
``` | ||
|
||
### Known issues | ||
This is a bit of a footgun, but the extensions produced by this template may (or may not) be broken on windows on python3.11 | ||
with the following error on extension load: | ||
```shell | ||
IO Error: Extension '<name>.duckdb_extension' could not be loaded: The specified module could not be found | ||
``` | ||
This was resolved by using python 3.12 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# DuckDB C API Headers | ||
This directory contains the C API headers of DuckDB. These headers should be of the same | ||
DuckDB version as is specified in `Makefile`. Note that these headers can be updated automatically | ||
to match the `MINIMUM_DUCKDB_VERSION` makefile variable by running (assuming the default makefile setup): | ||
|
||
```shell | ||
make update_duckdb_headers | ||
``` | ||
|
||
Of course manually updating the headers is also fine, just make sure that the headers are always from the same | ||
DuckDB version and that they are not from a later release of DuckDB than is specified in the `MINIMUM_DUCKDB_VERSION` | ||
build variable. Using headers from an older version than `MINIMUM_DUCKDB_VERSION` is allowed, but you probably don't want | ||
that. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
# Reusable makefile for the C/C++ extensions targeting the C extension API | ||
# | ||
# Inputs | ||
# EXTENSION_NAME : name of the extension (lower case) | ||
# EXTENSION_LIB_FILENAME : the library name that is produced by the build | ||
# MINIMUM_DUCKDB_VERSION : full version tag (including v) | ||
# MINIMUM_DUCKDB_VERSION_MAJOR : major version | ||
# MINIMUM_DUCKDB_VERSION_MINOR : minor version | ||
# MINIMUM_DUCKDB_VERSION_PATCH : patch version | ||
# CMAKE_EXTRA_BUILD_FLAGS : additional CMake flags to pass | ||
|
||
|
||
.PHONY: build_extension_library_debug build_extension_library_release update_duckdb_headers | ||
|
||
# Create build params to pass name and version | ||
CMAKE_VERSION_PARAMS = -DEXTENSION_NAME=$(EXTENSION_NAME) | ||
CMAKE_VERSION_PARAMS += -DMINIMUM_DUCKDB_VERSION=$(MINIMUM_DUCKDB_VERSION_MAJOR) | ||
CMAKE_VERSION_PARAMS += -DMINIMUM_DUCKDB_VERSION_MINOR=$(MINIMUM_DUCKDB_VERSION_MINOR) | ||
CMAKE_VERSION_PARAMS += -DMINIMUM_DUCKDB_VERSION_PATCH=$(MINIMUM_DUCKDB_VERSION_PATCH) | ||
|
||
CMAKE_BUILD_FLAGS = $(CMAKE_VERSION_PARAMS) $(CMAKE_EXTRA_BUILD_FLAGS) | ||
|
||
############################################# | ||
### Rust Build targets | ||
############################################# | ||
|
||
build_extension_library_debug: check_configure | ||
cmake $(CMAKE_BUILD_FLAGS) -DCMAKE_BUILD_TYPE=Debug -S $(PROJ_DIR) -B cmake_build/debug | ||
cmake --build cmake_build/debug --config Debug | ||
$(PYTHON_VENV_BIN) -c "from pathlib import Path;Path('./build/debug/extension/$(EXTENSION_NAME)').mkdir(parents=True, exist_ok=True)" | ||
$(PYTHON_VENV_BIN) -c "import shutil;shutil.copyfile('cmake_build/debug/$(EXTENSION_LIB_FILENAME)', 'build/debug/$(EXTENSION_LIB_FILENAME)')" | ||
|
||
build_extension_library_release: check_configure | ||
cmake $(CMAKE_BUILD_FLAGS) -DCMAKE_BUILD_TYPE=Release -S $(PROJ_DIR) -B cmake_build/release | ||
cmake --build cmake_build/release --config Release | ||
$(PYTHON_VENV_BIN) -c "from pathlib import Path;Path('./build/release/extension/$(EXTENSION_NAME)').mkdir(parents=True, exist_ok=True)" | ||
$(PYTHON_VENV_BIN) -c "import shutil;shutil.copyfile('cmake_build/release/$(EXTENSION_LIB_FILENAME)', 'build/release/$(EXTENSION_LIB_FILENAME)')" | ||
|
||
############################################# | ||
### Misc | ||
############################################# | ||
# TODO: switch this to use the $(MINIMUM_DUCKDB_VERSION) after v1.2.0 is released | ||
BASE_HEADER_URL=https://raw.githubusercontent.com/duckdb/duckdb/refs/heads/main/src/include | ||
DUCKDB_C_HEADER_URL=$(BASE_HEADER_URL)/duckdb.h | ||
DUCKDB_C_EXTENSION_HEADER_URL=$(BASE_HEADER_URL)/duckdb_extension.h | ||
|
||
update_duckdb_headers: | ||
$(PYTHON_VENV_BIN) -c "import urllib.request;urllib.request.urlretrieve('$(DUCKDB_C_HEADER_URL)', 'duckdb_capi/duckdb.h')" | ||
$(PYTHON_VENV_BIN) -c "import urllib.request;urllib.request.urlretrieve('$(DUCKDB_C_EXTENSION_HEADER_URL)', 'duckdb_capi/duckdb_extension.h')" | ||
|
||
clean_cmake: | ||
rm -rf cmake_build |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,18 @@ | ||
# name: test/sql/capi_quack.test | ||
# description: test capi_quack extension | ||
# group: [quack] | ||
# group: [capi_quack] | ||
|
||
# Before we load the extension, this will fail | ||
statement error | ||
SELECT capi_quack('Sam'); | ||
SELECT multiply_numbers_together(1,2); | ||
---- | ||
Catalog Error: Scalar Function with name capi_quack does not exist! | ||
Catalog Error: Scalar Function with name multiply_numbers_together does not exist! | ||
|
||
# Require statement will ensure the extension is loaded from now on | ||
require capi_quack | ||
|
||
require icu | ||
|
||
# Confirm the extension works | ||
query I | ||
SELECT * from capi_quack('Sam'); | ||
SELECT multiply_numbers_together(5,10) | ||
---- | ||
Capi Quack Sam 🐥 | ||
50 |