Compare commits

...

3 Commits

Author SHA1 Message Date
Gregory Becker
a542b0cfc0 flake 2023-02-16 19:29:35 -08:00
Gregory Becker
0d02262bbc docs 2023-02-16 19:13:04 -08:00
Gregory Becker
9beac03142 SpecList: enforce ordering of matrices on constructed specs 2023-02-16 19:12:52 -08:00
5 changed files with 58 additions and 36 deletions

View File

@@ -346,7 +346,7 @@ the Environment and then install the concretized specs.
(see :ref:`build-jobs`). To speed up environment builds further, independent (see :ref:`build-jobs`). To speed up environment builds further, independent
packages can be installed in parallel by launching more Spack instances. For packages can be installed in parallel by launching more Spack instances. For
example, the following will build at most four packages in parallel using example, the following will build at most four packages in parallel using
three background jobs: three background jobs:
.. code-block:: console .. code-block:: console
@@ -394,7 +394,7 @@ version (and other constraints) passed as the spec argument to the
For packages with ``git`` attributes, git branches, tags, and commits can For packages with ``git`` attributes, git branches, tags, and commits can
also be used as valid concrete versions (see :ref:`version-specifier`). also be used as valid concrete versions (see :ref:`version-specifier`).
This means that for a package ``foo``, ``spack develop foo@git.main`` will clone This means that for a package ``foo``, ``spack develop foo@git.main`` will clone
the ``main`` branch of the package, and ``spack install`` will install from the ``main`` branch of the package, and ``spack install`` will install from
that git clone if ``foo`` is in the environment. that git clone if ``foo`` is in the environment.
Further development on ``foo`` can be tested by reinstalling the environment, Further development on ``foo`` can be tested by reinstalling the environment,
@@ -630,6 +630,35 @@ The following two Environment manifests are identical:
Spec matrices can be used to install swaths of software across various Spec matrices can be used to install swaths of software across various
toolchains. toolchains.
Note that ordering of matrices is important. For example, the
following environments are identical:
.. code-block:: yaml
spack:
specs:
- matrix:
- [hdf5@1.10.2+mpi]
- [^mpich, ^openmpi]
- ['%gcc']
- matrix:
- [hdf5@1.12.1+mpi]
- ['%gcc']
- [^mpich, ^openmpi]
spack:
specs:
- hdf5@1.10.2+mpi ^mpich%gcc
- hdf5@1.10.2+mpi ^openmpi%gcc
- hdf5@1.12.1+mpi %gcc ^mpich
- hdf5@1.12.1+mpi %gcc ^openmpi
Notice how the first matrix applies the compiler constraints to the
mpi dependencies, whereas the second matrix applies the compiler
constraints directly to the root hdf5 node. This gives users the full
breadth of expressiveness of the spec syntax through the matrix
interface.
^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^
Spec List References Spec List References
^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^
@@ -1120,19 +1149,19 @@ index once every package is pushed. Note how this target uses the generated
SPACK ?= spack SPACK ?= spack
BUILDCACHE_DIR = $(CURDIR)/tarballs BUILDCACHE_DIR = $(CURDIR)/tarballs
.PHONY: all .PHONY: all
all: push all: push
include env.mk include env.mk
example/push/%: example/install/% example/push/%: example/install/%
@mkdir -p $(dir $@) @mkdir -p $(dir $@)
$(info About to push $(SPEC) to a buildcache) $(info About to push $(SPEC) to a buildcache)
$(SPACK) -e . buildcache create --allow-root --only=package --directory $(BUILDCACHE_DIR) /$(HASH) $(SPACK) -e . buildcache create --allow-root --only=package --directory $(BUILDCACHE_DIR) /$(HASH)
@touch $@ @touch $@
push: $(addprefix example/push/,$(example/SPACK_PACKAGE_IDS)) push: $(addprefix example/push/,$(example/SPACK_PACKAGE_IDS))
$(info Updating the buildcache index) $(info Updating the buildcache index)
$(SPACK) -e . buildcache update-index --directory $(BUILDCACHE_DIR) $(SPACK) -e . buildcache update-index --directory $(BUILDCACHE_DIR)

View File

@@ -2265,15 +2265,12 @@ def _concretize_from_constraints(spec_constraints, tests=False):
m += "concretization target. all specs must have a single name " m += "concretization target. all specs must have a single name "
m += "constraint for concretization." m += "constraint for concretization."
raise InvalidSpecConstraintError(m) raise InvalidSpecConstraintError(m)
spec_constraints.remove(root_spec[0])
invalid_constraints = [] invalid_constraints = []
while True: while True:
# Attach all anonymous constraints to one named spec # Combine constraints into a single spec
s = root_spec[0].copy() s = Spec(" ".join([str(c) for c in spec_constraints if c not in invalid_constraints]))
for c in spec_constraints:
if c not in invalid_constraints:
s.constrain(c)
try: try:
return s.concretized(tests=tests) return s.concretized(tests=tests)
except spack.spec.InvalidDependencyError as e: except spack.spec.InvalidDependencyError as e:

