最近,Flutter 合併了 [*\#185868*](https://link.juejin.cn?target=https%3A%2F%2Fgithub.com%2Fflutter%2Fflutter%2Fpull%2F185868) 這個 PR,這個 PR 的作用是**將 Flutter iOS 工具鏈二進位檔升級為 Fat Binary,從而同時支援 `x86_64` 和 `arm64` 兩種架構**,也就是讓 Apple Silicon(M 系列晶片)不需要 Rosetta 也能原生執行這些工具。
你說 Flutter 不是很早就支援 Apple Silicon 了?其實這是兩個不同概念:
.app 產物(flutter build ios)編譯目標是 iOS 裝置,用的是 arm64 架構(iPhone/iPad 的 CPU 架構),和 Mac 主機是什麼架構完全無關arm64-simulator而這次的 PR 修的是 Flutter 工具鏈本身,也就是執行在 Mac 上的 Flutter 工具鏈裡的二進位工具:
工具用途idevicesyslog讀取 iOS 裝置的即時日誌idevicescreenshot擷取 iOS 裝置螢幕iproxyUSB 埠轉發(連接 Dart VM Service)libimobiledevice / libusbmuxd 等上述工具依賴的底層函式庫這些工具主要負責和 iOS 裝置通訊,它們基本由第三方開源專案(libimobiledevice 系列)編譯過來的,而由於歷史原因,之前一直只編譯了 x86_64,在 Apple Silicon Mac 上只能靠 Rosetta 2 轉譯才能執行。
所以,要讓這些工具支援 Apple Silicon,就需要修改 Flutter 基礎設施(infra)的建置 Recipe(執行在 Chromium CI 的 Python),而 libimobiledevice 生態本身的建置腳本需要正確支援 CFLAGS="-arch arm64 -arch x86_64",然後透過 autoconf/automake 工具鏈編譯出 Fat Binary,再用 lipo 合併:

實際上這個問題在 2022 年的 #121178 就被提出了,但 infra 端的修改(build recipe 的 CL)太容易弄出 bug,所以是直到最近才完成。
當時 #121178 就發現,在 Apple Silicon Mac 上透過 Rosetta 2 轉譯執行會有一些列潛在問題:
那為什麼最近又想起來要適配了?因為 Rosetta 要退出歷史舞臺了,所以如果再不適配,後面你想跑也跑不了,所以這次也是不得不上。

可能你覺得,不就是加一個編譯 target 罷了?還能整出什麼問題?是的,還真的可以,這個 PR 從提交到合併又整出了問題,簡單來說就是:

對,最後也不知道為什麼,反正合併即 Revert,然後回退舊版本解決問題,是不是很抽象?但是又有莫名的熟悉感?你說他們合併的時候為什麼不測試?

怎麼可能不測試,PR 在 AI 輔助 Code Review + CI 驗證都跑了好幾輪,但是問題就在於它不是必現,然後 idevicesyslog 可以啟動正常,但是啟動後不知道為什麼日誌流突然就停止了,所以只能在 merge 發布的時候被人發現後才知道這個缺陷。
所以基建鏈條,特別是 CI 鏈條,總有升級必掛、修改必崩的墨菲定律。
事實上整個 IosUsbArtifacts 的工作流程也挺複雜,除了建置成品之後,還需要在流程上每次合理下載和搭配成品,比如在 FlutterCache 裡就有 6 個 IosUsbArtifacts 實例:
arduino 体验AI代码助手 代码解读复制代码static const artifactNames = <String>[
'libimobiledevice', // 包含 idevicescreenshot、idevicesyslog
'libusbmuxd', // 包含 iproxy
'libplist',
'openssl',
'libimobiledeviceglue',
'ios-deploy',
];
對於下載後的 zip 需要做「可執行檔存在性檢查」和 stamp 正確檢查,下載解壓後的 .dylib 動態函式庫路徑需要注入到子程序的 DYLD_LIBRARY_PATH 中,否則執行 idevicesyslog 時 macOS 的動態連結器找不到 libimobiledevice.dylib 等相依套件等問題:

當然,最重要的是,這個 PR 目前還 CP 到了 3.41 上面,只能說兜兜轉轉,3.41 上合併了多少 iOS 編譯和除錯問題?雖然過程很抽象,但是結果還是好的,至少未來 Flutter 終於可以完全不需要 Rosetta,也是跟上了新的適配進度。

Flutter 3.41 還真成了 iOS 的主力修復戰場。