Source code for spack.externals_config
# Copyright Spack Project Developers. See COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
"""Helpers to build an ExternalSpecsParser from Spack configuration."""
import itertools
from typing import Any, Dict
import spack.compilers.config
import spack.compilers.libraries
import spack.config
import spack.platforms
import spack.repo
import spack.spec
from spack.externals import (
ExternalSpecsParser,
complete_architecture,
complete_variants_and_architecture,
extract_dicts_from_configuration,
)
def _normalize_packages_yaml(packages_yaml: Dict[str, Any]) -> None:
for pkg_name in list(packages_yaml.keys()):
is_virtual = spack.repo.PATH.is_virtual(pkg_name)
if pkg_name == "all" or not is_virtual:
continue
# Remove the virtual entry from the normalized configuration
data = packages_yaml.pop(pkg_name)
is_buildable = data.get("buildable", True)
if not is_buildable:
for provider in spack.repo.PATH.providers_for(pkg_name):
entry = packages_yaml.setdefault(provider.name, {})
entry["buildable"] = False
externals = data.get("externals", [])
def keyfn(x):
return spack.spec.Spec(x["spec"]).name
for provider, specs in itertools.groupby(externals, key=keyfn):
entry = packages_yaml.setdefault(provider, {})
entry.setdefault("externals", []).extend(specs)
[docs]
def external_config_with_implicit_externals(
configuration: spack.config.Configuration,
) -> Dict[str, Any]:
"""Return packages.yaml augmented with implicit libc externals on Linux.
Normalizes the configuration so that virtual-package keys are replaced by
their concrete providers, then adds any libc specs detected from configured
compilers when running on a libc-compatibility platform.
"""
packages_yaml = configuration.deepcopy_as_builtin("packages", line_info=True)
_normalize_packages_yaml(packages_yaml)
# Add externals for libc from compilers on Linux
if not spack.platforms.using_libc_compatibility():
return packages_yaml
seen = set()
for compiler in spack.compilers.config.all_compilers_from(configuration):
libc = spack.compilers.libraries.CompilerPropertyDetector(compiler).default_libc()
if libc and libc not in seen:
seen.add(libc)
entry = {"spec": f"{libc}", "prefix": libc.external_path}
packages_yaml.setdefault(libc.name, {}).setdefault("externals", []).append(entry)
return packages_yaml
[docs]
def create_external_parser(
packages_with_externals: Any, completion_mode: str
) -> ExternalSpecsParser:
"""Get externals from a pre-processed packages.yaml (with implicit externals)."""
external_dicts = extract_dicts_from_configuration(packages_with_externals)
if completion_mode == "default_variants":
complete_fn = complete_variants_and_architecture
elif completion_mode == "architecture_only":
complete_fn = complete_architecture
else:
raise ValueError(
f"Unknown value for concretizer:externals:completion: {completion_mode!r}"
)
return ExternalSpecsParser(external_dicts, complete_node=complete_fn)