Parse %
as ^
in specs (#49808)
This PR modifies the parser, so that `%` is parsed as a `DEPENDENCY`, and all node properties that follow are associated to the name after the `%`. e.g., in `foo %gcc +binutils` the `+binutils` refers to `gcc` and not to `foo`. `%` is still parsed as a build-type dependency, at the moment. Environments, config files and `package.py` files from before Spack v1.0 may have spec strings with package variants, targets, etc. *after* a build dependency, and these will need to be updated. You can use the `spack style --spec-strings` command to do this. To see what strings will be parsed differently under Spack v1.0, run: ``` spack style --spec-strings FILES ``` where `FILES` is a list of filenames that may contain old specs. To update these spec strings so that they parse correctly under both Spack 1.0 and Spack 0.x, you can run: ``` spack style --fix --spec-strings FILES ``` In the example above, `foo %gcc +binutils` would be rewritten as `foo +binutils %gcc`, which parses the same in any Spack version. In addition, this PR fixes several issues with `%` dependencies: - [x] Ensure we can still constrain compilers on reuse - [x] Ensure we can reuse a compiler by hash - [x] Add tests --------- Signed-off-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
This commit is contained in:
parent
1f0aaafc71
commit
f8538a1b1c
@ -18,8 +18,8 @@
|
|||||||
import spack.repo
|
import spack.repo
|
||||||
import spack.util.git
|
import spack.util.git
|
||||||
import spack.util.spack_yaml
|
import spack.util.spack_yaml
|
||||||
from spack.spec_parser import SPEC_TOKENIZER, SpecTokens
|
from spack.spec_parser import NAME, VERSION_LIST, SpecTokens
|
||||||
from spack.tokenize import Token
|
from spack.tokenize import Token, TokenBase, Tokenizer
|
||||||
from spack.util.executable import Executable, which
|
from spack.util.executable import Executable, which
|
||||||
|
|
||||||
description = "runs source code style checks on spack"
|
description = "runs source code style checks on spack"
|
||||||
@ -206,8 +206,8 @@ def setup_parser(subparser):
|
|||||||
"--spec-strings",
|
"--spec-strings",
|
||||||
action="store_true",
|
action="store_true",
|
||||||
help="upgrade spec strings in Python, JSON and YAML files for compatibility with Spack "
|
help="upgrade spec strings in Python, JSON and YAML files for compatibility with Spack "
|
||||||
"v1.0 and v0.x. Example: spack style --spec-strings $(git ls-files). Note: this flag "
|
"v1.0 and v0.x. Example: spack style --spec-strings $(git ls-files). Note: must be "
|
||||||
"will be removed in Spack v1.0.",
|
"used only on specs from spack v0.X.",
|
||||||
)
|
)
|
||||||
|
|
||||||
subparser.add_argument("files", nargs=argparse.REMAINDER, help="specific files to check")
|
subparser.add_argument("files", nargs=argparse.REMAINDER, help="specific files to check")
|
||||||
@ -521,20 +521,52 @@ def _bootstrap_dev_dependencies():
|
|||||||
IS_PROBABLY_COMPILER = re.compile(r"%[a-zA-Z_][a-zA-Z0-9\-]")
|
IS_PROBABLY_COMPILER = re.compile(r"%[a-zA-Z_][a-zA-Z0-9\-]")
|
||||||
|
|
||||||
|
|
||||||
|
class _LegacySpecTokens(TokenBase):
|
||||||
|
"""Reconstructs the tokens for previous specs, so we can reuse code to rotate them"""
|
||||||
|
|
||||||
|
# Dependency
|
||||||
|
START_EDGE_PROPERTIES = r"(?:\^\[)"
|
||||||
|
END_EDGE_PROPERTIES = r"(?:\])"
|
||||||
|
DEPENDENCY = r"(?:\^)"
|
||||||
|
# Version
|
||||||
|
VERSION_HASH_PAIR = SpecTokens.VERSION_HASH_PAIR.regex
|
||||||
|
GIT_VERSION = SpecTokens.GIT_VERSION.regex
|
||||||
|
VERSION = SpecTokens.VERSION.regex
|
||||||
|
# Variants
|
||||||
|
PROPAGATED_BOOL_VARIANT = SpecTokens.PROPAGATED_BOOL_VARIANT.regex
|
||||||
|
BOOL_VARIANT = SpecTokens.BOOL_VARIANT.regex
|
||||||
|
PROPAGATED_KEY_VALUE_PAIR = SpecTokens.PROPAGATED_KEY_VALUE_PAIR.regex
|
||||||
|
KEY_VALUE_PAIR = SpecTokens.KEY_VALUE_PAIR.regex
|
||||||
|
# Compilers
|
||||||
|
COMPILER_AND_VERSION = rf"(?:%\s*(?:{NAME})(?:[\s]*)@\s*(?:{VERSION_LIST}))"
|
||||||
|
COMPILER = rf"(?:%\s*(?:{NAME}))"
|
||||||
|
# FILENAME
|
||||||
|
FILENAME = SpecTokens.FILENAME.regex
|
||||||
|
# Package name
|
||||||
|
FULLY_QUALIFIED_PACKAGE_NAME = SpecTokens.FULLY_QUALIFIED_PACKAGE_NAME.regex
|
||||||
|
UNQUALIFIED_PACKAGE_NAME = SpecTokens.UNQUALIFIED_PACKAGE_NAME.regex
|
||||||
|
# DAG hash
|
||||||
|
DAG_HASH = SpecTokens.DAG_HASH.regex
|
||||||
|
# White spaces
|
||||||
|
WS = SpecTokens.WS.regex
|
||||||
|
# Unexpected character(s)
|
||||||
|
UNEXPECTED = SpecTokens.UNEXPECTED.regex
|
||||||
|
|
||||||
|
|
||||||
def _spec_str_reorder_compiler(idx: int, blocks: List[List[Token]]) -> None:
|
def _spec_str_reorder_compiler(idx: int, blocks: List[List[Token]]) -> None:
|
||||||
# only move the compiler to the back if it exists and is not already at the end
|
# only move the compiler to the back if it exists and is not already at the end
|
||||||
if not 0 <= idx < len(blocks) - 1:
|
if not 0 <= idx < len(blocks) - 1:
|
||||||
return
|
return
|
||||||
# if there's only whitespace after the compiler, don't move it
|
# if there's only whitespace after the compiler, don't move it
|
||||||
if all(token.kind == SpecTokens.WS for block in blocks[idx + 1 :] for token in block):
|
if all(token.kind == _LegacySpecTokens.WS for block in blocks[idx + 1 :] for token in block):
|
||||||
return
|
return
|
||||||
# rotate left and always add at least one WS token between compiler and previous token
|
# rotate left and always add at least one WS token between compiler and previous token
|
||||||
compiler_block = blocks.pop(idx)
|
compiler_block = blocks.pop(idx)
|
||||||
if compiler_block[0].kind != SpecTokens.WS:
|
if compiler_block[0].kind != _LegacySpecTokens.WS:
|
||||||
compiler_block.insert(0, Token(SpecTokens.WS, " "))
|
compiler_block.insert(0, Token(_LegacySpecTokens.WS, " "))
|
||||||
# delete the WS tokens from the new first block if it was at the very start, to prevent leading
|
# delete the WS tokens from the new first block if it was at the very start, to prevent leading
|
||||||
# WS tokens.
|
# WS tokens.
|
||||||
while idx == 0 and blocks[0][0].kind == SpecTokens.WS:
|
while idx == 0 and blocks[0][0].kind == _LegacySpecTokens.WS:
|
||||||
blocks[0].pop(0)
|
blocks[0].pop(0)
|
||||||
blocks.append(compiler_block)
|
blocks.append(compiler_block)
|
||||||
|
|
||||||
@ -552,11 +584,13 @@ def _spec_str_format(spec_str: str) -> Optional[str]:
|
|||||||
compiler_block_idx = -1
|
compiler_block_idx = -1
|
||||||
in_edge_attr = False
|
in_edge_attr = False
|
||||||
|
|
||||||
for token in SPEC_TOKENIZER.tokenize(spec_str):
|
legacy_tokenizer = Tokenizer(_LegacySpecTokens)
|
||||||
if token.kind == SpecTokens.UNEXPECTED:
|
|
||||||
|
for token in legacy_tokenizer.tokenize(spec_str):
|
||||||
|
if token.kind == _LegacySpecTokens.UNEXPECTED:
|
||||||
# parsing error, we cannot fix this string.
|
# parsing error, we cannot fix this string.
|
||||||
return None
|
return None
|
||||||
elif token.kind in (SpecTokens.COMPILER, SpecTokens.COMPILER_AND_VERSION):
|
elif token.kind in (_LegacySpecTokens.COMPILER, _LegacySpecTokens.COMPILER_AND_VERSION):
|
||||||
# multiple compilers are not supported in Spack v0.x, so early return
|
# multiple compilers are not supported in Spack v0.x, so early return
|
||||||
if compiler_block_idx != -1:
|
if compiler_block_idx != -1:
|
||||||
return None
|
return None
|
||||||
@ -565,19 +599,19 @@ def _spec_str_format(spec_str: str) -> Optional[str]:
|
|||||||
current_block = []
|
current_block = []
|
||||||
compiler_block_idx = len(blocks) - 1
|
compiler_block_idx = len(blocks) - 1
|
||||||
elif token.kind in (
|
elif token.kind in (
|
||||||
SpecTokens.START_EDGE_PROPERTIES,
|
_LegacySpecTokens.START_EDGE_PROPERTIES,
|
||||||
SpecTokens.DEPENDENCY,
|
_LegacySpecTokens.DEPENDENCY,
|
||||||
SpecTokens.UNQUALIFIED_PACKAGE_NAME,
|
_LegacySpecTokens.UNQUALIFIED_PACKAGE_NAME,
|
||||||
SpecTokens.FULLY_QUALIFIED_PACKAGE_NAME,
|
_LegacySpecTokens.FULLY_QUALIFIED_PACKAGE_NAME,
|
||||||
):
|
):
|
||||||
_spec_str_reorder_compiler(compiler_block_idx, blocks)
|
_spec_str_reorder_compiler(compiler_block_idx, blocks)
|
||||||
compiler_block_idx = -1
|
compiler_block_idx = -1
|
||||||
if token.kind == SpecTokens.START_EDGE_PROPERTIES:
|
if token.kind == _LegacySpecTokens.START_EDGE_PROPERTIES:
|
||||||
in_edge_attr = True
|
in_edge_attr = True
|
||||||
current_block.append(token)
|
current_block.append(token)
|
||||||
blocks.append(current_block)
|
blocks.append(current_block)
|
||||||
current_block = []
|
current_block = []
|
||||||
elif token.kind == SpecTokens.END_EDGE_PROPERTIES:
|
elif token.kind == _LegacySpecTokens.END_EDGE_PROPERTIES:
|
||||||
in_edge_attr = False
|
in_edge_attr = False
|
||||||
current_block.append(token)
|
current_block.append(token)
|
||||||
blocks.append(current_block)
|
blocks.append(current_block)
|
||||||
@ -585,19 +619,19 @@ def _spec_str_format(spec_str: str) -> Optional[str]:
|
|||||||
elif in_edge_attr:
|
elif in_edge_attr:
|
||||||
current_block.append(token)
|
current_block.append(token)
|
||||||
elif token.kind in (
|
elif token.kind in (
|
||||||
SpecTokens.VERSION_HASH_PAIR,
|
_LegacySpecTokens.VERSION_HASH_PAIR,
|
||||||
SpecTokens.GIT_VERSION,
|
_LegacySpecTokens.GIT_VERSION,
|
||||||
SpecTokens.VERSION,
|
_LegacySpecTokens.VERSION,
|
||||||
SpecTokens.PROPAGATED_BOOL_VARIANT,
|
_LegacySpecTokens.PROPAGATED_BOOL_VARIANT,
|
||||||
SpecTokens.BOOL_VARIANT,
|
_LegacySpecTokens.BOOL_VARIANT,
|
||||||
SpecTokens.PROPAGATED_KEY_VALUE_PAIR,
|
_LegacySpecTokens.PROPAGATED_KEY_VALUE_PAIR,
|
||||||
SpecTokens.KEY_VALUE_PAIR,
|
_LegacySpecTokens.KEY_VALUE_PAIR,
|
||||||
SpecTokens.DAG_HASH,
|
_LegacySpecTokens.DAG_HASH,
|
||||||
):
|
):
|
||||||
current_block.append(token)
|
current_block.append(token)
|
||||||
blocks.append(current_block)
|
blocks.append(current_block)
|
||||||
current_block = []
|
current_block = []
|
||||||
elif token.kind == SpecTokens.WS:
|
elif token.kind == _LegacySpecTokens.WS:
|
||||||
current_block.append(token)
|
current_block.append(token)
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"unexpected token {token}")
|
raise ValueError(f"unexpected token {token}")
|
||||||
|
@ -2556,7 +2556,7 @@ def _spec_clauses(
|
|||||||
|
|
||||||
edges = spec.edges_from_dependents()
|
edges = spec.edges_from_dependents()
|
||||||
virtuals = [x for x in itertools.chain.from_iterable([edge.virtuals for edge in edges])]
|
virtuals = [x for x in itertools.chain.from_iterable([edge.virtuals for edge in edges])]
|
||||||
if not body:
|
if not body and not spec.concrete:
|
||||||
for virtual in virtuals:
|
for virtual in virtuals:
|
||||||
clauses.append(fn.attr("provider_set", spec.name, virtual))
|
clauses.append(fn.attr("provider_set", spec.name, virtual))
|
||||||
clauses.append(fn.attr("virtual_node", virtual))
|
clauses.append(fn.attr("virtual_node", virtual))
|
||||||
|
@ -530,6 +530,32 @@ attr("concrete_variant_set", node(X, A1), Variant, Value, ID)
|
|||||||
attr("virtual_on_build_edge", ParentNode, BuildDependency, Virtual),
|
attr("virtual_on_build_edge", ParentNode, BuildDependency, Virtual),
|
||||||
not 1 { pkg_fact(BuildDependency, version_satisfies(Constraint, Version)) : hash_attr(BuildDependencyHash, "version", BuildDependency, Version) } 1.
|
not 1 { pkg_fact(BuildDependency, version_satisfies(Constraint, Version)) : hash_attr(BuildDependencyHash, "version", BuildDependency, Version) } 1.
|
||||||
|
|
||||||
|
error(100, "Cannot satisfy the request on {0} to have {1}={2}", BuildDependency, Variant, Value)
|
||||||
|
:- attr("build_requirement", ParentNode, build_requirement("variant_set", BuildDependency, Variant, Value)),
|
||||||
|
attr("concrete_build_dependency", ParentNode, BuildDependency, BuildDependencyHash),
|
||||||
|
not hash_attr(BuildDependencyHash, "variant_value", BuildDependency, Variant, Value).
|
||||||
|
|
||||||
|
error(100, "Cannot satisfy the request on {0} to have the target set to {1}", BuildDependency, Target)
|
||||||
|
:- attr("build_requirement", ParentNode, build_requirement("node_target_set", BuildDependency, Target)),
|
||||||
|
attr("concrete_build_dependency", ParentNode, BuildDependency, BuildDependencyHash),
|
||||||
|
not hash_attr(BuildDependencyHash, "node_target", BuildDependency, Target).
|
||||||
|
|
||||||
|
error(100, "Cannot satisfy the request on {0} to have the os set to {1}", BuildDependency, NodeOS)
|
||||||
|
:- attr("build_requirement", ParentNode, build_requirement("node_os_set", BuildDependency, NodeOS)),
|
||||||
|
attr("concrete_build_dependency", ParentNode, BuildDependency, BuildDependencyHash),
|
||||||
|
not hash_attr(BuildDependencyHash, "node_os", BuildDependency, NodeOS).
|
||||||
|
|
||||||
|
error(100, "Cannot satisfy the request on {0} to have the platform set to {1}", BuildDependency, Platform)
|
||||||
|
:- attr("build_requirement", ParentNode, build_requirement("node_platform_set", BuildDependency, Platform)),
|
||||||
|
attr("concrete_build_dependency", ParentNode, BuildDependency, BuildDependencyHash),
|
||||||
|
not hash_attr(BuildDependencyHash, "node_platform", BuildDependency, Platform).
|
||||||
|
|
||||||
|
error(100, "Cannot satisfy the request on {0} to have the following hash {1}", BuildDependency, BuildHash)
|
||||||
|
:- attr("build_requirement", ParentNode, build_requirement("node_target_set", BuildDependency, Target)),
|
||||||
|
attr("concrete_build_dependency", ParentNode, BuildDependency, BuildDependencyHash),
|
||||||
|
attr("build_requirement", ParentNode, build_requirement("hash", BuildDependency, BuildHash)),
|
||||||
|
BuildHash != BuildDependencyHash.
|
||||||
|
|
||||||
% External nodes
|
% External nodes
|
||||||
:- attr("build_requirement", ParentNode, build_requirement("node", BuildDependency)),
|
:- attr("build_requirement", ParentNode, build_requirement("node", BuildDependency)),
|
||||||
external(ParentNode),
|
external(ParentNode),
|
||||||
@ -576,6 +602,32 @@ attr("node_version_satisfies", node(X, BuildDependency), Constraint) :-
|
|||||||
attr("build_requirement", ParentNode, build_requirement("node_version_satisfies", BuildDependency, Constraint)),
|
attr("build_requirement", ParentNode, build_requirement("node_version_satisfies", BuildDependency, Constraint)),
|
||||||
build_requirement(ParentNode, node(X, BuildDependency)).
|
build_requirement(ParentNode, node(X, BuildDependency)).
|
||||||
|
|
||||||
|
% Account for properties on the build requirements
|
||||||
|
%
|
||||||
|
% root %gcc@12.0 <properties for gcc> ^dep
|
||||||
|
%
|
||||||
|
attr("variant_set", node(X, BuildDependency), Variant, Value) :-
|
||||||
|
attr("build_requirement", ParentNode, build_requirement("variant_set", BuildDependency, Variant, Value)),
|
||||||
|
build_requirement(ParentNode, node(X, BuildDependency)).
|
||||||
|
|
||||||
|
attr("depends_on", node(X, Parent), node(Y, BuildDependency), "build") :- build_requirement(node(X, Parent), node(Y, BuildDependency)).
|
||||||
|
|
||||||
|
attr("node_target_set", node(X, BuildDependency), Target) :-
|
||||||
|
attr("build_requirement", ParentNode, build_requirement("node_target_set", BuildDependency, Target)),
|
||||||
|
build_requirement(ParentNode, node(X, BuildDependency)).
|
||||||
|
|
||||||
|
attr("node_os_set", node(X, BuildDependency), NodeOS) :-
|
||||||
|
attr("build_requirement", ParentNode, build_requirement("node_os_set", BuildDependency, NodeOS)),
|
||||||
|
build_requirement(ParentNode, node(X, BuildDependency)).
|
||||||
|
|
||||||
|
attr("node_platform_set", node(X, BuildDependency), NodePlatform) :-
|
||||||
|
attr("build_requirement", ParentNode, build_requirement("node_platform_set", BuildDependency, NodePlatform)),
|
||||||
|
build_requirement(ParentNode, node(X, BuildDependency)).
|
||||||
|
|
||||||
|
attr("hash", node(X, BuildDependency), BuildHash) :-
|
||||||
|
attr("build_requirement", ParentNode, build_requirement("hash", BuildDependency, BuildHash)),
|
||||||
|
build_requirement(ParentNode, node(X, BuildDependency)).
|
||||||
|
|
||||||
|
|
||||||
1 { attr("provider_set", node(X, BuildDependency), node(0..Y-1, Virtual)) : max_dupes(Virtual, Y) } 1 :-
|
1 { attr("provider_set", node(X, BuildDependency), node(0..Y-1, Virtual)) : max_dupes(Virtual, Y) } 1 :-
|
||||||
attr("build_requirement", ParentNode, build_requirement("provider_set", BuildDependency, Virtual)),
|
attr("build_requirement", ParentNode, build_requirement("provider_set", BuildDependency, Virtual)),
|
||||||
|
@ -2233,15 +2233,21 @@ def lookup_hash(self):
|
|||||||
spec._dup(self._lookup_hash())
|
spec._dup(self._lookup_hash())
|
||||||
return spec
|
return spec
|
||||||
|
|
||||||
# Get dependencies that need to be replaced
|
# Map the dependencies that need to be replaced
|
||||||
for node in self.traverse(root=False):
|
node_lookup = {
|
||||||
if node.abstract_hash:
|
id(node): node._lookup_hash()
|
||||||
spec._add_dependency(node._lookup_hash(), depflag=0, virtuals=())
|
for node in self.traverse(root=False)
|
||||||
|
if node.abstract_hash
|
||||||
|
}
|
||||||
|
|
||||||
# reattach nodes that were not otherwise satisfied by new dependencies
|
# Reconstruct dependencies
|
||||||
for node in self.traverse(root=False):
|
for edge in self.traverse_edges(root=False):
|
||||||
if not any(n.satisfies(node) for n in spec.traverse()):
|
key = edge.parent.name
|
||||||
spec._add_dependency(node.copy(), depflag=0, virtuals=())
|
current_node = spec if key == spec.name else spec[key]
|
||||||
|
child_node = node_lookup.get(id(edge.spec), edge.spec.copy())
|
||||||
|
current_node._add_dependency(
|
||||||
|
child_node, depflag=edge.depflag, virtuals=edge.virtuals, direct=edge.direct
|
||||||
|
)
|
||||||
|
|
||||||
return spec
|
return spec
|
||||||
|
|
||||||
|
@ -101,9 +101,6 @@
|
|||||||
|
|
||||||
SPLIT_KVP = re.compile(rf"^({NAME})(:?==?)(.*)$")
|
SPLIT_KVP = re.compile(rf"^({NAME})(:?==?)(.*)$")
|
||||||
|
|
||||||
#: Regex with groups to use for splitting %[virtuals=...] tokens
|
|
||||||
SPLIT_COMPILER_TOKEN = re.compile(rf"^%\[virtuals=({VALUE}|{QUOTED_VALUE})]\s*(.*)$")
|
|
||||||
|
|
||||||
#: A filename starts either with a "." or a "/" or a "{name}/, or on Windows, a drive letter
|
#: A filename starts either with a "." or a "/" or a "{name}/, or on Windows, a drive letter
|
||||||
#: followed by a colon and "\" or "." or {name}\
|
#: followed by a colon and "\" or "." or {name}\
|
||||||
WINDOWS_FILENAME = r"(?:\.|[a-zA-Z0-9-_]*\\|[a-zA-Z]:\\)(?:[a-zA-Z0-9-_\.\\]*)(?:\.json|\.yaml)"
|
WINDOWS_FILENAME = r"(?:\.|[a-zA-Z0-9-_]*\\|[a-zA-Z]:\\)(?:[a-zA-Z0-9-_\.\\]*)(?:\.json|\.yaml)"
|
||||||
@ -124,9 +121,9 @@ class SpecTokens(TokenBase):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
# Dependency
|
# Dependency
|
||||||
START_EDGE_PROPERTIES = r"(?:\^\[)"
|
START_EDGE_PROPERTIES = r"(?:[\^%]\[)"
|
||||||
END_EDGE_PROPERTIES = r"(?:\])"
|
END_EDGE_PROPERTIES = r"(?:\])"
|
||||||
DEPENDENCY = r"(?:\^)"
|
DEPENDENCY = r"(?:[\^\%])"
|
||||||
# Version
|
# Version
|
||||||
VERSION_HASH_PAIR = rf"(?:@(?:{GIT_VERSION_PATTERN})=(?:{VERSION}))"
|
VERSION_HASH_PAIR = rf"(?:@(?:{GIT_VERSION_PATTERN})=(?:{VERSION}))"
|
||||||
GIT_VERSION = rf"@(?:{GIT_VERSION_PATTERN})"
|
GIT_VERSION = rf"@(?:{GIT_VERSION_PATTERN})"
|
||||||
@ -136,14 +133,6 @@ class SpecTokens(TokenBase):
|
|||||||
BOOL_VARIANT = rf"(?:[~+-]\s*{NAME})"
|
BOOL_VARIANT = rf"(?:[~+-]\s*{NAME})"
|
||||||
PROPAGATED_KEY_VALUE_PAIR = rf"(?:{NAME}:?==(?:{VALUE}|{QUOTED_VALUE}))"
|
PROPAGATED_KEY_VALUE_PAIR = rf"(?:{NAME}:?==(?:{VALUE}|{QUOTED_VALUE}))"
|
||||||
KEY_VALUE_PAIR = rf"(?:{NAME}:?=(?:{VALUE}|{QUOTED_VALUE}))"
|
KEY_VALUE_PAIR = rf"(?:{NAME}:?=(?:{VALUE}|{QUOTED_VALUE}))"
|
||||||
# Compilers
|
|
||||||
COMPILER_AND_VERSION = rf"(?:%\s*(?:{NAME})(?:[\s]*)@\s*(?:{VERSION_LIST}))"
|
|
||||||
COMPILER = rf"(?:%\s*(?:{NAME}))"
|
|
||||||
COMPILER_AND_VERSION_WITH_VIRTUALS = (
|
|
||||||
rf"(?:%\[virtuals=(?:{VALUE}|{QUOTED_VALUE})\]"
|
|
||||||
rf"\s*(?:{NAME})(?:[\s]*)@\s*(?:{VERSION_LIST}))"
|
|
||||||
)
|
|
||||||
COMPILER_WITH_VIRTUALS = rf"(?:%\[virtuals=(?:{VALUE}|{QUOTED_VALUE})\]\s*(?:{NAME}))"
|
|
||||||
# FILENAME
|
# FILENAME
|
||||||
FILENAME = rf"(?:{FILENAME})"
|
FILENAME = rf"(?:{FILENAME})"
|
||||||
# Package name
|
# Package name
|
||||||
@ -275,25 +264,58 @@ def next_spec(
|
|||||||
def add_dependency(dep, **edge_properties):
|
def add_dependency(dep, **edge_properties):
|
||||||
"""wrapper around root_spec._add_dependency"""
|
"""wrapper around root_spec._add_dependency"""
|
||||||
try:
|
try:
|
||||||
root_spec._add_dependency(dep, **edge_properties)
|
target_spec._add_dependency(dep, **edge_properties)
|
||||||
except spack.error.SpecError as e:
|
except spack.error.SpecError as e:
|
||||||
raise SpecParsingError(str(e), self.ctx.current_token, self.literal_str) from e
|
raise SpecParsingError(str(e), self.ctx.current_token, self.literal_str) from e
|
||||||
|
|
||||||
initial_spec = initial_spec or spack.spec.Spec()
|
initial_spec = initial_spec or spack.spec.Spec()
|
||||||
root_spec, parser_warnings = SpecNodeParser(self.ctx, self.literal_str).parse(initial_spec)
|
root_spec, parser_warnings = SpecNodeParser(self.ctx, self.literal_str).parse(initial_spec)
|
||||||
|
current_spec = root_spec
|
||||||
while True:
|
while True:
|
||||||
if self.ctx.accept(SpecTokens.START_EDGE_PROPERTIES):
|
if self.ctx.accept(SpecTokens.START_EDGE_PROPERTIES):
|
||||||
|
is_direct = self.ctx.current_token.value[0] == "%"
|
||||||
|
|
||||||
edge_properties = EdgeAttributeParser(self.ctx, self.literal_str).parse()
|
edge_properties = EdgeAttributeParser(self.ctx, self.literal_str).parse()
|
||||||
edge_properties.setdefault("depflag", 0)
|
|
||||||
edge_properties.setdefault("virtuals", ())
|
edge_properties.setdefault("virtuals", ())
|
||||||
|
edge_properties["direct"] = is_direct
|
||||||
|
|
||||||
dependency, warnings = self._parse_node(root_spec)
|
dependency, warnings = self._parse_node(root_spec)
|
||||||
|
|
||||||
|
if is_direct:
|
||||||
|
target_spec = current_spec
|
||||||
|
edge_properties.setdefault("depflag", spack.deptypes.BUILD)
|
||||||
|
if dependency.name in LEGACY_COMPILER_TO_BUILTIN:
|
||||||
|
dependency.name = LEGACY_COMPILER_TO_BUILTIN[dependency.name]
|
||||||
|
|
||||||
|
else:
|
||||||
|
current_spec = dependency
|
||||||
|
target_spec = root_spec
|
||||||
|
edge_properties.setdefault("depflag", 0)
|
||||||
|
|
||||||
|
# print(f"[{current_spec}], {target_spec}->{dependency} {is_direct}")
|
||||||
parser_warnings.extend(warnings)
|
parser_warnings.extend(warnings)
|
||||||
add_dependency(dependency, **edge_properties)
|
add_dependency(dependency, **edge_properties)
|
||||||
|
|
||||||
elif self.ctx.accept(SpecTokens.DEPENDENCY):
|
elif self.ctx.accept(SpecTokens.DEPENDENCY):
|
||||||
|
is_direct = self.ctx.current_token.value[0] == "%"
|
||||||
dependency, warnings = self._parse_node(root_spec)
|
dependency, warnings = self._parse_node(root_spec)
|
||||||
|
edge_properties = {}
|
||||||
|
edge_properties["direct"] = is_direct
|
||||||
|
edge_properties["virtuals"] = tuple()
|
||||||
|
if is_direct:
|
||||||
|
target_spec = current_spec
|
||||||
|
edge_properties.setdefault("depflag", spack.deptypes.BUILD)
|
||||||
|
if dependency.name in LEGACY_COMPILER_TO_BUILTIN:
|
||||||
|
dependency.name = LEGACY_COMPILER_TO_BUILTIN[dependency.name]
|
||||||
|
else:
|
||||||
|
current_spec = dependency
|
||||||
|
target_spec = root_spec
|
||||||
|
edge_properties.setdefault("depflag", 0)
|
||||||
|
|
||||||
|
# print(f"[{current_spec}], {target_spec}->{dependency} {is_direct}")
|
||||||
|
|
||||||
parser_warnings.extend(warnings)
|
parser_warnings.extend(warnings)
|
||||||
add_dependency(dependency, depflag=0, virtuals=())
|
add_dependency(dependency, **edge_properties)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
@ -384,34 +406,6 @@ def warn_if_after_compiler(token: str):
|
|||||||
|
|
||||||
while True:
|
while True:
|
||||||
if (
|
if (
|
||||||
self.ctx.accept(SpecTokens.COMPILER)
|
|
||||||
or self.ctx.accept(SpecTokens.COMPILER_AND_VERSION)
|
|
||||||
or self.ctx.accept(SpecTokens.COMPILER_WITH_VIRTUALS)
|
|
||||||
or self.ctx.accept(SpecTokens.COMPILER_AND_VERSION_WITH_VIRTUALS)
|
|
||||||
):
|
|
||||||
current_token = self.ctx.current_token
|
|
||||||
if current_token.kind in (
|
|
||||||
SpecTokens.COMPILER_WITH_VIRTUALS,
|
|
||||||
SpecTokens.COMPILER_AND_VERSION_WITH_VIRTUALS,
|
|
||||||
):
|
|
||||||
m = SPLIT_COMPILER_TOKEN.match(current_token.value)
|
|
||||||
assert m, "SPLIT_COMPILER_TOKEN and COMPILER_* do not agree."
|
|
||||||
virtuals_str, compiler_str = m.groups()
|
|
||||||
virtuals = tuple(virtuals_str.strip("'\" ").split(","))
|
|
||||||
else:
|
|
||||||
virtuals = tuple()
|
|
||||||
compiler_str = current_token.value[1:]
|
|
||||||
|
|
||||||
build_dependency = spack.spec.Spec(compiler_str)
|
|
||||||
if build_dependency.name in LEGACY_COMPILER_TO_BUILTIN:
|
|
||||||
build_dependency.name = LEGACY_COMPILER_TO_BUILTIN[build_dependency.name]
|
|
||||||
|
|
||||||
initial_spec._add_dependency(
|
|
||||||
build_dependency, depflag=spack.deptypes.BUILD, virtuals=virtuals, direct=True
|
|
||||||
)
|
|
||||||
last_compiler = self.ctx.current_token.value
|
|
||||||
|
|
||||||
elif (
|
|
||||||
self.ctx.accept(SpecTokens.VERSION_HASH_PAIR)
|
self.ctx.accept(SpecTokens.VERSION_HASH_PAIR)
|
||||||
or self.ctx.accept(SpecTokens.GIT_VERSION)
|
or self.ctx.accept(SpecTokens.GIT_VERSION)
|
||||||
or self.ctx.accept(SpecTokens.VERSION)
|
or self.ctx.accept(SpecTokens.VERSION)
|
||||||
|
@ -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 platform
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import _vendoring.jinja2
|
import _vendoring.jinja2
|
||||||
@ -3566,3 +3567,144 @@ def test_concrete_multi_valued_variants_when_args(default_mock_concretization):
|
|||||||
for c in ("foo:=a", "foo:=a,b,c", "foo:=a,b", "foo:=a,c"):
|
for c in ("foo:=a", "foo:=a,b,c", "foo:=a,b", "foo:=a,c"):
|
||||||
s = default_mock_concretization(f"mvdefaults {c}")
|
s = default_mock_concretization(f"mvdefaults {c}")
|
||||||
assert not s.satisfies("^pkg-b")
|
assert not s.satisfies("^pkg-b")
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures("mock_packages")
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"constraint_in_yaml,unsat_request,sat_request",
|
||||||
|
[
|
||||||
|
# Arch parts
|
||||||
|
pytest.param(
|
||||||
|
"target=x86_64",
|
||||||
|
"target=core2",
|
||||||
|
"target=x86_64",
|
||||||
|
marks=pytest.mark.skipif(
|
||||||
|
platform.machine() != "x86_64", reason="only valid for x86_64"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
pytest.param(
|
||||||
|
"target=core2",
|
||||||
|
"target=x86_64",
|
||||||
|
"target=core2",
|
||||||
|
marks=pytest.mark.skipif(
|
||||||
|
platform.machine() != "x86_64", reason="only valid for x86_64"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("os=debian6", "os=redhat6", "os=debian6"),
|
||||||
|
("platform=test", "platform=linux", "platform=test"),
|
||||||
|
# Variants
|
||||||
|
("~lld", "+lld", "~lld"),
|
||||||
|
("+lld", "~lld", "+lld"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_spec_parts_on_fresh_compilers(
|
||||||
|
constraint_in_yaml, unsat_request, sat_request, mutable_config, tmp_path
|
||||||
|
):
|
||||||
|
"""Tests that spec parts like targets and variants in `%<package> target=<target> <variants>`
|
||||||
|
are associated with `package` for `%` just as they would be for `^`, when we concretize
|
||||||
|
without reusing.
|
||||||
|
"""
|
||||||
|
packages_yaml = syaml.load_config(
|
||||||
|
f"""
|
||||||
|
packages:
|
||||||
|
llvm::
|
||||||
|
buildable: false
|
||||||
|
externals:
|
||||||
|
- spec: "llvm+clang@20 {constraint_in_yaml}"
|
||||||
|
prefix: {tmp_path / 'llvm-20'}
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
mutable_config.set("packages", packages_yaml["packages"])
|
||||||
|
|
||||||
|
# Check the abstract spec is formed correctly
|
||||||
|
abstract_spec = Spec(f"pkg-a %llvm@20 +clang {unsat_request}")
|
||||||
|
assert abstract_spec["llvm"].satisfies(f"@20 +clang {unsat_request}")
|
||||||
|
|
||||||
|
# Check that we can't concretize the spec, since llvm is not buildable
|
||||||
|
with pytest.raises(spack.solver.asp.UnsatisfiableSpecError):
|
||||||
|
spack.concretize.concretize_one(abstract_spec)
|
||||||
|
|
||||||
|
# Check we can instead concretize if we use the correct constraint
|
||||||
|
s = spack.concretize.concretize_one(f"pkg-a %llvm@20 +clang {sat_request}")
|
||||||
|
assert s["c"].external and s["c"].satisfies(f"@20 +clang {sat_request}")
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures("mock_packages", "mutable_database")
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"constraint_in_yaml,unsat_request,sat_request",
|
||||||
|
[
|
||||||
|
# Arch parts
|
||||||
|
pytest.param(
|
||||||
|
"target=x86_64",
|
||||||
|
"target=core2",
|
||||||
|
"target=x86_64",
|
||||||
|
marks=pytest.mark.skipif(
|
||||||
|
platform.machine() != "x86_64", reason="only valid for x86_64"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
pytest.param(
|
||||||
|
"target=core2",
|
||||||
|
"target=x86_64",
|
||||||
|
"target=core2",
|
||||||
|
marks=pytest.mark.skipif(
|
||||||
|
platform.machine() != "x86_64", reason="only valid for x86_64"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("os=debian6", "os=redhat6", "os=debian6"),
|
||||||
|
("platform=test", "platform=linux", "platform=test"),
|
||||||
|
# Variants
|
||||||
|
("~lld", "+lld", "~lld"),
|
||||||
|
("+lld", "~lld", "+lld"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_spec_parts_on_reused_compilers(
|
||||||
|
constraint_in_yaml, unsat_request, sat_request, mutable_config, tmp_path
|
||||||
|
):
|
||||||
|
"""Tests that requests of the form <package>%<compiler> <requests> are considered for reused
|
||||||
|
specs, even though build dependency are not part of the ASP problem.
|
||||||
|
"""
|
||||||
|
packages_yaml = syaml.load_config(
|
||||||
|
f"""
|
||||||
|
packages:
|
||||||
|
c:
|
||||||
|
require: llvm
|
||||||
|
cxx:
|
||||||
|
require: llvm
|
||||||
|
llvm::
|
||||||
|
buildable: false
|
||||||
|
externals:
|
||||||
|
- spec: "llvm+clang@20 {constraint_in_yaml}"
|
||||||
|
prefix: {tmp_path / 'llvm-20'}
|
||||||
|
mpileaks:
|
||||||
|
buildable: true
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
mutable_config.set("packages", packages_yaml["packages"])
|
||||||
|
|
||||||
|
# Install the spec
|
||||||
|
installed_spec = spack.concretize.concretize_one(f"mpileaks %llvm@20 {sat_request}")
|
||||||
|
PackageInstaller([installed_spec.package], fake=True, explicit=True).install()
|
||||||
|
|
||||||
|
# Make mpileaks not buildable
|
||||||
|
mutable_config.set("packages:mpileaks:buildable", False)
|
||||||
|
|
||||||
|
# Check we can't concretize with the unsat request...
|
||||||
|
with pytest.raises(spack.solver.asp.UnsatisfiableSpecError):
|
||||||
|
spack.concretize.concretize_one(f"mpileaks %llvm@20 {unsat_request}")
|
||||||
|
|
||||||
|
# ...but we can with the original constraint
|
||||||
|
with spack.config.override("concretizer:reuse", True):
|
||||||
|
s = spack.concretize.concretize_one(f"mpileaks %llvm@20 {sat_request}")
|
||||||
|
|
||||||
|
assert s.dag_hash() == installed_spec.dag_hash()
|
||||||
|
|
||||||
|
|
||||||
|
def test_use_compiler_by_hash(mock_packages, mutable_database, mutable_config):
|
||||||
|
"""Tests that we can reuse an installed compiler specifying its hash"""
|
||||||
|
installed_spec = spack.concretize.concretize_one("gcc@14.0")
|
||||||
|
PackageInstaller([installed_spec.package], fake=True, explicit=True).install()
|
||||||
|
|
||||||
|
with spack.config.override("concretizer:reuse", True):
|
||||||
|
s = spack.concretize.concretize_one(f"mpileaks %gcc/{installed_spec.dag_hash()}")
|
||||||
|
|
||||||
|
assert s["c"].dag_hash() == installed_spec.dag_hash()
|
||||||
|
@ -163,16 +163,15 @@ def test_flag_order_and_grouping(
|
|||||||
if cmp_flags:
|
if cmp_flags:
|
||||||
compiler_spec = "%gcc@12.100.100"
|
compiler_spec = "%gcc@12.100.100"
|
||||||
|
|
||||||
|
cmd_flags_str = f'cflags="{cmd_flags}"' if cmd_flags else ""
|
||||||
|
|
||||||
if dflags:
|
if dflags:
|
||||||
spec_str = f"x+activatemultiflag {compiler_spec} ^y"
|
spec_str = f"x+activatemultiflag {compiler_spec} ^y {cmd_flags_str}"
|
||||||
expected_dflags = "-d1 -d2"
|
expected_dflags = "-d1 -d2"
|
||||||
else:
|
else:
|
||||||
spec_str = f"y {compiler_spec}"
|
spec_str = f"y {cmd_flags_str} {compiler_spec}"
|
||||||
expected_dflags = None
|
expected_dflags = None
|
||||||
|
|
||||||
if cmd_flags:
|
|
||||||
spec_str += f' cflags="{cmd_flags}"'
|
|
||||||
|
|
||||||
root_spec = spack.concretize.concretize_one(spec_str)
|
root_spec = spack.concretize.concretize_one(spec_str)
|
||||||
spec = root_spec["y"]
|
spec = root_spec["y"]
|
||||||
satisfy_flags = " ".join(x for x in [cmd_flags, req_flags, cmp_flags, expected_dflags] if x)
|
satisfy_flags = " ".join(x for x in [cmd_flags, req_flags, cmp_flags, expected_dflags] if x)
|
||||||
@ -277,6 +276,6 @@ def test_flag_injection_different_compilers(mock_packages, mutable_config):
|
|||||||
"""Tests that flag propagation is not activated on nodes with a compiler that is different
|
"""Tests that flag propagation is not activated on nodes with a compiler that is different
|
||||||
from the propagation source.
|
from the propagation source.
|
||||||
"""
|
"""
|
||||||
s = spack.concretize.concretize_one('mpileaks %gcc cflags=="-O2" ^callpath %llvm')
|
s = spack.concretize.concretize_one('mpileaks cflags=="-O2" %gcc ^callpath %llvm')
|
||||||
assert s.satisfies('cflags="-O2"') and s["c"].name == "gcc"
|
assert s.satisfies('cflags="-O2"') and s["c"].name == "gcc"
|
||||||
assert not s["callpath"].satisfies('cflags="-O2"') and s["callpath"]["c"].name == "llvm"
|
assert not s["callpath"].satisfies('cflags="-O2"') and s["callpath"]["c"].name == "llvm"
|
||||||
|
@ -137,7 +137,14 @@ def test_spec_list_nested_matrices(self, parser_and_speclist):
|
|||||||
expected_components = itertools.product(
|
expected_components = itertools.product(
|
||||||
["zlib", "libelf"], ["%gcc", "%intel"], ["+shared", "~shared"]
|
["zlib", "libelf"], ["%gcc", "%intel"], ["+shared", "~shared"]
|
||||||
)
|
)
|
||||||
expected = [Spec(" ".join(combo)) for combo in expected_components]
|
|
||||||
|
def _reduce(*, combo):
|
||||||
|
root = Spec(combo[0])
|
||||||
|
for x in combo[1:]:
|
||||||
|
root.constrain(x)
|
||||||
|
return root
|
||||||
|
|
||||||
|
expected = [_reduce(combo=combo) for combo in expected_components]
|
||||||
assert set(result.specs) == set(expected)
|
assert set(result.specs) == set(expected)
|
||||||
|
|
||||||
@pytest.mark.regression("16897")
|
@pytest.mark.regression("16897")
|
||||||
|
@ -51,10 +51,6 @@ def dependency_with_version(text):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def compiler_with_version_range(text):
|
|
||||||
return text, [Token(SpecTokens.COMPILER_AND_VERSION, value=text)], text
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def specfile_for(default_mock_concretization):
|
def specfile_for(default_mock_concretization):
|
||||||
def _specfile_for(spec_str, filename):
|
def _specfile_for(spec_str, filename):
|
||||||
@ -84,7 +80,6 @@ def _specfile_for(spec_str, filename):
|
|||||||
simple_package_name("3dtk"),
|
simple_package_name("3dtk"),
|
||||||
simple_package_name("ns-3-dev"),
|
simple_package_name("ns-3-dev"),
|
||||||
# Single token anonymous specs
|
# Single token anonymous specs
|
||||||
("%intel", [Token(SpecTokens.COMPILER, value="%intel")], "%intel"),
|
|
||||||
("@2.7", [Token(SpecTokens.VERSION, value="@2.7")], "@2.7"),
|
("@2.7", [Token(SpecTokens.VERSION, value="@2.7")], "@2.7"),
|
||||||
("@2.7:", [Token(SpecTokens.VERSION, value="@2.7:")], "@2.7:"),
|
("@2.7:", [Token(SpecTokens.VERSION, value="@2.7:")], "@2.7:"),
|
||||||
("@:2.7", [Token(SpecTokens.VERSION, value="@:2.7")], "@:2.7"),
|
("@:2.7", [Token(SpecTokens.VERSION, value="@:2.7")], "@:2.7"),
|
||||||
@ -97,6 +92,14 @@ def _specfile_for(spec_str, filename):
|
|||||||
"arch=test-None-None",
|
"arch=test-None-None",
|
||||||
),
|
),
|
||||||
# Multiple tokens anonymous specs
|
# Multiple tokens anonymous specs
|
||||||
|
(
|
||||||
|
"%intel",
|
||||||
|
[
|
||||||
|
Token(SpecTokens.DEPENDENCY, value="%"),
|
||||||
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, "intel"),
|
||||||
|
],
|
||||||
|
"%intel",
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"languages=go @4.2:",
|
"languages=go @4.2:",
|
||||||
[
|
[
|
||||||
@ -159,7 +162,9 @@ def _specfile_for(spec_str, filename):
|
|||||||
[
|
[
|
||||||
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="foo"),
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="foo"),
|
||||||
Token(SpecTokens.VERSION, value="@2.0"),
|
Token(SpecTokens.VERSION, value="@2.0"),
|
||||||
Token(SpecTokens.COMPILER_AND_VERSION, value="%bar@1.0"),
|
Token(SpecTokens.DEPENDENCY, value="%"),
|
||||||
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="bar"),
|
||||||
|
Token(SpecTokens.VERSION, value="@1.0"),
|
||||||
],
|
],
|
||||||
"foo@2.0 %bar@1.0",
|
"foo@2.0 %bar@1.0",
|
||||||
),
|
),
|
||||||
@ -178,7 +183,9 @@ def _specfile_for(spec_str, filename):
|
|||||||
Token(SpecTokens.VERSION, value="@1.2:1.4,1.6"),
|
Token(SpecTokens.VERSION, value="@1.2:1.4,1.6"),
|
||||||
Token(SpecTokens.BOOL_VARIANT, value="+debug"),
|
Token(SpecTokens.BOOL_VARIANT, value="+debug"),
|
||||||
Token(SpecTokens.BOOL_VARIANT, value="~qt_4"),
|
Token(SpecTokens.BOOL_VARIANT, value="~qt_4"),
|
||||||
Token(SpecTokens.COMPILER_AND_VERSION, value="%intel@12.1"),
|
Token(SpecTokens.DEPENDENCY, value="%"),
|
||||||
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="intel"),
|
||||||
|
Token(SpecTokens.VERSION, value="@12.1"),
|
||||||
Token(SpecTokens.DEPENDENCY, value="^"),
|
Token(SpecTokens.DEPENDENCY, value="^"),
|
||||||
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="stackwalker"),
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="stackwalker"),
|
||||||
Token(SpecTokens.VERSION, value="@8.1_1e"),
|
Token(SpecTokens.VERSION, value="@8.1_1e"),
|
||||||
@ -194,7 +201,9 @@ def _specfile_for(spec_str, filename):
|
|||||||
Token(SpecTokens.VERSION, value="@1.2:1.4,1.6"),
|
Token(SpecTokens.VERSION, value="@1.2:1.4,1.6"),
|
||||||
Token(SpecTokens.BOOL_VARIANT, value="~qt_4"),
|
Token(SpecTokens.BOOL_VARIANT, value="~qt_4"),
|
||||||
Token(SpecTokens.KEY_VALUE_PAIR, value="debug=2"),
|
Token(SpecTokens.KEY_VALUE_PAIR, value="debug=2"),
|
||||||
Token(SpecTokens.COMPILER_AND_VERSION, value="%intel@12.1"),
|
Token(SpecTokens.DEPENDENCY, value="%"),
|
||||||
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="intel"),
|
||||||
|
Token(SpecTokens.VERSION, value="@12.1"),
|
||||||
Token(SpecTokens.DEPENDENCY, value="^"),
|
Token(SpecTokens.DEPENDENCY, value="^"),
|
||||||
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="stackwalker"),
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="stackwalker"),
|
||||||
Token(SpecTokens.VERSION, value="@8.1_1e"),
|
Token(SpecTokens.VERSION, value="@8.1_1e"),
|
||||||
@ -212,7 +221,9 @@ def _specfile_for(spec_str, filename):
|
|||||||
Token(SpecTokens.KEY_VALUE_PAIR, value="cppflags=-O3"),
|
Token(SpecTokens.KEY_VALUE_PAIR, value="cppflags=-O3"),
|
||||||
Token(SpecTokens.BOOL_VARIANT, value="+debug"),
|
Token(SpecTokens.BOOL_VARIANT, value="+debug"),
|
||||||
Token(SpecTokens.BOOL_VARIANT, value="~qt_4"),
|
Token(SpecTokens.BOOL_VARIANT, value="~qt_4"),
|
||||||
Token(SpecTokens.COMPILER_AND_VERSION, value="%intel@12.1"),
|
Token(SpecTokens.DEPENDENCY, value="%"),
|
||||||
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="intel"),
|
||||||
|
Token(SpecTokens.VERSION, value="@12.1"),
|
||||||
Token(SpecTokens.DEPENDENCY, value="^"),
|
Token(SpecTokens.DEPENDENCY, value="^"),
|
||||||
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="stackwalker"),
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="stackwalker"),
|
||||||
Token(SpecTokens.VERSION, value="@8.1_1e"),
|
Token(SpecTokens.VERSION, value="@8.1_1e"),
|
||||||
@ -226,7 +237,9 @@ def _specfile_for(spec_str, filename):
|
|||||||
[
|
[
|
||||||
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="yaml-cpp"),
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="yaml-cpp"),
|
||||||
Token(SpecTokens.VERSION, value="@0.1.8"),
|
Token(SpecTokens.VERSION, value="@0.1.8"),
|
||||||
Token(SpecTokens.COMPILER_AND_VERSION, value="%intel@12.1"),
|
Token(SpecTokens.DEPENDENCY, value="%"),
|
||||||
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="intel"),
|
||||||
|
Token(SpecTokens.VERSION, value="@12.1"),
|
||||||
Token(SpecTokens.DEPENDENCY, value="^"),
|
Token(SpecTokens.DEPENDENCY, value="^"),
|
||||||
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="boost"),
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="boost"),
|
||||||
Token(SpecTokens.VERSION, value="@3.1.4"),
|
Token(SpecTokens.VERSION, value="@3.1.4"),
|
||||||
@ -237,7 +250,8 @@ def _specfile_for(spec_str, filename):
|
|||||||
r"builtin.yaml-cpp%gcc",
|
r"builtin.yaml-cpp%gcc",
|
||||||
[
|
[
|
||||||
Token(SpecTokens.FULLY_QUALIFIED_PACKAGE_NAME, value="builtin.yaml-cpp"),
|
Token(SpecTokens.FULLY_QUALIFIED_PACKAGE_NAME, value="builtin.yaml-cpp"),
|
||||||
Token(SpecTokens.COMPILER, value="%gcc"),
|
Token(SpecTokens.DEPENDENCY, value="%"),
|
||||||
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="gcc"),
|
||||||
],
|
],
|
||||||
"yaml-cpp %gcc",
|
"yaml-cpp %gcc",
|
||||||
),
|
),
|
||||||
@ -245,7 +259,8 @@ def _specfile_for(spec_str, filename):
|
|||||||
r"testrepo.yaml-cpp%gcc",
|
r"testrepo.yaml-cpp%gcc",
|
||||||
[
|
[
|
||||||
Token(SpecTokens.FULLY_QUALIFIED_PACKAGE_NAME, value="testrepo.yaml-cpp"),
|
Token(SpecTokens.FULLY_QUALIFIED_PACKAGE_NAME, value="testrepo.yaml-cpp"),
|
||||||
Token(SpecTokens.COMPILER, value="%gcc"),
|
Token(SpecTokens.DEPENDENCY, value="%"),
|
||||||
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="gcc"),
|
||||||
],
|
],
|
||||||
"yaml-cpp %gcc",
|
"yaml-cpp %gcc",
|
||||||
),
|
),
|
||||||
@ -254,7 +269,9 @@ def _specfile_for(spec_str, filename):
|
|||||||
[
|
[
|
||||||
Token(SpecTokens.FULLY_QUALIFIED_PACKAGE_NAME, value="builtin.yaml-cpp"),
|
Token(SpecTokens.FULLY_QUALIFIED_PACKAGE_NAME, value="builtin.yaml-cpp"),
|
||||||
Token(SpecTokens.VERSION, value="@0.1.8"),
|
Token(SpecTokens.VERSION, value="@0.1.8"),
|
||||||
Token(SpecTokens.COMPILER_AND_VERSION, value="%gcc@7.2.0"),
|
Token(SpecTokens.DEPENDENCY, value="%"),
|
||||||
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="gcc"),
|
||||||
|
Token(SpecTokens.VERSION, value="@7.2.0"),
|
||||||
Token(SpecTokens.DEPENDENCY, value="^"),
|
Token(SpecTokens.DEPENDENCY, value="^"),
|
||||||
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="boost"),
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="boost"),
|
||||||
Token(SpecTokens.VERSION, value="@3.1.4"),
|
Token(SpecTokens.VERSION, value="@3.1.4"),
|
||||||
@ -419,11 +436,51 @@ def _specfile_for(spec_str, filename):
|
|||||||
f"develop-branch-version@git.{'a' * 40}=develop+var1+var2",
|
f"develop-branch-version@git.{'a' * 40}=develop+var1+var2",
|
||||||
),
|
),
|
||||||
# Compiler with version ranges
|
# Compiler with version ranges
|
||||||
compiler_with_version_range("%gcc@10.2.1:"),
|
(
|
||||||
compiler_with_version_range("%gcc@:10.2.1"),
|
"%gcc@10.2.1:",
|
||||||
compiler_with_version_range("%gcc@10.2.1:12.1.0"),
|
[
|
||||||
compiler_with_version_range("%gcc@10.1.0,12.2.1:"),
|
Token(SpecTokens.DEPENDENCY, value="%"),
|
||||||
compiler_with_version_range("%gcc@:8.4.3,10.2.1:12.1.0"),
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="gcc"),
|
||||||
|
Token(SpecTokens.VERSION, value="@10.2.1:"),
|
||||||
|
],
|
||||||
|
"%gcc@10.2.1:",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"%gcc@:10.2.1",
|
||||||
|
[
|
||||||
|
Token(SpecTokens.DEPENDENCY, value="%"),
|
||||||
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="gcc"),
|
||||||
|
Token(SpecTokens.VERSION, value="@:10.2.1"),
|
||||||
|
],
|
||||||
|
"%gcc@:10.2.1",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"%gcc@10.2.1:12.1.0",
|
||||||
|
[
|
||||||
|
Token(SpecTokens.DEPENDENCY, value="%"),
|
||||||
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="gcc"),
|
||||||
|
Token(SpecTokens.VERSION, value="@10.2.1:12.1.0"),
|
||||||
|
],
|
||||||
|
"%gcc@10.2.1:12.1.0",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"%gcc@10.1.0,12.2.1:",
|
||||||
|
[
|
||||||
|
Token(SpecTokens.DEPENDENCY, value="%"),
|
||||||
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="gcc"),
|
||||||
|
Token(SpecTokens.VERSION, value="@10.1.0,12.2.1:"),
|
||||||
|
],
|
||||||
|
"%gcc@10.1.0,12.2.1:",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"%gcc@:8.4.3,10.2.1:12.1.0",
|
||||||
|
[
|
||||||
|
Token(SpecTokens.DEPENDENCY, value="%"),
|
||||||
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="gcc"),
|
||||||
|
Token(SpecTokens.VERSION, value="@:8.4.3,10.2.1:12.1.0"),
|
||||||
|
],
|
||||||
|
"%gcc@:8.4.3,10.2.1:12.1.0",
|
||||||
|
),
|
||||||
# Special key value arguments
|
# Special key value arguments
|
||||||
("dev_path=*", [Token(SpecTokens.KEY_VALUE_PAIR, value="dev_path=*")], "dev_path='*'"),
|
("dev_path=*", [Token(SpecTokens.KEY_VALUE_PAIR, value="dev_path=*")], "dev_path='*'"),
|
||||||
(
|
(
|
||||||
@ -484,7 +541,9 @@ def _specfile_for(spec_str, filename):
|
|||||||
"+ debug % intel @ 12.1:12.6",
|
"+ debug % intel @ 12.1:12.6",
|
||||||
[
|
[
|
||||||
Token(SpecTokens.BOOL_VARIANT, value="+ debug"),
|
Token(SpecTokens.BOOL_VARIANT, value="+ debug"),
|
||||||
Token(SpecTokens.COMPILER_AND_VERSION, value="% intel @ 12.1:12.6"),
|
Token(SpecTokens.DEPENDENCY, value="%"),
|
||||||
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="intel"),
|
||||||
|
Token(SpecTokens.VERSION, value="@ 12.1:12.6"),
|
||||||
],
|
],
|
||||||
"+debug %intel@12.1:12.6",
|
"+debug %intel@12.1:12.6",
|
||||||
),
|
),
|
||||||
@ -509,7 +568,8 @@ def _specfile_for(spec_str, filename):
|
|||||||
"@:0.4 % nvhpc",
|
"@:0.4 % nvhpc",
|
||||||
[
|
[
|
||||||
Token(SpecTokens.VERSION, value="@:0.4"),
|
Token(SpecTokens.VERSION, value="@:0.4"),
|
||||||
Token(SpecTokens.COMPILER, value="% nvhpc"),
|
Token(SpecTokens.DEPENDENCY, value="%"),
|
||||||
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="nvhpc"),
|
||||||
],
|
],
|
||||||
"@:0.4 %nvhpc",
|
"@:0.4 %nvhpc",
|
||||||
),
|
),
|
||||||
@ -602,7 +662,10 @@ def _specfile_for(spec_str, filename):
|
|||||||
"zlib %[virtuals=c] gcc",
|
"zlib %[virtuals=c] gcc",
|
||||||
[
|
[
|
||||||
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, "zlib"),
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, "zlib"),
|
||||||
Token(SpecTokens.COMPILER_WITH_VIRTUALS, "%[virtuals=c] gcc"),
|
Token(SpecTokens.START_EDGE_PROPERTIES, value="%["),
|
||||||
|
Token(SpecTokens.KEY_VALUE_PAIR, value="virtuals=c"),
|
||||||
|
Token(SpecTokens.END_EDGE_PROPERTIES, value="]"),
|
||||||
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="gcc"),
|
||||||
],
|
],
|
||||||
"zlib %[virtuals=c] gcc",
|
"zlib %[virtuals=c] gcc",
|
||||||
),
|
),
|
||||||
@ -610,7 +673,10 @@ def _specfile_for(spec_str, filename):
|
|||||||
"zlib %[virtuals=c,cxx] gcc",
|
"zlib %[virtuals=c,cxx] gcc",
|
||||||
[
|
[
|
||||||
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, "zlib"),
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, "zlib"),
|
||||||
Token(SpecTokens.COMPILER_WITH_VIRTUALS, "%[virtuals=c,cxx] gcc"),
|
Token(SpecTokens.START_EDGE_PROPERTIES, value="%["),
|
||||||
|
Token(SpecTokens.KEY_VALUE_PAIR, value="virtuals=c,cxx"),
|
||||||
|
Token(SpecTokens.END_EDGE_PROPERTIES, value="]"),
|
||||||
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="gcc"),
|
||||||
],
|
],
|
||||||
"zlib %[virtuals=c,cxx] gcc",
|
"zlib %[virtuals=c,cxx] gcc",
|
||||||
),
|
),
|
||||||
@ -618,7 +684,11 @@ def _specfile_for(spec_str, filename):
|
|||||||
"zlib %[virtuals=c,cxx] gcc@14.1",
|
"zlib %[virtuals=c,cxx] gcc@14.1",
|
||||||
[
|
[
|
||||||
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, "zlib"),
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, "zlib"),
|
||||||
Token(SpecTokens.COMPILER_AND_VERSION_WITH_VIRTUALS, "%[virtuals=c,cxx] gcc@14.1"),
|
Token(SpecTokens.START_EDGE_PROPERTIES, value="%["),
|
||||||
|
Token(SpecTokens.KEY_VALUE_PAIR, value="virtuals=c,cxx"),
|
||||||
|
Token(SpecTokens.END_EDGE_PROPERTIES, value="]"),
|
||||||
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="gcc"),
|
||||||
|
Token(SpecTokens.VERSION, value="@14.1"),
|
||||||
],
|
],
|
||||||
"zlib %[virtuals=c,cxx] gcc@14.1",
|
"zlib %[virtuals=c,cxx] gcc@14.1",
|
||||||
),
|
),
|
||||||
@ -626,10 +696,15 @@ def _specfile_for(spec_str, filename):
|
|||||||
"zlib %[virtuals=fortran] gcc@14.1 %[virtuals=c,cxx] clang",
|
"zlib %[virtuals=fortran] gcc@14.1 %[virtuals=c,cxx] clang",
|
||||||
[
|
[
|
||||||
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, "zlib"),
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, "zlib"),
|
||||||
Token(
|
Token(SpecTokens.START_EDGE_PROPERTIES, value="%["),
|
||||||
SpecTokens.COMPILER_AND_VERSION_WITH_VIRTUALS, "%[virtuals=fortran] gcc@14.1"
|
Token(SpecTokens.KEY_VALUE_PAIR, value="virtuals=fortran"),
|
||||||
),
|
Token(SpecTokens.END_EDGE_PROPERTIES, value="]"),
|
||||||
Token(SpecTokens.COMPILER_WITH_VIRTUALS, "%[virtuals=c,cxx] clang"),
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="gcc"),
|
||||||
|
Token(SpecTokens.VERSION, value="@14.1"),
|
||||||
|
Token(SpecTokens.START_EDGE_PROPERTIES, value="%["),
|
||||||
|
Token(SpecTokens.KEY_VALUE_PAIR, value="virtuals=c,cxx"),
|
||||||
|
Token(SpecTokens.END_EDGE_PROPERTIES, value="]"),
|
||||||
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="clang"),
|
||||||
],
|
],
|
||||||
"zlib %[virtuals=fortran] gcc@14.1 %[virtuals=c,cxx] clang",
|
"zlib %[virtuals=fortran] gcc@14.1 %[virtuals=c,cxx] clang",
|
||||||
),
|
),
|
||||||
@ -650,6 +725,18 @@ def _specfile_for(spec_str, filename):
|
|||||||
],
|
],
|
||||||
"gcc languages:=='c,c++'",
|
"gcc languages:=='c,c++'",
|
||||||
),
|
),
|
||||||
|
# test <variants> etc. after %
|
||||||
|
(
|
||||||
|
"mvapich %gcc languages:=c,c++ target=x86_64",
|
||||||
|
[
|
||||||
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, "mvapich"),
|
||||||
|
Token(SpecTokens.DEPENDENCY, "%"),
|
||||||
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, "gcc"),
|
||||||
|
Token(SpecTokens.KEY_VALUE_PAIR, "languages:=c,c++"),
|
||||||
|
Token(SpecTokens.KEY_VALUE_PAIR, "target=x86_64"),
|
||||||
|
],
|
||||||
|
"mvapich %gcc languages:='c,c++' arch=None-None-x86_64",
|
||||||
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_parse_single_spec(spec_str, tokens, expected_roundtrip, mock_git_test_package):
|
def test_parse_single_spec(spec_str, tokens, expected_roundtrip, mock_git_test_package):
|
||||||
@ -694,7 +781,8 @@ def test_parse_single_spec(spec_str, tokens, expected_roundtrip, mock_git_test_p
|
|||||||
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="emacs"),
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="emacs"),
|
||||||
Token(SpecTokens.VERSION, value="@1.1.1"),
|
Token(SpecTokens.VERSION, value="@1.1.1"),
|
||||||
Token(SpecTokens.KEY_VALUE_PAIR, value="cflags=-O3"),
|
Token(SpecTokens.KEY_VALUE_PAIR, value="cflags=-O3"),
|
||||||
Token(SpecTokens.COMPILER, value="%intel"),
|
Token(SpecTokens.DEPENDENCY, value="%"),
|
||||||
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="intel"),
|
||||||
],
|
],
|
||||||
["mvapich", "emacs @1.1.1 cflags=-O3 %intel"],
|
["mvapich", "emacs @1.1.1 cflags=-O3 %intel"],
|
||||||
),
|
),
|
||||||
@ -706,10 +794,27 @@ def test_parse_single_spec(spec_str, tokens, expected_roundtrip, mock_git_test_p
|
|||||||
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="emacs"),
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="emacs"),
|
||||||
Token(SpecTokens.DEPENDENCY, value="^"),
|
Token(SpecTokens.DEPENDENCY, value="^"),
|
||||||
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="ncurses"),
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="ncurses"),
|
||||||
Token(SpecTokens.COMPILER, value="%intel"),
|
Token(SpecTokens.DEPENDENCY, value="%"),
|
||||||
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="intel"),
|
||||||
],
|
],
|
||||||
['mvapich cflags="-O3 -fPIC"', "emacs ^ncurses%intel"],
|
['mvapich cflags="-O3 -fPIC"', "emacs ^ncurses%intel"],
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
"mvapich %gcc languages=c,c++ emacs ^ncurses%gcc languages:=c",
|
||||||
|
[
|
||||||
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="mvapich"),
|
||||||
|
Token(SpecTokens.DEPENDENCY, value="%"),
|
||||||
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="gcc"),
|
||||||
|
Token(SpecTokens.KEY_VALUE_PAIR, value="languages=c,c++"),
|
||||||
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="emacs"),
|
||||||
|
Token(SpecTokens.DEPENDENCY, value="^"),
|
||||||
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="ncurses"),
|
||||||
|
Token(SpecTokens.DEPENDENCY, value="%"),
|
||||||
|
Token(SpecTokens.UNQUALIFIED_PACKAGE_NAME, value="gcc"),
|
||||||
|
Token(SpecTokens.KEY_VALUE_PAIR, value="languages:=c"),
|
||||||
|
],
|
||||||
|
["mvapich %gcc languages=c,c++", "emacs ^ncurses%gcc languages:=c"],
|
||||||
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_parse_multiple_specs(text, tokens, expected_specs):
|
def test_parse_multiple_specs(text, tokens, expected_specs):
|
||||||
|
@ -2935,7 +2935,7 @@ complete -c spack -n '__fish_spack_using_command style' -s t -l tool -r -d 'spec
|
|||||||
complete -c spack -n '__fish_spack_using_command style' -s s -l skip -r -f -a skip
|
complete -c spack -n '__fish_spack_using_command style' -s s -l skip -r -f -a skip
|
||||||
complete -c spack -n '__fish_spack_using_command style' -s s -l skip -r -d 'specify tools to skip (choose from import, isort, black, flake8, mypy)'
|
complete -c spack -n '__fish_spack_using_command style' -s s -l skip -r -d 'specify tools to skip (choose from import, isort, black, flake8, mypy)'
|
||||||
complete -c spack -n '__fish_spack_using_command style' -l spec-strings -f -a spec_strings
|
complete -c spack -n '__fish_spack_using_command style' -l spec-strings -f -a spec_strings
|
||||||
complete -c spack -n '__fish_spack_using_command style' -l spec-strings -d 'upgrade spec strings in Python, JSON and YAML files for compatibility with Spack v1.0 and v0.x. Example: spack style --spec-strings $(git ls-files). Note: this flag will be removed in Spack v1.0.'
|
complete -c spack -n '__fish_spack_using_command style' -l spec-strings -d 'upgrade spec strings in Python, JSON and YAML files for compatibility with Spack v1.0 and v0.x. Example: spack style --spec-strings $(git ls-files). Note: must be used only on specs from spack v0.X.'
|
||||||
|
|
||||||
# spack tags
|
# spack tags
|
||||||
set -g __fish_spack_optspecs_spack_tags h/help i/installed a/all
|
set -g __fish_spack_optspecs_spack_tags h/help i/installed a/all
|
||||||
|
@ -17,6 +17,7 @@ class Llvm(Package, CompilerPackage):
|
|||||||
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("lld", default=True, description="Build the LLVM linker")
|
||||||
|
|
||||||
provides("c", "cxx", when="+clang")
|
provides("c", "cxx", when="+clang")
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user