我的 macOS 14.2.1 (Darwin 23.2.0) 默认为
arm64
。我为不同的应用程序设置了一堆 x86_64
版本(也设置了 Rosetta 2)。例如,cmake 和 Homebrew。但是当我用 arch -x86_64
前缀调用它们时,操作系统找不到它们:
arch -x86_64 cmake
arch: posix_spawnp: cmake: Bad CPU type in executable
以下方法有效:
arch -x86_64 /usr/local/Homebrew/Cellar/cmake/3.31.4/bin/cmake
为 x86_64 安装的其他应用程序也是如此。 即使我调用
arch -x86_64 zsh
并将 bash 切换到 x86_64 模式,它也找不到路径。当我打电话时
which cmake
当我使用arm64或x86_64版本的zsh时,它总是只显示一条路径(arm64):
/opt/homebrew/bin/cmake
我应该手动将 x86_64 应用程序的所有路径添加到
$PATH
还是有更好的方法告诉操作系统自动执行此操作?
这不是切片选择的工作原理(这是
arch
二进制文件和底层 posix_spawnp
选项的作用)。当您在同一文件中拥有具有多个架构的胖 Mach-O 时,切片选择就有效。
您所拥有的只是不同路径中具有相同基本名称的不同二进制文件。当您运行
arch -x86_64 cmake
并且 /opt/homebrew/bin/cmake
是路径中的第一个 cmake
时,则相当于调用 arch -x86_64 /opt/homebrew/bin/cmake
,但 /opt/homebrew/bin/cmake
只有一个 arm64 切片,因此没有可供选择的 x86_64
切片.
一种选择是手动浏览为多个架构编译的所有文件,并使用
lipo
将它们合并到胖二进制文件中,然后将它们放在 $PATH
中的某个位置,该位置优先于 Homebrew - 但我想这不太可维护。
另一种选择是手动迭代
$PATH
中的所有匹配二进制文件,检查它们是否具有所需的架构,然后运行它们。使用 zsh,这可以例如完成 whence -pa
和 lipo -archs
:
arm64()
{
bin="$1";
shift;
whence -pa "$bin" | while read -r p; do
if lipo -archs "$p" 2>/dev/null | fgrep -q 'arm64'; then
arch -arm64 "$p" "$@";
break;
fi;
done;
}
x86_64()
{
bin="$1";
shift;
whence -pa "$bin" | while read -r p; do
if lipo -archs "$p" 2>/dev/null | fgrep -q 'x86_64'; then
arch -x86_64 "$p" "$@";
break;
fi;
done;
}
请注意,这有意不使用 (f)grep 中的
-w
标志,因此 arm64e
和 x86_64h
也算作匹配。我确信您可以将这两者结合起来,并将它们设计成围绕 arch
的包装器,但如果您想支持全套 i386
/x86_64
/x86_64h
/arm64
/arm64e
和-32
/-64
标志,那么就有一整个一堆边缘情况、默认值和偏好规则,我现在不想深入研究。