行x86-64 Windows程序:FEX-Emu與DXMT實(shí)戰(zhàn))
1. 項(xiàng)目緣起為什么要在 iOS 上折騰 x86-64 的 Windows 程序第一次看到 Madeira 這個(gè)代號(hào)是在一個(gè)折騰跨平臺(tái)兼容層的討論串里。當(dāng)時(shí)有人提到 FEX-Emu 和 DXMT 這兩個(gè)名字說(shuō)它們組合起來(lái)能在 Apple Silicon 的 Mac 上跑 Windows 的 x86-64 游戲和軟件而且性能比想象中好得多。我當(dāng)時(shí)的反應(yīng)是這不就是把 Wine 那套東西又往前推了一大步嗎先說(shuō)清楚 Madeira 到底是個(gè)什么定位。它不是某一個(gè)單獨(dú)的軟件而是一套技術(shù)路線的代稱——核心思路是在 ARM 架構(gòu)的蘋果設(shè)備上通過(guò)FEX-Emu做 x86-64 到 ARM64 的指令翻譯再通過(guò)DXMT把 Direct3D 調(diào)用翻譯成 Metal最后用Wine提供 Windows API 的兼容層。三者疊在一起目標(biāo)就是讓那些原本只能在 Windows 上跑的 x86-64 程序在 iOS 和 macOS 上能跑起來(lái)。為什么這件事值得關(guān)注因?yàn)檫^(guò)去在蘋果生態(tài)里跑 Windows 程序主流方案要么是虛擬機(jī)性能損耗大、資源占用高要么是遠(yuǎn)程桌面依賴網(wǎng)絡(luò)、體驗(yàn)割裂。而 Madeira 這條路線的野心在于不模擬完整的 Windows 系統(tǒng)只翻譯指令和 API 調(diào)用理論上能拿到更接近原生的性能。對(duì)于 iOS 設(shè)備來(lái)說(shuō)這意味著 iPhone 或 iPad 有可能直接運(yùn)行一些輕量級(jí)的 Windows 程序而不需要越獄或外接設(shè)備。適合誰(shuí)來(lái)參考這篇內(nèi)容如果你是對(duì)跨平臺(tái)兼容層感興趣的開(kāi)發(fā)者或者手頭有 Apple Silicon 設(shè)備想折騰 Windows 程序又或者你只是好奇 Wine 在 iOS 上到底能跑成什么樣那接下來(lái)的內(nèi)容應(yīng)該能給你一些實(shí)在的參考。我會(huì)盡量把原理講透把操作步驟拆細(xì)把踩過(guò)的坑都擺出來(lái)。提示本文討論的技術(shù)方案涉及編譯、簽名、側(cè)載等操作需要一定的命令行基礎(chǔ)和蘋果開(kāi)發(fā)者賬號(hào)。如果你只是想簡(jiǎn)單體驗(yàn)建議先從 macOS 版本入手iOS 端的限制會(huì)多不少。2. 核心組件拆解FEX-Emu、DXMT 和 Wine 各自扮演什么角色2.1 FEX-Emu把 x86-64 指令翻譯成 ARM64 的翻譯官FEX-Emu 是整個(gè)鏈條里最底層的一環(huán)。它的工作可以類比成同聲傳譯Windows 程序編譯出來(lái)的是 x86-64 指令而 Apple Silicon 芯片只認(rèn) ARM64 指令FEX-Emu 就在中間做實(shí)時(shí)翻譯。這里有個(gè)關(guān)鍵點(diǎn)需要理解FEX-Emu 不是傳統(tǒng)的模擬器。傳統(tǒng)模擬器會(huì)模擬一整套硬件環(huán)境每條指令都要走一遍 取指-譯碼-執(zhí)行 的完整流程開(kāi)銷很大。FEX-Emu 采用的是動(dòng)態(tài)二進(jìn)制翻譯加緩存的策略——第一次遇到某段 x86-64 代碼時(shí)把它翻譯成 ARM64 代碼并緩存起來(lái)下次再執(zhí)行同一段代碼就直接跑緩存省去重復(fù)翻譯的開(kāi)銷。實(shí)測(cè)下來(lái)這種方案在計(jì)算密集型任務(wù)上的性能損失大約在 20% 到 40% 之間具體取決于代碼特征。如果程序大量依賴浮點(diǎn)運(yùn)算或 SIMD 指令翻譯開(kāi)銷會(huì)更高如果是簡(jiǎn)單的邏輯控制流損失就小得多。FEX-Emu 還有一個(gè)值得注意的特性它支持64 位地址空間。這意味著它可以運(yùn)行那些需要大內(nèi)存的 x86-64 程序而不像某些 32 位翻譯層那樣受限于 4GB 地址空間。對(duì)于現(xiàn)代游戲和生產(chǎn)力軟件來(lái)說(shuō)這一點(diǎn)很關(guān)鍵。2.2 DXMT把 Direct3D 調(diào)用翻譯成 Metal 的圖形橋梁DXMT 解決的是圖形 API 的翻譯問(wèn)題。Windows 程序通常調(diào)用 Direct3D 來(lái)渲染畫面而蘋果設(shè)備用的是 Metal。DXMT 的工作就是把 D3D 的調(diào)用轉(zhuǎn)換成 Metal 的調(diào)用。為什么不用現(xiàn)成的方案因?yàn)橹?macOS 上跑 Windows 游戲主流是用 DXVK 把 D3D 轉(zhuǎn)成 Vulkan再通過(guò) MoltenVK 把 Vulkan 轉(zhuǎn)成 Metal。這條鏈路太長(zhǎng)了每一層轉(zhuǎn)換都有開(kāi)銷。DXMT 的思路是直接從 D3D 轉(zhuǎn)到 Metal少了一層中間商理論上延遲更低、兼容性更好。DXMT 目前主要支持 Direct3D 11 和部分 Direct3D 12 的特性。對(duì)于老游戲D3D 9 時(shí)代和較新的 3A 大作D3D 12支持程度不太一樣。我實(shí)測(cè)下來(lái)D3D 11 的游戲兼容性最好D3D 12 的游戲有些能跑但會(huì)有畫面異常D3D 9 的老游戲反而因?yàn)?Wine 自帶的 D3D 翻譯層已經(jīng)比較成熟不一定需要 DXMT。2.3 Wine提供 Windows API 的兼容層Wine 是整個(gè)方案里歷史最悠久的部分。它的作用是在非 Windows 系統(tǒng)上提供一套 Windows API 的實(shí)現(xiàn)讓 Windows 程序以為自己運(yùn)行在真正的 Windows 上。Wine 在 Madeira 方案里的角色是 膠水層它負(fù)責(zé)處理文件系統(tǒng)、注冊(cè)表、窗口管理、輸入輸出這些系統(tǒng)級(jí)調(diào)用把 Windows 程序的請(qǐng)求翻譯成宿主系統(tǒng)能理解的操作。FEX-Emu 負(fù)責(zé)指令翻譯DXMT 負(fù)責(zé)圖形翻譯Wine 負(fù)責(zé) API 翻譯三者各司其職。這里有個(gè)常見(jiàn)的誤解很多人以為 Wine 是模擬器其實(shí)不是。Wine 的全稱是 Wine Is Not an Emulator它不模擬硬件只翻譯 API。所以在 x86-64 的 Linux 上跑 x86-64 的 Windows 程序Wine 幾乎沒(méi)有性能損失但在 ARM 設(shè)備上跑 x86-64 程序就需要 FEX-Emu 這樣的指令翻譯層來(lái)補(bǔ)足架構(gòu)差異。2.4 三者的協(xié)作關(guān)系把這三個(gè)組件串起來(lái)看一個(gè) Windows 程序的執(zhí)行流程大致是這樣的程序啟動(dòng)Wine 加載 PE 文件初始化 Windows API 環(huán)境程序代碼被 FEX-Emu 翻譯成 ARM64 指令并緩存程序調(diào)用 Direct3D 渲染時(shí)DXMT 把調(diào)用轉(zhuǎn)成 MetalWine 處理窗口創(chuàng)建、輸入事件、文件讀寫等系統(tǒng)調(diào)用最終畫面通過(guò) Metal 渲染到屏幕上這個(gè)鏈條里任何一環(huán)出問(wèn)題程序就跑不起來(lái)。所以排查故障時(shí)需要先判斷是哪一層出了問(wèn)題——是 FEX-Emu 翻譯失敗還是 DXMT 圖形轉(zhuǎn)換出錯(cuò)還是 Wine 的 API 實(shí)現(xiàn)有缺失。3. iOS 端的特殊挑戰(zhàn)為什么比 macOS 難搞得多3.1 沙盒限制與 JIT 權(quán)限iOS 和 macOS 最大的區(qū)別在于沙盒機(jī)制。macOS 上你可以相對(duì)自由地編譯、運(yùn)行、調(diào)試程序而 iOS 上每個(gè) App 都運(yùn)行在獨(dú)立的沙盒里不能隨意訪問(wèn)系統(tǒng)資源也不能動(dòng)態(tài)生成可執(zhí)行代碼。這對(duì) FEX-Emu 來(lái)說(shuō)是致命的FEX-Emu 需要JIT即時(shí)編譯權(quán)限才能把 x86-64 指令翻譯成 ARM64 指令并執(zhí)行。而 iOS 默認(rèn)不允許普通 App 使用 JIT只有 Safari 和少數(shù)系統(tǒng)組件有這個(gè)特權(quán)。那怎么繞過(guò)這個(gè)限制目前主要有兩條路使用開(kāi)發(fā)者模式在 iOS 16 及以上版本開(kāi)啟開(kāi)發(fā)者模式后某些調(diào)試場(chǎng)景下可以申請(qǐng) JIT 權(quán)限。但這需要設(shè)備連接 Xcode而且每次重啟后都要重新授權(quán)。使用 TrollStore 等永久簽名工具這類工具利用系統(tǒng)漏洞給 App 授予特殊權(quán)限包括 JIT。但這對(duì)系統(tǒng)版本有嚴(yán)格要求而且隨著 iOS 更新漏洞會(huì)被封堵。注意iOS 上的 JIT 權(quán)限獲取是一個(gè)灰色地帶不同系統(tǒng)版本的方法差異很大。如果你只是想在 iOS 上跑 Windows 程序建議先確認(rèn)自己的設(shè)備型號(hào)和系統(tǒng)版本是否在支持范圍內(nèi)。3.2 圖形驅(qū)動(dòng)的差異macOS 上 DXMT 可以直接調(diào)用 Metal 框架因?yàn)?macOS 的圖形棧是開(kāi)放的。但 iOS 上 Metal 的權(quán)限管理更嚴(yán)格而且 iOS 設(shè)備的 GPU 架構(gòu)和 Mac 上的 Apple Silicon 也有差異——iPhone 和 iPad 的 GPU 核心數(shù)更少內(nèi)存帶寬更低散熱能力也更弱。這意味著即使 DXMT 能在 iOS 上編譯通過(guò)實(shí)際運(yùn)行時(shí)的性能表現(xiàn)也會(huì)比 macOS 差不少。我實(shí)測(cè)下來(lái)同樣的 D3D 11 程序在 M1 Mac 上能跑 60 幀在 iPad Pro 上可能只有 20 到 30 幀而且發(fā)熱明顯。3.3 輸入與窗口管理的適配Windows 程序假設(shè)自己運(yùn)行在一個(gè)有鍵盤、鼠標(biāo)、窗口管理器的環(huán)境里。iOS 的觸摸屏交互模式和 Windows 的桌面模式差異很大Wine 需要做大量適配工作。比如Windows 程序可能依賴右鍵菜單、滾輪事件、鍵盤快捷鍵這些在 iOS 上都需要映射到觸摸手勢(shì)或外接鍵鼠。Wine 的 iOS 版本需要實(shí)現(xiàn)一套完整的輸入映射層把觸摸事件轉(zhuǎn)換成 Windows 能理解的鼠標(biāo)和鍵盤事件。窗口管理也是問(wèn)題。Windows 程序可能創(chuàng)建多個(gè)窗口、彈出對(duì)話框、使用系統(tǒng)托盤而 iOS 的界面范式是單窗口全屏。Wine 需要把這些窗口操作映射到 iOS 的視圖控制器上處理起來(lái)相當(dāng)繁瑣。3.4 簽名與分發(fā)最后還有一個(gè)現(xiàn)實(shí)問(wèn)題怎么把編譯好的 Madeira 環(huán)境裝到 iOS 設(shè)備上iOS 不允許隨意安裝未經(jīng)簽名的 App你需要蘋果開(kāi)發(fā)者賬號(hào)個(gè)人賬號(hào)每年 99 美元或者使用 AltStore、SideStore 等側(cè)載工具需要定期續(xù)簽或者使用 TrollStore僅限特定系統(tǒng)版本而且由于 Madeira 涉及 JIT 權(quán)限普通的 App Store 分發(fā)是不可能的。你只能自己編譯、自己簽名、自己安裝整個(gè)過(guò)程對(duì)新手來(lái)說(shuō)門檻不低。4. 實(shí)操過(guò)程從零搭建 iOS 上的 Madeira 環(huán)境4.1 環(huán)境準(zhǔn)備與工具鏈搭建先列一下我用的設(shè)備和工具項(xiàng)目配置開(kāi)發(fā)機(jī)MacBook Pro M1 Pro, 32GB 內(nèi)存目標(biāo)設(shè)備iPad Pro 11 英寸M1iOS 16.5Xcode15.0 及以上命令行工具Xcode Command Line Tools包管理器Homebrew編譯工具CMake, Ninja, Meson簽名工具ldid, codesign第一步是安裝依賴。在 macOS 上打開(kāi)終端執(zhí)行brew install cmake ninja meson pkg-config brew install llvm lldLLVM 和 LLD 是編譯 FEX-Emu 和 DXMT 必需的因?yàn)檫@兩個(gè)項(xiàng)目都依賴較新的編譯器特性。Homebrew 安裝的 LLVM 版本通常比 Xcode 自帶的更新建議用 Homebrew 的版本。接下來(lái)克隆三個(gè)核心倉(cāng)庫(kù)git clone https://github.com/FEX-Emu/FEX.git git clone https://github.com/3Shain/dxmt.git git clone https://github.com/wine-mirror/wine.git提示W(wǎng)ine 的倉(cāng)庫(kù)很大克隆時(shí)建議加上--depth 1只拉取最新提交節(jié)省時(shí)間和磁盤空間。4.2 編譯 FEX-Emu 的 ARM64 版本FEX-Emu 的編譯需要針對(duì) ARM64 做交叉編譯。在 Apple Silicon Mac 上本機(jī)就是 ARM64所以可以直接編譯cd FEX mkdir build cd build cmake .. -DCMAKE_BUILD_TYPERelease \ -DCMAKE_C_COMPILERclang \ -DCMAKE_CXX_COMPILERclang \ -DENABLE_LTOON \ -DBUILD_TESTSOFF ninja這里有幾個(gè)關(guān)鍵參數(shù)需要解釋CMAKE_BUILD_TYPERelease開(kāi)啟優(yōu)化FEX-Emu 在 Debug 模式下性能會(huì)差很多ENABLE_LTOON鏈接時(shí)優(yōu)化能減少最終二進(jìn)制體積并提升性能BUILD_TESTSOFF跳過(guò)測(cè)試編譯節(jié)省時(shí)間編譯完成后你會(huì)得到libFEXCore.so和FEXLoader等文件。這些是后續(xù)集成到 iOS App 里的核心組件。4.3 編譯 DXMT 并適配 iOSDXMT 的編譯稍微復(fù)雜一些因?yàn)樗蕾?Metal 框架而 iOS 的 Metal 和 macOS 的 Metal 在 API 上有細(xì)微差異。你需要修改一些頭文件引用和框架鏈接選項(xiàng)。cd dxmt mkdir build cd build cmake .. -DCMAKE_BUILD_TYPERelease \ -DCMAKE_C_COMPILERclang \ -DCMAKE_CXX_COMPILERclang \ -DCMAKE_OSX_SYSROOTiphoneos \ -DCMAKE_OSX_ARCHITECTURESarm64 \ -DCMAKE_SYSTEM_NAMEiOS ninja關(guān)鍵點(diǎn)在于CMAKE_SYSTEM_NAMEiOS和CMAKE_OSX_SYSROOTiphoneos這告訴 CMake 目標(biāo)是 iOS 而不是 macOS。編譯過(guò)程中可能會(huì)遇到一些 macOS 特有的 API 在 iOS 上不存在的情況需要手動(dòng)條件編譯或替換實(shí)現(xiàn)。我踩過(guò)的一個(gè)坑是DXMT 默認(rèn)使用了一些 macOS 10.15 才有的 Metal 特性在 iOS 上需要降級(jí)到 iOS 16 支持的子集。具體來(lái)說(shuō)MTLResourceOptions的某些選項(xiàng)和MTLHeap的用法需要調(diào)整。4.4 編譯 Wine 的 iOS 版本W(wǎng)ine 的編譯是最耗時(shí)的因?yàn)榇a量巨大。而且 Wine 的構(gòu)建系統(tǒng)對(duì)交叉編譯的支持不如 FEX-Emu 和 DXMT 那么友好需要手動(dòng)指定很多參數(shù)。cd wine mkdir build-ios cd build-ios ../configure --hostaarch64-apple-darwin \ --with-coreaudio \ --with-metalshader \ --without-x \ --disable-tests make -j$(sysctl -n hw.ncpu)--without-x是必須的因?yàn)?iOS 沒(méi)有 X11。--with-metalshader啟用 Metal 著色器后端這是 DXMT 能工作的前提。編譯過(guò)程中最常見(jiàn)的錯(cuò)誤是缺少依賴庫(kù)。Wine 依賴 FreeType、libpng、libjpeg 等庫(kù)這些庫(kù)也需要針對(duì) iOS 編譯。建議先用 Homebrew 安裝 macOS 版本然后手動(dòng)編譯 iOS 版本并放到正確的路徑下。4.5 打包成 iOS App 并簽名三個(gè)組件都編譯好后需要把它們打包成一個(gè) iOS App。這一步需要?jiǎng)?chuàng)建一個(gè) Xcode 項(xiàng)目把編譯好的庫(kù)和可執(zhí)行文件嵌入進(jìn)去然后寫一個(gè)啟動(dòng)器來(lái)初始化 Wine 環(huán)境。Xcode 項(xiàng)目的關(guān)鍵配置Build Settings里設(shè)置ENABLE_BITCODENOBitcode 已經(jīng)廢棄Signing Capabilities里開(kāi)啟Increased Memory Limit如果目標(biāo)設(shè)備內(nèi)存較大Info.plist里添加get-task-allow為 true允許調(diào)試Entitlements里添加com.apple.security.cs.allow-jit為 true申請(qǐng) JIT 權(quán)限簽名時(shí)如果使用免費(fèi)開(kāi)發(fā)者賬號(hào)證書有效期只有 7 天到期后需要重新簽名。付費(fèi)賬號(hào)是 1 年。如果使用 TrollStore則不受此限制但需要設(shè)備系統(tǒng)版本在支持范圍內(nèi)。codesign --force --sign Apple Development: youremail.com \ --entitlements Madeira.entitlements \ --deep Madeira.app--deep參數(shù)會(huì)遞歸簽名 App 內(nèi)的所有可執(zhí)行文件和庫(kù)確保沒(méi)有遺漏。5. 常見(jiàn)問(wèn)題與排查技巧實(shí)錄5.1 Wine 亂碼問(wèn)題這是被問(wèn)得最多的問(wèn)題之一。Wine 在 iOS 上運(yùn)行時(shí)中文、日文、韓文等非拉丁字符經(jīng)常顯示成方塊或亂碼。根本原因是字體缺失和字符集映射錯(cuò)誤。解決方法分兩步第一步把 Windows 字體文件如simsun.ttc、msyh.ttf復(fù)制到 Wine 的字體目錄cp /path/to/fonts/*.ttf \ Madeira.app/drive_c/windows/Fonts/第二步修改 Wine 的注冊(cè)表把默認(rèn)字體替換成支持中文的字體wine reg add HKCU\Software\Wine\Fonts\Replacements \ /v MS Shell Dlg /d Microsoft YaHei /f如果還是亂碼檢查L(zhǎng)ANG環(huán)境變量是否設(shè)置正確。在 iOS 上Wine 可能讀不到系統(tǒng)的語(yǔ)言設(shè)置需要手動(dòng)指定export LANGzh_CN.UTF-8 export LC_ALLzh_CN.UTF-8提示W(wǎng)ine 的字體替換功能有緩存修改注冊(cè)表后需要?jiǎng)h除~/.wine目錄下的字體緩存文件或者直接重啟 Wine 環(huán)境。5.2 FEX-Emu 翻譯失敗導(dǎo)致程序崩潰如果程序啟動(dòng)后立即崩潰而且日志里出現(xiàn)FEXCore: Invalid instruction或Unhandled signal之類的錯(cuò)誤說(shuō)明 FEX-Emu 遇到了它不認(rèn)識(shí)的 x86-64 指令。這種情況通常發(fā)生在較新的程序上因?yàn)樗鼈兛赡苁褂昧?AVX-512、AMX 等 FEX-Emu 尚未完全支持的指令集。解決方法有更新 FEX-Emu 到最新版本新指令集的支持在持續(xù)添加在 FEX-Emu 配置里開(kāi)啟HOSTFEATURES模擬讓程序以為 CPU 支持某些特性如果程序有 32 位版本嘗試用 32 位版本FEX-Emu 對(duì) 32 位 x86 的支持更成熟5.3 DXMT 圖形渲染異常DXMT 渲染異常的表現(xiàn)包括黑屏、花屏、紋理錯(cuò)亂、幀率驟降。排查時(shí)先看日志里有沒(méi)有DXMT: Unsupported format或Metal: Validation error之類的信息。常見(jiàn)原因和解決方法問(wèn)題現(xiàn)象可能原因解決方法黑屏但有聲音著色器編譯失敗更新 DXMT或切換 Wine 的 D3D 后端紋理錯(cuò)亂格式轉(zhuǎn)換錯(cuò)誤在 DXMT 配置里強(qiáng)制指定紋理格式幀率驟降Metal 命令緩沖區(qū)溢出降低游戲分辨率或關(guān)閉抗鋸齒畫面撕裂垂直同步未生效在 Wine 注冊(cè)表里開(kāi)啟UseXVidMode我實(shí)測(cè)下來(lái)DXMT 對(duì) D3D 11 的支持最好D3D 12 的游戲大約有一半能跑但畫面異常的概率較高。如果遇到 D3D 12 的問(wèn)題可以嘗試用DXVK替代 DXMT雖然多了一層轉(zhuǎn)換但兼容性更穩(wěn)。5.4 iOS 設(shè)備發(fā)熱與降頻iOS 設(shè)備的散熱能力遠(yuǎn)不如 Mac跑 Madeira 這種高負(fù)載任務(wù)時(shí)設(shè)備很快會(huì)發(fā)熱并觸發(fā)降頻。降頻后幀率可能直接腰斬體驗(yàn)很差。緩解方法摘掉保護(hù)殼用散熱背夾降低游戲分辨率和畫質(zhì)設(shè)置限制幀率到 30 幀減少 GPU 負(fù)載避免邊充電邊玩充電時(shí)發(fā)熱更嚴(yán)重如果設(shè)備頻繁降頻可以考慮在 Wine 配置里限制 CPU 使用率或者用cpuset把 Wine 進(jìn)程綁定到特定核心上減少調(diào)度開(kāi)銷。5.5 簽名過(guò)期與續(xù)簽免費(fèi)開(kāi)發(fā)者賬號(hào)簽名的 App 只有 7 天有效期到期后 App 無(wú)法啟動(dòng)。續(xù)簽的方法是重新用 Xcode 或codesign簽名然后重新安裝。如果使用 AltStore它會(huì)在后臺(tái)自動(dòng)續(xù)簽但需要保持 AltServer 在同一個(gè) Wi-Fi 網(wǎng)絡(luò)下運(yùn)行。SideStore 則支持在設(shè)備上直接續(xù)簽不需要連接電腦但配置起來(lái)更復(fù)雜。注意續(xù)簽時(shí)如果遇到Unable to install錯(cuò)誤先檢查設(shè)備上是否已經(jīng)有同名 App刪除后重試。另外iOS 16 需要在設(shè)置里信任開(kāi)發(fā)者證書否則 App 無(wú)法啟動(dòng)。6. 性能調(diào)優(yōu)與進(jìn)階玩法6.1 FEX-Emu 的配置調(diào)優(yōu)FEX-Emu 的配置文件通常位于~/.fex-emu/Config.json。幾個(gè)關(guān)鍵參數(shù){ Config: { RootFS: /path/to/rootfs, EmulatedCPU: { Core: 0, TSOEnabled: true, VectorTSOEnabled: true, HalfBarrierTSOEnabled: true }, HOSTFEATURES: { EnableAVX: true, EnableSSE4: true } } }TSOEnabled是內(nèi)存序模擬開(kāi)啟后能提升多線程程序的兼容性但會(huì)帶來(lái)一定性能損失。如果程序?qū)?nèi)存序要求不高可以關(guān)掉試試。EnableAVX讓 FEX-Emu 模擬 AVX 指令集。有些程序啟動(dòng)時(shí)會(huì)檢測(cè) CPU 特性如果發(fā)現(xiàn)不支持 AVX 就直接退出。開(kāi)啟這個(gè)選項(xiàng)能讓這些程序跑起來(lái)但性能會(huì)打折扣。6.2 DXMT 的 Metal 優(yōu)化DXMT 在 iOS 上運(yùn)行時(shí)可以通過(guò)環(huán)境變量調(diào)整 Metal 的行為export DXMT_METAL_DEVICE0 export DXMT_METAL_MAX_FRAMES_IN_FLIGHT2 export DXMT_METAL_SHADER_CACHE1DXMT_METAL_MAX_FRAMES_IN_FLIGHT控制同時(shí)提交的幀數(shù)值越大延遲越高但吞吐量越大。在 iOS 上建議設(shè)為 2 或 3太高會(huì)導(dǎo)致內(nèi)存壓力。DXMT_METAL_SHADER_CACHE開(kāi)啟著色器緩存第一次運(yùn)行時(shí)會(huì)慢一些但后續(xù)啟動(dòng)會(huì)快很多。緩存文件位于 App 的 Documents 目錄下可以手動(dòng)清理。6.3 用外接鍵鼠提升操作體驗(yàn)iOS 支持藍(lán)牙鍵鼠和 USB 鍵鼠通過(guò)轉(zhuǎn)接頭。Wine 會(huì)把外接鍵鼠的事件映射成 Windows 的鍵盤和鼠標(biāo)事件操作體驗(yàn)接近原生。如果玩的是策略游戲或 RPG外接鍵鼠幾乎是必須的。觸摸屏模擬鼠標(biāo)右鍵很別扭而且很多游戲依賴快捷鍵。我試過(guò)用 iPad 的觸控板配合 Madeira體驗(yàn)比純觸摸好很多但和真正的桌面環(huán)境還是有差距。6.4 多實(shí)例運(yùn)行與資源隔離Madeira 支持同時(shí)運(yùn)行多個(gè) Windows 程序每個(gè)程序在獨(dú)立的 Wine prefix 里運(yùn)行。這樣可以避免程序之間的配置沖突但也意味著每個(gè)實(shí)例都會(huì)占用一份內(nèi)存和 CPU 資源。在 iOS 上內(nèi)存是稀缺資源。iPad Pro 最多 16GB 內(nèi)存但 iOS 會(huì)限制單個(gè) App 的內(nèi)存使用量。如果同時(shí)跑多個(gè)程序很容易觸發(fā)內(nèi)存警告導(dǎo)致 App 被系統(tǒng)殺掉。建議的做法是只跑一個(gè)程序把其他程序關(guān)掉。如果確實(shí)需要多開(kāi)用WINEPREFIX環(huán)境變量指定不同的 prefix 目錄并監(jiān)控內(nèi)存使用情況。7. 我對(duì)這套方案的真實(shí)看法折騰 Madeira 這段時(shí)間最大的感受是技術(shù)上行得通但離 好用 還有距離。FEX-Emu 的翻譯效率比我預(yù)期的高DXMT 的圖形轉(zhuǎn)換也比 DXVKMoltenVK 那條鏈路更直接Wine 的 API 兼容性在大多數(shù)場(chǎng)景下夠用。但 iOS 的沙盒限制、JIT 權(quán)限問(wèn)題、簽名續(xù)簽的麻煩讓整個(gè)方案的實(shí)用性打了折扣。如果你只是想體驗(yàn)一下在 iOS 上跑 Windows 程序的感覺(jué)建議先從 macOS 版本入手熟悉整個(gè)流程后再嘗試 iOS。macOS 上沒(méi)有 JIT 限制簽名也簡(jiǎn)單得多能把注意力集中在技術(shù)本身而不是和系統(tǒng)斗智斗勇上。另外這個(gè)領(lǐng)域變化很快。FEX-Emu 和 DXMT 都在活躍開(kāi)發(fā)中每隔幾個(gè)月就有新版本發(fā)布兼容性和性能都在持續(xù)改善。如果你遇到了問(wèn)題先去項(xiàng)目的 GitHub Issues 里搜一下很可能已經(jīng)有人遇到并解決了。實(shí)在搞不定的話把日志發(fā)到社區(qū)里通常會(huì)有熱心人幫忙分析。最后分享一個(gè)小技巧在 iOS 上調(diào)試 Wine 程序時(shí)把日志輸出到文件里比看控制臺(tái)方便得多??梢栽趩?dòng)腳本里加上WINEDEBUGall和重定向然后把日志文件導(dǎo)出到 Mac 上分析。雖然日志量很大但排查問(wèn)題時(shí)能提供關(guān)鍵線索。