Injected flags have a consistent order (#9960)

Fixes #9908

Spack was assembling flags in a manner that could in different
orderings for repeated concretizations of the same spec and config
This commit is contained in:
Massimiliano Culpo 2018-11-28 19:23:38 +01:00 committed by Peter Scheibel
parent 5cea4a75d7
commit e998a399da
4 changed files with 30 additions and 16 deletions

View File

@ -380,13 +380,12 @@ def concretize_compiler_flags(self, spec):
if (compiler_match(p) and if (compiler_match(p) and
(p is not spec) and (p is not spec) and
flag in p.compiler_flags)) flag in p.compiler_flags))
nearest_flags = set(nearest.compiler_flags.get(flag, [])) nearest_flags = nearest.compiler_flags.get(flag, [])
flags = set(spec.compiler_flags.get(flag, [])) flags = spec.compiler_flags.get(flag, [])
if (nearest_flags - flags): if set(nearest_flags) - set(flags):
# TODO: these set operations may reorder the flags, which spec.compiler_flags[flag] = list(
# for some orders of flags can be invalid. See: llnl.util.lang.dedupe(nearest_flags + flags)
# https://github.com/spack/spack/issues/6154#issuecomment-342365573 )
spec.compiler_flags[flag] = list(nearest_flags | flags)
ret = True ret = True
except StopIteration: except StopIteration:
pass pass
@ -402,10 +401,12 @@ def concretize_compiler_flags(self, spec):
raise raise
return ret return ret
for flag in compiler.flags: for flag in compiler.flags:
config_flags = set(compiler.flags.get(flag, [])) config_flags = compiler.flags.get(flag, [])
flags = set(spec.compiler_flags.get(flag, [])) flags = spec.compiler_flags.get(flag, [])
spec.compiler_flags[flag] = list(config_flags | flags) spec.compiler_flags[flag] = list(
if (config_flags - flags): llnl.util.lang.dedupe(config_flags + flags)
)
if set(config_flags) - set(flags):
ret = True ret = True
return ret return ret

View File

@ -179,9 +179,9 @@ def test_different_compilers_get_different_flags(self):
' ^cmake %clang@3.5 platform=test os=fe target=fe') ' ^cmake %clang@3.5 platform=test os=fe target=fe')
client.concretize() client.concretize()
cmake = client['cmake'] cmake = client['cmake']
assert set(client.compiler_flags['cflags']) == set(['-O0']) assert set(client.compiler_flags['cflags']) == set(['-O0', '-g'])
assert set(cmake.compiler_flags['cflags']) == set(['-O3']) assert set(cmake.compiler_flags['cflags']) == set(['-O3'])
assert set(client.compiler_flags['fflags']) == set(['-O0']) assert set(client.compiler_flags['fflags']) == set(['-O0', '-g'])
assert not set(cmake.compiler_flags['fflags']) assert not set(cmake.compiler_flags['fflags'])
def test_architecture_inheritance(self): def test_architecture_inheritance(self):

View File

@ -98,9 +98,9 @@ compilers:
f77: /path/to/gfortran472 f77: /path/to/gfortran472
fc: /path/to/gfortran472 fc: /path/to/gfortran472
flags: flags:
cflags: -O0 cflags: -O0 -g
cxxflags: -O0 cxxflags: -O0 -g
fflags: -O0 fflags: -O0 -g
modules: 'None' modules: 'None'
- compiler: - compiler:
spec: clang@3.5 spec: clang@3.5

View File

@ -743,3 +743,16 @@ def test_spec_formatting(self):
expected = getattr(arch, prop, "") expected = getattr(arch, prop, "")
actual = spec.format(named_str) actual = spec.format(named_str)
assert str(expected) == actual assert str(expected) == actual
@pytest.mark.regression('9908')
def test_spec_flags_maintain_order(self):
# Spack was assembling flags in a manner that could result in
# different orderings for repeated concretizations of the same
# spec and config
spec_str = 'libelf %gcc@4.7.2 os=redhat6'
for _ in range(25):
s = Spec(spec_str).concretized()
assert all(
s.compiler_flags[x] == ['-O0', '-g']
for x in ('cflags', 'cxxflags', 'fflags')
)