test/cmd/compiler.py: use mock packages (#50362)

Signed-off-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
Co-authored-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
This commit is contained in:
Tamara Dahlgren 2025-05-16 02:53:36 -07:00 committed by GitHub
parent e3a7d5763f
commit 9738f1c026
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 69 additions and 10 deletions

View File

@ -15,6 +15,8 @@
compiler = spack.main.SpackCommand("compiler") compiler = spack.main.SpackCommand("compiler")
pytestmark = [pytest.mark.usefixtures("mock_packages")]
@pytest.fixture @pytest.fixture
def compilers_dir(mock_executable): def compilers_dir(mock_executable):
@ -80,7 +82,7 @@ def test_compiler_find_without_paths(no_packages_yaml, working_env, mock_executa
@pytest.mark.regression("37996") @pytest.mark.regression("37996")
def test_compiler_remove(mutable_config, mock_packages): def test_compiler_remove(mutable_config):
"""Tests that we can remove a compiler from configuration.""" """Tests that we can remove a compiler from configuration."""
assert any( assert any(
compiler.satisfies("gcc@=9.4.0") for compiler in spack.compilers.config.all_compilers() compiler.satisfies("gcc@=9.4.0") for compiler in spack.compilers.config.all_compilers()
@ -93,7 +95,7 @@ def test_compiler_remove(mutable_config, mock_packages):
@pytest.mark.regression("37996") @pytest.mark.regression("37996")
def test_removing_compilers_from_multiple_scopes(mutable_config, mock_packages): def test_removing_compilers_from_multiple_scopes(mutable_config):
# Duplicate "site" scope into "user" scope # Duplicate "site" scope into "user" scope
site_config = spack.config.get("packages", scope="site") site_config = spack.config.get("packages", scope="site")
spack.config.set("packages", site_config, scope="user") spack.config.set("packages", site_config, scope="user")
@ -189,12 +191,12 @@ def test_compiler_find_path_order(no_packages_yaml, working_env, compilers_dir):
} }
def test_compiler_list_empty(no_packages_yaml, working_env, compilers_dir): def test_compiler_list_empty(no_packages_yaml, compilers_dir, monkeypatch):
"""Spack should not automatically search for compilers when listing them and none are """Spack should not automatically search for compilers when listing them and none are
available. And when stdout is not a tty like in tests, there should be no output and available. And when stdout is not a tty like in tests, there should be no output and
no error exit code. no error exit code.
""" """
os.environ["PATH"] = str(compilers_dir) monkeypatch.setenv("PATH", str(compilers_dir), prepend=":")
out = compiler("list") out = compiler("list")
assert not out assert not out
assert compiler.returncode == 0 assert compiler.returncode == 0

View File

@ -4286,7 +4286,7 @@ def test_env_include_packages_url(
"""Test inclusion of a (GitHub) URL.""" """Test inclusion of a (GitHub) URL."""
develop_url = "https://github.com/fake/fake/blob/develop/" develop_url = "https://github.com/fake/fake/blob/develop/"
default_packages = develop_url + "etc/fake/defaults/packages.yaml" default_packages = develop_url + "etc/fake/defaults/packages.yaml"
sha256 = "8b69d9c6e983dfb8bac2ddc3910a86265cffdd9c85f905c716d426ec5b0d9847" sha256 = "6a1b26c857ca7e5bcd7342092e2f218da43d64b78bd72771f603027ea3c8b4af"
spack_yaml = tmpdir.join("spack.yaml") spack_yaml = tmpdir.join("spack.yaml")
with spack_yaml.open("w") as f: with spack_yaml.open("w") as f:
f.write( f.write(

View File

@ -759,7 +759,7 @@ def test_virtual_is_fully_expanded_for_mpileaks(self):
@pytest.mark.parametrize( @pytest.mark.parametrize(
"spec_str,expected,not_expected", "spec_str,expected,not_expected",
[ [
# clang only provides C, and C++ compilers, while gcc has also fortran # clang (llvm~flang) only provides C, and C++ compilers, while gcc has also fortran
# #
# If we ask mpileaks%clang, then %gcc must be used for fortran, and since # If we ask mpileaks%clang, then %gcc must be used for fortran, and since
# %gcc is preferred to clang in config, it will be used for most nodes # %gcc is preferred to clang in config, it will be used for most nodes

View File

@ -887,6 +887,7 @@ def no_packages_yaml(mutable_config):
compilers_yaml = local_config.get_section_filename("packages") compilers_yaml = local_config.get_section_filename("packages")
if os.path.exists(compilers_yaml): if os.path.exists(compilers_yaml):
os.remove(compilers_yaml) os.remove(compilers_yaml)
mutable_config.clear_caches()
return mutable_config return mutable_config

View File

@ -81,7 +81,7 @@ packages:
fortran: /path/bin/gfortran-10 fortran: /path/bin/gfortran-10
llvm: llvm:
externals: externals:
- spec: "llvm@15.0.0 +clang os={linux_os.name}{linux_os.version} target={target}" - spec: "llvm@15.0.0 +clang~flang os={linux_os.name}{linux_os.version} target={target}"
prefix: /path prefix: /path
extra_attributes: extra_attributes:
compilers: compilers:

View File

@ -52,9 +52,9 @@ def test_rfc_remote_local_path_no_dest():
packages_yaml_sha256 = ( packages_yaml_sha256 = (
"8b69d9c6e983dfb8bac2ddc3910a86265cffdd9c85f905c716d426ec5b0d9847" "6a1b26c857ca7e5bcd7342092e2f218da43d64b78bd72771f603027ea3c8b4af"
if sys.platform != "win32" if sys.platform != "win32"
else "182a5cdfdd88f50be23e55607b46285854c664c064e5a9f3f1e0200ebca6a1db" else "ae3239d769f9e6dc137a998489b0d44c70b03e21de4ecd6a623a3463a1a5c3f4"
) )

View File

@ -2,6 +2,7 @@
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os import os
import re
from spack.package import * from spack.package import *
@ -12,20 +13,75 @@ class Llvm(Package, CompilerPackage):
homepage = "http://www.example.com" homepage = "http://www.example.com"
url = "http://www.example.com/gcc-1.0.tar.gz" url = "http://www.example.com/gcc-1.0.tar.gz"
tags = ["compiler"]
version("18.1.8", md5="0123456789abcdef0123456789abcdef") version("18.1.8", md5="0123456789abcdef0123456789abcdef")
variant( variant(
"clang", default=True, description="Build the LLVM C/C++/Objective-C compiler frontend" "clang", default=True, description="Build the LLVM C/C++/Objective-C compiler frontend"
) )
variant(
"flang",
default=False,
description="Build the LLVM Fortran compiler frontend "
"(experimental - parser only, needs GCC)",
)
variant("lld", default=True, description="Build the LLVM linker") variant("lld", default=True, description="Build the LLVM linker")
provides("c", "cxx", when="+clang") provides("c", "cxx", when="+clang")
provides("fortran", when="+flang")
depends_on("c") depends_on("c")
compiler_version_argument = "--version"
c_names = ["clang"] c_names = ["clang"]
cxx_names = ["clang++"] cxx_names = ["clang++"]
fortran_names = ["flang"]
clang_and_friends = "(?:clang|flang|flang-new)"
compiler_version_regex = (
# Normal clang compiler versions are left as-is
rf"{clang_and_friends} version ([^ )\n]+)-svn[~.\w\d-]*|"
# Don't include hyphenated patch numbers in the version
# (see https://github.com/spack/spack/pull/14365 for details)
rf"{clang_and_friends} version ([^ )\n]+?)-[~.\w\d-]*|"
rf"{clang_and_friends} version ([^ )\n]+)|"
# LLDB
r"lldb version ([^ )\n]+)|"
# LLD
r"LLD ([^ )\n]+) \(compatible with GNU linkers\)"
)
fortran_names = ["flang", "flang-new"]
@classmethod
def determine_version(cls, exe):
try:
compiler = Executable(exe)
output = compiler(cls.compiler_version_argument, output=str, error=str)
if "Apple" in output:
return None
if "AMD" in output:
return None
match = re.search(cls.compiler_version_regex, output)
if match:
return match.group(match.lastindex)
except ProcessError:
pass
except Exception as e:
tty.debug(e)
return None
@classmethod
def filter_detected_exes(cls, prefix, exes_in_prefix):
# Executables like lldb-vscode-X are daemon listening on some port and would hang Spack
# during detection. clang-cl, clang-cpp, etc. are dev tools that we don't need to test
reject = re.compile(
r"-(vscode|cpp|cl|ocl|gpu|tidy|rename|scan-deps|format|refactor|offload|"
r"check|query|doc|move|extdef|apply|reorder|change-namespace|"
r"include-fixer|import-test|dap|server|PerfectShuffle)"
)
return [x for x in exes_in_prefix if not reject.search(x)]
def install(self, spec, prefix): def install(self, spec, prefix):
# Create the minimal compiler that will fool `spack compiler find` # Create the minimal compiler that will fool `spack compiler find`