🔨

duckdb-spatial などの DuckDB 拡張(C++)をビルドする時のメモ

に公開

duckdb-spatial にちょっとコントリビュートをしたかっただけなんですが、ビルドに手こずりまくったのでメモです。macOS と WSL(Ubuntu 24.04)ではこれでビルドできました。たぶん他の C++ 拡張でも同じだと思うので、参考になればと思いシェアします。

必要なものをインストール

vcpkg

duckdb の C++ 拡張は、依存ライブラリのインストールに vcpkg を使っています。extension-template の README に書かれている手順に従って vcpkg を導入します。

cd 適当な場所
git clone https://github.com/Microsoft/vcpkg.git
sh ./vcpkg/scripts/bootstrap.sh -disableMetrics
export VCPKG_TOOLCHAIN_PATH="$(pwd)/vcpkg/scripts/buildsystems/vcpkg.cmake"

ちなみに、vcpkg 公式の手順としては以下の環境変数も設定するようになっていたので、念のためこっちも設定しました。不要かも。

export VCPKG_ROOT="$(pwd)/vcpkg"
export PATH="$VCPKG_ROOT:$PATH"

CMake

CMake はビルドに必須なのでインストールします。

Ubuntu の場合は、build-essential に入ってますっけ...? 何でインストールしたかあんまり覚えてないですが、入ってなかったら sudo apt install cmake すればインストールできると思います。

# macOS
brew install cmake

# Ubuntu
sudo apt install cmake

ccache と ninja

なくても動きますが、extension-template の README の「Tips for speedy builds」というセクションで入れることをおすすめされているので入れます。

ccache はキャッシュサイズの設定とか色々あると思うんですけど、よくわからないのでいじっていません)

# macOS
brew install ccache ninja

# Ubuntu
sudo apt install ccache ninja-build

ビルド

clone してきて make debug するだけです。まずはレポジトリを clone します。サブモジュールがあるので git submodule の操作も必要です。

gh repo clone duckdb/duckdb-spatial
cd duckdb-spatial
git submodule update --init

あとは、さっきと別セッションであればまた環境変数を設定し、

export VCPKG_TOOLCHAIN_PATH=/path/to/vcpkg/scripts/buildsystems/vcpkg.cmake
export VCPKG_ROOT=/path/to/vcpkg
export PATH=$VCPKG_ROOT:$PATH

make debug します。 リリースビルドの方がよければ(後述)、make です。また、GEN=ninja をつけておけば速くなるということでそうします。

GEN=ninja make debug

WSL の場合

私の環境だと、WSL の場合は以下のエラーが出ました。どうやら、WSL にはメモリ割り当ての制限があり、デフォルトの 8GB(たぶん)だと足りなくて OOM が起こっているようです。

collect2: fatal error: ld terminated with signal 9 [Killed]

ということで、メモリを上げます。C:\Users\ユーザー名\.wslconfig に以下を書きます。私の場合は 16 GB あれば大丈夫でした。

[wsl2]
memory=16GB
swap=8GB

参考:

https://learn.microsoft.com/ja-jp/windows/wsl/wsl-config#example-wslconfig-file

動作確認

ビルドされた拡張は build/debug/extension/spatial/spatial.duckdb_extension にあるので、LOAD で読み込めます。

LOAD 'build/debug/extension/spatial/spatial.duckdb_extension';

ただし、C API の extension と違って、C++ extension は DuckDB を静的リンクしているので、完全に同じバージョンの DuckDB でしか動きません。もしリリース版の DuckDB で読み込もうとするとこういうエラーが出ます。

Invalid Input Error:
Failed to load 'build/debug/extension/spatial/spatial.duckdb_extension', 
The file was built specifically for DuckDB version 'e92be6795f' and can
only be loaded with that version of DuckDB. (this version of DuckDB is 
'v1.3.0')

ではどうするかというと、 build/debug/duckdb にそのバージョンの DuckDB がビルドされているのでこれを使います。-unsigned をつけなくてもデバッグ用の拡張を読み込めます。

build/debug/duckdb

テスト

DuckDB 拡張には、実行する SQL とその想定結果を書いておくとユニットテストができるという謎の仕組みがあります(どこに詳しいドキュメントがあるのか見つけられていません…)。動作はよくわからないのですが、test/sql 下にあるファイルを真似してこんな感じのを書くとテストができます。

require spatial

# Move a point of (1,1) by (2, 3) 
query I
SELECT ST_Affine(ST_Point(1, 1), 1, 0, 0, 0, 1, 0, 0, 0, 1, 2, 3, 0);
----
POINT (3 4)

テストの実行は make test_debug です。デバッグビルドのせいなのか、ちょっと時間がかかるみたいです。リリースビルドでテストしたい場合は make test_release でいけます。

make test_debug

テストがこけるとこういうメッセージが出ます。

Wrong result in query! (/path/to/duckdb-spatial/test/sql/geometry/st_area.test:9)!
================================================================================
SELECT ST_Affine(ST_Point(1, 1), 1, 0, 0, 0, 1, 0, 0, 0, 1, 2, 3, 0);
================================================================================
Mismatch on row 1, column st_affine(st_point(1, 1), 1, 0, 0, 0, 1, 0, 0, 0, 1, 2, 3, 0)(index 1)
POINT (4 1) <> POINT (3 4)
================================================================================
Expected result:
================================================================================
POINT (3 4)
================================================================================
Actual result:
================================================================================
POINT (4 1)

WSL の場合

私の環境では、WSL は以下のエラーになりました。これもメモリ不足とかなのかなあ(メモリ割り当てに失敗したけど適切にエラーになってなくて null pointer が渡されている、とか?)とおもったりするのですが、これ以上は私の知識では追えませんでした。

[0/97] (0%): ...geometry_serialization.cpp:103:9: runtime error: null
pointer passed as argument 2, which is declared to never be null
make: *** [extension-ci-tools/makefiles/duckdb_extension.Makefile:104:
 test_debug_internal] Error 1

解決策としては、リリースビルドだとエラーにならなかったです。

make test_release

Discussion