はじめに
あんまりまとまった日本語のドキュメントが見つけられなかったので、自分用のメモも兼ねて書いてみます。
公式リファレンスがいまいち探しにくいので、リンクもできるだけ貼るようにします。
何をするツールなのか
C++用のコマンドラインビルドツールです。
Makeみたいなものです。
MakeよりもC++のソースファイルのビルドに特化しているので記述量が少なく簡単に書けます。
何が便利なのか
ちょこっとプログラムを書いて、ちょこっとテストしてみるのが、すっごい便利です。
つまり、テストを書きながら開発していく(TDD)ときにとても便利です。
例えれば、PHPやRubyくらいお手軽です。
xcodeやVisual Studioでプロジェクト作ってごにょごにょするよりずっと簡単!
(Gitやコマンドラインに慣れていれば)
準備する
Boost C++ Library ( http://www.boost.org/ )のソースをダウンロードしてきて展開するか、GitHubからクローンしてくると使えるようになります。
./bootstrap.sh みたいなシェルを実行すると、bjamとb2が生成され準備完了です。
ライブラリは必要に応じて勝手にビルドされるので、あらかじめビルドしておく必要はありません。
環境変数BOOST_ROOTにBoost C++ Libraryを展開したディレクトリーを設定しておくと何かと便利です。
環境変数PATHにbjamとb2が実行でいるようにディレクトリーを追加しておきましょう。
使ってみる
Hello world をビルドしてみる
適当なプログラムを作り、プロジェクトファイルとしてJamroot.jamを作ります。
(Jamroot.jamはいくつか名前があり、例えば拡張子がないJamrootでも大丈夫です)
#include <iostream>
using namespace std;
int main()
{
cout << "Hello world" << endl;
return 0;
}
exe hello_world : hello_world.cpp ;
コマンドラインから
./b2
と実行すれば、ビルドが完了しbin/以下に実行ファイルができます。
注意点として、セミコロンやコロンのまわりにはスペースや改行が必要です。
これは他のプログラミング言語とは異なりますので注意してください。
このあたりに書いてあります。
http://www.boost.org/boost-build2/doc/html/bbv2/tasks.html#bbv2.tasks.programs
Hello worldをTDDしてみる
ビルドしてみるだけだと、Makeでも簡単だし何も面白くありません。
ビルドと同じくらい簡単にテストが実行ができるのがいいところです。
Jamroot.jamを書き直してみます。
import testing ;
unit-test hello_world : hello_world.cpp ;
これで
./b2
と実行すると、ビルドとテスト実行が同時にできています。
ここでいうテストとは、プロセスの終了コードが0(正常終了)か0以外(異常終了)かを見ています。
以下のように書くと、さらに記述量を減らせて便利です。普段はこっちを使います。
import testing ;
run hello_world.cpp ;
リファレンスではここを参照です。
http://www.boost.org/boost-build2/doc/html/bbv2/builtins/testing.html
複数のテストを実行したいとき
いくつか方法はありますが、単純に並べて書くこともできます。
import testing ;
run test1.cpp ;
run test2.cpp ;
run test3.cpp ;
run test4.cpp ;
フォルダー内のファイルを自動的にビルドしてテスト実行するなんてこともできます。
import testing ;
for f in [ glob *.cpp ]
{
run $(f) ;
}
このあたりは普通のスクリプト言語のように自由にできます。
forやifなど言語構造に関することはこちらに書いてあります。
ソースファイルが複数あるとき
ファイルを並べればOKです。
import testing ;
run main.cpp
source1.cpp
source2.cpp
;
もしやりたければ、 glob
などでファイルのリストを作って渡すこともできます。
インクルードパスを指定するには
例えば、ソースはsrc/フォルダーに、インクルードファイルはinclude/以下にあるというプロジェクトもあると思います。そんな場合はインクルードパスを指定すればOKです。
import testing ;
run src/main.cpp
src/source1.cpp
src/source2.cpp
:
:
:
<include>include
;
環境変数からインクルードパスを取得するには
os.environで環境変数にアクセスできます。
import testing ;
import os ;
local BOOST_ROOT = [ os.environ BOOST_ROOT ] ;
run src/main.cpp
src/source1.cpp
src/source2.cpp
:
:
:
<include>$(BOOST_ROOT)
;
リファレンスだとここに書いてあります。
http://www.boost.org/boost-build2/doc/html/bbv2/faq/envar.html
Boostライブラリーとリンクするには
Boostのように、Boost.Buildで管理されているプロジェクトであればとても簡単です。
以下の例を見てください。
import testing ;
import os ;
use-project /boost : [ os.environ BOOST_ROOT ] ;
run hello_world.cpp /boost/system ;
ここで私が最初わからなかったのは、use-projectに何を指定すればよいのかと、/boost/systemとは何か、なぜ/boostではないのかです。
一応この辺を何回も読めばさらっと書いてあるような気もしますが
http://www.boost.org/boost-build2/doc/html/bbv2/tutorial/hierarchy.html
結構大事なことなのにわかりにくいです。
まず、use-projectでJamroot(またはJamfile)のあるフォルダーへのエイリアスを作り、そこからたどっていきます。
この例だと /boost にはJamrootがあります。
そのなかでいくつかサブプロジェクトが定義されており、/boost/systemはサブプロジェクトの名前になります。
プロジェクトを指定するだけではなく、さらにプロジェクトの中のライブラリ名まで明示したいような場合は、//で区切って名前を書きます。
例えば以下のような感じです。
import testing ;
import os ;
use-project /boost : [ os.environ BOOST_ROOT ] ;
run hello_world.cpp /boost/system//boost_system ;
逆に、他の人が書いたプロジェクトファイルを調べたいときは、
まず、use-projectされている先にJamrootかJamfileがあるのでそこを見ます。
次に、もし/boost/systemのようにサブプロジェクトが使われている場合は、Jamrootの中のサブプロジェクトの定義(エイリアス)を探すか、あるいはフォルダ階層を探します。
//が指定されている場合は、さらにライブラリーなどのターゲットが明示的に指定されています。
外部ライブラリーとリンクするには
例として、Google Testを利用してみます。
まずはGoogle Testのソースコードを vendor/gtest/google-test/
の中に展開します。
Google TestをビルドするためのJamfileを作ります。
lib gtest
:
googletest/src/gtest-all.cc
:
<include>googletest/include
<include>googletest
<link>static
:
:
<include>googletest/include
;
それをJamrootからuse-projectして利用します。
import testing ;
import os ;
use-project /boost : [ os.environ BOOST_ROOT ] ;
use-project /gtest : vendor/gtest ;
run hello_world.cpp /boost/system /gtest ;
工夫としては、外部のライブラリーの中にプロジェクトファイルを置くのは嫌だったので、ひとつフォルダーを入れてそこにプロジェクトファイルを置いたことですね。
まとめると
Boost.Buildはとても短い記述でビルドからテスト実行まで面倒をみてくれるのでとても便利です。
コマンドラインツールだから小回りもきくし、Jenkinsとの相性も良いです。
みなさん、もっとbjam使いましょう! ← 言いたかったこと
もっと詳しく知るには
以下に参考になるサイトを書いておきます。