概要

Go + QtでGUIアプリ開発する環境を整えてみたのでメモを残しておきます。環境構築してサンプルを動かしただけで、開発はまだ全然進んでません。

Qtとは?

マルチプラットフォームなアプリケーション開発フレームワークです。GUI開発で有名だそうです。
Wikipediaによると登場したのは1992年となかなか歴史が長く、最新版の5.15が出たのが2020年5月26日(記事執筆日の25日前)と現在も活発に開発が進められている、いい感じのフレームワークです。

本来はC++で開発するようなのですが、他の言語でも使えるように多くのバインディングが提供されています。それでGoにも対応しているというわけです。

なぜGo?

macOSとWindowsの両方で動作し、なおかつランタイム不要なGUIアプリを作りたいと考えていたのですが、「マルチプラットフォーム」で「ランタイム不要」となるとGoだろうという先入観があり、調べてみたらQtとの組み合わせでいけそうだったので使ってみることにしました。
最近流行っているのはElectronでしょうし、Electronでも要件は満たせるわけですが、環境構築で躓いたので断念しました。
あとはJavaFXで作ってネイティブイメージ化する手もありますが、というか個人的なスキルセット(Javaで飯食ってる。Goは昔勉強したけど覚えてない)からするとそちらを選ぶべきなんですが、
せっかくの機会なのでJava以外の言語でもいろいろ作ってみたいという気持ちだったのでGoに決めました。
JavaFXは、開発がうまくいかなかった時の逃げ道、最後の手段として残しておきます。1

macOSでの環境構築

私はmacOS Catalinaを使っているので、そちらでの環境構築手順メモです。
公式のガイドを参考にしました。
https://github.com/therecipe/qt/wiki/Installation-on-macOS#homebrew-version-without-iosandroid-support

いくつか方法がありますが、簡単そうなHomeBrewを使った方法にしました。(ただし、HomeBrew版は罠があります。詳しくは後述)

まずXcodeとHomeBrewのインストールですが、これらは導入済みだったのでスキップしました。
ただ、環境変数として QT_HOMEBREW=true を設定する必要があります。
Catalinaから既定のシェルがzshになりましたが、私は引き続きbashを使っているので.bash_profileに追記しました。

echo "export QT_HOMEBREW=true" >> .bash_profile
source .bash_profile

続いてqt自体のインストールです。これは簡単です。それなりの容量のデータがダウンロードされるので、ネット環境によっては時間がかかるかもしれません。

brew install qt

お次はGoのインストールですが、昔入れたのが残ってたのでアップグレードしてみました。

brew upgrade go

(実際にはgoって打つの忘れたので全部アップグレードされて待たされました)
GOPATHとかも設定済みだったので特に作業なし。

そしていよいよQtバインディングのインストールです。

go get -v -tags=no_env github.com/therecipe/qt/cmd/...

... ってなんだろう、何か省略されているのかなと思ったのですが、そのままで大丈夫でした。

そしてセットアップコマンドの実行です。

$(go env GOPATH)/bin/qtsetup

最後に、適当なサンプルプログラムを作成して動作確認です。
なんとなく、こちらのサイトのソースを使わせていただきました。
https://tyablog.net/2018/02/03/go-qt-setup-for-macosx/

go build main.go

ビルドはけっこう遅いです。ビルドが終わったら実行してみます。

./main

Screen Shot 2020-06-20 at 23.22.32.png

参考サイトのと同じウィンドウが立ち上がりました。簡単ですね!

…と言いたいところだったのですが、私の場合はあちこちのサイトを参照して混乱したり、QT_HOMEBREWを設定する時にexportが抜けていたりしてたっぷり時間を無駄にしました。ご注意ください。

Windows版のバイナリを生成する(できるとは言っていない)

さて、冒頭のほうで書いたように、同じプログラムをWindowsでも動かしたいのです。幸い、Goはクロスコンパイルに対応しています。macOS上でWindows用の実行ファイルにコンパイルすることができるわけです。
そういうわけで早速試してみます。

GOOS=windows GOARCH=amd64 go build main.go

これでコンパイル…できませんでした!
あえて詳細には書きませんが、なんかよくわからないエラーが出ました。go buildではダメなのでしょうか。
別の方法を試してみました。

qtdeploy build windows

このコマンドの実行結果はこちらです。

FATA[0000] windows is not supported as a deploy target on darwin with HomeBrew/MacPorts/Nix -> install the official Qt version instead and try again

なんと、HomeBrew版だとWindowsの実行ファイルにコンパイルすることはできないとのこと…
上のほうで書いたHomeBrew版の罠とはこのことを指していました。困りました。2
まあ、「official Qt version」とやらであればサポートしていると読めるので、そちらも試してみます。
公式版の手順はこちらです。
https://github.com/therecipe/qt/wiki/Installation-on-macOS#official-version-with-iosandroid-support

…結果としてはダメでした。おそらく私の手順ミスか何かだと思うのですが、色々なエラーが出て、最終的にはどうしていいかわからなくなり諦めました。うまくいかなかった時の手順なんて書いても仕方ないので詳細には書きません。
気が向いたらまた試してみようと思います。(ただ、気が向かないので試さないということになるかも)

さて、困りました。Windowsでも動いてくれないと作る意味がないので…
ただ、対処方法がないわけではありません。

Windowsでの環境構築

はい、Windows上で環境構築すれば、当然Windows版の実行ファイルへコンパイルできるはずです。幸いWindowsのマシンも持っているので、そちらで試しました。
クロスコンパイルができるというGoの利点を活かせないのは残念ですが、ランタイム不要で動かせるという利点もありますから、それでもGoを採用する価値はあります。

それで、Windows版の環境構築ですが、こちらを参考にしました。(なぜ公式サイトを参照しなかったし…)
https://qiita.com/yupyom/items/030d99e81cea0afbdbe7

ちょっと長くなってきてしまったので簡単に書きます。
基本的に、Goのインストールからtherecipe/qtのインストールまで、参考サイトに通りに実施しました。
GOCHACHEは注釈の通り、C:\Users\your-name\AppData\Local\go-build にしました。
Qtインストール時のコンポーネントはどれが必要なのかわからなかったので、明らかにいらないとわかるものだけチェックを外して、それ以外は全部入れました。
あとはGitがないとかg++がないとか色々怒られたので、都度インストールして対応しました。
qtsetupはものすごく時間がかかりました。昼食の弁当を買いに行って、帰宅したら終わってました。

そして動作確認ですが、go build main.goだとバイナリは生成できましたが、起動時にdllの参照エラーになってしまいました。
最終的には、ソースがある場所でqtdeployを実行することでWindows版バイナリと必要なdllが生成され、実行できることを確認しました。
シングルバイナリではないのでなんかGoっぽくないですが、まあ配布にあたっては特に問題はないのでよしとします。

gui.png

なんか小さいですが、同じアプリを起動できました。

最後に

環境構築だけでものすごく時間がかかりました。ちょっと不本意な点もありますが、最低限の環境構築ができてよかったです。まあ、エディタをどうするとか、環境構築という意味ではまだ終わってないのですが…
たぶんVSCodeか、もしくはIntelliJ IDEAにプラグインを入れて使うと思います。GoLandというIDEもあるのですが、こちらは無償版がないのでちょっとハードルが高いです。

まあ、とにかく開発を進めないとですね。頑張ります。

参考


  1. JavaFXで盛大に躓く可能性もありますが… 

  2. まるでgo buildの後にすぐqtdeployを試したかのように書いていますが、実際にはエラーメッセージでググり、解決策を試して別のエラーが出て、またエラーメッセージでググり…というのを繰り返し挙句のことでした。