Boost.Build v2 (bjam) についていくつか

以下の話は全て Boost.Build v2 の話. v1 の話はしない.時間がないのでちょー箇条書き.
以下, Boost のソースツリーのルートを BOOST_ROOT と書く.

bjam を動かすために

bjam を動かすための設定方法はいくつかあるけれど

が恐らく一番楽.

v1 と v2

bjam のコマンドはデフォルトで v2 なモードで動作する.ただし $(BOOST_ROOT) 以下でのみ,デフォルトで v1 なモードで動作する. $(BOOST_ROOT) 以下で v2 として bjam を動かしたければ bjam に --v2 オプションを指定する.

モジュールのヘルプ

Boost.Build v2 には標準でいくつかのモジュールが用意されている. bjam --help (モジュール名) で各モジュールのヘルプが参照できる(これで出力されるヘルプは Boost.Build v2 のモジュールのソースに埋め込まれたもの).例えば次のとおり.

bjam --help path

この例では path モジュールのヘルプを出力する.そのほか,詳しいヘルプの出力については

bjam --help

というコマンドを参照.
昔,面白そうなモジュールについて調べた結果が
http://d.hatena.ne.jp/Cryolite/01001215
http://d.hatena.ne.jp/Cryolite/01001214
http://d.hatena.ne.jp/Cryolite/01001213
に放置してあります.
後,昔自分が書いた bjam のモジュールのヘルプをちょーてけとーに整形するための Ruby スクリプトを発掘したのでおいておきます.
http://park7.wakwak.com/~cryolite/hatena/cpp/format_help.rb
使い方は

です. Windows な環境でしか動作しないはずです.すいません.終わり.

Boost のライブラリの引っ張り方(必要なライブラリを Boost.Build v2 でソースから直接ビルドする)

pre-build な Boost のライブラリ(つまり,普通一般に「Boost をビルドする」と呼ばれている方法でビルドしたライブラリファイル)を引っ張る方法と,(Boost を使う)自分のライブラリのビルドプロセスに Boost のライブラリのビルドプロセスを直接組み込む方法の2種類あるけれど,ここでは後者の方法を簡単に紹介.
以下では BOOST_ROOT という環境変数に, Boost のソースツリーのルートへの絶対パスが設定されていると仮定.

import modules ; # modules モジュールをインポート
import testing ;

boost-root = [ modules.peek : BOOST_ROOT ] ; # 環境変数 BOOST_ROOT の値を取得
boost-root = [ path.make $(boost-root) ] ; # パスを正規化

use-project /boost : $(boost-root) ; # 以下, /boost というエイリアスを使って
                                     # Boost 以下のターゲットにアクセスできる

project my
  : requirements
    <define>BOOST_ALL_NO_LIB     # 下記参照
    <include>$(boost-root)       # Boost のディレクトリをインクルードパスに含める
  ;

run hello.cpp                                  # run ルールについては下記参照
    /boost/test//boost_unit_test_framework     # boost_unit_test_framework ライブラリを直接引っ張ってくる
  ;

rigarash さんに指摘していただいた個所を修正.しかし,なんでこんな間違いをしたのやら…….
注意がいくつか.

  • Boost のライブラリのビルドは $(BOOST_ROOT) 以下で行われるので,$(BOOST_ROOT) 以下に対する適切な(書き込み)アクセス許可を設定しておくこと
  • BOOST_ALL_NO_LIB を忘れないこと.これを忘れると auto_link が利用できるツール(MSVC など)でリンク時にエラーが起きる(auto_link で引っ張ってこられたライブラリと衝突する).

手続き的挙動と宣言的挙動の同居

jamfile では手続き的な書き方と,宣言的なターゲットのビルドが同居する.

import path ;
import testing ;

for local i in [ path.glob test : *_ut.cpp ]
{
  run $(i)
      /boost/test//boost_unit_test_framework
    ;
}

上の例は, test というフォルダにあって "*_ut.cpp" というパタンにマッチする全てのファイルに対して run ルールを実行する.このため, test フォルダに *_ut.cpp なファイルを追加するだけでビルドプロセスにテストが自動で追加される.上の構文の解釈は,まず最初の段階(parsing phase と呼ばれる)で手続き的に for 文が実行されて, test フォルダにある *_ut.cpp なファイルに対して各々 run ルールによるターゲットが宣言される.次の段階で生成されたターゲットに対して(依存関係に基づいて)実際にターゲットのビルドが走る.

explicit

ターゲットはデフォルトで全て all ターゲット(デフォルトのターゲット)に依存される.この暗黙の依存関係を設定したくなければ explicit をターゲットに指定する.

exe hello
  : hello.cpp
  ;
explicit hello ; # hello ターゲットは暗黙ではビルドされない

これによって hello ターゲットは

bjam hello

と明示的にターゲットを指定しない限りビルドされない.

run, run-fail, compile, compile-fail

これらを使うには testing モジュールのインポートが必要.

import testing ;

run, run-fail, compile, compile-fail はそれぞれ以下のような感じ.

run sources
  : argument
  : input-file
  : requirements
  : target-name
  : default-build
  ;

argument は実行するプログラムに与える引数. input-file にファイル指定すると,そのファイルにターゲットが依存する.つまり input-file に指定されたファイルが変更されると,ターゲットも更新される(つまりプログラムが実行される). requirements と default-build は普通の requirements 及び default-build と同じ. target-name で run のターゲットに名前をつけることができる.名前をつけることによって explicit を指定したり, テストの実行結果に他のターゲットを依存させることが可能になる.

run-fail sources
  : argument
  : input-file
  : requirements
  : target-name
  : default-build
  ;

run の逆.プログラムの実行が失敗すれば(ターゲットのビルドとしては)成功.

compile sources
  : requirements
  : target-name
  : default-build
  ;

コンパイルの成功のみをターゲットとするルール(リンクの成否は対象にならない).これと BOOST_MPL_ASSERT などを組み合わせてコンパイル単体テストを構成できる.

compile-fail sources
  : requirements
  : target-name
  : default-build
  ;

compile の逆.コンパイルが失敗すれば(ターゲットのビルドとしては)成功.期待通りにコンパイル時エラーを生成するかどうかのテストに使用できる.