首页 / Wails 入门教程 / 跨平台构建概览

Wails 入门教程

跨平台构建概览

本教程共 42 篇 · 第 32 篇 · 更新于 2026-08-03

Wails桌面开发跨平台构建GitHub Actions

32. 跨平台构建概览

本节目标

  • 说清楚 Wails 应用在三个操作系统上分别编译出什么东西
  • 理解「Go 能交叉编译,Wails 却不能随便交叉编译」这件事的根源
  • 记住每个平台构建前必须准备好的依赖
  • 会查 -platform 支持的取值表,知道 darwin/universal 是什么
  • 能搭一条 GitHub Actions 矩阵流水线,一次产出三平台产物

32-1 三个平台各自产出什么

先把结论摆出来。同一份 Wails 代码,在不同系统上执行 wails build,落到 build/bin/ 目录里的东西并不一样。

平台默认产物常见分发形式
Windows应用名.exe直接发 exe,或再生成 NSIS 安装包
macOS应用名.app(一个目录形态的应用包)打成 .dmg.zip
Linux无扩展名的可执行文件直接发二进制,或再做 deb / rpm / AppImage

有一点三端是一致的:前端资源被编译进了那个可执行文件里。构建时 Wails 会先跑 frontend:build,把 Vite 打出来的 HTML、JS、CSS 通过 Go 的 embed 塞进二进制。所以你不需要在 exe 旁边额外放一个 dist 文件夹。

Note

wails dev 时前端是从磁盘实时读取的,改一行 CSS 立刻生效;wails build 之后前端已经固化在二进制里,改磁盘上的文件不会有任何反应。这两种加载方式的区别在第 6 章讲过,构建阶段会再一次撞上它。

macOS 的 .app 需要单独说一句。它在 Finder 里看着像一个文件,实际是一个目录,里面有 Contents/MacOS/ 放可执行文件、Contents/Info.plist 放元数据、Contents/Resources/ 放图标。Wails 会用项目里的 build/darwin/Info.plist 来生成这份元数据。

Linux 那边最朴素,就是一个 ELF 可执行文件。但它不是完全自足的——运行时依赖系统上的 GTK3 和 WebKit2GTK 动态库,这点第 36 章会展开。

32-2 为什么 Wails 不能随便交叉编译

Go 的交叉编译好用到什么程度?设个 GOOS=windows GOARCH=amd64 就能在 Mac 上编出 Windows 程序。很多人第一次用 Wails 时会顺手试一下,然后发现编不过。

原因是 Wails 不是纯 Go 项目。它要调用各个平台的原生 WebView:

  • Windows 走 WebView2,底层是 COM 接口
  • macOS 走 WKWebView,底层是 Objective-C
  • Linux 走 WebKit2GTK,底层是 C 库

这些调用统统经过 CGO。一旦启用 CGO,交叉编译就需要目标平台的 C 工具链和头文件,成本陡增。所以官方的建议很直白:在哪个系统上分发,就在哪个系统上构建

Warning

网上能搜到一些「在 Linux 上交叉编译 Windows 版 Wails」的偏方,通常靠 mingw 或 Docker 镜像。它们在特定版本下可能跑通,但不在官方支持范围内,升级 Wails 或系统后很容易碎掉。生产项目别把发布流程压在这种方案上。

-platform 这个参数还有什么用?它的主要价值在同一个操作系统内切换架构。比如在 Apple Silicon 的 Mac 上编 Intel 版:

wails build -platform darwin/amd64

这条命令能跑通,因为 Xcode 命令行工具自带了两种架构的 SDK。但在这台 Mac 上写 -platform windows/amd64 就不行了。

32-3 各平台的构建前置条件

真正开始构建前,把依赖补齐。三个平台的清单如下。

Windows

  • Go 1.20 及以上
  • Node.js LTS(跑前端构建)
  • WebView2 Runtime(Windows 11 自带,Windows 10 部分机器需要装)
  • 如果要生成安装包,还需要 NSIS,见第 34 章

macOS

  • Go 1.20 及以上、Node.js LTS
  • Xcode 命令行工具,装法是 xcode-select --install
  • 要签名和公证的话,需要 Apple 开发者账号,见第 35 章

Linux

  • Go 1.20 及以上、Node.js LTS
  • gcc、pkg-config
  • GTK3 和 WebKit2GTK 的开发包

Debian 系的安装命令长这样:

sudo apt update
sudo apt install -y build-essential pkg-config libgtk-3-dev libwebkit2gtk-4.1-dev
Tip

拿不准环境齐不齐,跑一次 wails doctor。它会扫描系统、列出每个依赖的安装状态,缺什么直接告诉你安装命令。构建报错先看它,比对着报错信息瞎猜快得多。

