LAPACK 3.5.0 を MinGW 64bit (MinGW-w64) でビルドしてついでに Visual Studio 2013 で使う (2)

前回の続き。 MinGW-w64 の x86_64-4.9.2-win32-seh-rt_v3-rev1 で Lapack 3.5.0 を ビルドしてみます。

・まずここからソースを落としてきます。 (svn もあるようですのでそちらでもOK)

・tar  で落としてきた lapack-3.5.0.gz を適当なディレクトリに展開し、作業と生成物の展開用に build_space, build ディレクトリを中に作っておきます。 (別に決まりはないので、場所も名前も好きなもので可)

・ x86_64-4.9.2-win32-seh-rt_v3-rev1 のインストールディレクトリの下に mingw-w64.bat と言うバッチファイルがあるので展開した lapack-3.5.0 ディレクトリの下にコピーしておきます。

・ コピーした mingw-w64.bat をダブルクリックして起動したコマンドプロンプトから cmake-gui を起動します。 (C:\Program Files (x86)\CMake\bin には Path を通しておいて下さい)

lapack-build-0

・ 起動した CMake に lapack-3.5.0 フォルダーの下にある CMakeList.txt をドラッグアンドドロップし、「Where to build the binaries」 に lapack-3.5.0/build_space への path を指定した後 「Configure」 ボタンを押します。

lapack-build-1

・ 以下のような window が出てきますので 「MinGW Makefiles」 「Use default native compilers」 を選択し、「Finish」 を押します。

lapack-build-2

・ 次にビルドの為の設定画面が出てきますので以下のように設定し、もう一度 「Configure」 ボタンを押します。

  • BUILD_SHARED_LIBS = ON
  • BUILD_STATIC_LIBS = OFF
  • CMAKE_BUILD_TYPE = None
  • CMAKE_GNUtoMS = ON
  • CMAKE_INSTALL_PREFIX = lapack-3.5.0/build への path
  • LAPACKE = ON

lapack-build-3

※ デフォルトでは LAPACK は reference BLAS と呼ばれる最適化がされていない BLAS を利用するようです。 もし、 最適化が施された BLAS を使用したい場合は別に用意して USE_OPTIMIZED_BLAS = ON にして configure する必要があります。

・  VCVARSAMD64-NOTFOUND と出ますので、VCVARSAMD64 に 「C:/Program Files (x86)/Microsoft Visual Studio 12.0/VC/bin/x86_amd64/vcvarsx86_amd64.bat」 を指定し、もう一度 「Configure」 ボタンを押します。

・ configuration が完了したら 「Generate」 ボタンを押します。

・ ここで最初に mingw-x64.bat で起動したコマンドプロンプトに戻り、 cd build_space でカレントディレクトリを lapack-3.5.0/build_space に変更した後 mingw32-make と入力してビルドを開始します。

$cd build_space
$mingw32-make

・ ビルド 終了後 mingw32-make install を実行します。

$mingw32-make install

「これで完了!」と思いきや、なんと install に失敗してしまいます。 見てみると 「cannot find liblapacke.lib」 と言うことで怒られています。

lapack-build-4

調べてみると確かに  liblapacke.lib ができていない… 困った… でもビルド自体は正常に終了しているし、深追いするのも微妙だな…  と言うことで manual で lib ファイルを作ってしまいました。

・まず、「C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\Tools\Shortcuts\VS2013 x64 Cross Tools コマンド プロンプト」を lapack-3.5.0 の下にコピーします。

・ 次に pexports をここから取得、同じく lapack-3.5.0 の下に pexports.exe を展開した後、「VS2013 x64 Cross Tools コマンド プロンプト」を立ち上げて以下のようにコマンドを入力します。

$pexports build_space/bin/liblapacke.dll > build_space/lapacke/liblapacke.def
$lib /MACHINE:X64 /DEF:build_space/lapacke/liblapacke.def
$move liblapacke.* build_space/lib

・最後に mingw-x64.bat で起動したコマンドプロンプトに戻り、もう一度 mingw32-make install を実行すると今度はエラー無く終了して lapack-3.5.0/build の下に必要なファイルが出力されているはずです。

MSVC用の import library も一緒に作りましたので、ビルドした 64bit DLL 一式は MinGW だけでなく MSVC2013 でも使用できます。ただし DLL はMinGW 64bit  のランタイムに依存していますので、MSVC2013 で利用するには libgcc_s_seh-1.dll と libgfortran-3.dll を LAPACK 関係の DLL と一緒に置くように下さい。また、実際に利用する際には以下をプロジェクトのプロセッサ定義に加えておく必要がありますのでこちらもお忘れなく。

・ADD_
・HAVE_LAPACK_CONFIG_H
・LAPACK_COMPLEX_STRUCTURE

広告

LAPACK 3.5.0 を MinGW 64bit (MinGW-w64) でビルドしてついでに Visual Studio 2013 で使う (1)

LAPACK と言えば、数値計算を行うような分野では知らぬ者はいない大変著名な線形代数ライブラリです。 MATLAB などの高機能数値解析ソフトウェアも内部エンジンで LAPACK を採用しているケースが多いようですので、LAPACK 自体直接触った事が無くてもその恩恵に預かっている人は結構多いのではないでしょうか。

しかし LAPACK は本体が Fortran で記述されているため C/C++ からはそのまま手軽に利用する事ができず、CLapack などの fortran –> C ソースコード変換系のライブラリを利用するか、calling convention を調整する系のラッパーライブラリーを使うしかない……. と今まで思っていたのですが、最近改めて見たところ version 3.4.0 から LAPACKE と言う Intel の Math Kernel Library Team の仕事による C 言語 API が LAPACK 本体と同時に配布されるようになったようです。

Standard C language APIs for LAPACK

Windows 向けの導入解説サイトもなんかもあったりしてちょっと興味をそそられたので、試し食い目的で目を通してみました。

Windows で LAPACK を使うには?

  1. もし Intel compiler を持っているなら、Intel のライブラリを利用するビルド済みの static link library を利用すべし
  2. もし Intel compiler を持ってないなら MinGW 32bit か MinGW-w64 を用意して(これは gfortran と gcc の runtime だけが目的) ビルド済みの DLL をダウンロードして利用すべし

まぁまさにその分野に身をおいている人は別として、多くの人は Intel compiler なんて持っていないでしょうから必然的に 2 の方法になると思われます。 またその辺の事情を考慮してか MinGW 32bit 向けの LAPACK 関係の DLL と MinGW  32bit の runtime を利用する Visual Studio 2010 の sample solution が一緒に配布されています (なんて親切 …)

今回は 64bit で利用したいので、 以下のリンクから x64 系のバイナリと LAPACKE 関係の Header 一式をダウンロードしました。

lapack_dll_dl

で早速落としてきた DLL を Dependency Walker にかけてみたのですが、なんと libgcc_s_sjlj-1.dll に依存している… (しかも 「SJLJ の runtime なんか入れた記憶がないのに !」 と思ったら PATH が通ってる関係で strawberry perl が中に抱いてる runtime に解決されている…)

lapack_dependency

現在 MSVC2013 と MinGW-w64 の SEH 版 (x86_64-4.9.2-win32-seh-rt_v3-rev1) をセットで利用しているのでこれはちょっと微妙…. LAPACK の DLL が例外を投げてくる事は思いますし、例外機構の異なる処理系に同梱されている runtime にそれぞれ依存するだけなので問題無いはずなのですが、なんか嫌だなー気持ち悪いなー …..

と言うことで自分の環境向けにソースからビルドする事にしました。ビルドの詳細は次回に。

可変長テンプレート引数を利用した DLL の動的管理クラス

従来の方法で DLL を管理するラッパークラスを作成して内部のメソッドを呼び出そうとした場合、少なくとも

  1. DLL 内部の関数型とそのポインターを定義
  2. GetProcAddress で取得したポインターを保持
  3. 内部で関数ポインタを呼び出すメンバー関数を定義

と言ったようなコードを記述する必要があるかと思います。

もちろんこれでも全然 OK なのですが、 DLL 内部の関数の数が増えてくるにつれ「自分一体何やってるんだろ…」感がふつふつと湧き上がって来ます。 (なぜなら似たようなコードをたくさん書く必要があるので)

このケースにおいても C++11 で導入された可変長テンプレート引数が希望の光を投げかけます。

従来の方法では色々とコードが増えがちだった DLL 管理のラッパークラスですが可変長テンプレート引数を利用してコードを共通化することで、記述量をかなり減らす事ができます。

実際に使用してみるとこんな感じです。

実際に使用するにはエラーチェックなどもう少し追加のコードが必要ですが、それでもかなり簡潔に記述できます。

Qt で作成したアプリケーションを Windows 向けに deploy する

クリーンな windows 環境で Qt アプリケーションを動作させるためには SDK の DLL や開発環境の runtime を持っていくだけでは不十分で実はほかにも色々とファイルが必要になります。
Windows 向けの Qt SDK には windeployqt.exe と言う実行ファイルの依存関係を解析して必要なファイルを集めてくれるツールが標準で付属しており、(Qt 関係のファイルに限ってですが)このツールを使うと面倒な deploy の作業を自動化することが出来ます。

Qt for Windows – Deployment

※ちなみに正しく deploy 出来ていない状態で実行ファイルを dependency walker にかけると以下の DLL が未解決になるようです。

  • API-MS-WIN-APPMODEL-RUNTIME-L1-1-0.DLL
  • API-MS-WIN-CORE-WINRT-ERROR-L1-1-0.DLL
  • API-MS-WIN-CORE-WINRT-L1-1-0.DLL
  • API-MS-WIN-CORE-WINRT-ROBUFFER-L1-1-0.DLL
  • API-MS-WIN-CORE-WINRT-STRING-L1-1-0.DLL
  • API-MS-WIN-SHCORE-SCALING-L1-1-1.DLL

例えば sample で付属している analogclock のプロジェクトを deploy するにはプロジェクトの release 出力ディレクトリへ移動し以下のようにします。

$windeployqt --release --libdir d:/deploy analogclock.exe

ちなみに mingw でビルドしたサンプルをこのコマンドでdeploy すると、 d:/deploy フォルダーの下には以下のようなファイルが集められます。

deploy

実行ファイル自身や他に使用している 3rd party 製のライブラリ DLL などは置いてけぼりですので、必要な物があれば別途持ってきましょう。

 

Qt 5.3.1 を MinGW 64bit (MinGW-w64) で ビルドする

Qt Project の wiki に幾つか情報は載っているのですが、開発ブランチで作業する人向けな内容だったり、そうでなかったり、イマイチまとまりに欠けると言うか分かりにくい部分がありますのでまとめてみました (ちなみに最新版のビルド記事はこちら)

○使用するツール一式

今回は以下のツールを使用しました。

  • mingw-w64 (x86_64-4.8.3-win32-seh-rt_v3-rev0)
  • starawberry prel 5.18.2 (64bit)
  • python 2.7.8 (64bit)
  • msys git version 1.9.4

また、それぞれ以下のパスにインストールを行いました。

  • C:\Qt\Tools\mingw-w64\x86_64-4.8.3-win32-seh-rt_v3-rev0;
  • C:\strawberry;
  • C:\Python27;
  • C:\Program Files (x86)\Git;

※もし違うパスにインストールする場合は以下の内容を適宜読み替えてください。

○ビルドの手順

(1) Tool 類のパスの設定
環境変数 PATH の先頭に以下の順序になるように使用するツール類のパスを追加します。

  • C:\Qt\Tools\mingw-w64\x86_64-4.8.3-win32-seh-rt_v3-rev0\mingw64\bin;
  • C:\strawberry\perl\bin;
  • C:\Python27;
  • C:\Program Files (x86)\Git\cmd;

※ strawberry perl のパスは git より前に追加されていないと、msys git に添付されている古いバージョンの perl が呼ばれてエラーになってしまいますのでこの二つの順番には注意して下さい (Make sure that Perl is added to the path in front of git since that ships an outdated version (Perl 5.8), which will cause the scripts to fail.)

(2) レポジトリの clone と checkout
まず msys git を立ち上げて以下のサーバーからレポジトリを clone します。

$git clone git://gitorious.org/qt/qt5.git qt5

リモートには幾つか branch が存在していますが、ここでは 2014/08/19 現在の最新リリースである 5.3.1 を checkout する事にします。

  • origin/5.3
  • origin/5.3.0
  • origin/5.3.1
  • origin/5.4
  • origin/HEAD -> origin/5.3
  • origin/dev
  • origin/stable

clone した qt5 ディレクトリに移動し、 branch 5.3.1 を checkout します。

$cd qt5
$git checkout 5.3.1

(3) レポジトリ内のフォルダーへのパスを環境変数 PATH へ追加
環境変数 PATH にさらに以下の3つのフォルダーへのパスを追加します。

  • qt5\qtbase\bin;
  • qt5\qtrepotools\bin;
  • qt5\gnuwin32\bin;

