在Linux下使用Wine构建与测试Windows应用

在Wine环境中使用Meson/Vala构建GTK应用并进行测试

Posted by wszqkzqk on June 3, 2025
本文字数:6247

前言

许多开发者倾向于使用Linux作为主力开发环境,但在开发需要支持Windows平台的应用程序时,为了验证程序的跨平台兼容性,通常还需要切换到Windows下进行编译和测试,反复重启切换系统会非常不便。本文将介绍一种通用方法,通过配置Wine环境,在Linux下实现针对Windows平台的各类应用的构建测试。本文方法实际上不仅仅局限于特定的工具链与语言,也可以用于其他需要在Windows平台上构建的应用程序。通过这种方式,开发者可以在Linux环境下高效地完成Windows平台的构建与初步验证,甚至可以将Linux和Windows的构建集成到同一个工作流。

相比于开销较大的虚拟机等方式,Wine通过API转换层(Windows Syscall → Linux Syscall)直接执行原生x86指令,不涉及虚拟化或指令集模拟。Wine具有更短的系统调用路径、更低的上下文切换开销,还可以通过宿主调度器及文件系统直接管理资源,CPU、内存、硬盘IO的开销也明显更小。

通过Wine运行的纯CPU、无硬件加速的程序的性能大致与在Windows下运行的性能相当,甚至有时会更好(Wine对某些系统调用及内置函数的优化可能更好)。因此,Wine是一个非常适合在Linux下进行Windows平台应用开发和测试的工具。

为了具体说明这一流程,本文将以Windows下的GTK/Vala应用构建为例,讲解如何配置Wine环境来在Linux下实现其构建与测试。通过这种方式,开发者可以在Linux环境下高效地完成Windows平台的构建、分发与初步验证

安装Windows下的GTK/Vala开发环境

首先需要获取Windows下的开发环境,这个环节可能要处理很多依赖,在Windows下进行比较方便,可以在Windows下下载好后将环境复制或者挂载到Linux下使用。另外,在Windows下保有开发环境也是有必要的,因此本文先从Windows下的GTK/Vala开发环境安装讲起,再介绍如何在Linux下使用Wine来构建和测试。

如果读者有更好的获取方式,可以使用自己的方式获取并跳过这一部分。

MSYS2简介

在Windows下,GTK和Vala的开发环境可以通过MSYS2来安装。MSYS2是一个轻量级包管理系统,提供了类似于Arch Linux的包管理体验。MSYS2继承了Arch Linux的哲学设计,提供了大量的开源软件包,无论是日用的GIMP、VLC、Inkscape,还是开发用的GCC、Clang、Python等,都可以通过MSYS2轻松安装。

MSYS2的核心优势在于其对原生Windows应用的支持。不同于在Windows平台上提供Linux环境的WSL(Windows Subsystem for Linux),以及侧重于在Windows上模拟Unix环境的Cygwin,MSYS2的ucrt64/mingw64/clang64等mingw-w64环境构建的软件包是完全原生的Windows二进制文件

这意味着通过MSYS2安装的GTK、GCC/Vala编译器、Meson等工具链,这些工具本身以及编译出的应用程序都是真正的Windows本地应用,不依赖于MSYS2环境本身(除了msys环境中的基础Unix兼容工具依赖于msys-2.0.dll进行syscall映射)。这使其成为在Windows上进行原生开源软件开发(如GTK/Vala应用)的理想选择。许多知名的开源项目,例如Git for Windows、Inkscape、GTKWave、KeePassXC、Xournal++、Neovim和darktable等,都利用MSYS2来构建其Windows版本。1

安装MSYS2

MSYS2的安装非常简单,从官网下载即可一键安装。如果需要在Windows下对MSYS2进行更好的集成,可参考我之前的博客文章。当然,如果只是用于下载和安装GTK/Vala开发环境,默认安装完成后直接使用亦可。(推荐使用ucrt64环境)

安装软件包

在MSYS2中,GTK4/Libadwaita/Vala/Meson的开发环境可以通过以下命令安装:

pacman -S mingw-w64-ucrt-x86_64-gtk4 mingw-w64-ucrt-x86_64-libadwaita mingw-w64-ucrt-x86_64-gcc mingw-w64-ucrt-x86_64-vala mingw-w64-ucrt-x86_64-meson

如果希望使用其他工具链(如clangrust)、其他基础库(如Qt)、其他构建系统(如CMake)等,也可以通过类似的方式安装相应的包。

Linux下Wine环境的配置

在Linux下,我们可以通过Wine来提供Windows兼容环境,从而在Linux上构建和测试Windows平台的GTK/Vala应用。Wine是一个开源的兼容层,可以让Linux用户运行Windows应用程序。

安装Wine

在大多数Linux发行版中,Wine可以通过包管理器直接安装。在Arch Linux中,可以使用以下命令安装Wine:

