diff --git a/lib/spack/external/__init__.py b/lib/spack/external/__init__.py index 5030ee5f73d..0d1be14a41c 100644 --- a/lib/spack/external/__init__.py +++ b/lib/spack/external/__init__.py @@ -18,7 +18,7 @@ * Homepage: https://pypi.python.org/pypi/archspec * Usage: Labeling, comparison and detection of microarchitectures -* Version: 0.2.3 (commit 7b8fe60b69e2861e7dac104bc1c183decfcd3daf) +* Version: 0.2.4 (commit 48b92512b9ce203ded0ebd1ac41b42593e931f7c) astunparse ---------------- diff --git a/lib/spack/external/archspec/__init__.py b/lib/spack/external/archspec/__init__.py index 7568bbd0e90..2930ad719e4 100644 --- a/lib/spack/external/archspec/__init__.py +++ b/lib/spack/external/archspec/__init__.py @@ -1,3 +1,3 @@ """Init file to avoid namespace packages""" -__version__ = "0.2.3" +__version__ = "0.2.4" diff --git a/lib/spack/external/archspec/cpu/__init__.py b/lib/spack/external/archspec/cpu/__init__.py index 5fa60d28748..6fbb43b785d 100644 --- a/lib/spack/external/archspec/cpu/__init__.py +++ b/lib/spack/external/archspec/cpu/__init__.py @@ -5,9 +5,10 @@ """The "cpu" package permits to query and compare different CPU microarchitectures. """ -from .detect import host +from .detect import brand_string, host from .microarchitecture import ( TARGETS, + InvalidCompilerVersion, Microarchitecture, UnsupportedMicroarchitecture, generic_microarchitecture, @@ -15,10 +16,12 @@ ) __all__ = [ + "brand_string", + "host", + "TARGETS", + "InvalidCompilerVersion", "Microarchitecture", "UnsupportedMicroarchitecture", - "TARGETS", "generic_microarchitecture", - "host", "version_components", ] diff --git a/lib/spack/external/archspec/cpu/detect.py b/lib/spack/external/archspec/cpu/detect.py index 179b7a947b1..d99295d9071 100644 --- a/lib/spack/external/archspec/cpu/detect.py +++ b/lib/spack/external/archspec/cpu/detect.py @@ -155,6 +155,31 @@ def _is_bit_set(self, register: int, bit: int) -> bool: mask = 1 << bit return register & mask > 0 + def brand_string(self) -> Optional[str]: + """Returns the brand string, if available.""" + if self.highest_extension_support < 0x80000004: + return None + + r1 = self.cpuid.registers_for(eax=0x80000002, ecx=0) + r2 = self.cpuid.registers_for(eax=0x80000003, ecx=0) + r3 = self.cpuid.registers_for(eax=0x80000004, ecx=0) + result = struct.pack( + "IIIIIIIIIIII", + r1.eax, + r1.ebx, + r1.ecx, + r1.edx, + r2.eax, + r2.ebx, + r2.ecx, + r2.edx, + r3.eax, + r3.ebx, + r3.ecx, + r3.edx, + ).decode("utf-8") + return result.strip("\x00") + @detection(operating_system="Windows") def cpuid_info(): @@ -174,8 +199,8 @@ def _check_output(args, env): WINDOWS_MAPPING = { - "AMD64": "x86_64", - "ARM64": "aarch64", + "AMD64": X86_64, + "ARM64": AARCH64, } @@ -409,3 +434,16 @@ def compatibility_check_for_riscv64(info, target): return (target == arch_root or arch_root in target.ancestors) and ( target.name == info.name or target.vendor == "generic" ) + + +def brand_string() -> Optional[str]: + """Returns the brand string of the host, if detected, or None.""" + if platform.system() == "Darwin": + return _check_output( + ["sysctl", "-n", "machdep.cpu.brand_string"], env=_ensure_bin_usrbin_in_path() + ).strip() + + if host().family == X86_64: + return CpuidInfoCollector().brand_string() + + return None diff --git a/lib/spack/external/archspec/cpu/microarchitecture.py b/lib/spack/external/archspec/cpu/microarchitecture.py index a6526aa9266..7a251b905e2 100644 --- a/lib/spack/external/archspec/cpu/microarchitecture.py +++ b/lib/spack/external/archspec/cpu/microarchitecture.py @@ -208,6 +208,8 @@ def optimization_flags(self, compiler, version): """Returns a string containing the optimization flags that needs to be used to produce code optimized for this micro-architecture. + The version is expected to be a string of dot separated digits. + If there is no information on the compiler passed as argument the function returns an empty string. If it is known that the compiler version we want to use does not support this architecture the function @@ -216,6 +218,11 @@ def optimization_flags(self, compiler, version): Args: compiler (str): name of the compiler to be used version (str): version of the compiler to be used + + Raises: + UnsupportedMicroarchitecture: if the requested compiler does not support + this micro-architecture. + ValueError: if the version doesn't match the expected format """ # If we don't have information on compiler at all return an empty string if compiler not in self.family.compilers: @@ -232,6 +239,14 @@ def optimization_flags(self, compiler, version): msg = msg.format(compiler, best_target, best_target.family) raise UnsupportedMicroarchitecture(msg) + # Check that the version matches the expected format + if not re.match(r"^(?:\d+\.)*\d+$", version): + msg = ( + "invalid format for the compiler version argument. " + "Only dot separated digits are allowed." + ) + raise InvalidCompilerVersion(msg) + # If we have information on this compiler we need to check the # version being used compiler_info = self.compilers[compiler] @@ -292,7 +307,7 @@ def generic_microarchitecture(name): Args: name (str): name of the micro-architecture """ - return Microarchitecture(name, parents=[], vendor="generic", features=[], compilers={}) + return Microarchitecture(name, parents=[], vendor="generic", features=set(), compilers={}) def version_components(version): @@ -367,7 +382,15 @@ def fill_target_from_dict(name, data, targets): TARGETS = LazyDictionary(_known_microarchitectures) -class UnsupportedMicroarchitecture(ValueError): +class ArchspecError(Exception): + """Base class for errors within archspec""" + + +class UnsupportedMicroarchitecture(ArchspecError, ValueError): """Raised if a compiler version does not support optimization for a given micro-architecture. """ + + +class InvalidCompilerVersion(ArchspecError, ValueError): + """Raised when an invalid format is used for compiler versions in archspec.""" diff --git a/lib/spack/external/archspec/json/cpu/microarchitectures.json b/lib/spack/external/archspec/json/cpu/microarchitectures.json index 1e77caba4ae..1e8a8caa35c 100644 --- a/lib/spack/external/archspec/json/cpu/microarchitectures.json +++ b/lib/spack/external/archspec/json/cpu/microarchitectures.json @@ -2937,8 +2937,6 @@ "ilrcpc", "flagm", "ssbs", - "paca", - "pacg", "dcpodp", "svei8mm", "svebf16", @@ -3066,8 +3064,6 @@ "flagm", "ssbs", "sb", - "paca", - "pacg", "dcpodp", "sve2", "sveaes", @@ -3081,8 +3077,7 @@ "svebf16", "i8mm", "bf16", - "dgh", - "bti" + "dgh" ], "compilers" : { "gcc": [ diff --git a/lib/spack/spack/solver/asp.py b/lib/spack/spack/solver/asp.py index 94a471c8494..6a9d6f95c38 100644 --- a/lib/spack/spack/solver/asp.py +++ b/lib/spack/spack/solver/asp.py @@ -2185,7 +2185,7 @@ def _supported_targets(self, compiler_name, compiler_version, targets): try: with warnings.catch_warnings(): warnings.simplefilter("ignore") - target.optimization_flags(compiler_name, compiler_version) + target.optimization_flags(compiler_name, str(compiler_version)) supported.append(target) except archspec.cpu.UnsupportedMicroarchitecture: continue diff --git a/lib/spack/spack/test/concretize.py b/lib/spack/spack/test/concretize.py index 47fcc639c9e..c8a7ef3eb25 100644 --- a/lib/spack/spack/test/concretize.py +++ b/lib/spack/spack/test/concretize.py @@ -1203,10 +1203,11 @@ def test_variant_not_default(self): @pytest.mark.regression("20055") @pytest.mark.only_clingo("Use case not supported by the original concretizer") - def test_custom_compiler_version(self, mutable_config, compiler_factory): + def test_custom_compiler_version(self, mutable_config, compiler_factory, monkeypatch): mutable_config.set( "compilers", [compiler_factory(spec="gcc@10foo", operating_system="redhat6")] ) + monkeypatch.setattr(spack.compiler.Compiler, "real_version", "10.2.1") s = Spec("pkg-a %gcc@10foo os=redhat6").concretized() assert "%gcc@10foo" in s