Wailsでデスクトップアプリを作る #6 ビルドと配布 — プラットフォーム別パッケージング

アプリが完成したので、残る仕事はひとつです。他の人のコンピュータで実行できる形にすることです。今回はwails buildが作り出す成果物の構造、プラットフォーム別のパッケージング、そしてWailsの配布で最もよくぶつかるクロスコンパイルの制約と、その解決策であるCIマトリックスビルドを扱います。シリーズの最終回です。

全 8 編(本編 6 編 + 応用 2 編)です。

  • #1 Wailsとは — Goで作る軽量デスクトップアプリ
  • #2 プロジェクト構造と開発ループ — wails devとバインディング
  • #3 Goとフロントエンドの連携 — メソッドバインディングとイベント
  • #4 システム統合 — ダイアログ・メニュー・ウィンドウ制御
  • #5 実践機能 — 設定の保存とエラー処理
  • #6 ビルドと配布 — プラットフォーム別パッケージング ← この記事

wails build — 単一バイナリ #

プロダクションビルドはコマンドひとつです。

プロダクションビルド
wails build
# 成果物: build/bin/ の下

この過程でフロントエンドがプロダクションモードでビルドされ、その結果がGoバイナリの中にembedされます。HTML、JS、CSSがすべて1つの実行ファイルに入るため、配布物の隣にアセットフォルダを別に置く必要はありません。wails devのホットリロードサーバーは開発専用で、ビルドされたアプリは内蔵アセットだけで動作します。

プラットフォーム別の成果物 #

ビルドを実行したOSによって、成果物の形が異なります。

プラットフォームデフォルトの成果物配布形態
Windowsアプリ名.exeそのまま渡すか、NSISインストーラー
macOSアプリ名.app バンドルdmgで包むか、zipで渡す
Linux実行バイナリそのまま渡す。ディストリのパッケージングは別途

Windows はexeひとつでも配布できますが、スタートメニューへの登録とアンインストール対応まで揃えるならインストーラーを作ります。WailsはNSISインストーラーの生成を組み込みでサポートしています。

Windowsインストーラーの生成
wails build -nsis

macOS の成果物は.appバンドルです。ここで現実的なハードルになるのがコード署名と公証(notarization)です。署名のないアプリはGatekeeperの警告を出し、公証まで済ませてはじめて、ダウンロードしたユーザーが警告なしに実行できます。Apple Developer Programのアカウント(年99ドル)とcodesignnotarytoolの手順が必要だという事実までがこのシリーズの範囲で、個人配布の段階ではzipで渡して右クリックで開く案内から始めるケースも多くあります。

Linux はバイナリがそのまま出力され、実行にはWebKitGTKライブラリがシステムにあることが必要です。ディストリビューションのパッケージ(deb、AppImageなど)にするのは別のツールの領域です。

アイコンとアプリのメタデータ #

プロジェクトのbuild/ディレクトリがパッケージングリソースの置き場所です。build/appicon.pngを差し替えるとビルド時に各プラットフォームの形式(icns、ico)へ変換されて組み込まれ、build/darwin/Info.plistbuild/windows/配下のファイルでプラットフォーム別のメタデータを調整します。アプリ名と成果物のファイル名はプロジェクトルートのwails.jsonで管理します。

wails.json — 主な項目
{
  "name": "wails-todo",
  "outputfilename": "wails-todo",
  "frontend:install": "npm install",
  "frontend:build": "npm run build"
}

クロスコンパイルの制約とCIマトリックスビルド #

Goはクロスコンパイルが自由な言語ですが、Wailsアプリは原則として対象OSの上でビルドする必要があります。各プラットフォームのWebViewとネイティブコードに依存しているためです。macOSからWindows向けをビルドする回避策も一部ありますが、公式の推奨はプラットフォーム別のビルドです。

3つのOSをすべて持っていなくても方法があります。GitHub Actionsのマトリックスビルドが、3つのプラットフォームのランナーでそれぞれビルドしてくれます。

.github/workflows/build.yml — マトリックスビルドの骨格
jobs:
  build:
    strategy:
      matrix:
        os: [windows-latest, macos-latest, ubuntu-latest]
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-go@v5
        with: { go-version: stable }
      - uses: actions/setup-node@v4
        with: { node-version: 20 }
      - run: go install github.com/wailsapp/wails/v2/cmd/wails@latest
      - run: wails build
      - uses: actions/upload-artifact@v4
        with:
          name: app-${{ matrix.os }}
          path: build/bin/

LinuxランナーではWebKitGTK開発パッケージをインストールするステップが追加で必要です。タグをプッシュすると3つのプラットフォームの成果物がリリースに添付される構成まで広げれば、ひとりでも3プラットフォームの配布を維持できます。

サイズとパフォーマンスの感覚 #

Wailsを選んだ理由が数字で確認できる地点です。ToDoアプリ規模のプロジェクトなら、成果物はおおよそ次の範囲に収まります。

  • Wails — バイナリは1桁MB台(フロントエンドのアセットを含む)。実行時にOSのWebViewを借りるため、ブラウザエンジンを抱えません。
  • Electron — 同じアプリでもChromiumとNode.jsを同梱するため、100MB台から始まります。

メモリ使用量も同じ構造的理由で軽くなります。ただしOSのWebViewを使うということは、レンダリングエンジンがOSのバージョンによって変わるという意味でもあるため、ごく新しいCSS機能は対象OSのWebViewバージョンを確認してから使う慎重さが必要です。

注記
Wails v3はこの記事の時点でアルファ段階にあり、マルチウィンドウ、システムトレイの改善、より柔軟なAPI構造を予告しています。このシリーズで扱ったバインディング、ランタイム統合、ビルドの概念はv3でもそのまま通用するため、v2で身につけた内容は移行コストなしに有効です。正式リリースの時点でマイグレーションガイドを確認すれば十分です。

シリーズ全体のまとめ #

全6回の要点を1行ずつ整理します。

  • #1 WailsはGoバックエンドとWebフロントエンドをOSのWebViewでまとめる、Electronより軽いデスクトップフレームワークです。
  • #2 wails devがホットリロードの開発ループを提供し、プロジェクトはGoルートとfrontendディレクトリに分かれます。
  • #3 Goのメソッドはバインディングでフロントエンドの関数になり、逆方向の通知はイベントとして流れます。
  • #4 ダイアログ、メニュー、ウィンドウ制御、クリップボードといったOS統合はruntimeパッケージが担当します。
  • #5 データはUserConfigDirに保存し、Goのerrorはフロントエンドの拒否されたPromiseにつながります。
  • #6 ビルドは単一バイナリとして出力され、プラットフォーム別ビルドの制約はCIマトリックスで解決します。

おわりに — そして応用 #

Web技術で画面を作り、Goでシステムを扱う組み合わせは、Web開発の経験がある人がデスクトップアプリに入っていく最もなだらかな道のひとつです。ここまでついてきたなら、アイデアを実行ファイルにして届けるまでの1サイクルを完走したことになります。

本編はここで終わり、応用の 2 編が続きます。本編でバニラで進めた前側をフレームワークに変える #7 フロントエンドフレームワークを付ける、そして詰まったときに原因を見つける #8 デバッグ です。一つのアプリを配信と完成度まで持っていく実践は、Wails 実践講座 で扱います。

X