go-qmlをWindowsで使う

Windowsを含むクロスプラットフォーム対応で、Go言語でGUIを使う方法として、[go-qml](https://github.com/go-qml/qml "go-qml/qml")というものを試してみました。

今回は、以下の2つの環境を構築しました。

* 32bitアプリ構築環境  
  - Go 1.4.2 amd64 (32bit向けクロスコンパイル)
  - Qt 5.4.1 (MinGW 4.9.1 32bit版) 公式バイナリを利用。
* 64bitアプリ構築環境  
  - Go 1.4.2 amd64
  - Qt 5.4.1 (MinGW-w64 4.9.2 64bit版) MSYS2によるバイナリを利用。

※追記
本記事初出時はGo 1.4.2を使用していましたが、Go 1.5以降の使用を推奨します。（詳細は後述）


# 32bitアプリ構築環境

## Goの32bit向けクロスコンパイル環境の準備

64bit版のGoコンパイラを使って、32bit版バイナリをコンパイルするには、クロスコンパイル環境を準備する必要があります。「[golang でのクロスコンパイルの留意事項 — KaoriYa](http://www.kaoriya.net/blog/2015/03/06/ "golang でのクロスコンパイルの留意事項 — KaoriYa")」にあるように、64bit版のgccにパスが通っている必要があります。今回は、[MSYS2](https://msys2.github.io/ "MSYS2 installer")からgccをインストールすることにしましょう。

```sh:sh
pacman -S mingw-w64-x86_64-gcc
```

64bit版gccは、`C:\msys64\mingw64\bin`にインストールされるので、そこにPATHを通し、必要な環境変数を設定してmakeを実行します。

```batch:batch
set GOOS=windows
set GOARCH=386
path C:\msys64\mingw64\bin;%path%
cd %GOROOT%\src\
make
```

## Qtのインストール

[Qt - Download Open Source Step 3](http://www.qt.io/download-open-source/ "Qt - Download Open Source Step 3")から"Qt Online Installer for Windows"をダウンロードし、インストーラを実行します。
コンポーネントの選択画面で、Qt→Qt 5.4→MinGW 4.9.1 (32bit) OpenGL を選択し、インストールします。

![qt-setup.png](https://qiita-image-store.s3.amazonaws.com/0/59454/5246ea72-6cdf-97e2-0ce0-53f032119bc5.png)

既に、別のコンパイラ向けのQtをインストール済みの際は、スタートメニューからQt Maintenance Toolを実行し、パッケージマネージャを選択すると、この画面になります。

Qtは、`C:\Qt\5.4\mingw491_32`にインストールされます。また、依存関係により、32bit版MinGW 4.9.1が`C:\Qt\Tools\mingw491_32`にインストールされます。

### pkg-config用設定ファイルの修正

[go-qml > windows release build](https://groups.google.com/d/msg/go-qml/b49wjhT_6tk/TfFboNk-qBsJ) にあるとおり、QtのMinGW版公式バイナリは、pkg-configの設定ファイルが、デバッグ版DLLにリンクする設定となっています。
`C:\Qt\5.4\mingw491_32\lib\pkgconfig` にある `*.pc` ファイルを見ると、例えば、`Qt5Core.pc` の場合、`-lQt5Cored` のようにライブラリ名の末尾に `d` がついていることが分かります。
例えば次のようにして、末尾の `d` を削除することで、リリース版DLLにリンクするように出来ます。

```sh:sh
$ cd 'C:\Qt\5.4\mingw491_32\lib'
$ mv pkgconfig pkgconfig-debug
$ mkdir pkgconfig
$ cd pkgconfig-debug
$ for i in *.pc; do awk '{ if ($1 == "Libs:") { sub(/d *$/, " ", $0) } print }' $i > ../pkgconfig/$i; done
$ cd ../pkgconfig
$ unix2dos *.pc
```

## pkg-configのインストール

go-qmlをインストールするには、pkg-configが必要になります。これもMSYS2からインストールします。32bit版のpkg-configは、`C:\msys64\mingw32\bin`にインストールされます。

```sh:sh
pacman -Ssq pkg-config  # pkg-configという名前を持つパッケージを検索
pacman -S mingw-w64-i686-pkg-config
```

なお、`C:\msys64\usr\bin`にインストールされるMSYS2用のpkg-configは、パスの扱い(特に```\```)が異なるため使用できません。

## go-qmlのインストール

必要な環境変数を設定した上で、`go get`でgo-qmlをインストールします。Goのクロスコンパイル環境構築の際とは異なり、Qtと一緒にインストールされた32bit版MinGW 4.9.1を使用します。

```batch:batch
set GOOS=windows
set GOARCH=386
set QTDIR=C:\Qt\5.4\mingw491_32
rem pkg-configにパスを通す。
path c:\msys64\mingw32\bin;%path%
set PKG_CONFIG_PATH=%QTDIR%\lib\pkgconfig
rem QtとMinGWにパスを通す。
%QTDIR%\bin\qtenv2.bat
cd %GOPATH%
rem クロスコンパイル時は、cgoが使用可能であることを明示する必要あり。
set CGO_ENABLED=1
go get gopkg.in/qml.v1
```

エラーが出なければgo-qmlのインストールは完了です。

なお、`set CGO_ENABLED=1`を設定していない場合は、以下のようなエラーメッセージが表示されてしまいます。

```
can't build package gopkg.in/qml.v1 because it contains C++ files (all.cpp) but it's not using cgo nor SWIG
```

## サンプルプログラムのビルドと実行

```batch:batch
cd %GOPATH%\src\gopkg.in\qml.v1\examples\controls\gallery
go build -ldflags="-H windowsgui"
```

うまくいけば、`gallery.exe`が作成されますので、それを実行すると以下のような画面が表示されるはずです。

![qt-component-gallery.png](https://qiita-image-store.s3.amazonaws.com/0/59454/80dc98a0-1d3a-dc7c-bb6c-95131e418345.png)

ただしWindows版 Go 1.4.x（あるいはそれ以前）は、外部リンカが使えない制約があるため、go-qmlがクラッシュしてしまいます。Go 1.5以降を使えば問題ありませんが、Go 1.4.xを使う場合は「[Windows support (until external linking will be supported by go build) by neclepsio · Pull Request #149 · go-qml/qml](https://github.com/go-qml/qml/pull/149)」のPRを適用することで、Windowsでも動作するようになります。

```batch:batch
rem PR#149を取得し、ビルド&インストール。
cd %GOPATH%\src\gopkg.in\qml.v1
git checkout -b neclepsio_v1
git pull https://github.com/neclepsio/qml.git v1
go install -a

rem サンプルプログラムをビルド。
cd %GOPATH%\src\gopkg.in\qml.v1\examples\controls\gallery
go build -ldflags="-H windowsgui"
```

# 64bitアプリ構築環境

## Qtのインストール

QtのMinGW 64bitビルド環境は、Qtの公式インストーラからはインストールできません。そこで、MSYS2からQtをインストールすることにします。

```sh:sh
pacman -S mingw-w64-x86_64-qt5
```

## pkg-configのインストール

go-qmlをインストールするには、pkg-configが必要になります。これもMSYS2からインストールします。64bit版のpkg-configは、`C:\msys64\mingw64\bin`にインストールされます。

```sh:sh
pacman -S mingw-w64-x86_64-pkg-config
```

## go-qmlのインストール

必要な環境変数を設定した上で、`go get`でgo-qmlをインストールします。クロスコンパイルではないため、32bit環境に比べ、必要な環境変数はかなり少なくなっています。

```batch:batch
set GOOS=windows
set GOARCH=amd64
path c:\msys64\mingw64\bin;%path%
cd %GOPATH%
go get gopkg.in/qml.v1
```

## サンプルプログラムのビルドと実行

```batch:batch
cd %GOPATH%\src\gopkg.in\qml.v1\examples\controls\gallery
go build -ldflags="-H windowsgui"
```

うまくいけば、`gallery.exe`が作成されます。
Go 1.4.x以前を使用したために`gallery.exe`がクラッシュする場合は、32bit版と同様に、[PR#149](https://github.com/go-qml/qml/pull/149)を適用してください。


# Tips

ビルド時に`-ldflags`に`-s`を指定すると、デバッグシンボルが削除され、実行ファイルのサイズが小さくなります。

```
go build -ldflags="-H windowsgui -s"
```


# 参考サイト

* [qml - GoDoc](http://godoc.org/gopkg.in/qml.v1 "qml - GoDoc") -- go-qmlのドキュメント。
* [QML Applications | Qt 5.4](http://doc.qt.io/qt-5/qmlapplications.html "QML Applications | Qt 5.4")
* [Getting Started Programming with Qt Quick | Qt 5.4](http://doc.qt.io/qt-5/gettingstartedqml.html "Getting Started Programming with Qt Quick | Qt 5.4")
* [QML Tutorial | Qt Quick 5.4](http://doc.qt.io/qt-5/qml-tutorial.html "QML Tutorial | Qt Quick 5.4") -- QMLのチュートリアル。
* [Qt QML 5.4](http://doc.qt.io/qt-5/qtqml-index.html "Qt QML 5.4") -- QMLのドキュメント。
* [第351回　GoとQMLとGUIアプリ：Ubuntu Weekly Recipe｜gihyo.jp … 技術評論社](http://gihyo.jp/admin/serial/01/ubuntu-recipe/0351 "第351回　GoとQMLとGUIアプリ：Ubuntu Weekly Recipe｜gihyo.jp … 技術評論社")
* [golang でのクロスコンパイルの留意事項 — KaoriYa](http://www.kaoriya.net/blog/2015/03/06/ "golang でのクロスコンパイルの留意事項 — KaoriYa")
* [Go のクロスコンパイル環境構築 - Qiita](http://qiita.com/Jxck_/items/02185f51162e92759ebe "Go のクロスコンパイル環境構築 - Qiita")
* [Windows7 64bit版でGo言語のクロスコンパイルを試す - taknb2nchのメモ](http://d.hatena.ne.jp/taknb2nch/20140220/1392908216 "Windows7 64bit版でGo言語のクロスコンパイルを試す - taknb2nchのメモ")
* [How to install pkg config in windows? - Stack Overflow](http://stackoverflow.com/questions/1710922/how-to-install-pkg-config-in-windows "How to install pkg config in windows? - Stack Overflow")


# その他のGo用GUIライブラリ

その他のGo用のGUIライブラリとしては以下のようなものがあります。

* [gxui](https://github.com/google/gxui "google/gxui")  
  Google製。 ~~公開されたばかり。2015/03/22時点ではOpenGL 3.2が必須なため、[実行環境を選ぶ](https://github.com/google/gxui/issues/67)。~~ 開発停止。
  - [Go用のGoogle製のGUIツールキットgxuiのインストール - Qiita](http://qiita.com/shibukawa/items/549bc3af2232099112ac "Go用のGoogle製のGUIツールキットgxuiのインストール - Qiita")
  - [Go用のGoogle製のGUIツールキットgxuiのインストール(Windows版) - Qiita](http://qiita.com/sago35/items/cc9ed3dc38d0b2f19bf9 "Go用のGoogle製のGUIツールキットgxuiのインストール(Windows版) - Qiita")
* [ui](https://github.com/andlabs/ui "andlabs/ui: Platform-native GUI library for Go.")  
  "Platform-native GUI library for Go." とのこと。Windows/Unix/Macに対応している。非常に活発に開発が行われている。
* [GoQt](https://github.com/visualfc/goqt "visualfc/goqt: Golang bindings to the Qt cross-platform application framework.")  
  Qt4/5バインディング。[go-ui](https://github.com/visualfc/go-ui "visualfc/go-ui")の後継。
* [go-qt5](https://github.com/salviati/go-qt5 "salviati/go-qt5: qt5 bindings for go")  
  Qt5バインディング。[go-ui](https://github.com/visualfc/go-ui "visualfc/go-ui")からの派生。
* [qt: Qt binding for Go](https://github.com/therecipe/qt "therecipe/qt: Qt binding for Go (Windows / macOS / Linux / Android / iOS / Sailfish OS / Raspberry Pi)")  
  別のQtバインディング。QMLも含んでいる？
* [go-gtk](https://github.com/mattn/go-gtk/ "mattn/go-gtk: Go binding for GTK")  
  GTKバインディング。
* [gotk3](https://github.com/conformal/gotk3 "conformal/gotk3: Go bindings for GTK3")  
  GTK3バインディング。
* [wxGo](https://github.com/dontpanic92/wxGo "dontpanic92/wxGo: Golang wxWidgets Wrapper")  
  wxWidgetsバインディング。
* [wxGo](https://github.com/JeroenD/wxGo "JeroenD/wxGo: Go Wrapper for the wxWidgets GUI")  
  別のwxWidgetsバインディング。2011年から更新されていない。
* ~~[wxgo](https://github.com/kevin-yuan/wxgo "kevin-yuan/wxgo")~~  
  ~~別のwxWidgetsバインディング。MinGWでも動かそうとしているが動いていないらしい。~~ プロジェクト消滅
* [walk](https://github.com/lxn/walk "lxn/walk")  
  Windows専用。
  - [WindowsでGo言語でGUIするにはWALKがいいかもしれない - Qiita](http://qiita.com/alucky0707/items/b066ccd2ff8517cf79fb "WindowsでGo言語でGUIするにはWALKがいいかもしれない - Qiita")