sudo pacman -S wine

在Wine中配置路径

将Windows下的GTK/Vala开发环境(如MSYS2下的ucrt64目录)复制或者挂载到Linux下,并在Wine中配置相应的路径。

在Linux的终端中运行wine regedit命令打开Wine的注册表编辑器,找到:

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment

找到Path变量,如果有,则双击它并将MSYS2的ucrt64/bin路径添加到最后:

C:\windows\system32;C:\windows;<MSYS2路径>\ucrt64\bin

其中,具体路径可以使用winepath从Linux路径转换为Wine路径,例如:

winepath -w /mnt/msys64/ucrt64/bin

# 输出为:'Z:\mnt\msys64\ucrt64\bin\'

如果没有,则右键点击右侧窗格的空白区域

  • 选择 新建字符串值
  • 将新值命名为 Path,添加默认路径和MSYS2的ucrt64/bin路径:
    C:\windows\system32;C:\windows;<MSYS2路径>\ucrt64\bin
    

需要注意的是,由于Wine目前尚不能兼容依赖msys-2.0.dll非Windows原生的工具,因此不应该添加MSYS2的usr/bin路径到Wine的Path中。

防止环境变量干扰

很多时候(例如安装了flatpak的情况下),Linux下会设置$XDG_DATA_DIRS等XDG相关的环境变量,这些变量在Linux下与Windows下均会被GLib读取,但是Linux使用:分隔符,而Windows使用;分隔符。在Linux下运行Wine时,如果Wine继承$XDG_DATA_DIRS等变量,GLib等库中的实现会按照Windows的规则来处理,但实际上接受到的却是Linux的风格,程序将无法按照正确的分隔符拆分,导致程序无法正确解析系统数据路径。

因此,我们需要确保Wine不会继承Linux下的$XDG_DATA_DIRS等变量。如果没有必要使用这些环境变量,可以清除这些变量设置;如果需要使用,可以在Wine中覆盖该变量。同样使用wine regedit命令打开Wine的注册表编辑器,找到:

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment

右键点击右侧窗格的空白区域:

  • 选择 新建字符串值
  • 将新值命名为 XDG_DATA_DIRS,添加默认路径和MSYS2的ucrt64/share路径:
    C:\ProgramData;C:\users\Public\Documents;<MSYS2路径>\ucrt64\share
    

对于其他的环境变量(如XDG_CONFIG_DIRSXDG_CACHE_HOME等),可以使用类似的方式进行配置。

在Wine中构建

经过上述配置后,我们就可以在Linux下使用Wine来构建Windows平台的GTK/Vala应用了。由于相关路径已经添加到了Wine的环境变量中,我们可以直接在Linux终端中使用wine <命令>的方式来运行构建命令。这几乎只是在Linux的对应命令前加上一个wine,十分方便。

例如,配置Meson构建目录:

wine meson setup release --buildtype=release

使用Meson构建项目:

wine meson compile -C release

由于Wine对Python、Meson、Vala、GCC等工具的兼容性较好,在大多数情况下,使用这些命令可以直接在Wine环境中完成构建。

msys环境的依赖解决

禁用文档生成(推荐)

很多构建失败往往是文档等内容依赖了msys环境下的工具(如help2man)等。因为Wine目前无法运行依赖msys-2.0.dll的程序,我们并没有将msys环境的路径添加到Wine中,因此会找不到对应的程序而报错。此时可以通过关闭相关文档生成选项来解决。

wine meson setup release --buildtype=release -Dmanpages=disabled -Ddocumentation=disabled

具体选项视待构建的上游项目而定。

使用Linux原生工具代替(有风险)

由于msys中的工具都是POSIX下常用工具的移植版本,因此在Linux下也可以找到类似的工具来代替。比如help2man可以使用Linux下的help2man命令来代替,或者直接使用pandoc等工具来生成文档。可以在构建的时候临时将Linux的/usr/bin路径添加到Wine的Path的末尾。

不过这样做可能存在潜在风险,可能会导致某些工具的行为与预期不符,因此需要谨慎使用。

在Wine中测试

由于我们已经将相关路径添加到Wine的环境变量中,因此可以直接在Wine环境中运行测试程序,无论是GUI应用还是命令行工具。对于受支持的DE,如果配置了XDG打开方式,也可以直接双击.exe文件来运行应用。

笔者编写的GTK4/Vala示例应用,无论是否基于Libadwaita,在Wine下构建均较为顺利。但在测试运行的时候,显示与渲染上效果相对欠佳,基于Libadwaita的应用存在黑边,纯GTK4应用也有较小的黑边,两者在某些时候偶尔有闪烁现象,但整体上仍然可以正常运行和操作。

