Skip to content

Commit 5047beb

Browse files
committed
Allow using newer solc on macOS without Rosetta
`solc` universal binaries are now available, starting from 0.8.24. Allow Macs without Rosetta to run those binaries.
1 parent ba3c63a commit 5047beb

File tree

4 files changed

+31
-9
lines changed

4 files changed

+31
-9
lines changed

README.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ To automatically install and use a version, run `solc-select use <version> --alw
2222

2323
### Running on ARM (Mac M1/M2)
2424

25-
`solc` requires Rosetta to be installed. See the FAQ on [how to install Rosetta](#oserror-errno-86-bad-cpu-type-in-executable).
25+
`solc` older than 0.8.24 requires Rosetta to be installed. See the FAQ on [how to install Rosetta](#oserror-errno-86-bad-cpu-type-in-executable).
2626

2727
## Usage
2828

@@ -85,10 +85,12 @@ Feel free to stop by our [Slack channel](https://empirehacking.slack.com/) for h
8585
### OSError: [Errno 86] Bad CPU type in executable
8686

8787
On newer `solc-select` versions, this might show as `solc binaries for macOS are
88-
Intel-only. Please install Rosetta on your Mac to continue.`
88+
Intel-only. Please install Rosetta on your Mac to continue.` or `solc binaries
89+
previous to 0.8.24 for macOS are Intel-only. Please install Rosetta on your Mac
90+
to continue.`
8991

90-
`solc` requires Rosetta to be installed. To see whether you have Rosetta
91-
installed on your Mac, run
92+
`solc` releases earlier than 0.8.24 require Rosetta to be installed. To see
93+
whether you have Rosetta installed on your Mac, run
9294

9395
```bash
9496
pgrep -q oahd && echo Rosetta is installed || echo Rosetta is NOT installed

solc_select/__main__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ def solc() -> None:
9494
(version, _) = res
9595
path = ARTIFACTS_DIR.joinpath(f"solc-{version}", f"solc-{version}")
9696
halt_old_architecture(path)
97-
halt_incompatible_system()
97+
halt_incompatible_system(path)
9898
try:
9999
subprocess.run(
100100
[str(path)] + sys.argv[1:],

solc_select/solc_select.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
CRYTIC_SOLC_ARTIFACTS,
2121
CRYTIC_SOLC_JSON,
2222
)
23-
from .utils import mac_can_run_intel_binaries
23+
from .utils import mac_binary_is_universal, mac_can_run_intel_binaries
2424

2525
Path.mkdir(ARTIFACTS_DIR, parents=True, exist_ok=True)
2626

@@ -32,10 +32,19 @@ def halt_old_architecture(path: Path) -> None:
3232
)
3333

3434

35-
def halt_incompatible_system() -> None:
36-
if soliditylang_platform() == MACOSX_AMD64 and not mac_can_run_intel_binaries():
35+
def halt_incompatible_system(path: Path) -> None:
36+
if soliditylang_platform() == MACOSX_AMD64:
37+
# If Rosetta is available, we can run all solc versions
38+
if mac_can_run_intel_binaries():
39+
return
40+
41+
# If this is a newer universal solc (>=0.8.24) we can always run it
42+
# https://github.com/ethereum/solidity/issues/12291#issuecomment-2223328961
43+
if mac_binary_is_universal(path):
44+
return
45+
3746
raise argparse.ArgumentTypeError(
38-
"solc binaries for macOS are Intel-only. Please install Rosetta on your Mac to continue. Refer to the solc-select README for instructions."
47+
"solc binaries previous to 0.8.24 for macOS are Intel-only. Please install Rosetta on your Mac to continue. Refer to the solc-select README for instructions."
3948
)
4049
# TODO: check for Linux aarch64 (e.g. RPi), presence of QEMU+binfmt
4150

solc_select/utils.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from pathlib import Path
12
import platform
23
import subprocess
34
import sys
@@ -6,6 +7,16 @@
67
from packaging.version import Version
78

89

10+
def mac_binary_is_universal(path: Path):
11+
"""Check if the Mac binary is Universal or not. Will throw an exception if run on non-macOS."""
12+
assert sys.platform == "darwin"
13+
result = subprocess.run(["/usr/bin/file", str(path)], capture_output=True, check=False)
14+
is_universal = all(
15+
text in result.stdout.decode() for text in ("Mach-O universal binary", "x86_64", "arm64")
16+
)
17+
return result.returncode == 0 and is_universal
18+
19+
920
def mac_can_run_intel_binaries() -> bool:
1021
"""Check if the Mac is Intel or M1 with available Rosetta. Will throw an exception if run on non-macOS."""
1122
assert sys.platform == "darwin"

0 commit comments

Comments
 (0)