前幾天拿到了新的 M1 MacBook Air,想說來試試看一些平常使用的工具以及 iOS App,結果發現很多常用的 iOS App 都還沒有開放 macOS 下載使用…… 但很多常用的工具都已經有原生支援的版本了,在使用上也沒有什麼太多的問題,但有些小技巧想分享給大家,希望大家在這個轉換之路(?)上可以再更順暢一些~

Rosetta 2 相關

這裡會列出一些與 Intel 相容模式(Rosetta 2)有關的一些小技巧:

原生支援?

在活動監視器(Activity Monitor)可以看到一個叫做「建築」[1]的欄位,在這裡我們可以看到有分成 Apple 以及 Intel,分別對應到原生 Apple silicon 以及 Rosetta 2[2] 相容的 Intel 模式。

如果你發現正在執行的應用程式是 Intel 表示他正在 Rosetta 2 底下運作。

手動安裝 Rosetta 2

個人覺得這個技巧至關重要,因為我曾經在 11.0.1 升級到 11.1 之後,Rosetta 就消失了,導致我還在用 Intel 架構的輸入法(對!連輸入法都可以靠 Rosetta 相容)死亡,也不知道為什麼 macOS 沒有主動提醒我要再安裝一次 Rosetta,直到我要安裝別的 Intel 應用程式時才又提醒,當時我才恍然大悟,原來我的 Rosetta 在升級的時候消失了……

方法也很簡單,只要打開終端機然後用軟體升級的方式安裝就可以了:

$ /usr/sbin/softwareupdate --install-rosetta --agree-to-license

雖然加了 --agree-to-license 之後就不會提醒你再看一次 SLA,但第一次使用前還是看一下吧XD

強制使用 Rosetta 來執行 Universal 應用程式

蘋果在轉換到 Apple silicon 的時候提出了一個以前[3]也用過的解決方案,對於這樣的通用架構應用程式,我們可以透過「取得資訊」來將通用架構應用程式設定為使用 Rosetta 開啓。

透過 CLI 強制使用 Rosetta

前面講的是可以將 .app 應用程式以 Rosetta 方式開啓的技巧,但如果在 CLI 下的話該如何操作呢?

方法也很簡單,我們可以透過 arch 這個指令來幫我們跳入 x86_64 的世界:

$ which uname
/usr/bin/uname
$ file /usr/bin/uname
/usr/bin/uname: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit executable x86_64] [arm64e:Mach-O 64-bit executable arm64e]
/usr/bin/uname (for architecture x86_64):	Mach-O 64-bit executable x86_64
/usr/bin/uname (for architecture arm64e):	Mach-O 64-bit executable arm64e
$ uname -u
arm64
$ arch -arch x86_64 uname -u
x86_64
$

同理,我們也可以靠 arch 指令來讓我們打開一個 x86_64 的 Shell,在裡面運作的程式就都會以 x86_64 優先了:

$ arch -arch x86_64 bash
[x86_64] $ uname -m
x86_64
$ arch -arch arm64e bash
[arm64e] $ uname -m
arm64
[arm64e] $

雖然這個範例中表示可以在 x86_64 模式下再跳回 arm64e 模式[4],但其實這件事情在 11.0.1 的時候還是不行的,會噴出不認識的 architecture 錯誤,但在 11.1 之後就可以了!

透過 sysctl 取得目前是不是在 Rosetta 中運作

這個也是一個實用的小技巧,我們可以透過 sysctl 瞭解目前的環境是不是在 Rosetta 中:

$ sysctl -n sysctl.proc_translated
0
$ arch -arch x86_64 sysctl -n sysctl.proc_translated
1
$

如果 sysctl.proc_translated 的值是 1 表示目前正在 Rosetta 中執行。

iOS App 相關

這裡會列出一些與 iOS App 相關的小技巧:

安裝 ipa 後無法執行

有時候會遇到安裝 .ipa 之後,macOS 卻阻止你執行的情況,這時候有可能是因為這個 App 被上了 com.apple.quarantine 這個屬性,我們只要用下面的方式就可以解開束縛:

