mirror of
https://github.com/retroSoC/retroSoC.git
synced 2026-11-04 22:32:36 +00:00
feat: add Perl to development environment and enhance toolchain accessibility
This commit is contained in:
6 files changed
+59
-2
No files matched your search
@@ -23,6 +23,7 @@ RUN apt-get update -qq \
|
||||
mold \
|
||||
numactl \
|
||||
openjdk-17-jre-headless \
|
||||
perl \
|
||||
python3 \
|
||||
python3-pip \
|
||||
python3-venv \
|
||||
|
||||
@@ -11,7 +11,8 @@ remote-bitbang debug acceptance flow. Docker, Nix, and manual Ubuntu installs
|
||||
provide Java 17 for SBT. Docker and Nix use Python 3.10 to match the
|
||||
hash-pinned Ubuntu 22.04 requirement sets. The environment also installs the
|
||||
locked Python build and quality dependencies, clang-format-14, GNU Make,
|
||||
C/C++ build tools, and runtime libraries required by those binaries.
|
||||
C/C++ build tools, Perl for Verilator, and runtime libraries required by those
|
||||
binaries.
|
||||
|
||||
The environment intentionally does not include PDK repositories, managed RTL,
|
||||
application archives, build output, or compiler caches. These inputs are
|
||||
@@ -33,6 +34,9 @@ Python requirements, and writes:
|
||||
|
||||
Bootstrap is idempotent. It reinstalls tools or Python packages when the
|
||||
dependency lock, selected tool set, or Python requirement hashes change.
|
||||
Installed public tool archives are made readable and their directories
|
||||
traversable by all users. This is required when Docker builds the image as root
|
||||
and runs regressions with the caller's user ID.
|
||||
|
||||
~~~sh
|
||||
python3 scripts/development_environment.py bootstrap
|
||||
|
||||
@@ -65,6 +65,7 @@
|
||||
ncurses5
|
||||
numactl
|
||||
jdk17_headless
|
||||
perl
|
||||
python310Full
|
||||
unzip
|
||||
which
|
||||
|
||||
@@ -60,6 +60,7 @@ SYSTEM_EXECUTABLES = (
|
||||
"make",
|
||||
"mold",
|
||||
"numactl",
|
||||
"perl",
|
||||
)
|
||||
STAMP_NAME = "development-environment.json"
|
||||
ACTIVATE_NAME = "activate.sh"
|
||||
|
||||
@@ -6,9 +6,11 @@ import argparse
|
||||
import os
|
||||
import posixpath
|
||||
import shutil
|
||||
import stat
|
||||
import sys
|
||||
import tarfile
|
||||
import tempfile
|
||||
from itertools import chain
|
||||
from pathlib import Path, PurePosixPath
|
||||
from typing import Any
|
||||
|
||||
@@ -38,6 +40,22 @@ def safe_extract(archive: Path, destination: Path) -> None:
|
||||
bundle.extractall(destination)
|
||||
|
||||
|
||||
def make_tree_world_readable(root: Path) -> None:
|
||||
"""Make a public tool archive usable by accounts other than its installer."""
|
||||
|
||||
for path in chain((root,), root.rglob("*")):
|
||||
if path.is_symlink():
|
||||
continue
|
||||
mode = stat.S_IMODE(path.stat().st_mode)
|
||||
if path.is_dir():
|
||||
path.chmod(mode | 0o555)
|
||||
elif path.is_file():
|
||||
shared_mode = mode | 0o444
|
||||
if mode & 0o111:
|
||||
shared_mode |= 0o111
|
||||
path.chmod(shared_mode)
|
||||
|
||||
|
||||
def install(name: str, spec: dict[str, Any], cache: Path, update: bool) -> Path:
|
||||
downloads = cache / "downloads"
|
||||
archive = downloads / spec["archive"]
|
||||
@@ -53,6 +71,7 @@ def install(name: str, spec: dict[str, Any], cache: Path, update: bool) -> Path:
|
||||
destination = cache / "toolchains" / f"{name}-{spec['version']}"
|
||||
marker = destination / ".complete"
|
||||
if marker.is_file() and marker.read_text(encoding="utf-8").strip() == spec["sha256"]:
|
||||
make_tree_world_readable(destination)
|
||||
return destination / spec["path"]
|
||||
|
||||
destination.parent.mkdir(parents=True, exist_ok=True)
|
||||
@@ -61,6 +80,7 @@ def install(name: str, spec: dict[str, Any], cache: Path, update: bool) -> Path:
|
||||
extracted.mkdir()
|
||||
safe_extract(archive, extracted)
|
||||
atomic_write(extracted / ".complete", spec["sha256"] + "\n")
|
||||
make_tree_world_readable(extracted)
|
||||
if destination.exists():
|
||||
shutil.rmtree(destination)
|
||||
os.replace(extracted, destination)
|
||||
|
||||
@@ -40,7 +40,7 @@ from scripts.development_environment import ( # noqa: E402
|
||||
write_activation,
|
||||
)
|
||||
from scripts.generate_mpw import render_active_manifest, validate_extension_bindings # noqa: E402
|
||||
from scripts.install_toolchain import safe_extract # noqa: E402
|
||||
from scripts.install_toolchain import make_tree_world_readable, safe_extract # noqa: E402
|
||||
from scripts.package import make_sbom # noqa: E402
|
||||
from scripts.prepare_mpw import patch_serv # noqa: E402
|
||||
from scripts import regress # noqa: E402
|
||||
@@ -1193,10 +1193,12 @@ def test_container_and_nix_environment_files_use_locked_inputs() -> None:
|
||||
|
||||
assert f"ubuntu@{lock['container_images']['ubuntu_22_04']['digest']}" in dockerfile
|
||||
assert "openjdk-17-jre-headless" in dockerfile
|
||||
assert " perl \\\n" in dockerfile
|
||||
assert "scripts/development_environment.py" in dockerfile
|
||||
assert "scripts/development_environment.py" in flake
|
||||
assert "buildFHSEnv" in flake
|
||||
assert "jdk17_headless" in flake
|
||||
assert " perl\n" in flake
|
||||
assert "python310Full" in flake
|
||||
assert "python3Full" not in flake
|
||||
assert "retrosoc-development retrosoc-dev" in flake
|
||||
@@ -2317,6 +2319,34 @@ def test_safe_extract_rejects_parent_traversal(tmp_path: Path) -> None:
|
||||
assert not (tmp_path / "outside").exists()
|
||||
|
||||
|
||||
def test_toolchain_tree_is_accessible_to_runtime_users(tmp_path: Path) -> None:
|
||||
toolchain = tmp_path / "toolchain"
|
||||
binary_directory = toolchain / "bundle/bin"
|
||||
binary_directory.mkdir(parents=True)
|
||||
executable = binary_directory / "tool"
|
||||
executable.write_text("#!/bin/sh\n", encoding="utf-8")
|
||||
data = toolchain / "bundle/data"
|
||||
data.write_text("public tool data\n", encoding="utf-8")
|
||||
marker = toolchain / ".complete"
|
||||
marker.write_text("digest\n", encoding="utf-8")
|
||||
|
||||
toolchain.chmod(0o700)
|
||||
(toolchain / "bundle").chmod(0o700)
|
||||
binary_directory.chmod(0o700)
|
||||
executable.chmod(0o700)
|
||||
data.chmod(0o600)
|
||||
marker.chmod(0o600)
|
||||
|
||||
make_tree_world_readable(toolchain)
|
||||
|
||||
assert toolchain.stat().st_mode & 0o777 == 0o755
|
||||
assert (toolchain / "bundle").stat().st_mode & 0o777 == 0o755
|
||||
assert binary_directory.stat().st_mode & 0o777 == 0o755
|
||||
assert executable.stat().st_mode & 0o777 == 0o755
|
||||
assert data.stat().st_mode & 0o777 == 0o644
|
||||
assert marker.stat().st_mode & 0o777 == 0o644
|
||||
|
||||
|
||||
def test_fatfs_update_reextracts_downloaded_archive(tmp_path: Path) -> None:
|
||||
module_path = ROOT / "app/setup.py"
|
||||
spec = importlib.util.spec_from_file_location("retrosoc_app_setup", module_path)
|
||||
|
||||
Reference in new issue
Block a user