使用 Wails 进行交叉编译(2025)
摘要
一位开发者在 Ubuntu 上测试交叉编译 Wails v2.11.0 Svelte 应用,成功构建了 Windows 和 Linux 的可执行文件/安装程序,并指出了 Linux 静态链接的问题。
暂无内容
查看缓存全文
缓存时间: 2026/08/09 20:29
# 使用 Wails 进行交叉编译
来源:https://chriswheeler.dev/posts/cross-compilation-with-wails/
2025年12月9日,我在一台运行 Ubuntu 24、使用 Go v1.25.5 的 amd64 笔记本电脑上,测试了 Wails(https://github.com/wailsapp/wails)v2.11.0 官方 Svelte 模板的交叉编译。Wails 是一个基于 Go 的桌面应用框架。当然,随着 Wails 和 Go 的不断改进,未来的结果可能会有所不同。众所周知,Go 让交叉编译比大多数其他语言容易得多,而在使用像 Wails 这样的框架时,这一点大体上仍然成立。要为多个平台分别生成可执行文件和/或安装程序,有时只需在一条命令中列出这些平台即可:
``
wails build -clean -nsis \
-platform 'linux/amd64,windows/amd64,windows/arm64,windows/386'
``
上面的命令会生成以下文件:
``
build
└── bin
├── my-app-386.exe
├── my-app-amd64.exe
├── my-app-amd64-installer.exe
├── my-app-arm64.exe
├── my-app-arm64-installer.exe
└── my-app-linux-amd64
``
这样,我们就已经拥有了 Linux 和 Windows 的可执行文件和安装程序!我没有在平台列表中加入 macOS,因为 Apple 通常不允许交叉编译。我认为 Wails 或 Go 对此也无能为力。(当我把 darwin 加入列表时,该平台会被跳过,并显示消息 `WARNING Crosscompiling to Mac not currently supported`。)
当我意外地加入了一个不存在的平台时,我得到了一条有用的提示消息,内容如下:
``
Supported platforms: darwin,darwin/amd64,darwin/arm64,darwin/universal,linux,linux/amd64,linux/arm64,linux/arm,windows,windows/amd64,windows/arm64,windows/386
``
## 它们是静态链接的吗?
根据 Linux 的 `ldd` 命令(该命令打印共享对象依赖项),Windows 可执行文件和安装程序是静态链接的,而 Linux 可执行文件是动态链接的:
``
$ ldd build/bin/*
build/bin/my-app-386.exe:
not a dynamic executable
build/bin/my-app-amd64.exe:
not a dynamic executable
build/bin/my-app-amd64-installer.exe:
not a dynamic executable
build/bin/my-app-arm64.exe:
not a dynamic executable
build/bin/my-app-arm64-installer.exe:
not a dynamic executable
build/bin/my-app-linux-amd64:
linux-vdso.so.1 (0x00007ffdbe4c7000)
libglib-2.0.so.0 => /lib/x86_64-linux-gnu/libglib-2.0.so.0 (0x000079e7a3ff0000)
libwebkit2gtk-4.0.so.37 => /lib/x86_64-linux-gnu/libwebkit2gtk-4.0.so.37 (0x000079e7a0400000)
libgtk-3.so.0 => /lib/x86_64-linux-gnu/libgtk-3.so.0 (0x000079e79fc00000)
...
``
`file` 命令证实了这一点:
``
$ file build/bin/*
build/bin/my-app-386.exe: PE32 executable (GUI) Intel 80386, for MS Windows, 7 sections
build/bin/my-app-amd64.exe: PE32+ executable (GUI) x86-64, for MS Windows, 9 sections
build/bin/my-app-amd64-installer.exe: PE32 executable (GUI) Intel 80386 (stripped to external PDB), for MS Windows, Nullsoft Installer self-extracting archive, 7 sections
build/bin/my-app-arm64.exe: PE32+ executable (GUI) Aarch64, for MS Windows, 7 sections
build/bin/my-app-arm64-installer.exe: PE32 executable (GUI) Intel 80386 (stripped to external PDB), for MS Windows, Nullsoft Installer self-extracting archive, 7 sections
build/bin/my-app-linux-amd64: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=8ce9189206c3fc10a0fdfb874b0a5cd7b5f61ec7, for GNU/Linux 3.2.0, stripped
``
我尝试使用 `-ldflags '-extldflags "-static"'` 强制对 Linux 可执行文件进行静态链接,但遇到了许多错误,包括:
``
/usr/bin/ld: /tmp/go-link-3304063632/000004.o: in function `_cgo_77133bf98b3a_C2func_getaddrinfo':
/tmp/go-build/cgo_unix_cgo.cgo2.c:60:(.text+0x37): warning: Using 'getaddrinfo' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
``
也许仍然有办法强制对 Linux 可执行文件进行静态链接,但我目前还不知道。
## 那 `linux/arm64` 呢?
遗憾的是,目前从 `linux/amd64` 交叉编译到 `linux/arm64` 还不可行(见下面的输出)。我搜索了 Wails 的仓库,发现其他人也遇到了同样的问题。似乎没有变通方法。以下是输出:
``
$ wails build -platform 'linux/arm64'
Wails CLI v2.11.0
# Build Options
Platform(s) | linux/arm64
Compiler | /usr/local/go/bin/go
Skip Bindings | false
Build Mode | production
Devtools | false
Frontend Directory | /home/chris/repos/my-app/frontend
Obfuscated | false
Skip Frontend | false
Compress | false
Package | true
Clean Bin Dir | false
LDFlags |
Tags | []
Race Detector | false
# Building target: linux/arm64
• Generating bindings: Done.
• Installing frontend dependencies: Done.
• Compiling frontend: Done.
• Compiling application: # runtime/cgo
gcc_arm64.S: Assembler messages:
gcc_arm64.S:30: Error: no such instruction: `stp x29,x30,[sp,'
gcc_arm64.S:34: Error: operand size mismatch for `mov'
gcc_arm64.S:36: Error: no such instruction: `stp x19,x20,[sp,'
gcc_arm64.S:39: Error: no such instruction: `stp x21,x22,[sp,'
gcc_arm64.S:42: Error: no such instruction: `stp x23,x24,[sp,'
gcc_arm64.S:45: Error: no such instruction: `stp x25,x26,[sp,'
gcc_arm64.S:48: Error: no such instruction: `stp x27,x28,[sp,'
gcc_arm64.S:52: Error: operand size mismatch for `mov'
gcc_arm64.S:53: Error: operand size mismatch for `mov'
gcc_arm64.S:54: Error: operand size mismatch for `mov'
gcc_arm64.S:56: Error: no such instruction: `blr x20'
gcc_arm64.S:57: Error: no such instruction: `blr x19'
gcc_arm64.S:59: Error: no such instruction: `ldp x27,x28,[sp,'
gcc_arm64.S:62: Error: no such instruction: `ldp x25,x26,[sp,'
gcc_arm64.S:65: Error: no such instruction: `ldp x23,x24,[sp,'
gcc_arm64.S:68: Error: no such instruction: `ldp x21,x22,[sp,'
gcc_arm64.S:71: Error: no such instruction: `ldp x19,x20,[sp,'
gcc_arm64.S:74: Error: no such instruction: `ldp x29,x30,[sp],'
ERROR exit status 1
``
当我使用 `-compiler` 选项并指定 `go1\.24\.11` 或 `go1\.23\.12` 时,也会出现相同的错误消息。(你可以安装多个版本的 Go(https://go.dev/doc/manage-install)。)
## `dAppServer/wails-build-action` GitHub Action
Wails 的网站提供了一个用于构建可执行文件的 GitHub Action 示例(https://wails.io/docs/guides/crossplatform-build/),该示例使用了 `dAppServer/wails-build-action` 这个 action。我测试了这个示例,并已将其中的 actions 更新到最新的稳定版本。
以下几点可能会让一些人犹豫是否使用 `dAppServer/wails-build-action`:
- Wails 网站上的示例会失败,并出现错误消息 `ditto: Cannot get the real path for source './build/bin/App.app'`
- 针对该错误的修复已通过 pull request 提交到 `dAppServer/wails-build-action` 仓库,但已被忽略 5 个月,并且还在继续(示例:https://github.com/Snider/build/pull/49/files)
- 它采用 copyleft 许可证
- 该项目的大部分文档是由 LLM 撰写的
如果你在目标平台列表中保留 `darwin/universal`,就会出现上面提到的错误消息。(我测试时 Linux 和 Windows 的构建都成功了。)
## GoReleaser
GoReleaser(https://goreleaser.com/)是一个非常棒的工具,可以自动化发布,包括创建可执行文件和安装程序。不过,我无法让 Wails 与它配合使用。
以下是我尝试过的 `.goreleaser.yaml` 的一部分:
``
builds:
- id: "wails-build"
goos:
- linux
- windows
tool: "go1.23.12"
# how: https://go.dev/doc/manage-install
# why: https://github.com/wailsapp/wails/issues/4605
hooks:
post:
- wails build -clean -nsis -compiler 'go1.23.12' -platform 'linux/amd64,linux/arm64,windows/amd64,windows/arm64,windows/386'
- cp ./build/bin/. ./dist
``
然后我使用 `goreleaser release --snapshot --clean` 进行了测试,得到了这个错误:
``
⨯ release failed after 6s
error=
│ post hook failed: shell: 'wails build -clean -nsis -compiler 'go1.23.12' -platform linux/amd64,linux/arm64,windows/amd64,windows/arm64,windows/386': exit status 1: Wails CLI v2.11.0
│ # Build Options
│
│ Platform(s) | linux/amd64,linux/arm64,windows/amd64,windows/arm64,windows/386
│ Compiler | /home/chris/go/bin/go1.23.12
│ Skip Bindings | false
│ Build Mode | production
│ Devtools | false
│ Frontend Directory | /home/chris/repos/my-app/frontend
│ Obfuscated | false
│ Skip Frontend | false
│ Compress | false
│ Package | true
│ Clean Bin Dir | true
│ LDFlags |
│ Tags | []
│ Race Detector | false
│ # Building target: linux/amd64
│
│ • Generating bindings: ERROR
│
│ fork/exec /tmp/wailsbindings: no such file or directory
│ ERROR
│
│ fork/exec /tmp/wailsbindings: no such file or directory
``
使用 `go1\.24\.11` 时,以及不指定 `tool` 和 `compiler` 而使用 Go v1.25.5 时,我遇到了同样的错误。我搜索了 Wails 的仓库,查找可能对此有帮助的 issues、PR 等,但没有找到任何有希望的东西。也许有办法让它工作,但我目前可能会手动创建发布。
为了以防万一,该错误只在我运行 `goreleaser release --snapshot --clean` 时出现,而在 GitHub Actions 中运行时不会出现,我也尝试了后者。错误消息变了,但似乎仍然没有变通方法:
``
⨯ release failed after 5s
error=
Error:
相似文章
weblings:在 WASM 内部将 Rust 编译为 WASM
Weblings 是一个编译为 WebAssembly 的 Rust 编译器工具链,通过带有 playground 和 Rustlings 练习的网页 UI,支持在浏览器中直接编译和执行 Rust 代码。
将我的C游戏移植到WASM,这是我遇到的所有Bug
一位开发者分享了将C游戏移植到WebAssembly的经验,详细介绍了因32位与64位差异遇到的Bug,并提供了调试技巧。
@QuixiAI: 在推动跨平台的过程中,我创建了一个原生构建系统(Jai风格),并正在构建一个 --emit-c 选项来补充…
开发者创建了一个原生构建系统,并正在构建一个 --emit-c 选项以补充 'with migrate' 功能,旨在实现跨平台支持并消除 Makefile 和 shell 脚本。
我制作了一款用于在 WSL/Ubuntu 中管理 llama.cpp 的 Windows 应用
llama.cpp Console 是一款 Windows 桌面应用,提供图形界面来管理 WSL/Ubuntu 中的 llama.cpp,涵盖安装、构建、模型下载和服务部署。
在 Linux 和 Unix 系统上编译 Emacs 以提升性能的技术指南
本技术指南提供了在各类 Linux 发行版上从源码编译 Emacs 的详细步骤,旨在通过 CPU 特定指令集和 Wayland 等现代显示协议来优化性能。文中还涵盖了依赖项配置以及微调原生 Lisp 编译器以提升执行速度的相关内容。