non vorrei lavorare

ブログ名の通りです。javascript three.js mruby rust OCaml golang julialang blender

Windows(MSVC)でplv8をビルドするまで

おはようございます。ちょっと前の事になりますが、休日になると体調を崩す次男でしたが、長男が習い事をしているのに、自分が何もしていないことに不満を覚え、そんな精神面からの体調不要だったのかと振り返ってみると思えます。そんな訳でで、昨日は次男も習い始めた習い事の教室へ長男とともに行きました。kjunichiです。

TL;DR

  • nugetコマンドを利用可能にする
  • CMakeコマンドを利用可能にする(choco install cmake)
  • plv8のMSVC版をクローン
git clone https://github.com/kjunichi/plv8.git
cd plv8
git checkout support-msvc
  • PostgreSQL本体のヘッダ(generic-msvc.h)を修正()
patch -u < generic-msvc.h.patch
  • MSVC環境下でcmakeでビルド
bootstrap.bat
cmake . -G "Visual Studio 14 2015 Win64" -DCMAKE_INSTALL_PREFIX="C:\Program Files\PostgreSQL\9.6" -DPOSTGRESQL_VERSION=9.6
cmake --build . --config Release --target Package
  • 出来たZipを解凍して中身をPostgreSQLのインストール先にコピー

背景

MSVCでPostgreSQLのビルドまでは前回の記事で出来ている。 すっかり忘れていたが、思い抱いたのでやってみることにした。

調査

WinodwsのPostgreSQL向けにplv8のバイナリを配っているサイトで解説ページを発見。

概略

上記のサイトによると、MSVCで動かすのだが、PostgreSQL含めてMingw環境でビルドして、最終的に出来上がったDLLを使うというもの。 これは、主に、Unix系のPostgreSQL向けのエコシステムが前提となているビルドシステムPGXN上でビルドしている為の模様。

V8はDLLだけっぽいからMSVCでも行けそうな気がしてしまった。(これが後でダメだと分かるのだが。。)

make staticでエラー

とりあえず、手元のMsys2?環境で64ビット向けにビルドを試みた。

PostgreSQL9.6の最新版のソースをドキドキしながらビルドしたが、あっさり成功してしまった。

しかし、plv8の最新リリース版を

make static

とREADME通りにビルドしたら、エラー。

v8のコードをgithubからクローンした後のv8のビルドツールninja周りが、Windows固有のセットアップが必要な 模様で、その辺でエラーとなってしまった。

V8を自前でビル

それではということで、MSVC環境で、plv8が要求しているバージョンのV8をビルドすることにした。

plv8が要求しているV8のバージョンは以下。

 to build the later versions of PL/v8 you need a v8 minimum version of 4.4.63.31

V8をMSVCでビルドする作戦に

dllとヘッダしか資料によると必要なさそうだったので、MSVCでのビルドを試みた

色々、あったが、結果的には不要な作業なので、自分用のメモとして 書くだけにしておく。

set DEPOT_TOOLS_WIN_TOOLCHAIN=0
set GYP_MSVS_VERSION=2015

slnファイルが作られない

このページを参考になんとか進めた。

必要だったもの

plv8本体をビルド

plv8のMakefileを直接編集してビルドしたV8の各種パスを設定した。

V8_OUTDIR = /C/Users/kjunichi/Documents/work/build/v8/out/Default
V8_SRCDIR = /C/Users/kjw_j/Documents/work/build/v8  
make 

C++の構文エラー的なものがゾロゾロ出て来た。

謎のC++エラーとの戦い

これはそこそこ長かったので、前回の記事にまとめた。

原因はPostgreSQLの内部でopenを定義していたのが原因だった

残念!リンクでシンボル参照エラー

openの定義を途中でundefして遂にすべてのコードをコンパイルが通った! しかし、V8の関数のシンボルらしものが、軒並みシンボル参照未解決となってしまった。

そういえば、Cはstdcallとかccallを合わせる程度でABI互換だけど、C++は全く互換性がcl.exeとg++.exeにはないというような 話を思い出した。。。

C++なdllはそもそもMinGWと互換性ないのでは疑惑

