当記事では、Visual Studio Communityを使ってBoost C++ライブラリをビルドする手順を紹介している。
この数年、ワテはこの手法でBoostをビルドしているが、いい感じで成功している。
追記1
2017/4/10
このページに記載している方法で、本日の時点で最新の boost_1_63_0 を Visual Studio 2017 Community でビルドしてみたが、上手く行った。
追記2
2017/10/2
このページに記載している方法で、本日の時点で最新の boost_1_65_1 をVisual Studio 2017 Community でビルドしてみたが、上手く行った。
追記3
2018/6/30
このページに記載している方法で、本日の時点で最新の boost_1_67_0 をVisual Studio 2017 Community でビルドしてみたが、上手く行った。
しかし、そのboostライブラリを利用するワテのC++プロジェクトをビルドすると、
重大度レベル コード 説明 プロジェクト ファイル 行 抑制状態
エラー LNK1104 ファイル 'libboost_regex-vc140-mt-sgd-1_61.lib' を開くことができません。
と言うエラーが出た。
stageフォルダの中を調べてみると
・・・ -vc141- ・・・
と言う名前のファイルが多数生成されているのが原因だ。
これを
・・・ -vc140- ・・・
にする為には、
b2 toolset=msvc-14.0 ・・・
のようにオプションを指定すれば成功した。
以下の記事を参考にした。
Version numbers for Visual Studio 2017, Boost and CMake
Attention Required! | Cloudflare
ただし本件は、ワテのC++プロジェクトが使っているワテ作成C++Libが古いboostの環境(boost_1_61_0の
libboost_regex-vc140-mt-sgd-1_61.libなど
)でビルドしていたのが原因だった。なので、そのワテC++Libを最新boost_1_67_0 でリビルドし直したら、boost_1_67_0 の -vc141- ファイル群を利用するように出来た。
追記4
2018/10/24
このページに記載している方法で、本日の時点で最新の boost_1_68_0 をVisual Studio 2017 Community でビルドしてみたが、上手く行った。
2019/05/05
このページに記載している方法で、本日の時点で最新の boost_1_70_0 をVisual Studio 2019 Community でビルドしてみたが、上手く行った。
では、本題に入ろう。
ワテはC#もやるが本当はC++が好み
このところ、C#を使う機会が多い。
C#とはシーシャープと読むが、鴻海精密工業に買収されたシャープ株式会社(SHARP)とはたぶん関係ない。
C#はメモリ管理が楽ちん
C#とは、マイクロソフトが開発した言語で、CやC++の文法によく似た言語だ。
特徴としては、.NET Frameworkの技術が使われているので、メモリの管理などは基本的にはプログラマがやらなくても、.NET Frameworkが裏で上手い具合にやってくれる。
CやC++などの言語では、メモリを利用する場合には自分で必要な量をmallocやnewで確保して使い終わったらfreeやdeleteして解放すると言う操作が必ず必要になるが、C#ではそれが必要ないので超楽ちんだ。
要するにC#ユーザーは、メモリ管理を殆ど意識しなくても良い。
と言う訳で、最近のワテは専らC#を使っている。
実はワテはCやC++コンパイラが好き
しかしながら、実はワテはCやC++コンパイラが好きだ。
何て言うかその、mallocで必要量だけメモリを確保して使い終わるとfreeでキッチリ解放する。
そう言う風に自分で必要なメモリを使って必要な処理をするというプログラミングスタイルが好きだ。
最近では32GBとか64GBもメモリを搭載したパソコンがあるが、昔はそんなにはメモリも無かったのでmallocで大量のメモリを確保しようとしても無いものは使えない。
そう言う場合に、うまく工夫して少ないメモリを効率良く活用してプログラムを作成して問題を解決すると言うそんなプログラムを昔はよく書いていた。
さて、ワテのそんな昔話は読者の皆さんには興味は無いと思うので本題に戻るが、今日、久しぶりにC++を使う必要が生じた。
古いC++プログラムをビルドしたらBoostでエラー
大したプログラムでは無いのだが、先日まで使っていた
- Windows7 Pro x64
- VS2013
- 自作C++コンソールプログラム
- 自作C++ライブラリ
- Boost 1.56
の環境で開発した簡単なコンソールプログラムだ。
今日、そのC++プログラムをワテの新しい作業環境である、
- Windows10 Pro x64
- VS2015 Community
でビルドしようとしたら、エラー多発。
こんなエラーが出ている。
重大度レベル コード 説明 プロジェクト ファイル 行 抑制状態 エラー LNK2038 '_MSC_VER' の不一致が検出されました。 値 '1800' が 1900 の値 'XXXXX.obj' と一致しません。 libboost_regex-vc120-mt-sgd-1_56.lib(winstances.obj) 1
まあ、それはそうだな。
エラーの理由は簡単で、以下の2つのライブラリは数か月前に古いVS2013でビルドしているのに、
- 自作C++ライブラリ
- Boost 1.56
最新のVS2015を使って
- 自作C++プログラム
をビルドしたので、「 ‘_MSC_VER’ の不一致が検出されました」 と言う事だ。
つまりコンパイルに使ったVisual Studioのバージョンが、異なっているというエラーだ。
Boost_1_61_0をVS2015でリビルドする
という事で久しぶりにBoostをリビルドしてみた。
昔のメモを見たらBoost_1_56_0をビルドしたのは2014年8月だったので約2年ぶりだ。
さて、早速ビルドしてみる。
なお、以下の手順はあくまでワテ流である。
Boostのビルドは、OSの種類(Linux, Windowsなど)や、使うコンパイラーの種類(gcc, MinGWのgcc, Visual StudioのCコンパイラなど)に応じて沢山のやり方が有るようだ。
ネットを検索して色んな記事を見てみたが、多種多様な手法があるのでどれが正しいのか良く分からない。日付の古い記事の場合、Boostのバージョンも古いものを対象とした記事なので、最新のBoostのインストールには当てはまらないものも多い。
と言う事で、以下はあくまでワテ流だ。
まあ、ワテの場合このやり方でBoostをビルドして問題なく使えているので、多分そんなには悪いやり方だとは思わない。
ワテ流のBoostビルド手順
最新のBoost_1_61_0をダウンロードして解凍する。
DOSのプロンプトを表示して、解凍したフォルダにチェンジディレクトリする。
一応念のために、管理者権限でDOSプロンプト画面を開いておいた。
そこで
E:\Boost C++ Libraries\boost_1_56_0>bootstrap.bat
を実行する。
実際に実行した画面が以下の通り(間違えて 1_56_0の画面をキャプチャーしてしまったが1_61_0でも似たような感じの出力になる)
E:\Boost C++ Libraries\boost_1_56_0>bootstrap.bat Building Boost.Build engine Bootstrapping is done. To build, run: .\b2 To adjust configuration, edit 'project-config.jam'. Further information: - Command line help: .\b2 --help - Getting started guide: http://boost.org/more/getting_started/windows.html - Boost.Build documentation: http://www.boost.org/boost-build2/doc/html/index.html E:\Boost C++ Libraries\boost_1_56_0>
なお、この bootstrap.bat を実行しても完了までに2,3分掛かる。
ワテのパソコンは Intel CPU Core i7 4770K 3.50GHz なので比較的速い部類に入ると思うがそれで2,3分掛かる。
さて、その後は、以下のコマンドを順次実行した。
b2 toolset=msvc threading=multi variant=debug,release link=static runtime-link=static address-model=32 --stagedir=stage/x86 -j 8 b2 toolset=msvc threading=multi variant=debug,release link=static runtime-link=shared address-model=32 --stagedir=stage/x86 -j 8 b2 toolset=msvc threading=multi variant=debug,release link=shared runtime-link=static address-model=32 --stagedir=stage/x86 -j 8 b2 toolset=msvc threading=multi variant=debug,release link=shared runtime-link=shared address-model=32 --stagedir=stage/x86 -j 8 b2 toolset=msvc threading=multi variant=debug,release link=static runtime-link=static address-model=64 --stagedir=stage/x64 -j 8 b2 toolset=msvc threading=multi variant=debug,release link=static runtime-link=shared address-model=64 --stagedir=stage/x64 -j 8 b2 toolset=msvc threading=multi variant=debug,release link=shared runtime-link=static address-model=64 --stagedir=stage/x64 -j 8 b2 toolset=msvc threading=multi variant=debug,release link=shared runtime-link=shared address-model=64 --stagedir=stage/x64 -j 8
あるいは一気に実行したいなら、 temp.bat のような適当なバッチファイルを作成して上の8行のコマンドを書いて実行すれば良い。
あるいは、もっと簡単に上の全部をコピーしてDOS画面にペーストしても良い。
そうするとビルドが開始して、10分くらい掛かって完了する。
その後で、以下のコマンドを実行した。
b2 toolset=msvc threading=multi variant=debug,release link=static runtime-link=static address-model=32 --stagedir=stage/x86 -j 8 --with-iostreams -s ZLIB_SOURCE=E:\zlib-1.2.11 b2 toolset=msvc threading=multi variant=debug,release link=static runtime-link=shared address-model=32 --stagedir=stage/x86 -j 8 --with-iostreams -s ZLIB_SOURCE=E:\zlib-1.2.11 b2 toolset=msvc threading=multi variant=debug,release link=shared runtime-link=static address-model=32 --stagedir=stage/x86 -j 8 --with-iostreams -s ZLIB_SOURCE=E:\zlib-1.2.11 b2 toolset=msvc threading=multi variant=debug,release link=shared runtime-link=shared address-model=32 --stagedir=stage/x86 -j 8 --with-iostreams -s ZLIB_SOURCE=E:\zlib-1.2.11 b2 toolset=msvc threading=multi variant=debug,release link=static runtime-link=static address-model=64 --stagedir=stage/x64 -j 8 --with-iostreams -s ZLIB_SOURCE=E:\zlib-1.2.11 b2 toolset=msvc threading=multi variant=debug,release link=static runtime-link=shared address-model=64 --stagedir=stage/x64 -j 8 --with-iostreams -s ZLIB_SOURCE=E:\zlib-1.2.11 b2 toolset=msvc threading=multi variant=debug,release link=shared runtime-link=static address-model=64 --stagedir=stage/x64 -j 8 --with-iostreams -s ZLIB_SOURCE=E:\zlib-1.2.11 b2 toolset=msvc threading=multi variant=debug,release link=shared runtime-link=shared address-model=64 --stagedir=stage/x64 -j 8 --with-iostreams -s ZLIB_SOURCE=E:\zlib-1.2.11
確か、zlibを使うようにするためのコマンドだったと思うのだが、詳細は忘れた。
もちろんzlibは事前にダウンロードして適当なフォルダに解凍しておく。
(zlibを使わない人はこのコマンドはやらなくても良い。)
なお、今回記事を書くに当たり、このあたりの情報も参考にした。
boost_1_60_0 .zip installation in windows
ワテの方法と同じような感じなので、やはりワテの方法もあながち間違っていないようだ。
8種類のビルドコマンドの説明
この8通りのコマンドの意味は以下の通り。
x86 x64 |
debug release |
static (.lib) shared (.dll) |
これで 2 x 2 x 2 = 8通りの組み合わせになるので、兎に角全部のlibやdllを作成しておくと言う作戦だ。
-j 8 は確か8コアを使ってビルドするという意味だったかな?忘れた。
これでboostを最新版にバージョンアップできたのだが、同時にVSも2013から2015に上げたので、過去の自作のC++プロジェクトでエラーが多数起こった。
以下、その症状と解決方法のメモ。
VS2013では問題なかったのにVS2015でエラー多発(その対策)
問題1. エラー C3872 ‘0x2191’: この文字を識別子で使用することはできません
ん?
0x2191とは ↑ と言う文字だ。
ワテの場合、関数名、変数名、マクロその他、文字が使える部分には全角文字も平気で使う。
変数名の中に上矢印↑を使っていたのだが、何故かVS2015でエラーした。
対策 「↑」文字の使用を中止(まあ、そんなヘンテコな変数名を使うのはワテくらいかもしれない)
問題2. エラー C2338 va_start argument must not have reference type and must not be parenthesized
対策
以下の一行をソースファイルの冒頭に追加したら解決した。
#define _CRT_NO_VA_START_VALIDATION
この記事に書いてあった。
なお、エラーの理由も意味も良く理解できていない。時間が有れば調査したい。
問題3. 「エラー C1107 アセンブリ ‘mscorlib.dll’ がみつかりませんでした」
重大度レベル コード 説明 プロジェクト ファイル 行 抑制状態 エラー C1107 アセンブリ 'mscorlib.dll' がみつかりませんでした: /AI または LIBPATH 環境変数を使用してアセンブリ検索パスを指定してください。 XXXXX(プロジェクト名) E:\Desktop\(プロジェクトフォルダのパス)\Stdafx.cpp
こんなエラーが出る。もう訳分からん。
ググったら
Visual Studio 2010 C++/CLI in Static Library Mode: could not find assembly ‘mscorlib.dll’
に類似の症状と対策が書いてあった。
幾つかの対策が書いてあるが、ワテの場合は勘で選んで↓この方法を試してみた。
I had the same problem when converting my solution from the VS2010 compiler to VS2013 compiler.
I resolved it by changing the project settings (for the project containing the managed .cpp file that was throwing this error) as follows: In Project Settings | C/C++ | General | Additional #using Directories I added the macro $(FrameworkPathOverride). This resolves to the reference assembly directory for the version of .NET that you’re targeting, which in my case is C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.5.1
つまり、
[CPPプロジェクトの設定]
[一般]
[追加の usingディレクトリ]
に以下のマクロを記述する。
$(FrameworkPathOverride)
早速やってみたら、なんと!無事に解決。
なお、このマクロの意味は良く分かっていない。後で調べよう。
また、CodeZineのこの記事にも何か関連する情報があるようだが、詳しくは読んでいない。
問題4. なぜか古いlibを探しに行く
重大度レベル コード 説明 プロジェクト ファイル 行 抑制状態 エラー LNK1104 ファイル 'libboost_regex-vc120-mt-gd-1_56.lib' を開くことができません。
こんなメッセージが出て解消しない。
今ビルドしているのは 1_61_0なのに、何故か一つ前の 1_56 のstatic libを探しに行くのだ。
libboost_regex-vc120-mt-gd-1_56.lib
と言うのは
vc120 = VS2013
vc140 = VS2015
なので、古いVS2013でビルドしたlibだ。
本来なら、
libboost_regex-vc140-mt-gd-1_60.lib
が使われるべきなのに。
対策
結局何が原因だったのか不明なのだが以下のようにしたら解決した。
Visual Studioアプリの場合、各言語で出力されるフォルダは以下の通り。
プロジェクト | 32bitアプリ | 64bitアプリ |
C++ | Win32 | x64 |
C# | x86 | x64 |
boost_1_61_0\stage | x86 | x64 |
boostのstageフォルダには、ビルドによって生成される各種の多数のdllやlibが保管されるのだが、それを使うワテのC++プロジェクトでは
[リンカー] → [全般] → [追加のライブラリディレクトリ] の設定を
E:\Boost C++ Libraries\boost_1_61_0\stage\$(Platform)\lib;
としている。この$(Platform)は上表のWin32やx64に置き換わる。
ところがBoostの32bitフォルダは Win32ではなくてx86になっているのでlibが見つからない問題が出る。
従ってx86フォルダ名をWin32に変更しても良いかなあと思ったのだが、オリジナルのx86は何となく残しておきたかった。
そこで、x86フォルダにシンボリックリンクを張って Win32 フォルダを作成した。
そのコマンド(管理者で実行する必要あり)
mklink /D "E:\Boost C++ Libraries\boost_1_61_0\stage\Win32" "E:\Boost C++ Libraries\boost_1_61_0\stage\x86"
これでC++のプロジェクトからBoostのライブラリが見えるようになったので、問題のプロジェクトをリビルドしてみたら無事に問題は解決した。
まあ良く分からんが解決したので良しとするか。
世の中分からん事が多いのか、ワテの記憶力が低下しているのか。
Visual Studioの既存プロジェクトでBoostのバージョンを変更する方法
例えば自作のC++プロジェクトがあり、現状ではboost_1_59_0をリンクして使っているとする。
それを、今回ビルドした最新版boost_1_68_0に変更したい場合、プロジェクトのプロパティを開いて変更すれば良い。
具体的には、下図に示すように、
- 追加のインクルードディレクトリ
- 追加のライブラリディレクトリ
の二カ所を変更する場合が多いだろう。
この場合、
Release, Debug
Win32, x64
の四通りの組み合わせがあるので、それら全ての構成に対して、上図の変更を行うのは少々手間が掛かる。
そう言う場合にお勧めなのが、そのプロジェクトの 〇〇〇.vcxproj ファイルを直接編集する方法だ。
念のために事前に 〇〇〇.vcxproj のコピーを作成しておくと良い。
そうすれば万一失敗しても元に戻せるから。
〇〇〇.vcxprojファイルを使い慣れたテキストエディタで開く。
ワテの場合はnotepad++を使っている。
あるいはVisual Studio自身で 〇〇〇.vcxproj を開いて編集しても良いが、ワテの場合は、この手の作業はVisual Studio以外の環境でやっている(Notepad++)。
Notepad++で 〇〇〇.vcxproj を開くと以下のように数か所にboostの設定が書き込まれている。
これらの設定は、さきほどプロジェクトのプロパティで確認した追加のインクルードディレクトリや追加のライブラリディレクトリのパスである。
その文字列を置換すれば良いのだ。
変更前 boost_1_59_0
変更後 boost_1_68_0
のように指定して一気に置換すれば良い。
そして 〇〇〇.vcxproj ファイルを上書き保存すれば良いのだ。
そうするとプロジェクトのプロパティを一瞬で書き換える事が出来て、boost関連は最新のboost_1_68_0を使う設定に出来るのだ。
まとめ
ワテの場合、Boostは便利そうだったので使い始めたのだが、今回のような問題が出やすいと思う。つまり、includeするファイルが見つからないとか、linkするlibファイルが見つからないとか。
また、C/C++の場合には、ヘッダーファイルのインクルードの多重インクルードの問題も出やすいが、Boostを使うとそう言う問題が頻繁に発生しやすくて悩まされた経験がある。
ほんの一か所でインクルードガードを忘れただけなのに、全く無関係みたいな場所でエラーが出るとか、兎に角C++のヘッダーファイルはワテは苦手だ。
まあ、それらはBoostのせいではなくてワテの技術の問題なのだが、ワテの場合はこのC/C++のヘッダーファイルのインクルードガードの作業は出来れば関わりたくないややこしい面倒な作業だ。
なので、ワテとしては最近はBoostを使わない方針にしている。
Boostが無くても、標準の機能だけで大抵の事は出来る。
必要最小限のものだけでプログラミングをこなす、プログラミングの断捨離を目指している。
本を読んでC/C++を勉強する
有名な本だ。
1200ページもある本を良く書けると思う。それも何冊も出している驚きのストラウストラップ先生だ。
コメント