Skip to content
Snippets Groups Projects
Commit 7dd14870 authored by Joseph Ciurej's avatar Joseph Ciurej Committed by Todd Gamblin
Browse files

Bug Fix : Apply Compiler Flags Specified by Manual Compiler Configuration (#1532)

* Fixed a bug causing config-specified compiler flags to be ignored.
Updated the compiler config so all flags are in a separate section.

* Updated the documentation for the `compilers.yaml` file spec.

* Implemented basic testing for the 'flags' section of compiler config.

* Fixed a few minor problems with the manual compiler config documentation.
parent e35c023c
No related branches found
No related tags found
No related merge requests found
...@@ -218,12 +218,14 @@ If you want to see specifics on a particular compiler, you can run ...@@ -218,12 +218,14 @@ If you want to see specifics on a particular compiler, you can run
$ spack compiler info intel@15 $ spack compiler info intel@15
intel@15.0.0: intel@15.0.0:
cc = /usr/local/bin/icc-15.0.090 paths:
cxx = /usr/local/bin/icpc-15.0.090 cc = /usr/local/bin/icc-15.0.090
f77 = /usr/local/bin/ifort-15.0.090 cxx = /usr/local/bin/icpc-15.0.090
fc = /usr/local/bin/ifort-15.0.090 f77 = /usr/local/bin/ifort-15.0.090
modules = [] fc = /usr/local/bin/ifort-15.0.090
operating system = centos6 modules = []
operating system = centos6
...
This shows which C, C++, and Fortran compilers were detected by Spack. This shows which C, C++, and Fortran compilers were detected by Spack.
Notice also that we didn't have to be too specific about the Notice also that we didn't have to be too specific about the
...@@ -244,7 +246,7 @@ Each compiler configuration in the file looks like this: ...@@ -244,7 +246,7 @@ Each compiler configuration in the file looks like this:
compilers: compilers:
- compiler: - compiler:
modules = [] modules: []
operating_system: centos6 operating_system: centos6
paths: paths:
cc: /usr/local/bin/icc-15.0.024-beta cc: /usr/local/bin/icc-15.0.024-beta
...@@ -253,39 +255,46 @@ Each compiler configuration in the file looks like this: ...@@ -253,39 +255,46 @@ Each compiler configuration in the file looks like this:
fc: /usr/local/bin/ifort-15.0.024-beta fc: /usr/local/bin/ifort-15.0.024-beta
spec: intel@15.0.0: spec: intel@15.0.0:
For compilers, like ``clang``, that do not support Fortran, put For compilers that do not support Fortran (like ``clang``), put
``None`` for ``f77`` and ``fc``: ``None`` for ``f77`` and ``fc``:
.. code-block:: yaml .. code-block:: yaml
compilers:
- compiler:
modules: []
operating_system: centos6
paths: paths:
cc: /usr/bin/clang cc: /usr/bin/clang
cxx: /usr/bin/clang++ cxx: /usr/bin/clang++
f77: None f77: None
fc: None fc: None
spec: clang@3.3svn: spec: clang@3.3svn
Once you save the file, the configured compilers will show up in the Once you save the file, the configured compilers will show up in the
list displayed by ``spack compilers``. list displayed by ``spack compilers``.
You can also add compiler flags to manually configured compilers. The You can also add compiler flags to manually configured compilers. These
valid flags are ``cflags``, ``cxxflags``, ``fflags``, ``cppflags``, flags should be specified in the ``flags`` section of the compiler
``ldflags``, and ``ldlibs``. For example: specification. The valid flags are ``cflags``, ``cxxflags``, ``fflags``,
``cppflags``, ``ldflags``, and ``ldlibs``. For example:
.. code-block:: yaml .. code-block:: yaml
compilers: compilers:
- compiler: - compiler:
modules = [] modules: []
operating_system: OS operating_system: centos6
paths: paths:
cc: /usr/local/bin/icc-15.0.024-beta cc: /usr/bin/gcc
cxx: /usr/local/bin/icpc-15.0.024-beta cxx: /usr/bin/g++
f77: /usr/local/bin/ifort-15.0.024-beta f77: /usr/bin/gfortran
fc: /usr/local/bin/ifort-15.0.024-beta fc: /usr/bin/gfortran
flags: flags:
cflags: -O3 -fPIC
cxxflags: -O3 -fPIC
cppflags: -O3 -fPIC cppflags: -O3 -fPIC
spec: intel@15.0.0: spec: gcc@4.7.2
These flags will be treated by spack as if they were entered from These flags will be treated by spack as if they were entered from
the command line each time this compiler is used. The compiler wrappers the command line each time this compiler is used. The compiler wrappers
...@@ -527,7 +536,7 @@ configuration in ``compilers.yaml`` illustrates this technique: ...@@ -527,7 +536,7 @@ configuration in ``compilers.yaml`` illustrates this technique:
compilers: compilers:
- compiler: - compiler:
modules = [gcc-4.9.3, intel-15.0.24] modules: [gcc-4.9.3, intel-15.0.24]
operating_system: centos7 operating_system: centos7
paths: paths:
cc: /opt/intel-15.0.24/bin/icc-15.0.24-beta cc: /opt/intel-15.0.24/bin/icc-15.0.24-beta
...@@ -568,7 +577,7 @@ flags to the ``icc`` command: ...@@ -568,7 +577,7 @@ flags to the ``icc`` command:
compilers: compilers:
- compiler: - compiler:
modules = [intel-15.0.24] modules: [intel-15.0.24]
operating_system: centos7 operating_system: centos7
paths: paths:
cc: /opt/intel-15.0.24/bin/icc-15.0.24-beta cc: /opt/intel-15.0.24/bin/icc-15.0.24-beta
......
...@@ -133,10 +133,13 @@ def compiler_info(args): ...@@ -133,10 +133,13 @@ def compiler_info(args):
else: else:
for c in compilers: for c in compilers:
print str(c.spec) + ":" print str(c.spec) + ":"
print "\tcc = %s" % c.cc print "\tpaths:"
print "\tcxx = %s" % c.cxx for cpath in ['cc', 'cxx', 'f77', 'fc']:
print "\tf77 = %s" % c.f77 print "\t\t%s = %s" % (cpath, getattr(c, cpath, None))
print "\tfc = %s" % c.fc if c.flags:
print "\tflags:"
for flag, flag_value in c.flags.iteritems():
print "\t\t%s = %s" % (flag, flag_value)
print "\tmodules = %s" % c.modules print "\tmodules = %s" % c.modules
print "\toperating system = %s" % c.operating_system print "\toperating system = %s" % c.operating_system
......
...@@ -65,6 +65,7 @@ def _to_dict(compiler): ...@@ -65,6 +65,7 @@ def _to_dict(compiler):
d['spec'] = str(compiler.spec) d['spec'] = str(compiler.spec)
d['paths'] = dict((attr, getattr(compiler, attr, None)) d['paths'] = dict((attr, getattr(compiler, attr, None))
for attr in _path_instance_vars) for attr in _path_instance_vars)
d['flags'] = dict((fname, fvals) for fname, fvals in compiler.flags)
d['operating_system'] = str(compiler.operating_system) d['operating_system'] = str(compiler.operating_system)
d['modules'] = compiler.modules if compiler.modules else [] d['modules'] = compiler.modules if compiler.modules else []
...@@ -212,7 +213,7 @@ def supported(compiler_spec): ...@@ -212,7 +213,7 @@ def supported(compiler_spec):
@_auto_compiler_spec @_auto_compiler_spec
def find(compiler_spec, scope=None): def find(compiler_spec, scope=None):
"""Return specs of available compilers that match the supplied """Return specs of available compilers that match the supplied
compiler spec. Return an list if nothing found.""" compiler spec. Return an empty list if nothing found."""
return [c for c in all_compilers(scope) if c.satisfies(compiler_spec)] return [c for c in all_compilers(scope) if c.satisfies(compiler_spec)]
...@@ -221,7 +222,7 @@ def compilers_for_spec(compiler_spec, scope=None, **kwargs): ...@@ -221,7 +222,7 @@ def compilers_for_spec(compiler_spec, scope=None, **kwargs):
"""This gets all compilers that satisfy the supplied CompilerSpec. """This gets all compilers that satisfy the supplied CompilerSpec.
Returns an empty list if none are found. Returns an empty list if none are found.
""" """
platform = kwargs.get("platform", None) platform = kwargs.get('platform', None)
config = all_compilers_config(scope) config = all_compilers_config(scope)
def get_compilers(cspec): def get_compilers(cspec):
...@@ -241,7 +242,7 @@ def get_compilers(cspec): ...@@ -241,7 +242,7 @@ def get_compilers(cspec):
compiler_paths = [] compiler_paths = []
for c in _path_instance_vars: for c in _path_instance_vars:
compiler_path = items['paths'][c] compiler_path = items['paths'][c]
if compiler_path != "None": if compiler_path != 'None':
compiler_paths.append(compiler_path) compiler_paths.append(compiler_path)
else: else:
compiler_paths.append(None) compiler_paths.append(None)
...@@ -250,21 +251,17 @@ def get_compilers(cspec): ...@@ -250,21 +251,17 @@ def get_compilers(cspec):
if mods == 'None': if mods == 'None':
mods = [] mods = []
os = None
if 'operating_system' in items: if 'operating_system' in items:
os = spack.architecture._operating_system_from_dict( os = spack.architecture._operating_system_from_dict(
items['operating_system'], platform) items['operating_system'], platform)
else:
os = None
alias = items['alias'] if 'alias' in items else None alias = items.get('alias', None)
flags = {} compiler_flags = items.get('flags', {})
for f in spack.spec.FlagMap.valid_compiler_flags():
if f in items:
flags[f] = items[f]
compilers.append( compilers.append(
cls(cspec, os, compiler_paths, mods, alias, **flags)) cls(cspec, os, compiler_paths, mods, alias, **compiler_flags))
return compilers return compilers
......
...@@ -52,7 +52,11 @@ ...@@ -52,7 +52,11 @@
'f77': {'anyOf': [{'type': 'string'}, 'f77': {'anyOf': [{'type': 'string'},
{'type': 'null'}]}, {'type': 'null'}]},
'fc': {'anyOf': [{'type': 'string'}, 'fc': {'anyOf': [{'type': 'string'},
{'type': 'null'}]}, {'type': 'null'}]}}},
'flags': {
'type': 'object',
'additionalProperties': False,
'properties': {
'cflags': {'anyOf': [{'type': 'string'}, 'cflags': {'anyOf': [{'type': 'string'},
{'type': 'null'}]}, {'type': 'null'}]},
'cxxflags': {'anyOf': [{'type': 'string'}, 'cxxflags': {'anyOf': [{'type': 'string'},
......
...@@ -51,7 +51,7 @@ ...@@ -51,7 +51,7 @@
'arg5', 'arg6'] 'arg5', 'arg6']
class CompilerTest(unittest.TestCase): class CompilerWrapperTest(unittest.TestCase):
def setUp(self): def setUp(self):
self.cc = Executable(join_path(spack.build_env_path, "cc")) self.cc = Executable(join_path(spack.build_env_path, "cc"))
......
...@@ -55,6 +55,21 @@ ...@@ -55,6 +55,21 @@
'spec': 'gcc@4.5.0', 'spec': 'gcc@4.5.0',
'operating_system': 'CNL10' 'operating_system': 'CNL10'
}}, }},
{'compiler': {
'paths': {
"cc": "/gcc422",
"cxx": "/g++422",
"f77": 'gfortran',
"fc": 'gfortran'
},
'flags': {
"cppflags": "-O0 -fpic",
"fflags": "-f77",
},
'modules': None,
'spec': 'gcc@4.2.2',
'operating_system': 'CNL10'
}},
{'compiler': { {'compiler': {
'paths': { 'paths': {
"cc": "<overwritten>", "cc": "<overwritten>",
...@@ -90,6 +105,21 @@ ...@@ -90,6 +105,21 @@
'spec': 'icc@11.1', 'spec': 'icc@11.1',
'operating_system': 'CNL10' 'operating_system': 'CNL10'
}}, }},
{'compiler': {
'paths': {
"cc": "/icc123",
"cxx": "/icp123",
"f77": 'ifort',
"fc": 'ifort'
},
'flags': {
"cppflags": "-O3",
"fflags": "-f77rtl",
},
'modules': None,
'spec': 'icc@12.3',
'operating_system': 'CNL10'
}},
{'compiler': { {'compiler': {
'paths': { 'paths': {
"cc": "<overwritten>", "cc": "<overwritten>",
...@@ -112,11 +142,13 @@ class ConfigTest(MockPackagesTest): ...@@ -112,11 +142,13 @@ class ConfigTest(MockPackagesTest):
def setUp(self): def setUp(self):
super(ConfigTest, self).setUp() super(ConfigTest, self).setUp()
self.tmp_dir = mkdtemp('.tmp', 'spack-config-test-') self.tmp_dir = mkdtemp('.tmp', 'spack-config-test-')
self.a_comp_specs = [ac['compiler']['spec'] for ac in a_comps]
self.b_comp_specs = [bc['compiler']['spec'] for bc in b_comps]
spack.config.config_scopes = OrderedDict() spack.config.config_scopes = OrderedDict()
spack.config.ConfigScope( for priority in ['low', 'high']:
'test_low_priority', os.path.join(self.tmp_dir, 'low')) spack.config.ConfigScope('test_{0}_priority'.format(priority),
spack.config.ConfigScope('test_high_priority', os.path.join(self.tmp_dir, priority))
os.path.join(self.tmp_dir, 'high'))
def tearDown(self): def tearDown(self):
super(ConfigTest, self).tearDown() super(ConfigTest, self).tearDown()
...@@ -126,19 +158,22 @@ def check_config(self, comps, *compiler_names): ...@@ -126,19 +158,22 @@ def check_config(self, comps, *compiler_names):
"""Check that named compilers in comps match Spack's config.""" """Check that named compilers in comps match Spack's config."""
config = spack.config.get_config('compilers') config = spack.config.get_config('compilers')
compiler_list = ['cc', 'cxx', 'f77', 'fc'] compiler_list = ['cc', 'cxx', 'f77', 'fc']
flag_list = ['cflags', 'cxxflags', 'fflags', 'cppflags',
'ldflags', 'ldlibs']
param_list = ['modules', 'paths', 'spec', 'operating_system'] param_list = ['modules', 'paths', 'spec', 'operating_system']
for compiler in config: for compiler in config:
conf = compiler['compiler'] conf = compiler['compiler']
if conf['spec'] in compiler_names: if conf['spec'] in compiler_names:
comp = None comp = next((c['compiler'] for c in comps if
for c in comps: c['compiler']['spec'] == conf['spec']), None)
if c['compiler']['spec'] == conf['spec']:
comp = c['compiler']
break
if not comp: if not comp:
self.fail('Bad config spec') self.fail('Bad config spec')
for p in param_list: for p in param_list:
self.assertEqual(conf[p], comp[p]) self.assertEqual(conf[p], comp[p])
for f in flag_list:
expected = comp.get('flags', {}).get(f, None)
actual = conf.get('flags', {}).get(f, None)
self.assertEqual(expected, actual)
for c in compiler_list: for c in compiler_list:
expected = comp['paths'][c] expected = comp['paths'][c]
actual = conf['paths'][c] actual = conf['paths'][c]
...@@ -156,8 +191,8 @@ def test_write_key_in_memory(self): ...@@ -156,8 +191,8 @@ def test_write_key_in_memory(self):
spack.config.update_config('compilers', b_comps, 'test_high_priority') spack.config.update_config('compilers', b_comps, 'test_high_priority')
# Make sure the config looks how we expect. # Make sure the config looks how we expect.
self.check_config(a_comps, 'gcc@4.7.3', 'gcc@4.5.0') self.check_config(a_comps, *self.a_comp_specs)
self.check_config(b_comps, 'icc@10.0', 'icc@11.1', 'clang@3.3') self.check_config(b_comps, *self.b_comp_specs)
def test_write_key_to_disk(self): def test_write_key_to_disk(self):
# Write b_comps "on top of" a_comps. # Write b_comps "on top of" a_comps.
...@@ -168,8 +203,8 @@ def test_write_key_to_disk(self): ...@@ -168,8 +203,8 @@ def test_write_key_to_disk(self):
spack.config.clear_config_caches() spack.config.clear_config_caches()
# Same check again, to ensure consistency. # Same check again, to ensure consistency.
self.check_config(a_comps, 'gcc@4.7.3', 'gcc@4.5.0') self.check_config(a_comps, *self.a_comp_specs)
self.check_config(b_comps, 'icc@10.0', 'icc@11.1', 'clang@3.3') self.check_config(b_comps, *self.b_comp_specs)
def test_write_to_same_priority_file(self): def test_write_to_same_priority_file(self):
# Write b_comps in the same file as a_comps. # Write b_comps in the same file as a_comps.
...@@ -180,5 +215,5 @@ def test_write_to_same_priority_file(self): ...@@ -180,5 +215,5 @@ def test_write_to_same_priority_file(self):
spack.config.clear_config_caches() spack.config.clear_config_caches()
# Same check again, to ensure consistency. # Same check again, to ensure consistency.
self.check_config(a_comps, 'gcc@4.7.3', 'gcc@4.5.0') self.check_config(a_comps, *self.a_comp_specs)
self.check_config(b_comps, 'icc@10.0', 'icc@11.1', 'clang@3.3') self.check_config(b_comps, *self.b_comp_specs)
...@@ -136,6 +136,31 @@ ...@@ -136,6 +136,31 @@
f77: None f77: None
fc: None fc: None
modules: 'None' modules: 'None'
- compiler:
spec: gcc@4.7.2
operating_system: redhat6
paths:
cc: /path/to/gcc472
cxx: /path/to/g++472
f77: /path/to/gfortran472
fc: /path/to/gfortran472
flags:
cflags: -O0
cxxflags: -O0
fflags: -O0
modules: 'None'
- compiler:
spec: clang@3.5
operating_system: redhat6
paths:
cc: /path/to/clang35
cxx: /path/to/clang++35
f77: None
fc: None
flags:
cflags: -O3
cxxflags: -O3
modules: 'None'
""".format(linux_os_name, linux_os_version) """.format(linux_os_name, linux_os_version)
mock_packages_config = """\ mock_packages_config = """\
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment