Skip to content

Commit bb6e444

Browse files
authored
Merge pull request #256 from crytic/arm64-linux
ARM64 linux support
2 parents ab8a7b7 + 3792cb6 commit bb6e444

20 files changed

+911
-1042
lines changed

.github/workflows/ci.yml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,18 @@ jobs:
2424
strategy:
2525
matrix:
2626
python: ["3.10", "3.11", "3.12", "3.13", "3.14"]
27-
os: ["ubuntu-latest", "macos-latest", "windows-2022"]
27+
os: ["ubuntu-latest", "ubuntu-24.04-arm", "macos-latest", "macos-15-intel", "windows-2022"]
2828
steps:
2929
- uses: actions/checkout@v6
3030
- uses: astral-sh/setup-uv@v7
3131
with:
3232
python-version: ${{ matrix.python }}
33+
- name: Install QEMU and libc
34+
if: matrix.os == 'ubuntu-24.04-arm'
35+
run: |
36+
sudo apt-get update
37+
sudo apt-get -y install qemu-user libc6-amd64-cross
38+
echo QEMU_LD_PREFIX=/usr/x86_64-linux-gnu >> "$GITHUB_ENV"
3339
- name: Install solc-select and test dependencies
3440
run: |
3541
uv sync --extra dev

solc_select/constants.py

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,10 @@
1717

1818
# soliditylang.org platform strings
1919
LINUX_AMD64 = "linux-amd64"
20+
LINUX_ARM64 = "linux-arm64"
2021
MACOSX_AMD64 = "macosx-amd64"
2122
WINDOWS_AMD64 = "windows-amd64"
2223