32-4 platform 参数支持哪些取值

-platform 接受的值是「操作系统/架构」的组合,逗号分隔可以一次给多个。v2.13.0 支持的完整列表:

取值含义
darwinmacOS,架构跟随构建机
darwin/amd64macOS 10.13+ Intel
darwin/arm64macOS 11.0+ Apple Silicon
darwin/universal同时包含两种架构的通用二进制
windowsWindows 10/11,架构跟随构建机
windows/amd64Windows 10/11 x64
windows/arm64Windows 10/11 ARM64
linuxLinux,架构跟随构建机
linux/amd64Linux x64
linux/arm64Linux ARM64

darwin/universal 值得单独讲。它编出来的 .app 里塞了 Intel 和 Apple Silicon 两套机器码,两种 Mac 都能原生跑,代价是体积翻倍。对外分发 macOS 版本时一般就用它,省得维护两个下载链接。

只写 -platform windows 不写架构时,架构取 runtime.GOARCH,也就是构建机自己的架构。完全不给 -platform,则平台和架构都取构建机的。

32-5 用 GitHub Actions 一次产出三平台

不能交叉编译,难道要自备三台机器?不用。GitHub Actions 提供了三个平台的 runner,用矩阵策略跑一遍就够了。

下面这份工作流在推送 tag 时触发,三个平台并行构建,产物上传成 artifact:

name: Wails build

on:
  push:
    tags:
      - '*'

env:
  NODE_OPTIONS: "--max-old-space-size=4096"

jobs:
  build:
    strategy:
      fail-fast: false
      matrix:
        include:
          - os: ubuntu-latest
            platform: linux/amd64
          - os: windows-latest
            platform: windows/amd64
          - os: macos-latest
            platform: darwin/universal
    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

      - name: Install Linux deps
        if: matrix.os == 'ubuntu-latest'
        run: |
          sudo apt update
          sudo apt install -y build-essential pkg-config libgtk-3-dev libwebkit2gtk-4.1-dev

      - name: Install Wails CLI
        run: go install github.com/wailsapp/wails/v2/cmd/wails@v2.13.0

      - name: Build
        run: wails build -platform ${{ matrix.platform }} -clean

      - uses: actions/upload-artifact@v4
        with:
          name: app-${{ matrix.os }}
          path: build/bin/*

几个细节解释一下。

fail-fast: false 让三个平台互不牵连,Linux 编挂了不影响 Windows 那条线继续跑完。默认值是 true,一个失败会把其他任务全部取消,调试时特别烦人。

NODE_OPTIONS 那行是给 Node 提内存上限的。CI 环境内存紧,前端体积大一点就可能因为 OOM 挂掉,提前设好省事。

安装 CLI 时我固定写了 @v2.13.0 而不是 @latest。构建产物的可复现性比「永远用最新版」更重要,CLI 版本一漂,某天的构建结果就跟上周不一样了。

Note

社区还维护了一个现成的 Action:dAppServer/wails-build-action,把上面这些步骤打包好了。想少写点 YAML 可以直接用;想完全掌控每一步,就照上面这份自己写。

跑通基本流程后,通常还会往上加这些东西:依赖缓存(Go module 和 node_modules)、代码签名、把产物挂到 GitHub Release、从 tag 里抽版本号通过 -ldflags 注入程序。这些都是在同一份工作流上叠加,不用推倒重来。

常见误区

以为 -platform windows/amd64 能在 Mac 上用。 前面说过,它只在同系统内切架构有效。写了跨系统的值,构建会在 CGO 环节报错。

忘了 Linux runner 要装 WebKit 开发包。 GitHub 的 ubuntu-latest 镜像不预装 libwebkit2gtk-4.1-dev,少这一步必挂。

在 CI 里用 @latest 装 CLI。 短期没事,时间一长就会遇到「上周还好好的,今天 CI 红了」,排查起来毫无头绪。

以为 Linux 二进制能到处跑。 它依赖系统的 GTK3 和 WebKit2GTK,不同发行版的库名和 ABI 版本都不同。这块坑不小,第 36 章专门讲。

小结

Wails 的跨平台构建,核心约束就一条:目标系统上构建,别指望交叉编译。理解了这条,剩下的都是工程问题——本地补齐依赖,CI 上用矩阵覆盖三个平台。

产物形态三端各异:Windows 是 exe,macOS 是 app 包,Linux 是裸二进制。前端资源都嵌在里面,不用额外分发。

下一章把 wails build 的参数逐个拆开讲,包括本章反复出现的 -platform-clean,以及压缩、调试、跳过前端构建这些实用开关。