上記の懸念を確認すべく、そもそもビルドしたV8が使えないのかどうかを、MSVCの処理系で確認することにした。

cl.exeでhello-worldはビルド出来た。

hello-world.ccが動かない!

ninjaでのビルドしたexeは動くが 自前でcl.exeコマンドでビルドするとだめ

原因?

環境変数LIBにV8のビルド結果のパスを指定していたのが原因っぽい。 必要な.dll.libファイルのみをフルパス指定することで解決した。

補足

にあるように、ちょっと前のNode.jsのセキュリティ問題に関連するのかもな スナップショットイメージファイルを2つカレントに置くこともお忘れなく。

ということで、V8自体は問題なさそうで、MSVCでビルドしている為に、gccでリンクが出来ない可能性が高まった。

ただ、このスナップショットイメージを使うV8は今回は動かしていない。。。 plv8がどこのカレントディレクトリで動いているかが分からず、PostgreSQL配下のbinやlibに置いては見たが、いずれもダメだった。

MSVCでplv8のビルドを試みる

もともと、MSVCでPostgresをビルドしたのも、MSVC環境で機能拡張をビルドする環境の 下準備をしていたわけで、MinGW作戦を諦め、当初の作戦にもどってさらに進めることにした。

contribフォルダに入れてビルドしてみた

前述のページによると、PostgreSQLのソースツリーがあれば、そこに置けば、ビルドできんじゃね?的な記述を見かけたので、 試してみたが、

plv8.sqlに必要なplv8.sql.inがないというエラーが出たので、 plv8.sql.commonをplv8.sqlにリネームしたら動き出した。

releaseフォルダ内にplv8フォルダができるが、 dllは作成されない。

ということで、早々に諦めて、明示的にCMakeでビルドする作戦に移った。

CMakeでのビルド

cmake . -G "Visual Studio 14 2015 Win64"  -DCMAKE_INSTALL_PREFIX="C:\Program Files\PostgreSQL\9.6" -DPOSTGRESQL_VERSION=9.6
cmake --build . --config Release

PostgreSQL本体のヘッダの修正

  • generic-msvc.h

手動インストール

sqlを以下のフォルダにコピー

C:\Program Files\PostgreSQL\9.6\share\extension

DLLの中身がない問題

どうやらエクスポートされていない

plv8のコードを修正

PG_FUNCTION_INFO_V1の手前に宣言文を移動して対応

PGDLLEXPORT Datum plv8_call_handler(PG_FUNCTION_ARGS);
PGDLLEXPORT Datum plv8_call_validator(PG_FUNCTION_ARGS);
PGDLLEXPORT Datum plcoffee_call_handler(PG_FUNCTION_ARGS);
PGDLLEXPORT Datum plcoffee_call_validator(PG_FUNCTION_ARGS);
PGDLLEXPORT Datum plls_call_handler(PG_FUNCTION_ARGS);
PGDLLEXPORT Datum plls_call_validator(PG_FUNCTION_ARGS);

PG_FUNCTION_INFO_V1(plv8_call_handler);
PG_FUNCTION_INFO_V1(plv8_call_validator);
PG_FUNCTION_INFO_V1(plcoffee_call_handler);
PG_FUNCTION_INFO_V1(plcoffee_call_validator);
PG_FUNCTION_INFO_V1(plls_call_handler);
PG_FUNCTION_INFO_V1(plls_call_validator);

_PG_initも必要だった

PGDLLEXPORT void _PG_init(void);

スナップショットが不要な版を導入

自前でビルドしたV8だとスナップショットを使おうとして、そこで落ちてしまったので、 ダメもとで、NugetからV8をplv8で要求している版に合うものを選んで落とした。

nuget install v8-v140-x64 -Version 5.8.283.38

結果

動いた!

まとめ

PostgreSQL9.6向けのplv8をWindows環境でもビルド出来た。 バイナリ配布しているものは1系のモノなので、2系のものが出来たので、 それなりにこの記事の価値は高いのではと自己満足気味w。

一応、日本語で記事書くだけではもったいないので、本家へもプルリク出してます。

関連記事