#~/img/wine/wine-solarangleadw.webp #~/img/wine/wine-solarangleadw-black.webp
基于Libadwaita的GTK4程序 基于Libadwaita的GTK4程序(深色模式)
#~/img/wine/wine-daylengthgtk.webp #~/img/wine/wine-solaranglegtk.webp
纯GTK4程序(1) 纯GTK4程序(2)

同样,非GUI的程序也可以这样构建与运行。笔者也测试了在Wine中构建出的这些程序在Windows下的运行情况,普遍较GUI的好,但是同样可能存在一些问题。以下是一些典型问题:

  • 在Linux下和较新Windows下可以通过ANSI转义序列直接控制终端输出颜色的程序,目前Wine则会将ANSI转义序列直接输出到终端,这是Wine中存在已久的已知问题。

    #~/img/wine/wine-live-photo-conv.webp
    默认情况下控制序列直接被输出(上),关闭颜色输出后则不再显示(下)
  • 非ASCII字符在GLib的-h/--help等帮助信息中无法正常输出,从第一个非ASCII字符开始输出被截断。其他输出一般正常。(甚至在其他地方打印的与--help一样的帮助信息也正常)但是同样都有可能因为非ASCII字符而导致输出被截断,在测试过程中应当尽量避免使用非ASCII字符

    #~/img/wine/wine-live-photo-conv-help.webp
    -h输出分别因为中文(上)和非ASCII的(中)而被截断,而非-h情况即使包含同样内容(下)也能正常输出
  • GStreamer的硬件加速解码不可用(但依赖CPU运算的基础功能在Wine下都能正常运行)。

    #~/img/wine/wine-live-photo-conv-gst.webp
    在Wine下运行的Live Photo转换程序,纯CPU完成的图片视频导出及元数据修改完全正常,但D3D硬件加速的逐帧导出解码在Gstreamer中卡住

    这一问题可以使用FFmpeg代替来解决。笔者的Live Photo转换程序也提供了FFmpeg后端,可以直接通过--use-ffmpeg使用,运行完全正常

    #~/img/wine/wine-live-photo-conv-ffmpeg.webp
    使用FFmpeg后端的Live Photo转换程序,能够正常逐帧导出

一般来说,Wine对GCC、Meson等基础构建工具的支持相当好,对非GUI的程序的支持一般也很不错。但是Wine对非常复杂的Win32 API调用(甚至像msys-2.0.dll这样的Hack)的支持可能并不理想。

由于基于GLib的程序一般都有原生Linux版本且往往表现比Windows版更好,因此Wine下GLib程序的某些高度依赖于平台的行为适配可能不太合适,需要开发者自行处理相关环境。

另外,由于图形界面渲染适配难度较大,复杂GUI程序兼容性风险往往相对更大。在笔者的示例中,几个GTK4/Vala应用(包括纯GTK4与基于Libadwaita的GTK4应用)在Wine下的运行效果都尚可接受,虽然有些小问题,但基本上可以使用。

总结

本文详细介绍了一种在Linux环境下通过Wine实现跨平台构建与测试Windows平台应用的通用方法,并以GTK/Vala应用为例展示了其具体实现。这种方法使开发者能够在仅使用Linux开发环境的情况下,高效验证各类应用在Windows平台的兼容性。

该方法能够显著简化需要支持Windows平台的应用的开发流程,使开发者能够在Linux环境下高效完成Windows平台的构建与初步验证,甚至可以将Linux和Windows的构建集成到同一个工作流。随着Wine和MSYS2等工具的持续改进,该工作流将更加完善,为各类应用的跨平台开发提供有力支持。

在结束本文前,我想分享对Wine定位的重新思考。曾经,我也将Wine视为单纯在Linux下运行Windows生态软件(如微信、QQ)的兼容层工具,但后来,我逐渐意识到它犹如一把双刃剑:短期虽能解决应用缺失的痛点,长期却可能削弱开发者适配原生Linux版本的意愿(毕竟“能用Wine运行”可能降低原生开发的意愿)。

而今,随着主流软件陆续推出原生Linux版本(如微信、QQ官方客户端),Wine运行方案的局限性愈发凸显:兼容性问题频发、性能远逊原生版本。这让我开始探索Wine更可持续的价值方向——将其转化为跨平台开发的基础设施

本文演示的实践正是这种转型的体现:通过Wine在Linux环境下直接构建、测试Windows原生应用,开发者既能保持使用自己习惯的Linux高效开发环境,又能无缝初步验证Windows平台兼容性。这种模式不仅可以提升开发效率(避免双系统切换),更重要的是,它聚焦于创造而非妥协——不再依赖Wine填补生态缺口,而是将其转化为赋能开源项目实现跨平台支持的技术桥梁。当开源开发者能如此便捷地在Linux下为Windows跨平台构建原生应用时,Linux桌面生态的长期繁荣,或许才能真正筑牢根基。

  1. 参考 MSYS2 Wiki 中的“Who is using MSYS2?”一文。