import copy import os from collections.abc import MutableMapping from pathlib import Path def add_spec_env( env: MutableMapping[str, str], spec_dir: Path, ) -> MutableMapping[str, str]: """ Add SPEC-specific configurations to an environment mapping. This function updates the provided environment mapping with SPEC-specific settings. It sets the 'SPEC' environment variable to the provided directory path and prepends the SPEC binary directory to the system PATH. Parameters ---------- env : MutableMapping[str, str] The environment dictionary to update. spec_dir : Path The path to the SPEC directory. Returns ------- MutableMapping[str, str] The updated environment dictionary. Examples -------- >>> import pathlib >>> env = {"PATH": "/usr/bin:/usr/local/bin"} >>> updated_env = add_spec_env(env, pathlib.Path("/path/to/spec")) >>> updated_env["SPEC"] '/path/to/spec' >>> updated_env["PATH"].startswith("/path/to/spec/bin:") True """ env["SPEC"] = str(spec_dir) env["PATH"] = os.pathsep.join( [ str(spec_dir / "bin"), *env["PATH"].split(os.pathsep), ] ) return env def create_spec_env(spec_dir: Path) -> MutableMapping[str, str]: """ Create a new environment with SPEC-specific configurations. This function creates a copy of the current environment variables and updates it with SPEC-specific settings using add_spec_env. Parameters ---------- spec_dir : Path The path to the SPEC directory. Returns ------- dict A dictionary containing the updated environment variables. Examples -------- >>> import pathlib >>> import os >>> os.environ["PATH"] = "/usr/bin:/usr/local/bin" >>> env = create_spec_env(pathlib.Path("/path/to/spec")) >>> env["SPEC"] '/path/to/spec' >>> "/path/to/spec/bin" in env["PATH"] True """ new_env = copy.deepcopy(os.environ) return add_spec_env(new_env, spec_dir) def find_build(build_dir: Path) -> Path: entries = list(sorted(os.listdir(build_dir))) for entry in entries: if entry.startswith("build"): return build_dir / entry raise RuntimeError(f"SPEC build directory not found at {build_dir}") class SPEC: dir: Path def __init__(self, dir: Path): self.dir = dir @property def config_dir(self) -> Path: return self.dir / "config" def env(self): return create_spec_env(self.dir) def mkcmd_runcpu( self, config: str, benchmarks: list[str], setprocgroup: bool = True, workload: str = "ref", output_root: Path | None = None, ): return [ "runcpu", *(["--setprocgroup"] if setprocgroup else []), "-i", workload, "-c", config, *(["--outputdir", str(output_root)] if output_root else []), *benchmarks, ]