Visual C++ 10(Visual Studio 2010)に、Boost 1.51を使ってプログラムを作ろうとして躓きました。
Boostは、次のサイトからビルド済みバイナリをインストールします。
で、program_optionsライブラリを使用したプログラムをビルドした際に、リンクエラーが発生しました。プログラムはWin32コンソールアプリケーションとしてプロジェクトを生成したものをベースに書いたものです。
LINK : fatal error LNK1104: ファイル 'libboost_program_options-vc100-mt-gd-1_51.lib' を開くことができません。
プログラムのプロジェクト設定は、Win32コンソールアプリケーションで生成したもので、ランタイムライブラリの種類はデフォルトのままで、「マルチスレッドデバッグDLL(/MDd)」が指定されています。
Boostのライブラリ種類は、インストール時に次の種類から選択できます。
- Multithreaded debug DLL
- Multithreaded DLL
- Multithreaded
- Multithreaded debug
- Multithreaded static runtime
- Multithreaded debug static runtime
- Single threaded static runtime
- Single threaded debug static runtime
最初の2つはDLLとあるように、実行時にDLLファイルを必要とする動的リンク、残りは実行時にDLLファイルを必要としない静的リンクです。
最後の4つはstatic runtimeとあるように、Cランタイムライブラリと静的リンクしたライブラリです。
最後の2つはSingle threadedとあるように、シングルスレッド版です。
それぞれライブラリファイル名が異なります。たとえば、program_optionライブラリの場合
- Multithreaded debug DLL
- boost_program_options-vc100-mt-gd-1_51.dll
- boost_program_options-vc100-mt-gd-1_51.lib
- Multithreaded DLL
- boost_program_options-vc100-mt-1_51.dll
- boost_program_options-vc100-mt-1_51.lib
- Multithreaded
- libboost_program_options-vc100-mt-1_51.lib
- Multithreaded debug
- libboost_program_options-vc100-mt-gd-1_51.lib
- Multithreaded static runtime
- libboost_program_options-vc100-mt-s-1_51.lib
- Multithreaded debug static runtime
- libboost_program_options-vc100-mt-sgd-1_51.lib
- Single threaded static runtime
- libboost_program_options-vc100-s-1_51.lib
- Single threaded debug static runtime
- libboost_program_options-vc100-sgd-1_51.lib
となります。
さらに、通常リンクするライブラリはプロジェクトの設定でファイル名を指定しますが、Boostの場合、Boostのヘッダーファイル*1にVC++固有の記述でリンク指示が定義されます。
#pragma comment(lib, "xxx.lib")
xxx.libの部分は、複雑なプリプロセッサの条件分岐の結果が適用されます。詳細を次に述べます。
リンクするライブラリファイル名の決定
まず、動的リンクか静的リンクかは、次の条件で判断されます。
条件1 | 条件2 | 判断結果 |
---|---|---|
○ | ○ | 動的リンク |
N/C | × | 静的リンク |
× | ○ | コンパイルエラー |
- N/C: Not Care.
条件の制御方法は、
- プロジェクトの設定でC/C++コード生成のランタイムライブラリを/MDまたは/MDdにする
- プロジェクトの設定でC/C++プリプロセッサの定義にBOOST_ALL_DYN_LINKを指定する(注:BOOST_DYN_LINKではなく)
次に、スレッド種類がMultithreadedかSingle threadedかは、次の条件で判断されます。
- プリプロセッサ定義_MTまはた__MT__が指定されている
条件1 | 判断結果 |
---|---|
○ | Multithreaded |
× | Single threaded |
条件の制御方法は、
- VC++ 10では、かならず_MTが定義される(シングルスレッドを指定するオプションがない、省略時は/MT扱い)
次にdebug, static runtimeかは次の条件で判断されます。
条件1 | 条件2 | 判断結果 |
---|---|---|
○ | ○ | debug |
× | ○ | debug static runtime |
○ | × | |
× | × | static runtime |
条件の制御方法は、プロジェクトの設定でC/C++コード生成のランタイムライブラリを
- /MDd に指定すると、_DLLと_DEBUGがともに指定
- /MTd に指定すると、_DEBUGが指定
- /MD に指定すると、_DLLが指定
- /MT に指定すると、指定なし
-
- プロジェクト設定では、ランタイムライブラリにシングルスレッドの選択肢が用意されていない
以上を整理すると、次のように単純化できます。
コンパイル指定 | BOOST_ALL_DYN_LINK定義 | 使用するライブラリ種類 |
---|---|---|
/MD | ○ | Multithreaded DLL |
/MD | × | Multithreaded |
/MDd | ○ | Multithreaded debug DLL |
/MDd | × | Multithreaded debug |
/MT | × | Multithreaded static runtime |
/MT | ○ | コンパイルエラー |
/MTd | × | Multithreaded debug static runtime |
/MTd | ○ | コンパイルエラー |
ということで、Visual C++のWin32コンソールアプリケーションで生成したプロジェクトのデフォルト設定(/MDや/MDdが指定される)でBoostを使用すると、MultithreadやMultithreaded debugがリンクされるので、
- libboost_program_options-vc100-mt-gd-1_51.lib
を探し、なければエラーとなります。
コンパイルオプションとプリプロセッサ定義については、次のURLに解説があります(日本語)。
この問題に一日はまってました。実は昔この問題に対処していましたが(次のWebにその対処を書いてます)、まったく覚えていませんでした。
同じ落とし穴に二度落ちたことになります・・・
*1:boost/config/auto_link.hpp