diff --git a/docs/development-environment.md b/docs/development-environment.md index 72130c8c..01f832d8 100644 --- a/docs/development-environment.md +++ b/docs/development-environment.md @@ -11,8 +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, Perl for Verilator, and runtime libraries required by those -binaries. +C/C++ build tools, Perl for Verilator, GNU MPC for the RISC-V compiler, 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 @@ -37,6 +37,8 @@ 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. +The environment stamp and activation script are also world-readable so those +runtime users can verify and activate the root-built environment. ~~~sh python3 scripts/development_environment.py bootstrap diff --git a/flake.nix b/flake.nix index 3585a23d..567030bb 100644 --- a/flake.nix +++ b/flake.nix @@ -61,6 +61,7 @@ gperftools launcher libunwind + libmpc mold ncurses5 numactl diff --git a/scripts/development_environment.py b/scripts/development_environment.py index dfdca436..fc1167b4 100644 --- a/scripts/development_environment.py +++ b/scripts/development_environment.py @@ -166,6 +166,11 @@ def write_activation(path: Path, content: str) -> None: path.chmod(0o644) +def write_stamp(path: Path, content: dict[str, Any]) -> None: + atomic_write(path, json.dumps(content, indent=2, sort_keys=True) + "\n") + path.chmod(0o644) + + def run(command: list[str]) -> None: print("+ " + " ".join(shlex.quote(argument) for argument in command), flush=True) subprocess.run(command, check=True) @@ -205,7 +210,7 @@ def bootstrap(args: argparse.Namespace) -> int: for name in tools: install(name, available[name], cache, update=args.update) create_virtualenv(root, cache) - atomic_write(cache / STAMP_NAME, json.dumps(expected_stamp, indent=2, sort_keys=True) + "\n") + write_stamp(cache / STAMP_NAME, expected_stamp) activation = args.output.resolve() if args.output else cache / ACTIVATE_NAME write_activation( activation, diff --git a/tests/test_script_tools.py b/tests/test_script_tools.py index 18795d93..e89ee538 100644 --- a/tests/test_script_tools.py +++ b/tests/test_script_tools.py @@ -38,6 +38,7 @@ from scripts.development_environment import ( # noqa: E402 render_activation, stamp_data, write_activation, + write_stamp, ) from scripts.generate_mpw import render_active_manifest, validate_extension_bindings # noqa: E402 from scripts.install_toolchain import make_tree_world_readable, safe_extract # noqa: E402 @@ -1183,6 +1184,10 @@ def test_development_environment_contract_is_lock_pinned(tmp_path: Path) -> None activation_path = tmp_path / "activate.sh" write_activation(activation_path, activation) assert activation_path.stat().st_mode & 0o777 == 0o644 + stamp_path = tmp_path / "development-environment.json" + write_stamp(stamp_path, stamp) + assert json.loads(stamp_path.read_text(encoding="utf-8")) == stamp + assert stamp_path.stat().st_mode & 0o777 == 0o644 def test_container_and_nix_environment_files_use_locked_inputs() -> None: @@ -1198,6 +1203,7 @@ def test_container_and_nix_environment_files_use_locked_inputs() -> None: assert "scripts/development_environment.py" in flake assert "buildFHSEnv" in flake assert "jdk17_headless" in flake + assert " libmpc\n" in flake assert " perl\n" in flake assert "python310Full" in flake assert "python3Full" not in flake