fix(installer): avoid mismatched bun architecture on apple silicon

The default install path only checked whether bun existed, so an
x86_64 bun running under Rosetta installed an x86_64 omp on Apple
Silicon (AVX warning, ~11s startup). Compare bun's process.arch to
the host, detecting Apple Silicon via `sysctl -in hw.optional.arm64`
so Rosetta can't spoof it, and fall back to the prebuilt native
binary on mismatch; `--source` now errors actionably. install_binary
also derives the arch from the real host instead of the
Rosetta-translated `uname -m`.

Fixes #6268
This commit is contained in:
roboomp
2026-07-22 07:11:40 +00:00
parent 7b141199d5
commit 329db086f4
2 changed files with 52 additions and 6 deletions
+4
View File
@@ -2,6 +2,10 @@
## [Unreleased]
### Fixed
- Fixed `scripts/install.sh` installing an x86_64 build on Apple Silicon when an x86_64 `bun` runs under Rosetta. The default path only checked whether `bun` existed; it now compares `bun`'s `process.arch` to the host (detected via `sysctl -in hw.optional.arm64` so Rosetta can't spoof it) and falls back to the prebuilt native binary on a mismatch, while `--source` errors with an actionable message. `install_binary` also derives the arch from the real host instead of the Rosetta-translated `uname -m` ([#6268](https://github.com/can1357/oh-my-pi/issues/6268)).
## [17.0.7] - 2026-07-21
### Fixed
+48 -6
View File
@@ -71,6 +71,38 @@ has_bun() {
command -v bun >/dev/null 2>&1
}
# Normalized host architecture (x64|arm64). On macOS this uses
# `sysctl hw.optional.arm64` so it stays correct inside a Rosetta session,
# where `uname -m` reports the translated x86_64.
host_arch() {
if [ "$(uname -s)" = "Darwin" ]; then
if [ "$(sysctl -in hw.optional.arm64 2>/dev/null)" = "1" ]; then
echo "arm64"
else
echo "x64"
fi
return
fi
case "$(uname -m)" in
x86_64|amd64) echo "x64" ;;
arm64|aarch64) echo "arm64" ;;
*) uname -m ;;
esac
}
# Bun's own architecture (x64|arm64), or empty when it can't be determined.
bun_arch() {
bun -e 'process.stdout.write(process.arch)' 2>/dev/null
}
# True when Bun's architecture matches the host. If Bun's arch can't be read,
# assume a match rather than block the install.
bun_arch_matches_host() {
ba="$(bun_arch)"
[ -z "$ba" ] && return 0
[ "$ba" = "$(host_arch)" ]
}
version_ge() {
current="$1"
minimum="$2"
@@ -187,7 +219,7 @@ install_via_bun() {
install_binary() {
# Detect platform
OS="$(uname -s)"
ARCH="$(uname -m)"
ARCH="$(host_arch)"
case "$OS" in
Linux) PLATFORM="linux" ;;
@@ -196,9 +228,8 @@ install_binary() {
esac
case "$ARCH" in
x86_64|amd64) ARCH="x64" ;;
arm64|aarch64) ARCH="arm64" ;;
*) echo "Unsupported architecture: $ARCH"; exit 1 ;;
x64|arm64) ;;
*) echo "Unsupported architecture: $ARCH"; exit 1 ;;
esac
BINARY="omp-${PLATFORM}-${ARCH}"
@@ -247,17 +278,28 @@ case "$MODE" in
install_bun
fi
require_bun_version
if ! bun_arch_matches_host; then
echo "Error: bun reports architecture '$(bun_arch)' but this host is '$(host_arch)'."
echo "Installing from source with this bun would produce a mismatched binary"
echo "(e.g. x86_64 under Rosetta on Apple Silicon), causing slow startup and AVX warnings."
echo "Install a native bun for your architecture, or re-run without --source to fetch the prebuilt $(host_arch) binary."
exit 1
fi
install_via_bun
;;
binary)
install_binary
;;
*)
# Default: use bun if available, otherwise binary
if has_bun; then
# Default: use bun only when it matches the host architecture, otherwise
# fall back to the prebuilt binary so Rosetta bun can't force an x86_64 build.
if has_bun && bun_arch_matches_host; then
require_bun_version
install_via_bun
else
if has_bun; then
echo "Detected bun with architecture '$(bun_arch)' on a '$(host_arch)' host; using the prebuilt binary instead."
fi
install_binary
fi
;;