Make Spec.compiler behavior stricter
Now the adaptor will raise if the Spec has no C, C++, or Fortran compiler.
This commit is contained in:
parent
10479101fa
commit
b6ce34607e
@ -72,7 +72,7 @@ def index_by(objects, *funcs):
|
|||||||
if isinstance(f, str):
|
if isinstance(f, str):
|
||||||
f = lambda x: getattr(x, funcs[0])
|
f = lambda x: getattr(x, funcs[0])
|
||||||
elif isinstance(f, tuple):
|
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 = {}
|
result = {}
|
||||||
for o in objects:
|
for o in objects:
|
||||||
|
@ -375,8 +375,13 @@ def iter_groups(specs, indent, all_headers):
|
|||||||
index = index_by(specs, ("architecture", "compiler"))
|
index = index_by(specs, ("architecture", "compiler"))
|
||||||
ispace = indent * " "
|
ispace = indent * " "
|
||||||
|
|
||||||
|
def _key(item):
|
||||||
|
if item is None:
|
||||||
|
return ""
|
||||||
|
return str(item)
|
||||||
|
|
||||||
# Traverse the index and print out each package
|
# 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:
|
if i > 0:
|
||||||
print()
|
print()
|
||||||
|
|
||||||
@ -449,7 +454,6 @@ def get_arg(name, default=None):
|
|||||||
hashes = get_arg("long", False)
|
hashes = get_arg("long", False)
|
||||||
namespaces = get_arg("namespaces", False)
|
namespaces = get_arg("namespaces", False)
|
||||||
flags = get_arg("show_flags", False)
|
flags = get_arg("show_flags", False)
|
||||||
full_compiler = get_arg("show_full_compiler", False)
|
|
||||||
variants = get_arg("variants", False)
|
variants = get_arg("variants", False)
|
||||||
groups = get_arg("groups", True)
|
groups = get_arg("groups", True)
|
||||||
all_headers = get_arg("all_headers", False)
|
all_headers = get_arg("all_headers", False)
|
||||||
@ -471,10 +475,7 @@ def get_arg(name, default=None):
|
|||||||
if format_string is None:
|
if format_string is None:
|
||||||
nfmt = "{fullname}" if namespaces else "{name}"
|
nfmt = "{fullname}" if namespaces else "{name}"
|
||||||
ffmt = ""
|
ffmt = ""
|
||||||
if full_compiler or flags:
|
if flags:
|
||||||
ffmt += "{%compiler.name}"
|
|
||||||
if full_compiler:
|
|
||||||
ffmt += "{@compiler.version}"
|
|
||||||
ffmt += " {compiler_flags}"
|
ffmt += " {compiler_flags}"
|
||||||
vfmt = "{variants}" if variants else ""
|
vfmt = "{variants}" if variants else ""
|
||||||
format_string = nfmt + "{@version}" + ffmt + vfmt
|
format_string = nfmt + "{@version}" + ffmt + vfmt
|
||||||
|
@ -518,8 +518,6 @@ def config_prefer_upstream(args):
|
|||||||
for spec in pref_specs:
|
for spec in pref_specs:
|
||||||
# Collect all the upstream compilers and versions for this package.
|
# Collect all the upstream compilers and versions for this package.
|
||||||
pkg = pkgs.get(spec.name, {"version": []})
|
pkg = pkgs.get(spec.name, {"version": []})
|
||||||
all = pkgs.get("all", {"compiler": []})
|
|
||||||
pkgs["all"] = all
|
|
||||||
pkgs[spec.name] = pkg
|
pkgs[spec.name] = pkg
|
||||||
|
|
||||||
# We have no existing variant if this is our first added version.
|
# 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"]:
|
if version not in pkg["version"]:
|
||||||
pkg["version"].append(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.
|
# Get and list all the variants that differ from the default.
|
||||||
variants = []
|
variants = []
|
||||||
for var_name, variant in spec.variants.items():
|
for var_name, variant in spec.variants.items():
|
||||||
|
@ -98,7 +98,7 @@ def setup_parser(subparser):
|
|||||||
"--show-full-compiler",
|
"--show-full-compiler",
|
||||||
action="store_true",
|
action="store_true",
|
||||||
dest="show_full_compiler",
|
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 = subparser.add_mutually_exclusive_group()
|
||||||
implicit_explicit.add_argument(
|
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
|
# these enforce details in the root specs to show what the user asked for
|
||||||
namespaces=True,
|
namespaces=True,
|
||||||
show_flags=True,
|
show_flags=True,
|
||||||
show_full_compiler=True,
|
|
||||||
decorator=root_decorator,
|
decorator=root_decorator,
|
||||||
variants=True,
|
variants=True,
|
||||||
)
|
)
|
||||||
@ -301,7 +300,6 @@ def root_decorator(spec, string):
|
|||||||
decorator=lambda s, f: color.colorize("@*{%s}" % f),
|
decorator=lambda s, f: color.colorize("@*{%s}" % f),
|
||||||
namespace=True,
|
namespace=True,
|
||||||
show_flags=True,
|
show_flags=True,
|
||||||
show_full_compiler=True,
|
|
||||||
variants=True,
|
variants=True,
|
||||||
)
|
)
|
||||||
print()
|
print()
|
||||||
|
@ -32,7 +32,6 @@
|
|||||||
from llnl.util.lang import classproperty, memoized
|
from llnl.util.lang import classproperty, memoized
|
||||||
from llnl.util.link_tree import LinkTree
|
from llnl.util.link_tree import LinkTree
|
||||||
|
|
||||||
import spack.compilers.config
|
|
||||||
import spack.config
|
import spack.config
|
||||||
import spack.dependency
|
import spack.dependency
|
||||||
import spack.deptypes as dt
|
import spack.deptypes as dt
|
||||||
@ -1932,17 +1931,14 @@ def _resource_stage(self, resource):
|
|||||||
return resource_stage_folder
|
return resource_stage_folder
|
||||||
|
|
||||||
def do_test(self, dirty=False, externals=False):
|
def do_test(self, dirty=False, externals=False):
|
||||||
if self.test_requires_compiler:
|
if self.test_requires_compiler and not any(
|
||||||
compilers = spack.compilers.config.compilers_for_spec(
|
lang in self.spec for lang in ("c", "cxx", "fortran")
|
||||||
self.spec.compiler, arch_spec=self.spec.architecture
|
):
|
||||||
|
tty.error(
|
||||||
|
f"Skipping tests for package {self.spec}, since a compiler is required, "
|
||||||
|
f"but not available"
|
||||||
)
|
)
|
||||||
if not compilers:
|
return
|
||||||
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
|
|
||||||
|
|
||||||
kwargs = {
|
kwargs = {
|
||||||
"dirty": dirty,
|
"dirty": dirty,
|
||||||
|
@ -77,7 +77,6 @@ def __enter__(self):
|
|||||||
"packages": [],
|
"packages": [],
|
||||||
}
|
}
|
||||||
spec_record["properties"].append(Property("architecture", input_spec.architecture))
|
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.init_spec_record(input_spec, spec_record)
|
||||||
self.specs.append(spec_record)
|
self.specs.append(spec_record)
|
||||||
|
|
||||||
|
@ -607,7 +607,7 @@ def __contains__(self, string):
|
|||||||
return string in str(self) or string in self.target
|
return string in str(self) or string in self.target
|
||||||
|
|
||||||
def complete_with_defaults(self) -> None:
|
def complete_with_defaults(self) -> None:
|
||||||
default_architecture = spack.spec.ArchSpec.default_arch()
|
default_architecture = ArchSpec.default_arch()
|
||||||
if not self.platform:
|
if not self.platform:
|
||||||
self.platform = default_architecture.platform
|
self.platform = default_architecture.platform
|
||||||
|
|
||||||
@ -680,7 +680,8 @@ def factory(self, instance, owner):
|
|||||||
deps = instance.dependencies(virtuals=language)
|
deps = instance.dependencies(virtuals=language)
|
||||||
if deps:
|
if deps:
|
||||||
return CompilerSpec(deps[0])
|
return CompilerSpec(deps[0])
|
||||||
return CompilerSpec(Spec())
|
|
||||||
|
raise AttributeError(f"{instance} has no C, C++, or Fortran compiler")
|
||||||
|
|
||||||
|
|
||||||
@lang.lazy_lexicographic_ordering
|
@lang.lazy_lexicographic_ordering
|
||||||
@ -1406,13 +1407,13 @@ def tree(
|
|||||||
class SpecAnnotations:
|
class SpecAnnotations:
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.original_spec_format = SPECFILE_FORMAT_VERSION
|
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":
|
def with_spec_format(self, spec_format: int) -> "SpecAnnotations":
|
||||||
self.original_spec_format = spec_format
|
self.original_spec_format = spec_format
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def with_compiler(self, compiler: "spack.spec.Spec") -> "SpecAnnotations":
|
def with_compiler(self, compiler: "Spec") -> "SpecAnnotations":
|
||||||
self.compiler_node_attribute = compiler
|
self.compiler_node_attribute = compiler
|
||||||
return self
|
return self
|
||||||
|
|
||||||
@ -3084,10 +3085,9 @@ def validate_or_raise(self):
|
|||||||
if (not spec.virtual) and spec.name:
|
if (not spec.virtual) and spec.name:
|
||||||
spack.repo.PATH.get_pkg_class(spec.fullname)
|
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"):
|
if spec.dependencies(deptype="build"):
|
||||||
pkg_cls = spack.repo.PATH.get_pkg_class(spec.fullname)
|
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()
|
pkg_dependencies = pkg_cls.dependency_names()
|
||||||
if not any(x in pkg_dependencies for x in ("c", "cxx", "fortran")):
|
if not any(x in pkg_dependencies for x in ("c", "cxx", "fortran")):
|
||||||
raise UnsupportedCompilerError(
|
raise UnsupportedCompilerError(
|
||||||
@ -4051,6 +4051,9 @@ def format_attribute(match_object: Match) -> str:
|
|||||||
try:
|
try:
|
||||||
current = getattr(current, part)
|
current = getattr(current, part)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
|
if part == "compiler":
|
||||||
|
return "none"
|
||||||
|
|
||||||
raise SpecFormatStringError(
|
raise SpecFormatStringError(
|
||||||
f"Attempted to format attribute {attribute}. "
|
f"Attempted to format attribute {attribute}. "
|
||||||
f"Spec {'.'.join(parts[:idx])} has no attribute {part}"
|
f"Spec {'.'.join(parts[:idx])} has no attribute {part}"
|
||||||
|
Loading…
Reference in New Issue
Block a user