summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorscheibelp <scheibel1@llnl.gov>2016-12-08 00:51:19 -0800
committerTodd Gamblin <tgamblin@llnl.gov>2016-12-08 00:51:19 -0800
commit30daf95ae8aa8e55b810ec14da7a0649b1e0ecb7 (patch)
treee1d636e1c23fc99fd318faccbf78240986e52e98 /lib
parent5f01f273e03e86696688154a31fedb6889d50c6c (diff)
downloadspack-30daf95ae8aa8e55b810ec14da7a0649b1e0ecb7.tar.gz
spack-30daf95ae8aa8e55b810ec14da7a0649b1e0ecb7.tar.bz2
spack-30daf95ae8aa8e55b810ec14da7a0649b1e0ecb7.tar.xz
spack-30daf95ae8aa8e55b810ec14da7a0649b1e0ecb7.zip
Use frontend OS for build/run deps by default (#2292)
Packages built targeting a backend may depend on packages like cmake which can be built against the frontend. With this commit, any build dependency or child of a build dependency will target the frontend by default. In compiler concretization when packages copy compilers from nearby packages, build dependencies use compiler information from other build dependencies, and link dependencies avoid using compiler information from build dependencies.
Diffstat (limited to 'lib')
-rw-r--r--lib/spack/spack/architecture.py5
-rw-r--r--lib/spack/spack/concretize.py56
-rw-r--r--lib/spack/spack/operating_systems/cnl.py2
-rw-r--r--lib/spack/spack/spec.py23
-rw-r--r--lib/spack/spack/test/concretize.py30
5 files changed, 91 insertions, 25 deletions
diff --git a/lib/spack/spack/architecture.py b/lib/spack/spack/architecture.py
index 6ea7bafb6a..a77832fcb1 100644
--- a/lib/spack/spack/architecture.py
+++ b/lib/spack/spack/architecture.py
@@ -513,3 +513,8 @@ def sys_type():
"""
arch = Arch(platform(), 'default_os', 'default_target')
return str(arch)
+
+
+@memoized
+def frontend_sys_type():
+ return str(Arch(platform(), 'frontend', 'frontend'))
diff --git a/lib/spack/spack/concretize.py b/lib/spack/spack/concretize.py
index 1bc933e543..51d3c777fc 100644
--- a/lib/spack/spack/concretize.py
+++ b/lib/spack/spack/concretize.py
@@ -251,8 +251,12 @@ class DefaultConcretizer(object):
DAG has an architecture, then use the root otherwise use the defaults
on the platform.
"""
- root_arch = spec.root.architecture
- sys_arch = spack.spec.ArchSpec(spack.architecture.sys_type())
+ root_arch = spec.link_root().architecture
+ if spec.build_dep() and spec.disjoint_build_tree():
+ sys_arch = spack.spec.ArchSpec(
+ spack.architecture.frontend_sys_type())
+ else:
+ sys_arch = spack.spec.ArchSpec(spack.architecture.sys_type())
spec_changed = False
if spec.architecture is None:
@@ -321,14 +325,21 @@ class DefaultConcretizer(object):
spec.compiler in all_compilers):
return False
- # Find the another spec that has a compiler, or the root if none do
- other_spec = spec if spec.compiler else find_spec(
- spec, lambda x: x.compiler)
+ if spec.compiler:
+ other_spec = spec
+ elif spec.build_dep() and spec.disjoint_build_tree():
+ link_root = spec.link_root()
+ build_subtree = list(link_root.traverse(direction='children'))
+ candidates = list(x for x in build_subtree if x.compiler)
+ other_spec = candidates[0] if candidates else link_root
+ else:
+ # Find another spec that has a compiler, or the root if none do.
+ # Prefer compiler info from other specs which are not build deps.
+ other_spec = (
+ find_spec(spec, lambda x: x.compiler and not x.build_dep()) or
+ spec.root)
- if not other_spec:
- other_spec = spec.root
other_compiler = other_spec.compiler
- assert(other_spec)
# Check if the compiler is already fully specified
if other_compiler in all_compilers:
@@ -372,16 +383,20 @@ class DefaultConcretizer(object):
# changes
return True
+ def compiler_match(spec1, spec2):
+ return ((spec1.compiler, spec1.architecture) ==
+ (spec2.compiler, spec2.architecture))
+
ret = False
for flag in spack.spec.FlagMap.valid_compiler_flags():
try:
nearest = next(p for p in spec.traverse(direction='parents')
- if ((p.compiler == spec.compiler and
- p is not spec) and
+ if ((p is not spec) and
+ compiler_match(p, spec) and
flag in p.compiler_flags))
- if flag not in spec.compiler_flags or \
- not (sorted(spec.compiler_flags[flag]) >=
- sorted(nearest.compiler_flags[flag])):
+ if (flag not in spec.compiler_flags or
+ (set(nearest.compiler_flags[flag]) -
+ set(spec.compiler_flags[flag]))):
if flag in spec.compiler_flags:
spec.compiler_flags[flag] = list(
set(spec.compiler_flags[flag]) |
@@ -392,10 +407,11 @@ class DefaultConcretizer(object):
ret = True
except StopIteration:
- if (flag in spec.root.compiler_flags and
- ((flag not in spec.compiler_flags) or
- sorted(spec.compiler_flags[flag]) !=
- sorted(spec.root.compiler_flags[flag]))):
+ if (compiler_match(spec.root, spec) and
+ flag in spec.root.compiler_flags and
+ ((flag not in spec.compiler_flags) or
+ (set(spec.root.compiler_flags[flag]) -
+ set(spec.compiler_flags[flag])))):
if flag in spec.compiler_flags:
spec.compiler_flags[flag] = list(
set(spec.compiler_flags[flag]) |
@@ -419,10 +435,8 @@ class DefaultConcretizer(object):
if compiler.flags[flag] != []:
ret = True
else:
- if ((sorted(spec.compiler_flags[flag]) !=
- sorted(compiler.flags[flag])) and
- (not set(spec.compiler_flags[flag]) >=
- set(compiler.flags[flag]))):
+ if (set(compiler.flags[flag]) -
+ set(spec.compiler_flags[flag])):
ret = True
spec.compiler_flags[flag] = list(
set(spec.compiler_flags[flag]) |
diff --git a/lib/spack/spack/operating_systems/cnl.py b/lib/spack/spack/operating_systems/cnl.py
index 78807865b3..fa5394ce66 100644
--- a/lib/spack/spack/operating_systems/cnl.py
+++ b/lib/spack/spack/operating_systems/cnl.py
@@ -22,7 +22,7 @@ class Cnl(OperatingSystem):
super(Cnl, self).__init__(name, version)
def __str__(self):
- return self.name
+ return self.name + self.version
def find_compilers(self, *paths):
types = spack.compilers.all_compiler_types()
diff --git a/lib/spack/spack/spec.py b/lib/spack/spack/spec.py
index 2ef3757689..aba0466076 100644
--- a/lib/spack/spack/spec.py
+++ b/lib/spack/spack/spec.py
@@ -1090,7 +1090,7 @@ class Spec(object):
successors = deps
if direction == 'parents':
- successors = self.dependents_dict() # TODO: deptype?
+ successors = self.dependents_dict(deptype)
visited.add(key)
for name in sorted(successors):
@@ -1308,6 +1308,23 @@ class Spec(object):
except Exception as e:
raise sjson.SpackJSONError("error parsing JSON spec:", str(e))
+ def build_dep(self):
+ # If this spec is the root, it will automatically be included in
+ # traverse
+ return not (self.root in
+ self.traverse(
+ deptype=('link', 'run'), direction='parents'))
+
+ def link_root(self):
+ parents = list(self.traverse(deptype=('link',), direction='parents',
+ order='pre'))
+ return parents[-1]
+
+ def disjoint_build_tree(self):
+ link_root = self.link_root()
+ build_subtree = list(link_root.traverse(direction='children'))
+ return all(x.build_dep() for x in build_subtree)
+
def _concretize_helper(self, presets=None, visited=None):
"""Recursive helper function for concretize().
This concretizes everything bottom-up. As things are
@@ -1326,8 +1343,8 @@ class Spec(object):
# Concretize deps first -- this is a bottom-up process.
for name in sorted(self._dependencies.keys()):
- changed |= self._dependencies[
- name].spec._concretize_helper(presets, visited)
+ dep = self._dependencies[name]
+ changed |= dep.spec._concretize_helper(presets, visited)
if self.name in presets:
changed |= self.constrain(presets[self.name])
diff --git a/lib/spack/spack/test/concretize.py b/lib/spack/spack/test/concretize.py
index 154e0eb68e..4e2354a17a 100644
--- a/lib/spack/spack/test/concretize.py
+++ b/lib/spack/spack/test/concretize.py
@@ -85,6 +85,36 @@ class ConcretizeTest(MockPackagesTest):
self.check_concretize('mpich debug=2')
self.check_concretize('mpich')
+ def test_concretize_with_build_dep(self):
+ # Set the target as the backend. Since the cmake build dependency is
+ # not explicitly configured to target the backend it should target
+ # the frontend (whatever compiler that is, it is different)
+ spec = self.check_concretize('cmake-client platform=test target=be')
+ client_compiler = spack.compilers.compiler_for_spec(
+ spec.compiler, spec.architecture)
+ cmake_spec = spec['cmake']
+ cmake_compiler = spack.compilers.compiler_for_spec(
+ cmake_spec.compiler, cmake_spec.architecture)
+ self.assertTrue(client_compiler.operating_system !=
+ cmake_compiler.operating_system)
+
+ def test_concretize_link_dep_of_build_dep(self):
+ # The link dep of the build dep should use the same compiler as
+ # the build dep, and both should be different from the root
+ spec = self.check_concretize('dttop platform=test target=be')
+ dttop_compiler = spack.compilers.compiler_for_spec(
+ spec.compiler, spec.architecture)
+ dtlink2_spec = spec['dtlink2']
+ dtlink2_compiler = spack.compilers.compiler_for_spec(
+ dtlink2_spec.compiler, dtlink2_spec.architecture)
+ dtbuild1_spec = spec['dtbuild1']
+ dtbuild1_compiler = spack.compilers.compiler_for_spec(
+ dtbuild1_spec.compiler, dtbuild1_spec.architecture)
+ self.assertTrue(dttop_compiler.operating_system !=
+ dtlink2_compiler.operating_system)
+ self.assertTrue(dtbuild1_compiler.operating_system ==
+ dtlink2_compiler.operating_system)
+
def test_conretize_compiler_flags(self):
self.check_concretize('mpich cppflags="-O3"')