diff --git a/lib/spack/llnl/util/lang.py b/lib/spack/llnl/util/lang.py index d2cce42a16d..83d4c8938cf 100644 --- a/lib/spack/llnl/util/lang.py +++ b/lib/spack/llnl/util/lang.py @@ -72,7 +72,7 @@ def index_by(objects, *funcs): if isinstance(f, str): f = lambda x: getattr(x, funcs[0]) elif isinstance(f, tuple): - f = lambda x: tuple(getattr(x, p) for p in funcs[0]) + f = lambda x: tuple(getattr(x, p, None) for p in funcs[0]) result = {} for o in objects: diff --git a/lib/spack/spack/cmd/__init__.py b/lib/spack/spack/cmd/__init__.py index 5cb02df6963..5150b437a76 100644 --- a/lib/spack/spack/cmd/__init__.py +++ b/lib/spack/spack/cmd/__init__.py @@ -375,8 +375,13 @@ def iter_groups(specs, indent, all_headers): index = index_by(specs, ("architecture", "compiler")) ispace = indent * " " + def _key(item): + if item is None: + return "" + return str(item) + # Traverse the index and print out each package - for i, (architecture, compiler) in enumerate(sorted(index)): + for i, (architecture, compiler) in enumerate(sorted(index, key=_key)): if i > 0: print() @@ -434,7 +439,6 @@ def display_specs(specs, args=None, **kwargs): """ - # FIXME (compiler as nodes): remove the "show full compiler" arguments, and its use def get_arg(name, default=None): """Prefer kwargs, then args, then default.""" if name in kwargs: @@ -449,7 +453,6 @@ def get_arg(name, default=None): hashes = get_arg("long", False) namespaces = get_arg("namespaces", False) flags = get_arg("show_flags", False) - full_compiler = get_arg("show_full_compiler", False) variants = get_arg("variants", False) groups = get_arg("groups", True) all_headers = get_arg("all_headers", False) @@ -471,10 +474,7 @@ def get_arg(name, default=None): if format_string is None: nfmt = "{fullname}" if namespaces else "{name}" ffmt = "" - if full_compiler or flags: - ffmt += "{%compiler.name}" - if full_compiler: - ffmt += "{@compiler.version}" + if flags: ffmt += " {compiler_flags}" vfmt = "{variants}" if variants else "" format_string = nfmt + "{@version}" + ffmt + vfmt diff --git a/lib/spack/spack/cmd/config.py b/lib/spack/spack/cmd/config.py index 90652e94316..9ae11b5e381 100644 --- a/lib/spack/spack/cmd/config.py +++ b/lib/spack/spack/cmd/config.py @@ -518,8 +518,6 @@ def config_prefer_upstream(args): for spec in pref_specs: # Collect all the upstream compilers and versions for this package. pkg = pkgs.get(spec.name, {"version": []}) - all = pkgs.get("all", {"compiler": []}) - pkgs["all"] = all pkgs[spec.name] = pkg # We have no existing variant if this is our first added version. @@ -529,10 +527,6 @@ def config_prefer_upstream(args): if version not in pkg["version"]: pkg["version"].append(version) - compiler = str(spec.compiler) - if compiler not in all["compiler"]: - all["compiler"].append(compiler) - # Get and list all the variants that differ from the default. variants = [] for var_name, variant in spec.variants.items(): diff --git a/lib/spack/spack/cmd/find.py b/lib/spack/spack/cmd/find.py index 24f11c5fe38..e17b6c5fe60 100644 --- a/lib/spack/spack/cmd/find.py +++ b/lib/spack/spack/cmd/find.py @@ -98,7 +98,7 @@ def setup_parser(subparser): "--show-full-compiler", action="store_true", dest="show_full_compiler", - help="(DEPRECATED) show full compiler specs", + help="(DEPRECATED) show full compiler specs. Currently it's a no-op", ) implicit_explicit = subparser.add_mutually_exclusive_group() implicit_explicit.add_argument( @@ -278,7 +278,6 @@ def root_decorator(spec, string): # these enforce details in the root specs to show what the user asked for namespaces=True, show_flags=True, - show_full_compiler=True, decorator=root_decorator, variants=True, ) @@ -301,7 +300,6 @@ def root_decorator(spec, string): decorator=lambda s, f: color.colorize("@*{%s}" % f), namespace=True, show_flags=True, - show_full_compiler=True, variants=True, ) print() diff --git a/lib/spack/spack/package_base.py b/lib/spack/spack/package_base.py index d8522c69e98..ad8f309fe61 100644 --- a/lib/spack/spack/package_base.py +++ b/lib/spack/spack/package_base.py @@ -30,7 +30,6 @@ import llnl.util.tty as tty from llnl.util.lang import classproperty, memoized -import spack.compilers.config import spack.config import spack.dependency import spack.deptypes as dt @@ -1813,17 +1812,14 @@ def _resource_stage(self, resource): return resource_stage_folder def do_test(self, dirty=False, externals=False): - if self.test_requires_compiler: - compilers = spack.compilers.config.compilers_for_spec( - self.spec.compiler, arch_spec=self.spec.architecture + if self.test_requires_compiler and not any( + lang in self.spec for lang in ("c", "cxx", "fortran") + ): + tty.error( + f"Skipping tests for package {self.spec}, since a compiler is required, " + f"but not available" ) - if not compilers: - tty.error( - "Skipping tests for package %s\n" - % self.spec.format("{name}-{version}-{hash:7}") - + "Package test requires missing compiler %s" % self.spec.compiler - ) - return + return kwargs = { "dirty": dirty, diff --git a/lib/spack/spack/report.py b/lib/spack/spack/report.py index 04bdac7b4aa..0f23fcd6e50 100644 --- a/lib/spack/spack/report.py +++ b/lib/spack/spack/report.py @@ -77,7 +77,6 @@ def __enter__(self): "packages": [], } spec_record["properties"].append(Property("architecture", input_spec.architecture)) - spec_record["properties"].append(Property("compiler", input_spec.compiler)) self.init_spec_record(input_spec, spec_record) self.specs.append(spec_record) diff --git a/lib/spack/spack/spec.py b/lib/spack/spack/spec.py index 5b24cd7018e..886191ff868 100644 --- a/lib/spack/spack/spec.py +++ b/lib/spack/spack/spec.py @@ -630,7 +630,7 @@ def __contains__(self, string): return string in str(self) or string in self.target def complete_with_defaults(self) -> None: - default_architecture = spack.spec.ArchSpec.default_arch() + default_architecture = ArchSpec.default_arch() if not self.platform: self.platform = default_architecture.platform @@ -703,7 +703,8 @@ def factory(self, instance, owner): deps = instance.dependencies(virtuals=language) if deps: return CompilerSpec(deps[0]) - return CompilerSpec(Spec()) + + raise AttributeError(f"{instance} has no C, C++, or Fortran compiler") @lang.lazy_lexicographic_ordering @@ -1435,13 +1436,13 @@ def tree( class SpecAnnotations: def __init__(self) -> None: self.original_spec_format = SPECFILE_FORMAT_VERSION - self.compiler_node_attribute: Optional["spack.spec.Spec"] = None + self.compiler_node_attribute: Optional["Spec"] = None def with_spec_format(self, spec_format: int) -> "SpecAnnotations": self.original_spec_format = spec_format return self - def with_compiler(self, compiler: "spack.spec.Spec") -> "SpecAnnotations": + def with_compiler(self, compiler: "Spec") -> "SpecAnnotations": self.compiler_node_attribute = compiler return self @@ -3009,10 +3010,9 @@ def validate_or_raise(self): if spec.name and not spack.repo.PATH.is_virtual(spec.name): spack.repo.PATH.get_pkg_class(spec.fullname) - # validate compiler in addition to the package name. + # FIXME: atm allow '%' on abstract specs only if they depend on C, C++, or Fortran if spec.dependencies(deptype="build"): pkg_cls = spack.repo.PATH.get_pkg_class(spec.fullname) - # FIXME (compiler as nodes): raise if we use %gcc on pkgs that do not depend on C pkg_dependencies = pkg_cls.dependency_names() if not any(x in pkg_dependencies for x in ("c", "cxx", "fortran")): raise UnsupportedCompilerError( @@ -3975,6 +3975,9 @@ def format_attribute(match_object: Match) -> str: try: current = getattr(current, part) except AttributeError: + if part == "compiler": + return "none" + raise SpecFormatStringError( f"Attempted to format attribute {attribute}. " f"Spec {'.'.join(parts[:idx])} has no attribute {part}"