最近、C++でGUIアプリケーションを開発したいなと思って少しだけ格闘してました。そこで詰まったことやら、分かったことなどを軽くまとめておきます。
そもそもアプリケーションを大雑把に分けると、CUIアプリケーションと、GUIアプリケーションの2つに分けられます。前者は「Character User Interface」の略で、後者は「Graphical User Interface」の略になっています。
C++で普通にint main(){...}
というようなコードを書いてコンパイルすると、CUIアプリケーションが出来上がります。ここでやりたいのは、そのようなCUIアプリケーションを作るのではなく、普段Webページを見るときに使っているようなブラウザや、PC内のファイルを確認するときに使うExplorer、Word、Excel、etc.といったように、マウス等でも操作できるようなアプリケーションを作ることです。
この記事では、wxWidgetsという外部ライブラリを利用してGUIプログラミングをやっていきます。ざっくりとした解説の流れは、「インストール、wxWidgetsの解説、実際のプログラム」といった感じで考えています。
なお、毎度のことながら、MSYS2環境で実行することを想定しています。バージョンは2022/1/3時点での最新版を使いましたが、どのバージョン以降であれば問題ないのかは分かりません(公式サイトに書いてありそうな気もしますが、調べてません)。もし上手くいかなかったら、最新版に更新していただければと思います。
※ここから、CUIとGUIについて軽く補足。すでに分かっている方は、最初の節まで飛ばしていただいても問題ないと思います。
CUIの「Character」という単語を見た方の中には、アニメやゲームのキャラクターを連想する方もいらっしゃるかもしれませんが、ここでの「Character」は「文字」という意味です。つまり「CUI」とは、文字を入力することで操作するインターフェイスということですな。
そして、「CUIアプリケーション」とは、コマンドラインから実行するようなプログラムの総称です。プログラムを組まない方や、プログラミングを勉強し始めた方だと、あまり馴染みがないかもしれませんが、Windowsに標準で装備されているコマンドプロンプトを開いていただければなんとなく雰囲気は分かるかと思います(「Windows+r」で、「ファイル名を指定して実行」という画面が表示されますので、そこに「cmd」と打ち込んで「Enter」を押していただければ、Windows11までならコマンドプロンプトが開くはずです)。
次にGUIを見てみると、「Graphical」という単語が使われていることが分かります。こちらも、パッと見た感じでは、「グラフ」という部分から、軸が2つあって、点とか線を描いたり、といったような数学で教わったいわゆる”グラフ”を連想する方もいらっしゃるかもしれません。
ですが、ここでの「Graphical」は「関数を図化したような」ではなく、「視覚的な」というような意味になります(日本語でも、たまにゲームとかで「グラフィック」みたいな言葉を使うことがありますが、そのグラフィックのような意味合いです)。なので、「GUI」は視覚的な操作で入力や出力を制御するようなインターフェイスということになります。
wxWidgetsのインストール
何はともあれ、まずはwxWidgetsをインストールしてみましょう。基本的なインストール方法はこちらに記載されていますので、その公式サイト通りに作業を進めていけば、基本的には問題なくwxWidgetsを導入できるかと思います。
もしWindows+Visual Studioという環境にwxWidgetsを導入したい場合でも、その公式サイトを見ていただければ、方法が書いてあります。
この記事では、MSYS2環境にwxWidgetsの静的リンクライブラリを導入することを目指します。動的リンクライブラリの場合でも、似たような操作で導入できるはずです。
まずは、インストール方法を確認します。wxWidgetsのgithubリポジトリがこちらにあるので、その中の「README-GIT.md」を見てみます。すると、次のように書かれています。
Please use
https://github.com/wxWidgets/wxWidgets/blob/master/README-GIT.md--recurse-submodules
option with the initialgit clone
. If you had already cloned the repository without this option, please rungit submodule update --init
to also get all 3rd party libraries code.
要するに、「git cloneコマンドを実行するときは、--recurse-submodules
というオプションを付けてね。もしくは、git cloneをオプションなしで実行した後に、git submodule update --init
というコマンドを後から実行してね」みたいなことです。なので、その指示通りにオプション付きで次のようなコマンドを実行します。
git clone --recurse-submodules https://github.com/wxWidgets/wxWidgets.git
ちなみに、オプションをつけ忘れた状態でmakeを実行すると、次のようなエラーが出ます。
configure: error:
Configured to use built-in PCRE library, but the file
../3rdparty/pcre/pcre2-config.in couldn't be found.
You might need to run:
git submodule update --init 3rdparty/pcre
to fix this.
これは、PCREというライブラリを使う必要があるけど、見つからなかったからビルドを完了できないよってエラーになります。なので、次のようなコマンドを実行する必要があります。
git submodule update --init 3rdparty/pcre && git submodule update --init 3rdparty/catch && git submodule update --init 3rdparty/nanosvg
(MSYS2のデフォルト設定のままなら、)ここまでが完了した時点で「C:/msys64/home/<ユーザー名>/」というディレクトリにwxWidgetsというフォルダが作られていると思います。後は、他のライブラリを使えるようにするときと同様に、以下の一連の操作で環境構築が完了します。
configure
スクリプトでmakefileを生成make
コマンドで生成されたmakefileを実行(ライブラリファイルの作成)make install
コマンドでライブラリファイルや、ヘッダファイルをMSYS2のlibフォルダやincludeフォルダにコピー
ただし、いくつか注意点やオプションの説明等があるので、それらを次の節以降で説明していきます。
ビルドディレクトリは作っておいた方が良さげ
上の節で説明したようなgit cloneコマンドが終わたら、後はcdコマンドでwxWidgetsのフォルダに入って、configureから順に進めていくだけなのですが、その注意点を説明します。
まず、素直にwxWidgetsフォルダで./configureとmakeをすると、カレントディレクトリ内に大量のファイルやらフォルダやら(wxWidgetsのライブラリを生成するためのオブジェクトファイルや、ライブラリを入れておくためのライブラリフォルダなど)が生成されます。
wxWidgetsのルート階層内に大量のファイルやフォルダが生成されると、後から見たときにどれが生成したもので、どれが生成に使ったものかが分かりにくくなります。それでは不便です。なので、生成されたファイルやフォルダを格納しておくためのフォルダを作って、その中にオブジェクトファイルやらライブラリファイルやらを生成していってくれた方がありがたいです。
これは公式でも次のように説明されています(MinGW Compilationという項目のUsing Configureの、手順1です)。
it is strongly recommended to not build the library in the directory containing the sources (
https://github.com/wxWidgets/wxWidgets/blob/master/docs/msw/install.md$WXWIN
) but to create a separate build directory instead.
要するに、「新しくビルドディレクトリを作った方が断然良いよ」と。
ここで推奨されているフォルダ構造を大雑把に図化すると、次のような感じ。
wxWidgets—色んなフォルダやファイル
|-ビルドした色々を格納するフォルダ—ライブラリフォルダとか
|-オブジェクトファイルとか
なので、僕は次のようなコマンドを実行しました。ただ、次のコマンドは、あくまでも「僕はこうした」という話であって、必ずしもこの通りにする必要はありません。ディレクトリ構成の参考になれば幸いです。
cd wxWidgets
mkdir BuildMSYS2
cd BuildMSYS2
mkdir Static && mkdir Dynamic
cd Static
mkdir debug && mkdir release
cd debug
MSYS2は、デフォルト設定では「C:/msys64/home/<ユーザ名>/」というディレクトリからスタートします。なので、まずはwxWidgetsの内部に入るために、1行目を実行します。
続く2行目で「BuildMSYS2」というフォルダを作っています(mkdir
コマンドは、カレントディレクトリ内にフォルダを作れというコマンドです)。先ほどの説明にあった「ビルドした色々を格納するフォルダ」というのがこれに当たります。
そして、そのフォルダの中に、さらに静的リンクに使うライブラリ用のフォルダと動的リンクに使うライブラリ用のフォルダを作りました。StaticというフォルダとDynamicというフォルダです。そして、Staticの中にdebugとreleaseというフォルダを作っています。
ここではDynamicの方にはフォルダを作っていませんが、もし動的リンクライブラリをビルドしたい場合は、Dynamicフォルダの中にもdebugとreleaseを作るといいかもしれません。カレントディレクトリをDynamicに移動させてから、Staticにいたときと同じコマンドを実行すればフォルダを追加できます。
ちなみに、上のコマンドを順に実行すると、フォルダ構成は次のようになります。
wxWidgets—色々なフォルダ
|-BuildMSYS2—Dynamic
|-Static —debug
|-release
そして、configureを実行してmakeを実行すると、カレントディレクトリに色々なファイル(それとフォルダ)が作られるので、カレントディレクトリを「wxWidgets/BuildMSYS2/Static/debug」にした状態でconfigureとmakeを実行することにします。
configure –disable-shared –enable-debugを実行
ディレクトリ構造を作りましたので、後はconfigureとmakeを進めていくだけです。
configureスクリプトを実行するときに使えるオプションはこちらや、こちらにまとめられています。どうやら、基本的には次の4つのオプションを操作すればよさそうです。
- –disable-shared
- –enable-monolithic
- –enable-unicode
- –enable-debug
これ以外にもオプションはありそうですが、よく分からなかったのと、特に必要性を感じなかったという理由で省略します。
ここでは静的リンクライブラリをビルドしたいので、–disable-sharedオプションが必要です。そして、ここではdebugをビルドすることにします。なので、–enable-debugオプションもつけることにします。
他の2つについてはデフォルト指定のままにしておきます。
なので、configure –disable-shared –enable-debugという感じで実行することになります。ただ、上の節のようなディレクトリ構成にしたので、カレントディレクトリを「wxWidgets/BuildMSYS2/Static/debug」にした状態で、次のようなコマンドを実行することになります。
../../../configure --enable-debug --enable-unicode --disable-shared
カレントディレクトリから、階層を3つ上がったところにconfigureがあるので、そのディレクトリにあるconfigureを指定しています。なんとなく–enable-unicodeも付けておきました。
configureスクリプトを実行すると、カレントディレクトリにmakefileが生成されます。なので、makeの実行は同じディレクトリで実行すれば、ライブラリファイル等の生成が始まります。
なので、上のconfigureスクリプトを実行したら、直後に次のコマンドを実行します。
make
これら、configureとmakeコマンドを合わせて次のようにして実行しても問題ありません。
../../../configure --enable-debug --enable-unicode --disable-shared && make
僕は連続で実行してくれる後者のコマンドの方を使いましたが、configureの結果が見づらくなってしまうので、どちらでもお好みでどうぞ。
make install
ここまでの操作を完了すれば、ライブラリを生成できているかと思います。なので、後はmake installを実行して、アプリケーション開発時に必要なファイルをMSYS2のライブラリディレクトリ等にコピーしましょう。特にオプションなどは必要なく、次のコマンドを実行するだけです。
make install
これで、MSYS2環境でwxWidgetsを使う準備が出来ました。
ただ、このmake installを実行するときに僕はかなり躓きました。というのも、make installを実行すると、13994行目で「予期しないファイル終了です」という表示が出て、エラーになったのです。
エラーを記録しておくのは忘れましたが、C:/msys64/usr/bin/shというファイルを実行しているときにエラーが出ていたようです。
shというものがよく分からなかったので調べてみると、シェルの一種だそうです。シェルにはいくつか種類があって、MSYS2でデフォルト設定になっているbashのほかに、shやzsh等があるらしいです。その中のshというものは、基本機能しか揃えていないシェルなのだそうな(bashよりも使える機能が少ないから、その分軽量なシェルとも言えそう。軽量性のために、わざわざshを使う必要は無いような気もしますが)。
そして調べてみると、どうやらmake installの中で、shが対応していないシェルコマンドが使われていたらしく、そのせいでエラーとなっていたようです。
正直なところ、適当に設定ファイルをいじっていたため、何をどう設定すればいいのかが分からなかったので、僕はMSYS2をアンインストールしてから、再インストールしました。おかげでwxWidgetsのconfigureからmake installまで不通に通るようになりました。よかったよかった。
サンプルを実行してみよう
wxWidgetsには豊富なサンプルが用意されています。なので、その中の一つを実際に動かしてみます。
ここでは、install.mdでも紹介されているminimal.cppをコンパイルして実行してみます。まずは、カレントディレクトリを「wxWidgets/BuildMSYS2/Static/debug/samples/minimal」に移動させます。
「samples/minimal」というディレクトリ内にmakefileが用意されているので、それを実行します。
もし、make installが終わった直後なら、次のようなコマンドを実行していただければ、サンプルをコンパイルできます。
cd samples/minimal
make
これで、「samples/minimal」ディレクトリにminimal.exeという実行ファイルが生成されます。それを実行しましょう。次のコマンドです。
./minimal.exe
いつもとは違うGUIが表示されたかと思います。個人的には、サンプルとは言え、C++プログラムでGUIアプリケーションを作れるということで、かなりワクワクしました。
まとめ
なぜそうしたのかを説明しながらの説明だったので、分かりにくいと感じた方もいらっしゃるかもしれません。なので、一応、この記事で実行したコマンドを次にまとめておきます。次のコマンドは、上から順に実行していただければと思います。
git clone --recurse-submodules https://github.com/wxWidgets/wxWidgets.git
cd wxWidgets
mkdir BuildMSYS2
cd BuildMSYS2
mkdir Static && mkdir Dynamic
cd Static
mkdir debug && mkdir release
cd debug
../../../configure --enable-debug --enable-unicode --disable-shared && make
make install
そして、続けてサンプルを実行する場合は次の通りにコマンドを実行してください。
cd samples/minimal
make
./minimal.exe
まぁ、想像通りというかなんというか、一つの記事に収まりませんでした。なので、次の記事以降で、wxWidgetsの具体的な使い方を解説していけたらと思います。
これも毎度のことながら、次の記事を実際に書いてみたら、まったく違った記事になる可能性はあります。が、一応、この記事を書いた時点では、次回記事でwxWidgetsの使い方を解説するつもりではあります。
P.S. この記事は、また何かしらのライブラリをインストールするときに問題が出たら、MSYS2自体をアンインストールするかもしれないので、そのときのための備忘録でもあります。