|
本サイトは移転しました。旧アドレスからのリダイレクトは2025年03月31日(月)まで有効です。
|
🛈 | ✖ |
boostライブラリを自分でビルドする手順を説明し、これを含めたデバッグ方法を示す。
本サイトはMSYS2でboostライブラリを導入した。これは簡便であるものの必ずしも最新版が得られず、ライブラリ内部までデバッガが追跡できないというデメリットがある。本記事はboostをソースコードからビルドするが、特にデバッグバージョンでライブラリ内部までデバッガを追跡させるための方法を示す。本記事はバージョン1.75.0を前提に記述する。
リンク先からboost_1_75_0.zipをダウンロードする。
ディレクトリは以下とする。異なるバージョンのソースコード展開ディレクトリはboostルートの配下に並列させる。
目的 | ディレクトリ |
---|---|
boostルート | C:\boost |
ソースコードの展開 | C:\boost\boost_1_75_0 |
ビルドの出力 | C:\boost\boost_1_75_0\stage\lib |
zipファイルをboostルートに置きエクスプローラー右クリック[すべて展開]で[圧縮(ZIP)形式フォルダーの展開]ダイアログ[ファイルを以下のフォルダーに展開する]をC:\boostに変更して[展開]する。デフォルトのままではboost_1_75_0ディレクトリをルートとして圧縮されているため一階層余分になる。boostライブラリはBoost.Build(B2)でビルドする。各ディレクトリに配置されるjamroot、jamfile、jamfile.v2、*.jamファイルはB2データで大雑把にはmakeメイクファイルに相当する。本記事での相対パスは展開ディレクトリ(C:\boost\boost_1_75_0)からとする。
boostは独立したライブラリの集合体で多くはヘッダーオンリーだがビルドするライブラリも存在し、そういったライブラリの一つregexを例として配置を示す。各ライブラリのファイルはインクルードを除きlibs\[ライブラリ名]ディレクトリに配置される。B2の実行ファイルはb2.exeでtools\buildディレクトリに供給されるソースコードをビルドする。b2.exeはMSYS2のmingw32/mingw64サブシステムにも存在し、こちらを用いるならビルドの必要は無い。
ディレクトリ | ファイル | 内容 |
---|---|---|
C:\boost | ||
└ boost_1_75_0 | jamroot | B2データ(メイン) |
│ | ... | ... |
├ boost | regex.hpp, *.hpp | ライブラリインクルート |
│︙ | ... | ... |
│├ regex | *.hpp | regex用サブインクルード |
│︙ | ... | ... |
├ libs | ||
│︙ | ... | ... |
│├ regex | ... | ... |
││├ build | Jamfile.v2 | regexビルド用B2データ |
││├ src | *.cpp | regexビルド用ソースコード |
││├ example | ... | (サンプル用ソースコードディレクトリ) |
││├ test | ... | (テスト用ソースコードディレクトリ) |
││├ doc | ... | (ドキュメントディレクトリ) |
│︙︙ | ... | ... |
├ tools | ... | ... |
│├ build | bootstrap.bat | b2.exe(インストールエンジン)ビルド用バッチ |
│││ | Jamroot.jam | b2.exeビルド用B2データ |
││├ src | ... | ... |
│││├ engine | *.cpp, *.h | b2.exeビルド用ソースコード/インクルード |
│︙︙︙ | ||
├ doc | (ドキュメントディレクトリ) | |
︙ |
標準的な手順は展開ディレクトリHTMLスタートページ(index.html)からたどるGetting Started on Windowsの5.2 Or, Build Binaries From Sourceに従い、最初にインストールエンジンとなるb2.exeをビルドし、次に一括して全ビルドライブラリをビルドする。本サイトはmingw32/mingw64サブシステムのb2.exeを用いて、そのビルドは省略する。一括して全ライブラリをビルドするが、pythonライブラリだけは本サイト設定において特別な処理を必要とするため独立して行う。
stage.batを展開ディレクトリに置きそこで実行する。コマンドプロンプト出力をログするためMSYS2のteeを利用し、その理由で環境変数LANGを設定しPATHへmsys2サブシステムを追加する。32ビット/64ビットでforループを形成しそれぞれに適切なPATHを設定する。b2.exeは--without-pythonでpythonビルドを抑止する。toolsetプロパティはgccとする。32ビット/64ビットコンパイラはPATHで切り替えるがaddress-modelプロパティも明示する。これを明示しないと64ビットコンパイラに-m32オプションを与え32ビットオブジェクト(*.o)を生成してしまう。その他のプロパティは_PROPERTIESに設定する。プロパティはマニュアル4.4.3で一覧できる。
1.75.0、32ビットのcontextライブラリはバグを含みログは以下のエラーを報告する。なおこのバグは1.78.0で解消されている事を確認している。
GNUとマイクロソフトのアセンブラ挙動の違いを混乱した開発者の一人が誤ったパッチを当てたためでいずれ元に戻される。
各ファイル最終行でエクスポートする名前先頭のアンダースコア_を削除する。stage.batを再実行する。
以下において大文字で始まるPythonは言語名称あるいはその実装、小文字で始まるpythonはboostライブラリの一つとする。python(Boost.Python)はC++とPythonを仲介するフレームワークである。対象とするPythonはCPythonと呼ばれる実装で、あなたの知るPythonは恐らくCPythonでありMSYS2が導入するPythonもまたCPythonである。Python(CPython)はpython.exeなど実行ファイルの他にDLLを配布し、C++はDLLエクスポート関数(Python/C API)を通じてPythonと連携する。pythonはエクスポート関数のラッパーライブラリで、実行はダイナミック/スタティックリンクに関係なくDLLを必要とし、ビルドはインクルードとインポートライブラリを必要とする。MSYS2はPythonの一部としてDLL(例えばbin\libpython3.8.dll)、インクルード(include\python3.8\*.h)、インポートライブラリ(lib\libpython3.8.dll.a)を提供する。
本サイトはMSYS2導入Pythonを利用してpythonをビルドするが、B2でデフォルトビルドするとコンパイルエラーとリンクエラーが発生する。
B2はlibs\python\build\Jamfileに従いPythonインストールを探索し必要な情報を推定してビルドを試みるが、インクルードパスに誤りコンパイルに失敗する。user-config.jamでインストール情報を明示して再ビルドする。
インポートライブラリ名をpython38(ファイル名ならlibpython38.a)と誤り、MSYS2導入はpython3.8.dll(libpython3.8.dll.a)なのでリンクに失敗する。B2側で修正するのが本筋だが適当な方法が見当たらず、乱暴だがlibpython3.8.dll.aを一時的にlibpython38.aへコピーする
結論として、user-config.jam、stage_python.batを展開ディレクトリに配置してそこでstage_python.batを実行する。user-config.jamのPythonインストール情報はmingw32/mingw64サブシステムで異なるためaddress-modelプロパティで切り替える。stage_python.batはuser-config.jamの位置をB2に伝えるため環境変数BOOST_BUILD_PATHを設定する。さらにインポートライブラリを一時的にコピーしてビルド終了後に消去する。Pythonバージョンは_PYVER、_PYVER_NODOTで指定しファイル名一部に利用する。b2.exeは--with-pythonでpythonのみビルドする。
stage.batとstage_python.batが生成するファイルの配置を示す。オブジェクトファイル(*.o)はbin.v2\libs\[ライブラリ名]\buildディレクトリのプロパティ名によるサブディレクトリ階層に出力する。デフォルトプロパティはディレクトリを維持し、それ以外は下位に[プロパティ名]ディレクトリを作るため分かりやすい階層にならない。ライブラリファイル(*.a、*.dll、*.dll.a)はstage\libに出力する。
ディレクトリ | ファイル | 内容 |
---|---|---|
C:\boost | ||
└ boost_1_75_0 | stage.bat, stage_python.bat | ビルド用バッチ |
│ | user-config.jam | B2コンフィグ |
│ | ... | ... |
├ boost | ... | ... |
│︙ | ... | ... |
├ libs | ||
│︙ | ... | ... |
├ tools | ... | ... |
│︙ | ... | ... |
├ bin.v2 | *.log | ログ |
│├ libs | ||
││︙ | ... | ... |
││├ regex | ... | ... |
│││└ build | ||
│││ └ gcc-10.2.0 | ||
│││ ├ debug | ||
│││ │├ address-model-64 | ||
│││ ││︙ | *.o | オブジェクト |
│││ │├ link-static | ||
│││ ││︙ | *.o | オブジェクト |
│││ │└ threading-multi | ||
│││ │ └ visibility-hidden | *.o | オブジェクト |
│││ └ release | ||
│︙︙ ︙ | *.o | オブジェクト |
├ stage | ||
│└ lib | *.a | スタティックリンクライブラリ |
│ | *.dll, *.dll.a | DLL、インポートライブラリ |
︙ |
ライブラリファイルは同一ディレクトリに32ビット/64ビットやデバッグ/リリースが混在するためファイル名で区別する。DLLも同じディレクトリに出力し実行や配布に注意する。
ファイル名 | 説明 |
---|---|
libboost_[ライブラリ名]-mgw10-mt-d-x32-1_75.a | 32ビットデバッグスタティックリンクライブラリ |
libboost_[ライブラリ名]-mgw10-mt-d-x32-1_75.dll | 32ビットデバッグDLL |
libboost_[ライブラリ名]-mgw10-mt-d-x32-1_75.dll.a | 32ビットデバッグインポートライブラリ |
libboost_[ライブラリ名]-mgw10-mt-x32-1_75.a | 32ビットリリーススタティックリンクライブラリ |
libboost_[ライブラリ名]-mgw10-mt-x32-1_75.dll | 32ビットリリースDLL |
libboost_[ライブラリ名]-mgw10-mt-x32-1_75.dll.a | 32ビットリリースインポートライブラリ |
libboost_[ライブラリ名]-mgw10-mt-d-x64-1_75.a | 64ビットデバッグスタティックリンクライブラリ |
libboost_[ライブラリ名]-mgw10-mt-d-x64-1_75.dll | 64ビットデバッグDLL |
libboost_[ライブラリ名]-mgw10-mt-d-x64-1_75.dll.a | 64ビットデバッグインポートライブラリ |
libboost_[ライブラリ名]-mgw10-mt-x64-1_75.a | 64ビットリリーススタティックリンクライブラリ |
libboost_[ライブラリ名]-mgw10-mt-x64-1_75.dll | 64ビットリリースDLL |
libboost_[ライブラリ名]-mgw10-mt-x64-1_75.dll.a | 64ビットリリースインポートライブラリ |
ビルドしたboostをクライアントプロジェクトが利用するにはコンパイラ/リンカ探索にMSYS2導入より優先してディレクトリを追加する。
種類 | MSYS2より前置するディレクトリ |
---|---|
インクルード | C:\boost\boost_1_75_0 |
ライブラリ | C:\boost\boost_1_75_0\stage\lib |
DLLを利用するにはプログラムと同じディレクトリにコピーするか、あるいは実行パス(環境変数PATH)を通す。
種類 | MSYS2より前置するディレクトリ |
---|---|
実行パス(PATH) | C:\boost\boost_1_75_0\stage\lib |
各ライブラリはlibs\[ライブラリ名]\testディレクトリにテストプロジェクトを用意する。例えばregexライブラリ64ビットをテストする。libs\regex\testディレクトリでコマンドプロンプトを開きmingw64サブシステムにパスを通しB2を実行する。B2はディレクトリ/サブディレクトリ各ターゲットをビルドして実行を確認する。regexはlibs\regex\exampleにサンプルプロジェクトを持つが、テストプロジェクトはこれも同時にビルド実行する。
一つの失敗(failed)が報告されるがこれはtest_warning.cppのコンパイルで、ウォーニングをエラーと見なすオプションを加えてウォーニング発生を調べるダミーターゲットであり、すなわちこの失敗は安全に無視できる。ビルド実行結果はbin.v2\libs\regex\test、bin.v2\libs\regex\test\[ターゲット名].test、bin.v2\libs\regex\example\[ターゲット名].testディレクトリのプロパティ名サブディレクトリ階層に出力する。出力結果を理解しても手間が掛かるわりに得る物が少なく、通常はB2実行の成功失敗で判断して良い。
例としてboostのregexライブラリgrepサンプルプログラム(C:\boost\boost_1_75_0\libs\regex\example\grep\grep.cpp)をCode::Blocksでコンソールアプリケーションとしてビルドする。最初にMSYS2導入boostライブラリにリンクして動作確認する。次にビルドしたboostライブラリの64ビットデバッグ版にリンクして動作確認する。最後にビルドboostライブラリでデバッグ追跡する。ライブラリは全てダイナミックリンクとする。スタティックリンクは必要ライブラリを芋づる式に記述する必要があり面倒くさい。ランタイムライブラリにその必要は無いが統一を重んじこれもダイナミックリンクとする。
動作確認(1)を参考に32ビットコンソールアプリケーションのスケルトンを作成する。例えばC:\Users\user\MinGW\TestDrive\TestDrive.workspaceワークスペースを開き、[File|New|Project]のConsole applicationウィザードで[Project title]BoostRegexGrep、[Folder to create project in]C:\Users\user\MinGW\TestDriveとして作成する。ランタイムライブラリは動的リンクのままとする。main.cppをエディタに開き内容をC:\boost\boost_1_75_0\libs\regex\example\grep\grep.cppに置き換える。[Project|Build option]の[Project build options]ダイアログでDebug32、Release32ターゲット両方とも[Linker setting]ページ[Link libraries]リストボックスを以下に設定する。
ライブラリ |
---|
libboost_program_options-mt.dll.a |
libboost_regex-mt.dll.a |
[Project|Set project arguments]の[Select target]ダイアログでDebug32、Release32ターゲット両方の[Program arguments]に以下を与える。
実行時実引数 |
---|
-E "^.*\bbool\b.*$" main.cpp |
Debug32およびRelease32ターゲットで[Build|Run]すればmain.cppソースコードの"bool"を含む行がコマンドプロンプトに出力される。引き続き動作確認(1)を参考に64ビットターゲットを作成する。[Project|Properties]でDebug32/Relase32ターゲットをDebug64/Release64ターゲットにコピーして[Project|Build option]でコンパイラをGNU GCC Compiler (64bit)に変更する。Debug64およびRelease64ターゲットで[Build|Run]して出力を確認する。
ビルドしたboostライブラリの64ビットデバッグ版にリンクする。[Project|Properties]でDebug64ターゲットをDebug64_b2ターゲットにコピーし[Project|Build option]で設定を以下に変更する。
ライブラリ |
---|
libboost_program_options-mgw10-mt-d-x64-1_75.dll.a |
libboost_regex-mgw10-mt-d-x64-1_75.dll.a |
コンパイラ/リンカ探索はビルドboostをMSYS2導入に優先させる。[Project|Build option]でDebug64_b2ターゲット[Search directories]ページの[Compiler]ページ、[Linker]ページの探索パスを以下に変更する。
ページ | 探索パス |
---|---|
[Compiler] | C:\boost\boost_1_75_0 |
[Linker] | C:\boost\boost_1_75_0\stage\lib |
ダイナミックリンクはDLLに実行パスを通す必要があるが、Code::Blocksでの実行はPATHにライブラリディレクトリを自動追加するので省略できる。Debug64_b2ターゲットで[Build|Run]して出力を確認する。
例えばboost::regex_search関数へ追跡する。main.cppのprocess_stream関数whileループ冒頭のboost::regex_search関数コールにテキストカーソルを置いて[Debug|Toggle breakpoint]でブレークポイントを設定する。Debug64_b2ターゲットで[Debug|Start / Continue]するとデバッガがスタートしブレークポイントで停止する。[Debug|Step into]するとboost::regex_searchへ追跡し、[Debug|Step into]や[Debug|Nest line]などで内部フローをステップ確認できる。[Debug|Start / Continue]で通常実行を再開する。ただしブレークポイントがループ内にありファイルから1行読み込む度に停止するので、必要に応じ[Debug|Toggle breakpoint]でブレークポイントを解除する。デバッガ上ではコンソールアプリケーションの終了と共にコマンドプロンプトは閉じるので、最終出力の確認が必要ならmain関数の最終行にブレークポイントを置く。