23-
# earliest releases supported in each platform
24-
EARLIEST_RELEASE = {"macosx-amd64": "0.3.6", "linux-amd64": "0.4.0", "windows-amd64": "0.4.5"}
25-
2624
# crytic/solc repo URLs
2725
CRYTIC_SOLC_ARTIFACTS = "https://raw.githubusercontent.com/crytic/solc/master/linux/amd64/"
2826
CRYTIC_SOLC_JSON = (
@@ -32,7 +30,3 @@
3230
# alloy-rs/solc-builds repo URLs
3331
ALLOY_SOLC_ARTIFACTS = "https://raw.githubusercontent.com/alloy-rs/solc-builds/203ef20a24a6c2cb763e1c8c4c1836e85db2512d/macosx/aarch64/"
3432
ALLOY_SOLC_JSON = "https://raw.githubusercontent.com/alloy-rs/solc-builds/203ef20a24a6c2cb763e1c8c4c1836e85db2512d/macosx/aarch64/list.json"
35-
36-
# Alloy ARM64 repo version range (0.8.24+ are universal binaries on soliditylang.org)
37-
ALLOY_ARM64_MIN_VERSION = "0.8.5"
38-
ALLOY_ARM64_MAX_VERSION = "0.8.23"
Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1 @@
1-
"""
2-
Infrastructure layer for solc-select.
3-
4-
This package contains low-level infrastructure concerns like
5-
filesystem operations and HTTP client configuration.
6-
"""
1+
"""Infrastructure layer for solc-select."""
Lines changed: 40 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,11 @@
1-
"""
2-
Filesystem operations for solc-select.
3-
4-
This module handles file system operations including version storage,
5-
configuration management, and directory operations.
6-
"""
1+
"""Filesystem operations for solc-select."""
72

83
import os
94
import shutil
105
from pathlib import Path
116

127
from ..constants import ARTIFACTS_DIR, SOLC_SELECT_DIR
13-
from ..models import SolcVersion
8+
from ..models.versions import SolcVersion
149

1510

1611
class FilesystemManager:
@@ -22,80 +17,47 @@ def __init__(self) -> None:
2217
self._ensure_directories()
2318

2419
def _ensure_directories(self) -> None:
25-
"""Ensure required directories exist."""
2620
self.artifacts_dir.mkdir(parents=True, exist_ok=True)
2721
self.config_dir.mkdir(parents=True, exist_ok=True)
2822

2923
def get_current_version(self) -> SolcVersion | None:
30-
"""Get the currently selected version.
31-
32-
Returns:
33-
Currently selected version or None if not set
34-
"""
35-
# Check environment variable first
24+
"""Get the currently selected version."""
3625
env_version = os.environ.get("SOLC_VERSION")
3726
if env_version:
3827
try:
3928
return SolcVersion.parse(env_version)
4029
except ValueError:
4130
return None
4231

43-
# Check global version file
4432
global_version_file = self.config_dir / "global-version"
4533
if global_version_file.exists():
4634
try:
4735
with open(global_version_file, encoding="utf-8") as f:
48-
version_str = f.read().strip()
49-
return SolcVersion.parse(version_str)
36+
return SolcVersion.parse(f.read().strip())
5037
except (OSError, ValueError):
5138
return None
5239

5340
return None
5441

5542
def set_global_version(self, version: SolcVersion) -> None:
56-
"""Set the global version.
57-
58-
Args:
59-
version: Version to set as global
60-
"""
43+
"""Set the global version."""
6144
global_version_file = self.config_dir / "global-version"
6245
with open(global_version_file, "w", encoding="utf-8") as f:
6346
f.write(str(version))
6447

6548
def get_version_source(self) -> str:
66-
"""Get the source of the current version setting.
67-
68-
Returns:
69-
Source description (environment variable or file path)
70-
"""
49+
"""Get the source of the current version setting."""
7150
if os.environ.get("SOLC_VERSION"):
7251
return "SOLC_VERSION"
73-
74-
global_version_file = self.config_dir / "global-version"
75-
return global_version_file.as_posix()
52+
return (self.config_dir / "global-version").as_posix()
7653

7754
def get_artifact_directory(self, version: SolcVersion) -> Path:
78-
"""Get the directory for a version's artifacts.
79-
80-
Args:
81-
version: Version to get directory for
82-
83-
Returns:
84-
Path to the artifact directory
85-
"""
55+
"""Get the directory for a version's artifacts."""
8656
return self.artifacts_dir / f"solc-{version}"
8757

8858
def get_binary_path(self, version: SolcVersion) -> Path:
89-
"""Get the path to a version's binary.
90-
91-
Args:
92-
version: Version to get binary path for
93-
94-
Returns:
95-
Path to the binary executable
96-
"""
97-
artifact_dir = self.get_artifact_directory(version)
98-
return artifact_dir / f"solc-{version}"
59+
"""Get the path to a version's binary."""
60+
return self.get_artifact_directory(version) / f"solc-{version}"
9961

10062
def cleanup_artifacts_directory(self) -> None:
10163
"""Remove the entire artifacts directory for upgrades."""
@@ -104,14 +66,35 @@ def cleanup_artifacts_directory(self) -> None:
10466
self.artifacts_dir.mkdir(parents=True, exist_ok=True)
10567

10668
def is_legacy_installation(self, version: SolcVersion) -> bool:
107-
"""Check if a version uses the old installation format.
108-
109-
Args:
110-
version: Version to check
111-
112-
Returns:
113-
True if using legacy format, False otherwise
114-
"""
115-
# Legacy format: artifacts/solc-{version} (file instead of directory)
69+
"""Check if a version uses the old installation format (file instead of directory)."""
11670
legacy_path = self.artifacts_dir / f"solc-{version}"
11771
return legacy_path.exists() and legacy_path.is_file()
72+
73+
def get_installed_versions(self) -> list[SolcVersion]:
74+
"""Get list of installed versions sorted by version number."""
75+
if not self.artifacts_dir.exists():
76+
return []
77+
78+
installed = []
79+
for item in self.artifacts_dir.iterdir():
80+
if item.is_dir() and item.name.startswith("solc-"):
81+
version_str = item.name.replace("solc-", "")
82+
try:
83+
version = SolcVersion.parse(version_str)
84+
if self.is_installed(version):
85+
installed.append(version)
86+
except ValueError:
87+
continue
88+
89+
installed.sort()
90+
return installed
91+
92+
def is_installed(self, version: SolcVersion) -> bool:
93+
"""Check if a version is installed."""
94+
return self.get_binary_path(version).exists()
95+
96+
def ensure_artifact_directory(self, version: SolcVersion) -> Path:
97+
"""Ensure artifact directory exists for a version."""
98+
artifact_dir = self.get_artifact_directory(version)
99+
artifact_dir.mkdir(parents=True, exist_ok=True)
100+
return artifact_dir

0 commit comments

Comments
 (0)