diff options
-rw-r--r-- | lib/spack/spack/architecture.py | 5 | ||||
-rw-r--r-- | lib/spack/spack/concretize.py | 56 | ||||
-rw-r--r-- | lib/spack/spack/operating_systems/cnl.py | 2 | ||||
-rw-r--r-- | lib/spack/spack/spec.py | 23 | ||||
-rw-r--r-- | lib/spack/spack/test/concretize.py | 30 |
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"') |