(4) レポジトリの初期化
コマンドプロンプトを立ち上げて qt5 フォルダー内の init-repository script を実行します。 上記の URL 内に 「Qt WebKit はサイズが大きくコンパイルに時間がかかる上、往々にしてコンパイルエラーの原因になるので、使用する予定がないのなら ダウンロードはお勧めしない」(This module is quite big, takes a long time to compile and is often a source of compile errors, so it is recommend to only download it if you intend to use it. You can always re-run init-repository later on to add it.) とありますので忠告に従い、今回は素直に –no-webkit オプションを指定します。

$perl init-repository --no-webkit

(5) configure スクリプトの実行
今回は以下のようにオプションを指定しました。

$configure -prefix C:\Qt\Qt5.3.1-build\mingw64-4.8.3 ^
-debug-and-release -opensource -confirm-license -platform win32-g++ ^
-c++11 -opengl desktop -nomake tests

(6) make
configure まで完了しましたので後は make するのみです。 環境にもよりますが、軽く1~2時間はかかると思いますので気長に待ちまましょう。

$make
$make install
$make docs
$make install_docs

以上の (1)~(6)をバッチファイルにしたのが以下です。 logfiles フォルダーを作って log を集めていますので、make が完了した後にエラーが出ていないか確認してください。

ビルドした SDK の使用方法についてはまた次回に…

Qt で MinGW-w64 を使用する際に必要になるスレッドモデルと例外機構の選択について

本家の MinGW プロジェクトでは host / target ともに 32bit gcc しかサポートされていないからだと思われますが、現在 Qt Project のページでは MinGW 64bit 向けの Qt SDK のバイナリと言ったものは提供はされていません。

http://qt-project.org/downloads

よって MinGW 64bit で Qt を使用したい場合は Qt SDK をソースから自前でビルドする必要があります。ちなみに Qt Project では 64bit 版の MinGW として Mingw-w64 project を推しているようですが。  Mingw-w64では個人でビルドしたもの (rubenvb と言うプロジェクトが有名だそう) や 、tdm-gcc や mingw-builds と言ったまた別のプロジェクトから集めてきたものを提供しているそうで所謂「公式ビルド」と言うものは存在していません。

http://qt-project.org/wiki/MinGW-64-bit

また、MinGW-w64 で提供されているバイナリは一種類では無く、例外機構とスレッディングモデルの違う複数のバイナリが提供されているため、自分でどれを使用するかを選択しなければなりません。

○ 例外機構

  • SJLJ (setjmp/longjmp)
    Cの標準ライブラリで、コンテキスト保存と大域分岐・復帰を行う setjmp/longjmp を使用した例外機構。例外がスローされない場合でもオーバーヘッドが存在し、例外を多用しているコードでは最大で 15% 程度パフォーマンスが低下する。32bit / 64bit のどちらのバイナリもこの方式に対応している。
  • DWARF (DW2, dwarf-2)
    デバッグ用フォーマットの DWARF を利用した例外機構。32bit のバイナリのみ対応。例外がスローされない限り実行時オーバーヘッドは無いが、呼び出される関数は全てDWARF が有効な状態でコンパイルされていなければ例外を搬送できない。 (なので例えば Windows の system 関連の DLL の中から例外が投げられるようなケースは NG)
  • SEH (zero overhead exception)
    windows 標準の構造化例外。GCC 4.8 の 64bit バイナリのみ対応。

○スレッドモデル

  • posix
    MinGW-w64 の winpthreads の機能を使うスレッドモデル。win32 向けの POSIX スレッドを使った実装も実験用ディレクトリの下に用意されている。主な目標は現時点で  POSIX スレッドの使用のみをサポートしている C++11 の標準スレッド関係の機能(thread, mutex, future) を提供する事。特定のシナリオでパフォーマンスが低下し、C++11 の機能についてはネイティブの win32 の実装はおろか MSVS2012 の実装よりもかなり遅い。
  • win32
    win32 ネイティブのスレッド関係の関数を使用。  C++11 の thread, mutex, future はサポートしないがパフォーマンス的には一番良い。

ちなみに Qtのページでは MinGW の 64bit  として gcc4.8 + seh + posix のパッケージがrecommended になっているようです。WIndows 向けの QThread の実装は win32 ネイティブの API を使用しているのだろう思っていたのですが、もしかしたら違うのかも…. 一度ソースを見て確認する必要あり。

—- 2014/11/12 追記 —
Qt 5.3.1 でソースを確認した所、Windows の QThread の実装には win32 ネイティブの API が使用されていました。