View File

@@ -51,7 +51,9 @@ def specs_as_constraints(self):
constraints = [] constraints = []
for item in self.specs_as_yaml_list: for item in self.specs_as_yaml_list:
if isinstance(item, dict): # matrix of specs if isinstance(item, dict): # matrix of specs
constraints.extend(_expand_matrix_constraints(item)) expanded = _expand_matrix_constraints(item)
for e in expanded:
constraints.append([Spec(x) for x in e])
else: # individual spec else: # individual spec
constraints.append([Spec(item)]) constraints.append([Spec(item)])
self._constraints = constraints self._constraints = constraints
@@ -62,13 +64,11 @@ def specs_as_constraints(self):
def specs(self): def specs(self):
if self._specs is None: if self._specs is None:
specs = [] specs = []
# This could be slightly faster done directly from yaml_list, for item in self.specs_as_yaml_list:
# but this way is easier to maintain. if isinstance(item, dict): # matrix of specs
for constraint_list in self.specs_as_constraints: specs.extend([Spec(" ".join(x)) for x in _expand_matrix_constraints(item)])
spec = constraint_list[0].copy() else: # individual spec
for const in constraint_list[1:]: specs.append(Spec(item))
spec.constrain(const)
specs.append(spec)
self._specs = specs self._specs = specs
return self._specs return self._specs
@@ -193,11 +193,7 @@ def _expand_matrix_constraints(matrix_config):
for combo in itertools.product(*expanded_rows): for combo in itertools.product(*expanded_rows):
# Construct a combined spec to test against excludes # Construct a combined spec to test against excludes
flat_combo = [constraint for constraint_list in combo for constraint in constraint_list] flat_combo = [constraint for constraint_list in combo for constraint in constraint_list]
flat_combo = [Spec(x) for x in flat_combo] test_spec = Spec(" ".join(flat_combo))
test_spec = flat_combo[0].copy()
for constraint in flat_combo[1:]:
test_spec.constrain(constraint)
# Abstract variants don't have normal satisfaction semantics # Abstract variants don't have normal satisfaction semantics
# Convert all variants to concrete types. # Convert all variants to concrete types.
@@ -213,7 +209,7 @@ def _expand_matrix_constraints(matrix_config):
continue continue
if sigil: if sigil:
flat_combo[0] = Spec(sigil + str(flat_combo[0])) flat_combo[0] = sigil + flat_combo[0]
# Add to list of constraints # Add to list of constraints
results.append(flat_combo) results.append(flat_combo)

View File

@@ -75,8 +75,8 @@ def test_env_change_spec(tmpdir, mock_packages, config):
- desired_specs: ["mpileaks@2.1"] - desired_specs: ["mpileaks@2.1"]
specs: specs:
- matrix: - matrix:
- [$compilers]
- [$desired_specs] - [$desired_specs]
- [$compilers]
""" """

View File

@@ -61,25 +61,25 @@ def test_spec_list_expansions(self):
@pytest.mark.parametrize( @pytest.mark.parametrize(
"specs,expected", "specs,expected",
[ [
# Constraints are ordered randomly # Constraints are ordered carefully to apply to appropriate node
( (
[ [
{ {
"matrix": [ "matrix": [
["^zmpi"],
["%gcc@4.5.0"],
["hypre", "libelf"], ["hypre", "libelf"],
["~shared"], ["~shared"],
["cflags=-O3", 'cflags="-g -O0"'],
["^foo"], ["^foo"],
["^zmpi"],
["%gcc@4.5.0"],
["cflags=-O3", 'cflags="-g -O0"'],
] ]
} }
], ],
[ [
"hypre cflags=-O3 ~shared %gcc@4.5.0 ^foo ^zmpi", "hypre ~shared ^foo ^zmpi cflags=-O3 %gcc@4.5.0",
'hypre cflags="-g -O0" ~shared %gcc@4.5.0 ^foo ^zmpi', 'hypre ~shared ^foo ^zmpi cflags="-g -O0" %gcc@4.5.0',
"libelf cflags=-O3 ~shared %gcc@4.5.0 ^foo ^zmpi", "libelf ~shared ^foo ^zmpi cflags=-O3 %gcc@4.5.0",
'libelf cflags="-g -O0" ~shared %gcc@4.5.0 ^foo ^zmpi', 'libelf ~shared ^foo ^zmpi cflags="-g -O0" %gcc@4.5.0',
], ],
), ),
# A constraint affects both the root and a dependency # A constraint affects both the root and a dependency