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
参考:
動作確認
ビルドされた拡張は 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