Windows + Visual Studio で Static Link できる Qt をビルドする

はじめに
=======

Qt で作ったアプリケーションを頒布するときには必要な DLL も一緒に含めてあげる必要があります．`windeployqt`を使うことで自動的に必要なファイルを集めてくることは可能ですが，どうしても頒布するファイルが多くなってしまったり，ファイルサイズが大きくなってしまいます．Static Linkで作成することでファイルサイズを必要ない関数を取り除き減少させ，単一ファイルで頒布することが出来るようになります．WebKitやWebEngineは使えない，複数の Qt で書かれたプログラムを頒布する場合にはかえってファイルサイズが大きくなる，GPLの制限により全ソースコードを公開する必要がある，などいくつかの制約はありますが，実行ファイル1つで手軽に頒布したい場合には有効な手段になります．

なお，この記事の作成に使ったのは Windows 7, Visual Studio 2015 Express, Qt 5.5.1です．公式ドキュメントには perl や ruby とかが必要と書かれていますが，この記事の範囲であれば必要ありません．

ダウンロード
===========
まずはソースコードをダウンロードします．
![download.PNG](https://qiita-image-store.s3.amazonaws.com/0/56302/14fe42ca-de71-f62c-02d4-49a7a92a0689.png)

Windows 用の zip ファイルを入手します．下の split source packages from here. からいくつかリンクをたどると 7zip 版も入手できますので，帯域に余裕がない場合にはそちらの方が240MBくらい小さくて済みます．Linux/OS X版は中身が若干違うので流用はできません．
![download2.png](https://qiita-image-store.s3.amazonaws.com/0/56302/5d64403c-93f7-1a3c-30df-7597e2c16f4b.png)

また，ビルド用にVisual Studio 2015 Express for Windows Desktopもダウンロードしてインストールしておきます．Community版でも大丈夫なはずですが，ここではExpress版で紹介します．

ソースコードの展開
================

ソースコードを展開します．今回は`C:\Qt\build`に展開しました．インストールは`C:\Qt\static`以下にすることにします．

![downloaded.png](https://qiita-image-store.s3.amazonaws.com/0/56302/9a93d41c-f9e8-92d3-caa3-354aa24309b5.png)

Configure & Build
=================

ビルド用のディレクトリを`C:\Qt\build\5.5.1-msvc2015-x86-opengl`と`C:\Qt\build\5.5.1-msvc2015-x64-opengl`に作成します．ビルド用のディレクトリを別に作っておくことで，ビルドの設定を変えたものを複数作る時にソースを毎回展開し直す必要がありません．今回は 32 bit 版と 64 bit 版の両方を作りたいので分けておきます．

まず，Visual Studioのコマンドプロンプトを開きます．
![start.png](https://qiita-image-store.s3.amazonaws.com/0/56302/012f9034-436f-3b94-2c93-9ff68d5b2ed6.png)
32 bit版をコンパイルするときには「VS2015 x86 Native Tools コマンドプロンプト」を開き，64 bit版をコンパイルするときには「VS2015 x85 x64 Cross Tools コマンドプロンプト」を開きます．

「VS2015 x86 Native Tools コマンドプロンプト」を開き，以下のコマンドを実行します．この例は Open Source 版で GPL のライセンスをすでに確認した人用です．商用版ライセンスを選択する場合や，ライセンスの確認が必要な人は`-confirm-license -opensource`を除いて実行してください．

```ps1
cd C:\Qt\build\5.5.1-msvc2015-x86
..\qt-everywhere-opensource-src-5.5.1\configure.bat -prefix C:\Qt\static\5.5.1-msvc2015-x86-opengl -release -confirm-license -opensource -static -nomake examples -skip qtwebkit -skip qtwebkit-examples -skip qtquick1 -skip qtdeclarative -skip qtwebengine -skip qtwebchannel -no-angle -saveconfig config -opengl desktop
nmake
nmake install
```

ビルド中の進捗は`C:\Qt\build\5.5.1-msvc2015-x86\qtbase\lib`や`C:\Qt\build\5.5.1-msvc2015-x86`にあるファイルで確認できます．ビルドが進むに従ってここにファイルが増えていきます．

最後に`C:\Qt\static\5.5.1-msvc2015-x86-opengl`ができ上がればこれでビルドは完了です． 64 bit 版を作るときには「VS2015 x85 x64 Cross Tools コマンドプロンプト」を開き`x86`を`x64`に置き換えれば作ることが出来ます．ビルドだけであれば 32 bit 版 OS でも出来るはずです．ビルドが完了したら`C:\Qt\build\5.5.1-msvc2015-x86-opengl`はもう不要ですので削除しても構いません．ディスクを結構な量使用していますので削除してしまったほうが良いでしょう．他のマシンにコピーするときには`C:\Qt\static\5.5.1-msvc2015-x86-opengl`だけ持っていけばOKです．

![installed.png](https://qiita-image-store.s3.amazonaws.com/0/56302/3f8bd8c7-7e41-c228-258b-7233c036ab24.png)
<small>上のスクリーンショットでは`msvc-2012`になっていますが，ただの間違いです．ビルドし直すのも面倒なのでそのままにしてあります．以下同様です．</small>

Configuration Tips
------------------
今回はビルド時に WebKit など一部のものをビルドしないように設定しています．また， Example もこんなものをビルドする必要に迫られる人には不要でしょうから除外してあります．Qtにはいろいろなモジュールがありますが，実際に使うものは一部でしょうから必要なものにしぼることでビルド時間を節約できます．また，このビルドでは利用する OpenGL として Desktop 版を指定しています． Qt では [Angle](https://github.com/google/angle) という OpenGL ES 2 を Direct3D を使って再実装したものが利用可能ですが， OpenGL が不要であれば別のライブラリをリンクしなければならない Angle より追加ライブラリの必要ない Desktop 版 OpenGL を指定したほうが良いでしょう．もし，OpenGLが必要であれば必要に応じて適切な方を選択してください．

ドキュメントのビルド
------------------
ドキュメントはデフォルトではビルドされないので，別途ビルドする必要があります．Qtのオフィシャルバイナリをインストールしていれば不要ですが，必要場合には以下のようにしてビルドします．順番が違うと失敗するもしくは上手く参照できないかもしれません．

```ps1
nmake docs
nmake install_docs
nmake html_docs
nmake install_html_docs
nmake install_docs
```

上手くいけば`Assistant.exe`を使ってヘルプが参照できるはずです．（CSS が適用されていない気がしますが，たぶん perl か何かが足らないせいでしょう）

Qt Creator に認識させる
======================

最後にカスタムビルドしたものを Qt Creator から使えるようにする方法を紹介します．まず，「オプション」を開き，左のリストから「ビルドと実行」を選びます．次に「Qtバージョン」タブを開いて，「追加」をクリックします．`qmake`を選択するように言われますので，先ほどビルドしてインストールした`qmake`を選択しましょう．`C:\Qt\static\5.5.1-msvc2015-x86-opengl\bin\qmake.exe`あたりにあるはずです．追加できたら「適用」ボタンを押しましょう．一部のコンポーネントを除外してビルドしたので！が出ていますが，気にせず次に進みます．

![add2.png](https://qiita-image-store.s3.amazonaws.com/0/56302/cc387c00-fdac-93d7-7cbc-e0a0df63a5d1.png)


次に「キット」タブに移動し，「追加」ボタンを押します．下に名前などを設定する画面が出てきますので，設定していきます．まず，名前は適当な分かりやすい名前を付けましょう．次にコンパイラは「Microsoft Visual C++ Compiler 14.0 (x86)」を選択します（32 bit版の場合）．Visual Studio 2015はバージョン14.0に相当します．最後にQtバージョンで先ほど追加したQtを選択します．これで「OK」を押すと利用できるようになります．

![add3.png](https://qiita-image-store.s3.amazonaws.com/0/56302/e94f0fd4-6a29-9d8d-5c14-8d92edb6f620.png)


実際に利用するときにはプロジェクトを開いて，Qt Creatorのトップにある左のリストから「プロジェクト」を選択し，「キットを追加」から先ほど作ったキットを追加します．今回はリリースビルドしか用意しませんでしたので，ビルド時にはデバッグではなくリリースを選択してください．

Qt にパスが通ったコマンドプロンプトを簡単に開くバッチファイルを作る
==========================

以下のバッチファイルを用意しておくと Qt と Visual Studio にパスの通ったコマンドプロンプトを簡単に開くことが出来ます．ビルド用のスクリプトを用意しているような場合には，これを使うとお手軽でしょう．システム全体のパスに通すと予期せぬ挙動をおこしかねないので，バッチファイルを用意することをおすすめします．

32 bit 版
--------

```ps1
@echo off
echo Setting up environment for Qt usage...
echo Qt 5.5.1 and Visual Studio 2010 for x86
title Qt 5.5.1 VS2015 for x86
set PATH=C:\Qt\static\5.5.1-msvc2015-x86-opengl\bin;%PATH%
cd /D %HOMEPATH%
cmd /A /Q /K "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"
```

64 bit 版
--------

```ps1
@echo off
echo Setting up environment for Qt usage...
echo Qt 5.5.1 and Visual Studio 2010 for x64
title Qt 5.5.1 VS2015 for x64
set PATH=C:\Qt\static\5.5.1-msvc2015-x64-opengl\bin;%PATH%
cd /D %HOMEPATH%
cmd /A /Q /K "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86_amd64
```
Visual Studio の再頒布可能パッケージをどうにかする
========================
Visual Studio を使ってビルドすると再頒布可能パッケージを一緒にインストールしてもらう必要があります．ただ，ユーザーに別途インストールしてもらうのは難しい場合もあるので，それをどうにかする方法を紹介します．

頒布用のインストーラーを作る
-----------------------
もはやQtの話題ではないですが，私が作っている[Hyokai](https://github.com/informationsea/Hyokai/)では[WiX](http://wixtoolset.org/)を使って再頒布可能パッケージ込みのインストーラーを用意しています（せっかく単一バイナリで頒布可能なビルドを作ったのに，インストーラーを用意するのでは本末転倒ですが）．インストーラーのソースコードは[HyokaiInstaller.wxs](https://github.com/informationsea/Hyokai/blob/master/scripts/script-for-windows/installer/HyokaiInstaller.wxs)をごらんください（コピーして使う場合にはGUIDを被らないように書き換えてくださいね）．

```xml
 <Merge Id="vsr_x86" DiskId="1" Language='1033' SourceFile="C:\Program Files (x86)\Common Files\Merge Modules\Microsoft_VC140_CRT_x86.msm" />
```
という行で再頒布可能パッケージをインストーラーの中に組み込んでいます．

再頒布可能パッケージ不要なQtビルドを作る
----------------------

Visual Studio を使った場合のコンパイルオプションは`C:\Qt\build\qt-everywhere-opensource-src-5.5.1\qtbase\mkspecs\common\msvc-desktop.conf`に書かれています．このファイルの31行目あたりの

```
QMAKE_CFLAGS_RELEASE    = -O2 -MD
QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += -O2 -MD -Zi
QMAKE_CFLAGS_DEBUG      = -Zi -MDd
```

と書かれているあたりが，実際のビルド時のコンパイルオプションになります．[MSDN](https://msdn.microsoft.com/ja-jp/library/2kzt1wy3.aspx)に書かれている通り，`-MD`を指定するとランタイムライブラリのDLLが必要になります．これを`-MT`に書き換えてあげることで再頒布可能パッケージ不要なビルドを作ることが出来ます．これは Qt をビルドする前に指定する必要があり，すでにインストールした後で`mkspec`の中身を書き換えるとリンク時にエラーになりますのでご注意ください．