c2ffiとは
C言語のバインディングを作成していると、CやC++のヘッダーファイルを自動的に解析してくれるツールがあったらなと思うことがあります。c2ffiはLLVMを利用したツールで、CやC++のヘッダーファイルを解析して、メタデータのjsonファイルを作成してくれる便利なツールです。
この記事ではc2ffiをUbuntuでc2ffiを利用するまでに行った手順を記録しています。
ソースコードを入手する
git clone https://github.com/rpav/c2ffi
LLVMのバージョンに合わせてブランチを切り替えます。ここではUbunutu groovyの配布しているパッケージのLLVMはversion11であるため、11に切り替えます。
sudo apt install llvm-dev libclang-dev
git branch -a # ブランチ一覧を表示
git checkout -b llvm-10.0.0 refs/remotes/origin/llvm-10.0.0
cmake(3.17〜)のインストール
ここで、公式READMEの言うとおりに、build
ディレクトリを作って cmake ..
を実行するとcmakeが古いと言われました。
mkdir build
cd build
cmake ..
エラーが発生する
CMake Error at CMakeLists.txt:1 (cmake_minimum_required):
CMake 3.17 or higher is required. You are running version 3.16.3
-- Configuring incomplete, errors occurred!
そこで、仕方ないのでcmakeの最新版をインストールします。
cd ../../ # c2ffiのディレクトリの外へ
git clone https://github.com/Kitware/CMake
cd CMake
git checkout -b v3.19.2 refs/tags/v3.19.2 # 最新のリリース版
./bootstrap && make # -j8
数分待ちます。
CMakeは恐らく色々なツールで使われるので、あとからトラブルになる可能性も十分にあります。あとから簡単にアンインストールできるようにmake install
ではなくcheckinstall
しておきます。
sudo checkinstall
適当にオプションとかを修正してインストールします。cmakeが大きいので、この工程もそこそこ時間がかかります。終わったら一旦シェルを起動し直すとcmakeが使えるようになります。cmakeが使えるか確認します。
# シェルの再起動
cmake --version
# cmake version 3.19.2
最新版のCMakeがインストールされました。c2ffiのディレクトリに戻ります。
cd ../c2ffi
makeする時に環境変数の設定が必要
今度こそうまくいくかとおもいきや
cd build
cmake .. # cmake -DBUILD_CONFIG=Release ..
make # -j8
/usr/bin/ld: -lclang-cpp が見つかりません
というエラーメッセージが出ます。
sudo apt install libclang-cpp10-dev
をして、以下のissueを参考に
LIBRARY_PATH=/usr/lib/llvm-11/lib/ make
とします。これで最後までいきました。このissueの記事を読むと、Macでも別の環境変数が必要になる場合があるようです。
checkinstallします。そのままだとSummaryやNameが正しく指定されないと思うので、c2ffiに書き直します。
sudo checkinstall
こちらはすぐに終了します。c2ffi
とタイプして、c2ffiが正しく使えるか試してみましょう。
c2ffi: unrecognized option '--version'
Usage: c2ffi [options ...] FILE
Options:
-I, --include Add a "LOCAL" include path
-i, --sys-include Add a <system> include path
-D, --driver Specify an output driver (default: json)
-o, --output Specify an output file (default: stdout)
-M, --macro-file Specify a file for macro definition output
--with-macro-defs Also include #defines for macro definitions
-N, --namespace Specify target namespace/package/etc
-A, --arch Specify the target triple for LLVM
(default: x86_64-pc-linux-gnu)
-x, --lang Specify language (c, c++, objc, objc++)
--std Specify the standard (c99, c++0x, c++11, ...)
-E Preprocessed output only, a la clang -E
このように表示されればOKだと思います。
あとはc2ffiをバインディング作成のお供に使っていきましょう。
公式ではcommon-lispとRuby用のバインディグ生成ツールを提供していますが、Rubyの方は古いので今でも動くかどうかはわかりません。
この記事は以上です。