にゃははー

はへらー

bjam AdC jp 2011 1日目

ついに始まりましたbjam Advent Calendar jp 2011!!これから25日かけてbjamのtipsを書き連ねていきます。
しかもなんと参加者2人!つまり25日を1人で書く予定が13日程度でいいことになります!!!!

第1回目の今日はpathモジュールについて少し触れることにします。
(これ書いてる時は10月だったりします...

pathモジュール

ビルドツールというのは特にファイルに対しての操作が多いので、ここらへんの機能がどれだけ提供されているかが重要になってきます。
Boost.Buildではpathモジュールでこれらのファイル関係の操作を多く提供しています。

path.jamは $BOOST_ROOT/tools/build/v2/util/path.jam もしくはBoost.Buildをインストールしたディレクト*1以下の util/path.jam です。

ファイルが存在するかどうかで条件分岐する

使うのはpathモジュールのexistsルールです。

path.existsのシグネチャ

rule exists ( file )

と非常にわかり易いです。

以下に例を示します。

import path ;

if [ path.exists "/hoge/fuga/piyo" ] {
  # /hoge/fuga/piyoが存在している時の操作
} else {
  # /hoge/fuga/piyoが無いときの操作
}

path.existsはfileが存在した場合trueを、なかった場合""を返します。そのため、残念ながら条件文ぐらいでしか使い道がないでしょう。

特定ディレクトリ以下のパターンにマッチするファイルを列挙する

使うのはpath.globルールまたはpath.glob-treeルールです。
path.globとpath.glob-treeの違いは、対象ディレクトリ以下を再帰的に探索するかどうかです。後者は再帰的に探索します。

また、projectモジュールにもglobルールとglob-treeルールがありますが、これは探索対象のディレクトリがプロジェクト下のものであるかどうかの違いがあります。
他にも引数の展開が微妙に違ったりしますが、基本的な挙動は変わりありません。

path.glob及びpath.glob-treeのシグネチャは以下のようになります。

rule glob ( dirs * : patterns + : exclude-patterns * )
rule glob-tree ( roots * : patterns + : exclude-patterns * )

dirs,roots共に複数指定することが出来ます。
また、exclude-patternsが双方複数設定できるので、除外したいファイルがある場合には使えます。もちろんなくても構いません。

patternsに探したいファイルにマッチする正規表現を与えると、その正規表現にマッチするファイルの一覧が空白区切りで返されます。
これは後々紹介しようと思うsequenceモジュール非常によく適合します。

特定ディレクトリ以下の .cpp と .c をexeに固めるような例を以下に示します。

import path ;

exe hoge : [ path.glob "/somedir" : "*.cpp" "*.c" ] ;

もしサブディレクトリ以下も含めるのであれば path.glob-tree を使います。

例えば 任意のディレクトリ以下にある nobuild ディレクトリ以下にあるソースをビルド対象外にしたい場合、

import path ;

exe hoge : [ path.glob-tree "/somedir" : "*.cpp" "*.c" : "nobuild" ] ;

とすればよいでしょう。
この場合、nobuild.cppというファイルがあった場合これもビルド対象となります。nobuild.cppというファイル自体も除外したい場合は、exclude-patternsに"nobuild.cpp"を追加すれば良いです。

まとめ

pathモジュールはビルドツールにとって必要不可欠なファイル操作を多く提供しているので便利。
pathモジュール便利。pathモジュール便利。

明日はなんと!あの!id:Cryoliteせんせです!!!!!!!!

*1:*nixでは /usr/locl/share/boost-build/ がデフォルトです