$ sudo xattr -dr com.apple.quarantine <Installed.app>

通常這個屬性代表的是不安全的應用程式,例如從瀏覽器下載回來的應用程式就會自動打上這個屬性,只是不知道為何從 ipa 安裝的 App 並不會提醒你是否允許執行,而是直接拒絕你執行。

CLI 相關

這裡列出一些跟 CLI 有關的小技巧,如果是有關如何在 CLI 執行 Rosetta 的話可以往上面的節次看:

安裝 Homebrew

這好像不管是不是 M1 Mac 都會用到,但由於 Homebrew 散佈的執行檔都是單一架構的,所以這邊會另外展示如何安裝 Intel 架構的 Homebrew(以取得 Intel 架構的執行檔)。

Apple Silicon 版本的 Homebrew,按照原先的安裝方式就可以了:

$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

再來是 Intel 架構的 Homebrew,雖然 Homebrew 是用 Ruby 撰寫而成,其實可以直接用前面提到的 arch 來切換至 Intel 架構執行,但我是建議把 Intel 架構用的 Homebrew 跟 Apple 架構用的 Homebrew 分開,避免 Homebrew 搞不清楚跨架構 library 之間的相依性。

所以我們需要用替代安裝[5]的方式把 Homebrew 安裝到指定的位置(這裡舉例是 /opt/homebrew.x86_64):

$ mkdir -p /opt/homebrew.x86_64
$ curl -L https://github.com/Homebrew/brew/tarball/master | tar xz --strip 1 -C /opt/homebrew.x86_64

接下來我會在我的 Terminal 中設定兩個 Profile,一個是 Apple 架構的 Shell、另一個是 Intel 架構的(一樣用 arch 關進 Intel 模式)Shell,並且在 shellrc 中加入環境偵測來判斷使用哪個 Homebrew:

# ~/.zprofile

if [ "$(sysctl -n sysctl.proc_translated)" = "1" ]; then
	eval $(/opt/homebrew.x86_64/bin/brew shellenv)
else
	eval $(/opt/homebrew/bin/brew shellenv)
fi
# ~/.config/fish/config.fish

set is_rosetta (sysctl -n sysctl.proc_translated)
if [ $is_rosetta = '1' ]
    set homebrew /opt/homebrew.x86_64/bin
else
    set homebrew /opt/homebrew/bin
end

set default_path /usr/local/bin /usr/bin /usr/sbin /bin /sbin
set -gx PATH $homebrew $default_path

雜記

最後小小抱怨一下 macOS 11.0.1 根本就是還沒有完成的版本……
Bug 有夠多[6],而且還沒辦法做雙向轉換(人家 Windows <> WSL 就可以互相呼叫),好險 11.1 之後這些缺點都有補回來。
再用一陣子也許還會再增加一些技巧,不過基於我還在複習 macOS(畢竟有好多年沒用 Mac 了……),所以可能需要再一下下才會更新XD


  1. 個人猜測是 Architecture 的翻譯啦…… 近年來蘋果很多名詞都會刻意找一個中文翻譯…… 以前不會的啊 QQ ↩︎

  2. Rosetta 2 可讓配備 Apple 晶片的 Mac 使用專為配備 Intel 處理器的 Mac 所開發的 App。 詳見 Apple 支援頁面 ↩︎

  3. 以前從 PowerPC 架構轉換至 Intel 架構時蘋果就有提出相同的解決方案,使得不同架構的應用程式可以同時存在於一個執行檔中。詳見維基百科的〈Universal Binary〉條目↩︎

  4. man arch 中有列出幾個可以使用的模式,包含:i386, x86_64, x86_64h(Haswell), arm64, arm64e(Apple Silicon)。 ↩︎

  5. 參考 Homebrew 安裝說明 ↩︎

  6. 有興趣看我踩到什麼雷的可以看看我發的廢推(ry ↩︎

因主題更新,留言功能暫時停用中。