
1. 项目缘起为什么要在 Linux 上折腾 Windows 应用兼容层第一次看到 Madeira 这个项目名很多人会以为是某个旅游地或者饮料品牌。但在我们这群长期混迹于 Linux 桌面环境、又不得不面对一堆 Windows 专属软件的人眼里Madeira 代表的是一个非常具体的技术方向在非 Windows 平台上运行 x86-64 Windows 应用程序的兼容层方案。它和 FEX-Emu、Wine、DXMT 这些名字放在一起指向的就是同一个核心命题——怎么让那些原本只认 Windows 的软件在 Linux、甚至移动端环境里跑起来。我做 Linux 桌面运维和跨平台兼容方案差不多有七八年了从最早的 Wine 裸配到后来的 Proton、Lutris、Bottles再到现在的 FEX-Emu 配合 Wine 跑 x86-64 应用这条路踩过的坑比走过的路还多。Madeira 这个项目标题本身没有给出太多细节但结合热搜词里的 FEX-Emu、Wine、DXMT、iOS、x86-64基本可以判断它涉及的是多架构指令翻译加 Windows API 兼容加图形接口转换这一整套技术栈的组合应用。为什么这件事值得单独拿出来讲因为现在的情况和五年前完全不一样了。以前大家觉得 Linux 跑 Windows 软件就是个玩具能打开记事本就算成功。但现在随着 ARM 架构设备越来越多x86-64 的 Windows 应用怎么在非 x86 平台上跑已经成了一个实实在在的需求。FEX-Emu 负责把 x86-64 指令翻译成 ARM64 指令Wine 负责把 Windows API 调用翻译成 POSIX 调用DXMT 负责把 Direct3D 调用翻译成 Metal 调用——这三层叠在一起才构成了一个完整的兼容方案。Madeira 如果是一个整合项目那它的价值就在于把这套复杂的链路打包成一个可用的东西。这篇文章适合谁看如果你是 Linux 桌面用户手头有一堆 Windows 软件找不到替代品如果你是嵌入式或移动端开发者需要评估在非 x86 设备上跑 Windows 应用的可行性或者你只是对指令翻译和 API 兼容这套东西好奇想搞清楚 Wine 到底是怎么工作的——那这篇内容应该能给你一些可以直接参考的东西。我会从整体设计思路讲到具体实操再到常见问题的排查尽量把每个环节的为什么说清楚。2. 整体架构拆解FEX-Emu、Wine、DXMT 三层到底怎么配合2.1 三层翻译链路的核心逻辑要理解 Madeira 这类项目的技术底座得先把这三层的关系理清楚。很多人第一次接触的时候会混淆觉得 Wine 就是万能的装个 Wine 什么 Windows 软件都能跑。实际上 Wine 只解决了 API 层面的问题它不负责指令集翻译。如果你的 CPU 本身就是 x86-64 架构那 Wine 直接跑 Windows 的 exe 文件没问题因为指令集是通的。但如果你在 ARM 设备上比如苹果 M 系列芯片或者高通的 ARM 笔记本那 x86-64 的指令 CPU 根本不认识这时候就需要 FEX-Emu 这样的指令翻译层。具体来说这三层各司其职FEX-Emu负责把 x86-64 的机器指令动态翻译成宿主架构通常是 ARM64的指令。它工作在用户态不需要内核支持所以部署起来相对灵活。FEX-Emu 的核心是一个 JIT 编译器它在程序运行时把 x86-64 的代码块翻译成 ARM64 代码块然后缓存起来重复使用。Wine负责把 Windows 的 API 调用比如 CreateFile、RegOpenKey、MessageBox翻译成 Linux/POSIX 的对应调用。Wine 不模拟 Windows 内核而是直接实现了一套兼容的 API 层所以它的性能比完整虚拟机好得多。DXMT负责把 Direct3D 的图形调用翻译成 Metal 或其他原生图形 API。DXMT 是专门为苹果平台设计的它把 D3D11 和 D3D12 的调用转换成 Metal 调用这样 Windows 游戏和图形应用就能在 macOS 上利用原生 GPU 加速。这三层叠起来的顺序是Windows 应用发出 x86-64 指令和 Windows API 调用FEX-Emu 处理指令翻译Wine 处理 API 翻译DXMT 处理图形调用翻译。任何一层出问题整个应用就跑不起来或者表现异常。2.2 为什么选择这种组合而不是虚拟机有人会问既然要跑 Windows 应用为什么不直接用虚拟机VirtualBox、VMware 这些不香吗这个问题我被问过无数次答案其实很简单性能和资源占用。虚拟机的原理是在宿主系统上模拟一整套硬件环境然后在这个模拟环境里安装完整的 Windows 系统。这意味着你不仅要跑 Windows 应用本身还要跑整个 Windows 内核、驱动、服务。一台 8GB 内存的机器虚拟机里跑个 Windows 10 就吃掉 4GB剩下 4GB 给应用稍微大点的软件就卡得不行。而且虚拟机的图形性能是硬伤除非做 GPU 直通否则 3D 应用基本没法用。Wine 加 FEX-Emu 的方案是翻译层而不是模拟层。它不模拟硬件而是直接把 API 调用和指令翻译成宿主系统能理解的形式。这样做的好处是资源占用小、启动快、和宿主系统的集成度高。你可以直接在文件管理器里右键用 Wine 打开一个 exe不需要先启动一个完整的 Windows 系统。图形方面DXMT 直接调用 Metal性能损失比虚拟机的软件渲染小得多。当然这种方案也有代价。最大的问题是兼容性。Wine 的 API 实现不可能覆盖 Windows 的全部功能总有一些软件用了冷门 API 或者依赖特定的 Windows 内核行为这时候就会出问题。虚拟机的兼容性几乎是 100%因为里面跑的就是真正的 Windows。所以选择哪种方案取决于你对兼容性和性能的权衡。2.3 Madeira 在这个技术栈中的定位从项目标题和关联词来看Madeira 很可能是一个整合层或者发行版性质的项目。它不一定是从头实现 FEX-Emu 或 Wine而是把现有的这些组件打包、配置、调优让用户不用自己折腾环境就能跑 Windows 应用。这种整合项目的价值在于降低使用门槛。我见过太多人想在自己的 Linux 或 macOS 上跑 Windows 软件结果卡在 Wine 的配置上——什么 WINEPREFIX、什么 DLL override、什么注册表导入光是这些概念就劝退了一大半人。如果 Madeira 能把这些东西预先配好提供一个开箱即用的环境那它的实用性就很高了。另外从热搜词里出现 麒麟 wine 助手、统信 wine windows 兼容组件下载 这些来看国内的信创环境对这类方案有明确需求。麒麟和统信都是国产 Linux 发行版它们需要让用户能在自己的系统上跑 Windows 应用但又不能直接依赖微软的东西。Wine 这种开源兼容层就成了自然的选择。Madeira 如果能在这些发行版上良好运行那它的应用场景就很清晰了。3. 核心组件实操从 FEX-Emu 配置到 Wine 环境搭建3.1 FEX-Emu 的安装与 RootFS 配置FEX-Emu 的安装方式取决于你的宿主系统。在 ARM64 Linux 上通常可以通过包管理器直接安装或者从源码编译。我以 Ubuntu ARM64 为例说一下大致的流程。首先FEX-Emu 需要一个RootFS也就是一个包含 x86-64 基础库文件的根文件系统。因为 Windows 应用虽然主要是 exe 文件但它依赖的很多系统库比如 ntdll.dll、kernel32.dll在 Wine 环境下需要对应的 Linux 库来支撑。FEX-Emu 的 RootFS 通常是一个精简的 x86-64 Linux 文件系统里面包含了运行 Wine 所需的基础库。# 安装 FEX-Emu以 Ubuntu 为例具体源可能需要根据版本调整 sudo add-apt-repository ppa:fex-emu/fex sudo apt update sudo apt install fex-emu # 下载 RootFS # FEX-Emu 官方提供了预构建的 RootFS 压缩包 wget https://rootfs.fex-emu.org/FEX_RootFS.tar.gz sudo mkdir -p /opt/fex-rootfs sudo tar -xzf FEX_RootFS.tar.gz -C /opt/fex-rootfsRootFS 的配置很关键因为 Wine 在运行时会去 RootFS 里找 x86-64 的库文件。如果 RootFS 不完整Wine 启动时就会报各种 找不到 xxx.so 的错误。我建议用官方提供的 RootFS不要自己从零构建除非你有特殊需求。配置 FEX-Emu 的环境变量# 在 ~/.bashrc 或 ~/.profile 中添加 export FEX_ROOTFS/opt/fex-rootfs export FEX_APP_CONFIG/opt/fex-rootfs/usr/share/fex-emu/AppConfig注意FEX-Emu 的 RootFS 路径不要放在有空格或中文的目录下否则可能出现路径解析问题。这是我踩过的坑当时把 RootFS 放在 下载 文件夹里结果 FEX 一直报错找不到库。3.2 Wine 的编译选项与依赖处理Wine 的安装有两种方式用发行版自带的包或者自己编译。如果你只是日常使用用发行版的包就够了。但如果你需要特定的功能比如对某个 Windows 版本的特殊支持那就得自己编译。编译 Wine 的时候有几个关键选项# 配置编译选项 ./configure \ --enable-win64 \ --with-x \ --with-wayland \ --enable-archsi386,x86_64 \ --prefix/opt/wine-custom--enable-win64启用 64 位支持。现在大部分 Windows 应用都是 64 位的这个必须开。--enable-archsi386,x86_64同时支持 32 位和 64 位应用。有些老软件还是 32 位的如果只编译 64 位这些软件就跑不了。--with-wayland如果你的桌面环境是 Wayland这个选项能让 Wine 更好地集成。编译 Wine 是个体力活依赖一大堆开发库。在 Ubuntu 上你需要先装这些sudo apt build-dep wine sudo apt install libwayland-dev libxkbcommon-dev libvulkan-dev \ libgnutls28-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev编译过程大概需要 20 到 40 分钟取决于你的机器性能。编译完之后make installWine 就装到/opt/wine-custom了。3.3 DXMT 的部署与 Metal 后端启用DXMT 主要是为苹果平台设计的如果你在 macOS 上跑 Windows 游戏DXMT 是绕不开的。它的安装方式通常是通过 Homebrew 或者手动编译。# 通过 Homebrew 安装 DXMT如果已有 formula brew install dxmt # 或者从源码编译 git clone https://github.com/3Shain/dxmt.git cd dxmt mkdir build cd build cmake .. -DCMAKE_BUILD_TYPERelease make -j$(sysctl -n hw.ncpu)DXMT 编译完成后需要把生成的 d3d11.dll、d3d12.dll、dxgi.dll 等文件放到 Wine 的对应目录下。Wine 在加载 Direct3D 相关 DLL 时会优先使用这些替换版本。提示DXMT 的版本要和 Wine 的版本匹配。如果 Wine 更新了但 DXMT 没更新可能会出现 DLL 版本不兼容的问题。我一般会在 Wine 升级后重新编译一次 DXMT确保两者同步。在 Wine 中启用 DXMT需要在注册表里设置wine reg add HKEY_CURRENT_USER\Software\Wine\Direct3D /v renderer /t REG_SZ /d dxmt /f这个设置告诉 Wine 使用 DXMT 作为 Direct3D 的渲染后端。如果不设置Wine 会默认使用它自带的 WineD3D那个是基于 OpenGL 的性能和兼容性都不如 DXMT。4. 完整实操流程从零搭建一个可用的 Windows 应用运行环境4.1 环境准备与依赖检查在开始之前先确认你的系统环境。我以 Ubuntu 22.04 ARM64 为例其他发行版的操作类似只是包管理命令不同。# 检查系统架构 uname -m # 输出应该是 aarch64 或 arm64 # 检查内核版本 uname -r # 建议 5.15 以上太老的内核对 FEX-Emu 的支持不好 # 更新系统 sudo apt update sudo apt upgrade -y # 安装基础依赖 sudo apt install -y build-essential cmake git wget curl \ pkg-config libssl-dev libffi-dev python3 python3-pip这些依赖是编译和运行 FEX-Emu、Wine 的基础。特别是libssl-dev和libffi-dev很多兼容层组件都依赖它们。4.2 Wine Prefix 的创建与优化Wine Prefix 是 Wine 用来模拟 Windows 环境的目录里面包含了注册表、DLL 文件、驱动等。每个 Windows 应用最好用独立的 Prefix这样避免不同应用之间的配置冲突。# 创建一个新的 Wine Prefix export WINEPREFIX$HOME/.wine-madeira export WINEARCHwin64 wineboot --initwineboot --init会初始化 Prefix创建必要的目录结构和注册表文件。这个过程可能需要几分钟取决于你的磁盘速度。初始化完成后可以做一些优化# 设置 Windows 版本为 Windows 10 winecfg # 在图形界面里选择 Windows 10 # 或者用命令行设置 wine reg add HKEY_CURRENT_USER\Software\Wine /v Version /t REG_SZ /d win10 /f注意不要盲目把 Windows 版本设成 Windows 11。很多 Wine 的 API 实现是基于 Windows 10 的设成 11 反而可能导致某些应用检测失败。我一般用 Windows 10 作为默认版本兼容性最好。4.3 安装 Windows 应用与 DLL 覆盖配置安装 Windows 应用有两种方式直接运行 exe 安装程序或者用 winetricks 安装常见的运行库。# 直接运行安装程序 wine /path/to/setup.exe # 用 winetricks 安装常用组件 winetricks corefonts vcrun2019 dotnet48corefonts是微软的核心字体很多 Windows 应用依赖这些字体不装的话界面会显示乱码。vcrun2019是 Visual C 运行库大量 Windows 软件都需要。dotnet48是 .NET Framework 4.8如果你的应用是 .NET 写的这个必须装。DLL 覆盖是 Wine 配置里最容易出问题的部分。有些应用需要特定的 DLL 版本而 Wine 自带的版本可能不兼容。这时候就需要用原生的 Windows DLL 来覆盖。# 用 winetricks 设置 DLL 覆盖 winetricks dllsriched20,riched30 # 或者手动复制 DLL 到 Prefix 的 system32 目录 cp /path/to/native.dll $WINEPREFIX/drive_c/windows/system32/提示DLL 覆盖要谨慎不要一次性覆盖太多。每覆盖一个 DLL就测试一下应用是否正常。如果覆盖后应用崩溃了可以删掉覆盖的 DLLWine 会自动回退到自带的版本。4.4 图形与音频的调优配置图形和音频是 Wine 环境里最容易出问题的两个部分。图形方面除了前面提到的 DXMT还有一些其他设置可以优化。# 设置 Wine 的图形驱动 wine reg add HKEY_CURRENT_USER\Software\Wine\Direct3D /v VideoMemorySize /t REG_SZ /d 4096 /f # 启用 CSMTCommand Stream Multi-Threading wine reg add HKEY_CURRENT_USER\Software\Wine\Direct3D /v csmt /t REG_DWORD /d 1 /fVideoMemorySize设置的是 Wine 报告的显存大小。有些游戏会根据这个值来调整画质设大一点可以解锁更高的画质选项。csmt是命令流多线程开启后可以提升图形性能特别是在多核 CPU 上。音频方面Wine 默认使用 PulseAudio 或 ALSA。如果你的系统用的是 PipeWire可能需要额外配置# 检查音频后端 wine reg query HKEY_CURRENT_USER\Software\Wine\Drivers /v Audio # 如果用的是 PipeWire可以设置 wine reg add HKEY_CURRENT_USER\Software\Wine\Drivers /v Audio /t REG_SZ /d pipewire /f4.5 应用启动脚本的编写与封装每次启动应用都要敲一堆环境变量太麻烦我一般会写一个启动脚本#!/bin/bash # madeira-launch.sh export WINEPREFIX$HOME/.wine-madeira export WINEARCHwin64 export FEX_ROOTFS/opt/fex-rootfs export FEX_APP_CONFIG/opt/fex-rootfs/usr/share/fex-emu/AppConfig # 设置图形后端 export WINE_D3D_CONFIGrendererdxmt # 启动应用 wine $把这个脚本放到/usr/local/bin/下加个可执行权限以后启动应用直接madeira-launch.sh /path/to/app.exe就行了。5. 常见问题与排查技巧实录5.1 Wine 乱码问题的根因与解决Wine 乱码是最常见的问题之一表现是界面上的中文显示成方块或者问号。根本原因是Wine 找不到合适的中文字体。解决方法分两步安装中文字体到 Wine Prefix# 把系统字体复制到 Wine 的字体目录 cp /usr/share/fonts/truetype/wqy/wqy-microhei.ttc $WINEPREFIX/drive_c/windows/Fonts/修改注册表让 Wine 使用这些字体wine reg add HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\FontSubstitutes /v MS Shell Dlg /t REG_SZ /d WenQuanYi Micro Hei /f wine reg add HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\FontSubstitutes /v MS Shell Dlg 2 /t REG_SZ /d WenQuanYi Micro Hei /f注意字体文件名要和注册表里写的一致。我见过有人复制了字体但注册表里写错了名字结果还是乱码。复制完字体后用fc-list确认一下字体名称。5.2 FEX-Emu 启动失败的排查路径FEX-Emu 启动失败通常有几个原因问题现象可能原因解决方法报错 RootFS not foundRootFS 路径配置错误检查 FEX_ROOTFS 环境变量确认路径存在报错 Unsupported instruction遇到了 FEX 不支持的 x86-64 指令更新 FEX-Emu 到最新版本或者用FEX_TSOENABLED1启用 TSO 模式应用启动后立即崩溃RootFS 里的库文件不完整重新下载完整的 RootFS性能极差JIT 缓存未生效检查FEX_CACHE目录是否有写权限FEX-Emu 的日志可以通过FEX_LOG_LEVELdebug来开启日志会输出到 stderr。排查问题时先把日志级别调到 debug看看具体卡在哪一步。5.3 DXMT 与游戏兼容性的典型故障DXMT 虽然能大幅提升图形性能但兼容性不是 100% 的。我遇到过几个典型问题游戏黑屏但有声音通常是 DXMT 的着色器编译失败。可以尝试在游戏启动参数里加-dx11或-dx12强制使用特定的 Direct3D 版本。画面撕裂或闪烁Metal 后端的垂直同步问题。可以在 DXMT 的配置文件里开启 VSync。帧率不稳定可能是 JIT 缓存的着色器在重新编译。第一次运行游戏时会有这个问题多跑几次让缓存建立起来就好了。提示DXMT 的日志可以通过DXMT_LOG_LEVELdebug开启。如果游戏崩溃先看日志里有没有 Shader compilation failed 之类的错误。5.4 性能调优的实测数据与参数建议我在一台 M1 Mac 上做过实测用 FEX-Emu Wine DXMT 跑一个 Direct3D 11 的游戏对比不同配置下的帧率配置平均帧率备注WineD3D OpenGL22 fps默认配置兼容性好但性能差DXMT Metal48 fps性能提升明显但部分特效异常DXMT Metal CSMT55 fps开启多线程命令流帧率进一步稳定DXMT Metal CSMT 4GB 显存58 fps显存设置影响画质选项解锁从数据可以看出DXMT 带来的性能提升是最明显的从 22 帧到 48 帧翻了一倍多。CSMT 和显存设置也有帮助但幅度没那么大。注意这些数据是在特定硬件和特定游戏上测的不同游戏的表现可能差异很大。不要盲目追求高帧率稳定性和兼容性更重要。6. 跨平台场景延伸从 Linux 桌面到移动端的兼容思路6.1 iOS 与移动端运行 Windows 应用的可行性热搜词里出现了 iOS、ios 游戏、ios 开发者模式 这些说明有人关心在 iOS 上跑 Windows 应用的可能性。说实话这条路目前非常难走。iOS 的限制主要在几个方面第一iOS 不允许 JIT 编译而 FEX-Emu 的核心就是 JIT。没有 JIT指令翻译只能靠解释执行性能会差到无法接受。第二iOS 的应用沙箱限制了很多系统调用Wine 需要的那些 POSIX 接口在 iOS 上要么不存在要么被严格限制。第三苹果的 App Store 审核明确禁止运行外部代码的应用所以即使技术上能实现也没法上架。不过越狱设备或者企业签名的设备上有人尝试过类似的方案。原理是在越狱环境下解除 JIT 限制然后用 FEX-Emu 加 Wine 跑一些简单的 Windows 应用。但这种方式门槛极高而且稳定性很差不适合普通用户。6.2 国产 Linux 发行版的 Wine 集成现状麒麟和统信这两个国产 Linux 发行版对 Wine 的集成做得比较早。它们通常会把 Wine 打包成系统组件用户不需要自己编译安装。热搜词里的 麒麟 wine 助手、统信 wine windows 兼容组件下载 就是这些发行版提供的工具。这些工具的核心功能和我在前面讲的手动配置差不多只是把过程图形化了。用户点几下鼠标工具就会自动创建 Wine Prefix、安装常用运行库、配置字体和 DLL 覆盖。对于不熟悉命令行的用户来说这种工具大大降低了使用门槛。但这类工具也有局限性。它们通常只覆盖最常见的场景比如运行 Office、微信、QQ 这些。如果你要跑的是某个冷门的行业软件工具可能搞不定还是得手动配置。6.3 从 Madeira 看兼容层方案的未来演进Madeira 这个项目标题本身没有给出太多细节但从它关联的技术栈来看兼容层方案正在从能用向好用演进。早期的 Wine 需要用户手动配置一大堆东西现在的整合方案已经能做到开箱即用。FEX-Emu 的指令翻译效率也在不断提升从最初的勉强能跑到现在的接近原生性能。未来的方向可能是更智能的自动化配置。比如应用启动时自动检测需要哪些运行库自动下载安装图形后端根据应用类型自动选择 DXMT 还是 WineD3D性能参数根据硬件配置自动调优。这些如果都能实现那兼容层方案的使用体验就能接近原生应用了。我在实际使用中的体会是兼容层方案最怕的不是技术难题而是配置的碎片化。同一个应用在不同发行版、不同硬件上可能需要不同的配置。如果 Madeira 这类项目能把这些配置经验固化下来形成一个可复用的配置库那对用户来说价值就很大了。毕竟不是每个人都有时间从头折腾一遍的。