LibToolingを使ってツールを作ってみよう

もう1月半分過ぎたのか…!

LLVM IR生成のライブラリがLibToolingにあるみたいだったので,使ってみることにしました.

homebrewで入れたのだとビルドし直すのどうしたらいいかわからなくなったので,環境構築やり直すことにしました….
環境構築はこれで最後にしたい!

前入ってたのを消す.

% brew uninstall llvm


(こっから先は本に載ってた通りにやっただけ)
ソースコード取得してきて正しいディレクトリに配置.

% mkdir ~/llvm34    
% cd ~/llvm34
% svn co http://llvm.org/svn/llvm-project/llvm/tags/REREASE_34/final llvm
% cd ~/llvm34/llvm/tools
% svn co http://llvm.org/svn/llvm-project/cfe/tags/REREASE_34/final clang
% cd ~/llvm34/llvm/projects
% svn co http://llvm.org/svn/llvm-project/compiler-rt/tags/REREASE_34/final compiler-rt

CMakeでビルド

% mkdir ~/llvm34/build_ninja
% cd ~/llvm34/build_ninja
% cmake -G Ninja ../llvm
% ninja

.zshrcにPATH設定

これで環境構築はできました.makeに比べてninja早かったです.

ツールを作ってみる

さて,本題のLibToolingを使ったツールを作ってみます.

Tutorial for building tools using LibTooling and LibASTMatchers — Clang 3.4 documentation

このページの Step 1: Create a ClangTool に沿ってやりました.

% cd ~/llvm34/llvm/tools/clang
% mkdir tools/extra/loop-convert
% echo 'add_subdirectory(loop-convert)' >> tools/extra/CMakeLists.txt

/llvm34/llvm/tools/clang/tools/extra/CMakeLists.txt に

add_subdirectory(tool-template) 

が追加される.
これで追加したloop-convertディレクトリのソースコードもビルドするように指定している.

次に,CMakeLists.txtを作る

% vim tools/extra/loop-convert/CMakeLists.txt

CMakeLists.txtの中身は,

set(LLVM_LINK_COMPONENTS support)
set(LLVM_USED_LIBS clangTooling clangBasic clangAST)

add_clang_executable(loop-convert
  LoopConvert.cpp
  )
target_link_libraries(loop-convert
  clangTooling
  clangBasic
  clangASTMatchers
  )

最後に,tools/extra/loop-convert/LoopConvert.cppを作る.

// Declares clang::SyntaxOnlyAction.
#include "clang/Frontend/FrontendActions.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
// Declares llvm::cl::extrahelp.
#include "llvm/Support/CommandLine.h"

using namespace clang::tooling;
using namespace llvm;

// CommonOptionsParser declares HelpMessage with a description of the common
// command-line options related to the compilation database and input files.
// It's nice to have this help message in all tools.
static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);

// A help message for this specific tool can be added afterwards.
static cl::extrahelp MoreHelp("\nMore help text...");

int main(int argc, const char **argv) {
  CommonOptionsParser OptionsParser(argc, argv);
  ClangTool Tool(OptionsParser.getCompilations(),
                 OptionsParser.getSourcePathList());
  return Tool.run(newFrontendActionFactory<clang::SyntaxOnlyAction>());
}

で,ビルドディレクトリにいって,ビルドする.

 % cd ~/build_ninja/build
 % ninja

これで,llvm34/build_ninja/binにloop-convertが追加されている.
作ったツールが使えるようになりました!
使ってみます.

% cat "int main() { return 0; }" > test.cpp
% bin/loop-convert test.cpp --

上のコマンドって何を表してるんだろう…?
エラー出たけど,test.cppに書き込んでるという認識でいいのかな….

使えてるのか……?

とりあえず,こんなかんじでCMakeFile作ってビルドすればいいんだなということはわかりました。


おまけ

今回使いたかったのはLibToolingですが,前回試したlibClangのpython bindingも使ってみました.

PYTHONPATHとLD_LIBRARY_PATHを設定

% export PYTHONPATH=~/llvm34/llvm/tools/clang/bindings/python 
% export LD_LIBRARY_PATH=$(llvm-config --libdir):$LD_LIBRARY_PATH

これで,無事うまくいきました.