Propagate architecture information during concretization (#7412)
This updates architecture concretization to * Search for the nearest parent in the DAG for architecture information rather than defaulting to the root of the DAG * Propagate architecture settings transitively, such that if for example the target is set at the root of the dag it will set the same target on indirect dependencies (assuming no intermediate dependency specifies a separate target). Previously this occurred in general but under some conditions did not, for example if an intermediate dependency specified some subset of architecture properties.
This commit is contained in:
parent
726c7e0f06
commit
f8657e3fd9
2 changed files with 57 additions and 17 deletions
|
@ -222,27 +222,29 @@ def concretize_architecture(self, spec):
|
||||||
DAG has an architecture, then use the root otherwise use the defaults
|
DAG has an architecture, then use the root otherwise use the defaults
|
||||||
on the platform.
|
on the platform.
|
||||||
"""
|
"""
|
||||||
root_arch = spec.root.architecture
|
try:
|
||||||
sys_arch = spack.spec.ArchSpec(spack.architecture.sys_type())
|
# Get the nearest architecture with any fields set
|
||||||
|
nearest = next(p for p in spec.traverse(direction='parents')
|
||||||
|
if (p.architecture and p is not spec))
|
||||||
|
nearest_arch = nearest.architecture
|
||||||
|
except StopIteration:
|
||||||
|
# Default to the system architecture if nothing set
|
||||||
|
nearest_arch = spack.spec.ArchSpec(spack.architecture.sys_type())
|
||||||
|
|
||||||
spec_changed = False
|
spec_changed = False
|
||||||
|
|
||||||
|
# ensure type safety for the architecture
|
||||||
if spec.architecture is None:
|
if spec.architecture is None:
|
||||||
spec.architecture = spack.spec.ArchSpec(sys_arch)
|
spec.architecture = spack.spec.ArchSpec()
|
||||||
spec_changed = True
|
spec_changed = True
|
||||||
|
|
||||||
default_archs = list(x for x in [root_arch, sys_arch] if x)
|
# replace each of the fields (platform, os, target) separately
|
||||||
for arch in default_archs:
|
nearest_dict = nearest_arch.to_cmp_dict()
|
||||||
if spec.architecture.concrete:
|
replacement_fields = [k for k, v in iteritems(nearest_dict)
|
||||||
break
|
if v and not getattr(spec.architecture, k)]
|
||||||
|
for field in replacement_fields:
|
||||||
replacement_fields = [k for k, v in iteritems(arch.to_cmp_dict())
|
setattr(spec.architecture, field, getattr(nearest_arch, field))
|
||||||
if v and not getattr(spec.architecture, k)]
|
spec_changed = True
|
||||||
for field in replacement_fields:
|
|
||||||
setattr(spec.architecture, field, getattr(arch, field))
|
|
||||||
spec_changed = True
|
|
||||||
|
|
||||||
if not spec.architecture.concrete:
|
|
||||||
raise InsufficientArchitectureInfoError(spec, default_archs)
|
|
||||||
|
|
||||||
return spec_changed
|
return spec_changed
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
##############################################################################
|
#############################################################################
|
||||||
# Copyright (c) 2013-2017, Lawrence Livermore National Security, LLC.
|
# Copyright (c) 2013-2017, Lawrence Livermore National Security, LLC.
|
||||||
# Produced at the Lawrence Livermore National Laboratory.
|
# Produced at the Lawrence Livermore National Laboratory.
|
||||||
#
|
#
|
||||||
|
@ -31,6 +31,7 @@
|
||||||
from spack.spec import Spec, CompilerSpec
|
from spack.spec import Spec, CompilerSpec
|
||||||
from spack.spec import ConflictsInSpecError, SpecError
|
from spack.spec import ConflictsInSpecError, SpecError
|
||||||
from spack.version import ver
|
from spack.version import ver
|
||||||
|
from spack.test.conftest import MockPackage, MockPackageMultiRepo
|
||||||
|
|
||||||
|
|
||||||
def check_spec(abstract, concrete):
|
def check_spec(abstract, concrete):
|
||||||
|
@ -204,6 +205,42 @@ def test_different_compilers_get_different_flags(self):
|
||||||
assert set(client.compiler_flags['fflags']) == set(['-O0'])
|
assert set(client.compiler_flags['fflags']) == set(['-O0'])
|
||||||
assert not set(cmake.compiler_flags['fflags'])
|
assert not set(cmake.compiler_flags['fflags'])
|
||||||
|
|
||||||
|
def test_architecture_inheritance(self):
|
||||||
|
"""test_architecture_inheritance is likely to fail with an
|
||||||
|
UnavailableCompilerVersionError if the architecture is concretized
|
||||||
|
incorrectly.
|
||||||
|
"""
|
||||||
|
spec = Spec('cmake-client %gcc@4.7.2 os=fe ^ cmake')
|
||||||
|
spec.concretize()
|
||||||
|
assert spec['cmake'].architecture == spec.architecture
|
||||||
|
|
||||||
|
def test_architecture_deep_inheritance(self):
|
||||||
|
"""Make sure that indirect dependencies receive architecture
|
||||||
|
information from the root even when partial architecture information
|
||||||
|
is provided by an intermediate dependency.
|
||||||
|
"""
|
||||||
|
saved_repo = spack.repo
|
||||||
|
|
||||||
|
default_dep = ('link', 'build')
|
||||||
|
|
||||||
|
bazpkg = MockPackage('bazpkg', [], [])
|
||||||
|
barpkg = MockPackage('barpkg', [bazpkg], [default_dep])
|
||||||
|
foopkg = MockPackage('foopkg', [barpkg], [default_dep])
|
||||||
|
mock_repo = MockPackageMultiRepo([foopkg, barpkg, bazpkg])
|
||||||
|
|
||||||
|
spack.repo = mock_repo
|
||||||
|
|
||||||
|
try:
|
||||||
|
spec = Spec('foopkg %clang@3.3 os=CNL target=footar' +
|
||||||
|
' ^barpkg os=SuSE11 ^bazpkg os=be')
|
||||||
|
spec.concretize()
|
||||||
|
|
||||||
|
for s in spec.traverse(root=False):
|
||||||
|
assert s.architecture.target == spec.architecture.target
|
||||||
|
|
||||||
|
finally:
|
||||||
|
spack.repo = saved_repo
|
||||||
|
|
||||||
def test_compiler_flags_from_user_are_grouped(self):
|
def test_compiler_flags_from_user_are_grouped(self):
|
||||||
spec = Spec('a%gcc cflags="-O -foo-flag foo-val" platform=test')
|
spec = Spec('a%gcc cflags="-O -foo-flag foo-val" platform=test')
|
||||||
spec.concretize()
|
spec.concretize()
|
||||||
|
@ -216,6 +253,7 @@ def concretize_multi_provider(self):
|
||||||
assert s['mpi'].version == ver('1.10.3')
|
assert s['mpi'].version == ver('1.10.3')
|
||||||
|
|
||||||
def test_concretize_two_virtuals(self):
|
def test_concretize_two_virtuals(self):
|
||||||
|
|
||||||
"""Test a package with multiple virtual dependencies."""
|
"""Test a package with multiple virtual dependencies."""
|
||||||
Spec('hypre').concretize()
|
Spec('hypre').concretize()
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue