この記事は、C++ (fork) Advent Calendar 2013の3日目です。


現在、Boostのソースコード管理はSubversionからGitへ乗り換えた上でGitHubへの移行が進められています (github.com/boostorg (Boost.org))。そこで、この記事ではGitリポジトリからBoostを使用する方法のまとめを書きます。

なお、この記事の対象はWindowsです。以下の説明でもmsysGitのgit bashとVisual Studioコマンドプロンプトが混在しています。$で始まる行はgit bash、>で始まる行はVisual C++へのパスが通ったコマンドプロンプトで実行したものです。実行速度が速いのでmsysGitで試しましたが、Cygwinでも可能だと思います。

最新版を使う

まず簡単なところからです。masterやdevelopブランチなど、とにかく最新のソースコードを取得・使用する方法です(TryModBoost — Boost C++ Librariesより)。

$ git clone --recursive https://github.com/boostorg/boost.git boost
> cd boost
> bootstrap.bat
> b2 headers

bootstrap.batでは、b2.exe (bjam.exe)をソースからビルドするので、何かしらコンパイラを使用できる環境が必要です。

各ライブラリがgit submoduleで管理されているので、--recursive付きでクローンしています。--recursiveを付けずにcloneしてしまった場合、以下にようにすれば大丈夫です。

$ git https://github.com/boostorg/boost.git boost
$ cd boost
$ git submodule init
$ git submodule update
> bootstrap.bat
> b2 headers

チェックアウトした直後の状態だと、doc, libs, bootstrap.bat, bootstrap.shなど見覚えのあるディレクトリ・ファイルが並ぶ中、ヘッダファイルがあるはずのboostディレクトリが見当たらないことに気がつきます。これを生成するのが b2 headersです。

ここまでできたら準備完了です。もう、Boost_*.7zあるいはBoost_*.tar.bz2などを展開した後の状態と同じように、インクルードパスを通したりb2 installb2 stageでライブラリをビルドしたりできるはずです。

リリース版を使う

次は、特定のバージョンを使用する方法です。実際のアプリケーション開発などでは、このほうがよく使うでしょう。

各バージョンについてタグが付けられているので、基本的にはそれをチェックアウトすればOKです。

$ cd boost
$ git checkout release-1.55.0
$ git submodule update

ただし、現時点で最新のBoost 1.55でも、モジュール化への対応が済んでいない状態であるため、そのままではうまくいきません。上記と同じ手順でb2 headersを実行すると、次のようなエラーメッセージが出ます。

link.jam: No such file or directory
Jamroot:145: in modules.load
ERROR: rule "link-directory" unknown in module "Jamfile".
…/boost/tools/build/v2/build\project.jam:311: in load-jamfile
…/boost/tools/build/v2/build\project.jam:64: in load
…/boost/tools/build/v2/build\project.jam:145: in project.find
…/boost/tools/build/v2\build-system.jam:535: in load
…\boost\tools\build\v2/kernel\modules.jam:289: in import
…\boost\tools\build\v2/kernel/bootstrap.jam:139: in boost-build
…\boost\boost-build.jam:17: in module scope

回避策の1つとしては、buildまわりだけ最新にする方法があるようです(nabble.com: Boost – Build – b2 headers working in modular-boost develop but not masterより)。こういうことが可能なところはsubmoduleならではですね。

$ cd boost
$ git checkout release-1.55.0
$ git submodule update
$ cd tools/build
$ git checkout master
$ cd ../..
> bootstrap.bat
> b2 headers

これも、あとは必要ならb2 installb2 stageを実行すれば良いというのは上と同じです。

もっと古いリリース版を使う

さらに昔のリリース版をチェックアウトした場合、上記の方法でもうまくいきません。

$ git checkout release-1.43.0
$ git submodule update

そのため、b2 headersの代わりにboostディレクトリを生成するバッチファイルを書きました。

初めは以下のバッチファイルで良いと思いましたが、やってみたら不十分でした。そのため、以下のようなVBScriptを作り直しました。フォルダごとのジャンクションではなく、ファイル個々にハードリンクを張るようにしています。

Set fso = CreateObject("Scripting.FileSystemObject")
Set shell = WScript.CreateObject("WScript.Shell")
 
' Boostをチェックアウトしたディレクトリ(libsが存在する場所)
' このコメントアウトを外した場合、コマンドライン引数で指定することになる。
' boostRoot = fso.GetAbsolutePathName(WScript.Arguments(0))
boostRoot = "……\boost"
 
For Each i In fso.GetFolder(fso.BuildPath(boostRoot, "libs")).SubFolders
  If fso.FolderExists(i.Path & "\include") Then
    Set includeSrc = i.SubFolders("include")
    Call MakeHardLink(includeSrc, includeSrc.SubFolders("boost"))
  End If
Next
For Each i In fso.GetFolder(fso.BuildPath(boostRoot, "libs\numeric")).SubFolders
  If fso.FolderExists(i.Path & "\include") Then
    Set includeSrc = i.SubFolders("include")
    Call MakeHardLink(includeSrc, includeSrc.SubFolders("boost"))
  End If
Next
 
Sub MakeHardLink(includeSrc, src)
  targetPath = fso.BuildPath(boostRoot, Right(src.Path, Len(src.Path) - Len(includeSrc.Path) - 1))
  If Not fso.FolderExists(targetPath) Then
    fso.CreateFolder(targetPath)
  End If
 
  For Each srcFile In src.Files
    relativePath = Right(srcFile.Path, Len(srcFile.Path) - Len(includeSrc.Path) - 1)
    linkPath = fso.BuildPath(boostRoot, relativePath)
    parent = fso.GetParentFolderName(linkPath)
    If Not fso.FileExists(linkPath) Then
      shell.Run "cmd /c mklink /h " & linkPath & " " & srcFile.Path, 0, True
    End If
  Next
 
  For Each subFolder In src.SubFolders
    Call MakeHardLink(includeSrc, subFolder)
  Next
End Sub
@echo off
mkdir boost\numeric
for /d %%i in (libs\* libs\numeric\*) do (
  if not %%i==libs\numeric (
    for /d %%j in (%%i\include\boost\*) do (
      if not exist boost\%%~nxj (
        mklink /j boost\%%~nxj %%j
      )
    )
    for %%j in (%%i\include\boost\*) do (
      if not exist boost\%%~nxj (
        mklink /h boost\%%~nxj %%j
      )
    )
  )
)

libs/*/include/boostの以下のファイル・ディレクトリに対して、boostからリンクを張っています。シンボリックリンク特権なしで実行できるよう、ジャンクション・ハードリンクでがんばっています。

以上、GitリポジトリからチェックアウトしてBoostを使用可能にする方法でした。C++ (fork) Advent Calendar 2013は明日に続くでしょうか?→ 続きが出ました:C++ (fork) Advent Calendar 2013 4 日目 ~constexpr with VC++~ – モノトーンの伝説日記

2014年7月5日追記:これだけではうまくいかない場合もあるようです。参考:Boost.Range でも regular が使いたい! – C++ AdC 2013 – にゃははーの追記と追記2


スポンサード リンク

この記事のカテゴリ

  • ⇒ Modularized Boost(GitHubへ移行したリポジトリ)を使用する