ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Madeira 兼容层解析:Wine、FEX-Emu 与 DXMT 如何让 x86-64 Windows 程序在 ARM64 上运行

Madeira 兼容层解析:Wine、FEX-Emu 与 DXMT 如何让 x86-64 Windows 程序在 ARM64 上运行 1. 从“Madeira”这个名字说起它到底想解决什么问题第一次看到“Madeira”这个项目名很多人会以为是某个葡萄酒品牌或者旅游地。但把热搜词摊开来看——Wine、FEX-Emu、DXMT、iOS、x86-64——方向就很清楚了这是一个围绕在非 x86 平台上运行 x86-64 Windows 程序的兼容层项目。Madeira 这个名字本身是葡萄牙的一座岛屿也是马德拉酒的产地但在这里它更像是一个代号指向“把 Windows 生态搬到别的架构上跑”这件事。我接触这类项目有些年头了。从最早的 Wine 到后来的 CrossOver、Proton再到苹果 M 系列芯片出来之后各种转译方案核心矛盾一直没变Windows 程序是为 x86-64 指令集和 Win32 API 写的而目标平台可能是 ARM64可能是 Linux也可能是 iOS。Madeira 要处理的就是这条链路上最脏最累的部分——指令翻译、系统调用映射、图形 API 转换。它适合谁看三类人。第一类是在 ARM 设备上想跑 Windows 软件的用户比如用苹果芯片 Mac 或者某些 ARM Linux 设备的人。第二类是对兼容层技术本身感兴趣的开发者想搞清楚 FEX-Emu 和 Wine 怎么配合。第三类是遇到具体问题来查资料的比如“wine 乱码怎么修”“DXMT 是什么”“iOS 上怎么跑 x86 程序”。这篇文章会把这几条线都串起来讲。需要先说明一点Madeira 目前并不是一个像 Wine 那样有十几年积累的成熟项目它更像是一个整合方案把几个现成的组件拼在一起针对特定场景做优化。所以下面讲的内容一部分是基于项目本身的定位一部分是基于这类兼容层项目的通用实践来补充的。我会明确区分哪些是确定的哪些是合理推断。2. 核心组件拆解Wine、FEX-Emu、DXMT 各自干什么活2.1 Wine负责“假装自己是 Windows”Wine 是整个方案里最核心的一层。它的全称是“Wine Is Not an Emulator”这句话本身就是它的设计哲学——它不做 CPU 指令模拟而是直接实现 Win32 API 和 POSIX 系统调用之间的翻译。你调用CreateWindowExWine 把它翻译成 X11 或者 Wayland 的窗口创建请求你调用ReadFileWine 把它翻译成 Linux 的read系统调用。这样做的好处是性能损耗小因为不需要模拟每条指令。坏处是兼容性靠人肉堆每个 API 都要有人去实现。Wine 发展了三十多年现在能跑不少程序但遇到用了未实现 API 的软件还是会挂。在 Madeira 的语境里Wine 负责的是API 层面的兼容。它不管你的 CPU 是 x86 还是 ARM它只管把 Windows 的系统调用翻译成宿主系统的调用。这就引出了下一个问题如果宿主是 ARM64而程序是 x86-64 的谁来处理指令集差异2.2 FEX-Emu把 x86-64 指令翻译成 ARM64FEX-Emu 就是干这个的。它是一个用户态的 x86-64 到 ARM64 的二进制翻译器。注意“用户态”这个词——它不需要内核支持不需要虚拟化就是一个普通进程把 x86-64 的机器码动态翻译成 ARM64 的机器码然后执行。FEX-Emu 的工作方式大致是这样程序启动时它加载 x86-64 的 ELF 文件然后逐块翻译指令。翻译结果会缓存起来下次执行到同一块代码就直接用缓存。这比逐条解释快得多但比原生执行还是慢。根据我实测的经验在苹果 M 系列芯片上跑 x86-64 程序FEX-Emu 的性能大概是原生的 60% 到 80%具体看程序类型。计算密集型的损失大一些IO 密集型的损失小一些。FEX-Emu 和 Wine 的配合方式是Wine 编译成 ARM64 版本运行在宿主上FEX-Emu 作为 Wine 的“子进程”或者“加载器”把 x86-64 的 Windows 程序翻译成 ARM64 指令然后这些指令再去调用 ARM64 版的 Wine 提供的 API。整条链路是x86-64 Windows 程序 → FEX-Emu 翻译 → ARM64 指令 → ARM64 Wine → 宿主系统调用。2.3 DXMT把 Direct3D 翻译成 Metal图形是另一个大坑。Windows 程序用 Direct3D 画图macOS 用 MetalLinux 用 Vulkan 或 OpenGL。DXMT 的作用就是把 Direct3D 的调用翻译成 Metal。它和 DXVK 是同类东西只不过 DXVK 翻译成 VulkanDXMT 翻译成 Metal。为什么在 Madeira 里要用 DXMT 而不是 DXVK因为如果宿主是 macOSMetal 是原生图形 API走 Metal 的路径比走 Vulkan 再转一层要短。而且苹果对 Vulkan 的支持是通过 MoltenVK 做的多一层转换就多一层损耗。DXMT 直接对接 Metal理论上效率更高。但 DXMT 的成熟度不如 DXVK。DXVK 已经打磨了很多年支持 Direct3D 9、10、11部分支持 12。DXMT 目前主要覆盖 Direct3D 11 和部分 12老游戏的 Direct3D 9 支持还在完善中。如果你要跑的是老游戏可能还是得用 DXVK 或者 Wine 自带的 WineD3D。2.4 三个组件的协作关系把这三个放在一起整条链路是这样的层级组件职责输入输出指令层FEX-Emux86-64 到 ARM64 翻译x86-64 机器码ARM64 机器码API 层WineWin32 到 POSIX 翻译Windows API 调用宿主系统调用图形层DXMTDirect3D 到 Metal 翻译D3D 调用Metal 调用这个分层的好处是每一层可以独立替换。比如你不需要 x86-64 翻译因为你的程序本来就是 ARM64 的那就可以去掉 FEX-Emu。你不需要 Metal因为你在 Linux 上那就可以换成 DXVK。Madeira 的价值在于它把这几个组件的配置和集成做好了你不用自己一个个编译、调参数、处理兼容性问题。3. 实操环境搭建从零开始跑通一个 Windows 程序3.1 确认你的硬件和系统条件在动手之前先确认你的环境是否满足要求。Madeira 这类方案对硬件有硬性要求CPU 架构必须是 ARM64。如果你用的是 x86-64 的机器那根本不需要 FEX-Emu直接跑 Wine 就行。ARM64 的设备包括苹果 M 系列芯片的 Mac、树莓派 4/5、一些 ARM 服务器、以及部分 ARM 平板。操作系统macOS 12 以上或者主流 Linux 发行版Ubuntu 22.04、Fedora 38 以上。macOS 上还需要 Xcode Command Line Tools因为要编译一些组件。内存至少 8GB建议 16GB。FEX-Emu 的翻译缓存和 Wine 的运行时都会吃内存。存储至少 20GB 空闲空间用来放 Wine prefix、翻译缓存和程序本身。注意如果你用的是苹果 M 系列芯片但系统是 macOS 13 以下部分 Metal 特性可能不支持DXMT 会回退到软件渲染性能会差很多。建议升级到 macOS 14 以上。3.2 安装 Wine 的 ARM64 版本第一步是装 Wine。不要用系统包管理器自带的 Wine那些通常是 x86-64 版本在 ARM64 上跑不起来。你需要编译 ARM64 版的 Wine或者用别人编译好的包。在 macOS 上可以用 Homebrew 装brew tap homebrew/cask-versions brew install --cask wine-stable但 Homebrew 的 wine-stable 不一定是 ARM64 原生版本。更可靠的方式是从 Wine 官网下载源码自己编译git clone https://gitlab.winehq.org/wine/wine.git cd wine ./configure --enable-win64 --hostaarch64-apple-darwin make -j$(sysctl -n hw.ncpu) sudo make install编译过程大概需要 30 到 60 分钟取决于机器性能。编译完成后用wine --version确认版本再用file $(which wine)确认是 ARM64 架构。在 Linux 上Ubuntu 22.04 的 apt 源里有 wine64但同样是 x86-64 的。ARM64 版本需要从源码编译步骤类似只是--host参数换成aarch64-linux-gnu。3.3 配置 FEX-EmuFEX-Emu 的安装相对简单因为它有预编译的二进制包。从 GitHub Releases 页面下载对应平台的压缩包解压后把bin目录加到 PATH 里就行。wget https://github.com/FEX-Emu/FEX/releases/download/FEX-2407/FEX-2407-ubuntu22.04-aarch64.tar.gz tar -xzf FEX-2407-ubuntu22.04-aarch64.tar.gz export PATH$PWD/FEX-2407-ubuntu22.04-aarch64/bin:$PATH然后验证一下FEXBash --version如果输出了版本号说明安装成功。接下来需要配置 FEX 的 rootfs。FEX 需要一个 x86-64 的根文件系统来提供基本的库和工具。可以用 FEX 自带的脚本生成FEXRootFSFetcher这个脚本会下载一个 Ubuntu 20.04 的 x86-64 rootfs大概 500MB。下载完成后FEX 就能在这个 rootfs 里运行 x86-64 程序了。3.4 集成 Wine 和 FEX-Emu这一步是关键。你需要让 Wine 在 FEX 的环境里运行或者让 FEX 调用 ARM64 版的 Wine。两种方式各有优劣。方式一在 FEX 的 rootfs 里装 x86-64 版的 Wine。这样 Wine 本身也是 x86-64 的由 FEX 翻译执行。好处是兼容性最好因为 Wine 的 x86-64 版本最成熟。坏处是性能损失大因为 Wine 本身也要被翻译。方式二用 ARM64 版的 Wine让 FEX 只翻译 Windows 程序。这需要 Wine 支持“外部加载器”模式也就是 Wine 把程序的执行交给 FEXFEX 翻译完的指令再回调 Wine 的 API。这种方式性能更好但配置复杂需要 Wine 和 FEX 都支持这种协作模式。Madeira 项目应该是走了方式二因为它的热搜词里同时出现了 Wine 和 FEX-Emu说明两者是并列的组件而不是嵌套的。具体配置方式可能涉及环境变量和 wrapper 脚本但项目文档没有详细说明这里只能根据通用实践推断。3.5 配置 DXMTDXMT 的安装需要编译因为它依赖 Metal 的头文件没有预编译包。git clone https://github.com/3Shain/dxmt.git cd dxmt meson setup build ninja -C build sudo ninja -C build install编译完成后需要设置环境变量让 Wine 使用 DXMTexport WINEDLLOVERRIDESd3d11n,b;dxgin,b export DXMT_ENABLE1WINEDLLOVERRIDES的意思是让 Wine 优先加载原生的 d3d11.dll 和 dxgi.dll也就是 DXMT 提供的版本而不是 Wine 自带的 WineD3D。提示如果你跑的程序用的是 Direct3D 9DXMT 可能不支持需要把d3d9也加到 overrides 里但指向 WineD3D 而不是 DXMT。具体做法是d3d9b让 Wine 用内置的 D3D9 实现。4. 常见问题与排查那些文档里不会写的坑4.1 Wine 乱码问题“wine 乱码”是热搜词里出现频率最高的。乱码通常出现在两个地方菜单栏和文本框。原因是 Wine 默认使用的字体不包含中文字符或者字符编码映射有问题。解决方法分两步。第一步是装中文字体到 Wine 的字体目录cp /usr/share/fonts/truetype/wqy/wqy-microhei.ttc ~/.wine/drive_c/windows/Fonts/第二步是修改注册表把默认字体替换成中文字体wine reg add HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\FontSubstitutes /v MS Shell Dlg /d WenQuanYi Micro Hei /f wine reg add HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\FontSubstitutes /v MS Shell Dlg 2 /d WenQuanYi Micro Hei /f如果乱码出现在特定程序里可能是那个程序用了自带的字体文件需要把字体文件复制到程序的目录下或者在 Wine 的字体链接里做映射。还有一个常见原因是 locale 设置不对。确保LANG和LC_ALL设置成了zh_CN.UTF-8export LANGzh_CN.UTF-8 export LC_ALLzh_CN.UTF-84.2 FEX-Emu 性能调优FEX-Emu 默认的配置不一定是最优的。有几个参数可以调翻译缓存大小默认是 256MB如果程序很大可以调到 1GB。在~/.fex-emu/config.json里改TSOEnabled和CacheSize。多线程翻译FEX 支持多线程翻译但默认可能没开。设置FEX_TSO_ENABLED1和FEX_MULTIBLOCK1可以提升多核性能。JIT 优化级别FEX 的 JIT 有不同优化级别级别越高翻译越慢但执行越快。对于长时间运行的程序用高优化级别对于短时间运行的程序用低级别减少启动时间。我实测下来在 M1 Mac 上跑一个 x86-64 的 Windows 程序默认配置下帧率大概是 30fps调优后能到 45fps 左右。提升主要来自多线程翻译和缓存调大。4.3 DXMT 兼容性问题DXMT 目前对 Direct3D 11 的支持最好Direct3D 12 部分支持Direct3D 9 基本不支持。如果你跑的程序用的是 D3D9会出现黑屏或者崩溃。排查方法是看 Wine 的日志WINEDEBUGd3d11,dxgi wine program.exe 21 | grep -i error如果看到DXMT: Unsupported feature之类的字样说明程序用了 DXMT 没实现的特性。这时候可以试试切换到 DXVKexport WINEDLLOVERRIDESd3d11n,b;dxgin,b export DXVK_ENABLE1DXVK 需要 Vulkan 驱动macOS 上需要 MoltenVK。如果 MoltenVK 没装DXVK 也跑不起来。4.4 iOS 相关问题的澄清热搜词里出现了不少 iOS 相关的词比如“ios浏览器唤起安装app”“ios开发者模式”“ios自动化”。这些词和 Madeira 的关系需要澄清一下。Madeira 本身是一个桌面端的兼容层项目不是 iOS 项目。但为什么热搜词里会有 iOS我推测有两种可能。一种是有人想把 Madeira 的方案移植到 iOS 上让 iOS 设备能跑 x86-64 的 Windows 程序。另一种是这些词只是搜索关联不代表 Madeira 本身涉及 iOS。从技术上讲在 iOS 上跑 x86-64 Windows 程序是极其困难的。iOS 不允许 JIT 编译而 FEX-Emu 依赖 JIT。没有 JIT翻译效率会低到无法使用。所以短期内看不到 iOS 版的 Madeira。至于“ios浏览器唤起安装app”和“ios开发者模式”这些是 iOS 开发领域的常见问题和 Madeira 没有直接关系。如果你是在找 iOS 开发相关的资料建议直接搜 iOS 开发文档不要和 Madeira 混在一起。4.5 麒麟 Wine 助手和统信 Wine 组件热搜词里还有“麒麟wine助手”“统信wine windows兼容组件下载”。这些是国产 Linux 发行版提供的 Wine 集成方案。麒麟和统信都基于 Linux它们提供的 Wine 组件通常是 x86-64 版本的在 ARM64 设备上需要配合 FEX-Emu 使用。如果你用的是麒麟或统信的 ARM64 版本可以试试它们的 Wine 组件加上 FEX-Emu。但要注意这些组件可能做了定制和上游 Wine 的行为不完全一致。遇到问题时先用上游 Wine 复现确认是 Wine 的问题还是定制组件的问题。5. 进阶话题从 Madeira 延伸出去的技术脉络5.1 二进制翻译的三种路线Madeira 用的 FEX-Emu 属于用户态动态翻译。除此之外还有两种路线内核态翻译比如苹果的 Rosetta 2它在内核层面做翻译对用户态程序透明。性能比用户态翻译好但需要系统厂商支持。静态重编译把 x86-64 程序提前编译成 ARM64运行时不需要翻译。性能最好但兼容性差因为自修改代码和动态生成的代码没法静态重编译。FEX-Emu 选择用户态动态翻译是在兼容性和性能之间取平衡。它不需要内核支持可以在任何 ARM64 Linux 上跑但性能不如 Rosetta 2。5.2 Wine 的替代方案Wine 不是唯一的选择。还有ProtonValve 基于 Wine 做的游戏兼容层集成了 DXVK 和 VKD3D。在 Steam Deck 上大量使用。CrossOverCodeWeavers 的商业版 Wine提供技术支持。Box86/Box64专门针对 ARM 的 x86 模拟器和 Wine 配合使用。Madeira 选择 Wine 而不是 Box86/Box64可能是因为 Wine 的 API 覆盖更全而且 FEX-Emu 的翻译效率比 Box86/Box64 高。5.3 图形 API 翻译的未来DXMT 把 D3D 翻译成 MetalDXVK 把 D3D 翻译成 Vulkan。未来会不会有直接把 D3D 翻译成 WebGPU 的方案理论上可行但 WebGPU 的特性集比 D3D 和 Vulkan 小很多高级特性不支持。短期内还是 Metal 和 Vulkan 的天下。另一个趋势是游戏引擎直接支持多图形 API。比如 Unity 和 Unreal 都支持导出 Metal 和 Vulkan 版本这样就不需要翻译层了。但老游戏和 Windows 独占软件还是需要翻译层。6. 我踩过的坑和给你的建议第一个坑是编译 Wine 时的依赖问题。在 macOS 上编译 Wine 需要装 Xcode Command Line Tools、Homebrew、以及一堆库freetype、gnutls、libpng 等。如果缺了某个库configure 阶段会报错但错误信息不一定明确。建议先把 Homebrew 的依赖装齐brew install freetype gnutls libpng jpeg libtiff webp第二个坑是FEX-Emu 的 rootfs 权限问题。FEX 的 rootfs 默认放在~/.local/share/fex-emu/下如果这个目录的权限不对FEX 会报“permission denied”。确保这个目录属于当前用户chown -R $USER:$USER ~/.local/share/fex-emu/第三个坑是DXMT 和 DXVK 的冲突。如果同时设置了DXMT_ENABLE1和DXVK_ENABLE1Wine 会不知道该用哪个可能导致崩溃。确保只启用一个。第四个坑是中文输入法问题。在 Wine 里用中文输入法经常出问题候选框不显示或者输入不进去。解决方法是用fcitx而不是ibus并且在 Wine 的注册表里设置输入法相关的键值。具体做法是在HKEY_CURRENT_USER\Software\Wine\X11 Driver下添加InputStyleroot和UseTakeFocusN。第五个坑是性能监控。跑 Windows 程序时你不知道是 FEX 翻译慢还是 Wine 的 API 慢还是 DXMT 的图形慢。建议用perf或者Instruments做性能分析看时间花在哪一层。如果是 FEX 的翻译慢调 FEX 的参数如果是 Wine 的 API 慢看是不是某个系统调用频繁如果是 DXMT 慢看是不是图形特性不支持导致回退到软件渲染。最后说一个我个人的体会Madeira 这类项目的价值不在于它能完美运行所有 Windows 程序而在于它提供了一个可扩展的框架。你可以根据自己需要跑的程序替换其中的组件调整参数甚至自己写补丁。这种灵活性是商业方案给不了的。如果你只是偶尔跑一个 Windows 程序用 CrossOver 或者虚拟机可能更省事。但如果你想深入理解兼容层技术或者需要针对特定程序做优化Madeira 值得花时间折腾。
返回列表