Allow packages to control handling of compiler flags (#4421)

* Initial work on flag trapping using functions called <flag>_handler and default_flag_handler

* Update packages so they do not obliterate flags

* Added append to EnvironmentModifications class

* changed EnvironmentModifications to have append_flags method

* changed flag_val to be a tuple

* Increased test coverage

* added documentation of flag handling
This commit is contained in:
becker33
2017-07-19 20:12:00 -07:00
committed by GitHub
parent acca75b368
commit f962aba6ce
16 changed files with 203 additions and 12 deletions

View File

@@ -2390,6 +2390,94 @@ build system.
Compiler flags
^^^^^^^^^^^^^^
Compiler flags set by the user through the Spec object can be passed to
the build in one of two ways. For packages inheriting from the
``CmakePackage`` or ``AutotoolsPackage`` classes, the build environment
passes those flags to the relevant environment variables (``CFLAGS``,
``CXXFLAGS``, etc) that are respected by the build system. For all other
packages, the default behavior is to inject the flags directly into the
compiler commands using Spack's compiler wrappers.
Individual packages can override the default behavior for the flag
handling. Packages can define a ``default_flag_handler`` method that
applies to all sets of flags handled by Spack, or may define
individual methods ``cflags_handler``, ``cxxflags_handler``,
etc. Spack will apply the individual method for a flag set if it
exists, otherwise the ``default_flag_handler`` method if it exists,
and fall back on the default for that package class if neither exists.
These methods are defined on the package class, and take two
parameters in addition to the packages itself. The ``env`` parameter
is an ``EnvironmentModifications`` object that can be used to change
the build environment. The ``flag_val`` parameter is a tuple. Its
first entry is the name of the flag (``cflags``, ``cxxflags``, etc.)
and its second entry is a list of the values for that flag.
There are three primary idioms that can be combined to create whatever
behavior the package requires.
1. The default behavior for packages inheriting from
``AutotoolsPackage`` or ``CmakePackage``.
.. code-block:: python
def default_flag_handler(self, env, flag_val):
env.append_flags(flag_val[0].upper(), ' '.join(flag_val[1]))
return []
2. The default behavior for other packages
.. code-block:: python
def default_flag_handler(self, env, flag_val):
return flag_val[1]
3. Packages may have additional flags to add to the build. These flags
can be added to either idiom above. For example:
.. code-block:: python
def default_flag_handler(self, env, flag_val):
flags = flag_val[1]
flags.append('-flag')
return flags
or
.. code-block:: python
def default_flag_handler(self, env, flag_val):
env.append_flags(flag_val[0].upper(), ' '.join(flag_val[1]))
env.append_flags(flag_val[0].upper(), '-flag')
return []
Packages may also opt for methods that include aspects of any of the
idioms above. E.g.
.. code-block:: python
def default_flag_handler(self, env, flag_val):
flags = []
if len(flag_val[1]) > 3:
env.append_flags(flag_val[0].upper(), ' '.join(flag_val[1][3:]))
flags = flag_val[1][:3]
else:
flags = flag_val[1]
flags.append('-flag')
return flags
Because these methods can pass values through environment variables,
it is important not to override these variables unnecessarily in other
package methods. In the ``setup_environment`` and
``setup_dependent_environment`` methods, use the ``append_flags``
method of the ``EnvironmentModifications`` class to append values to a
list of flags whenever there is no good reason to override the
existing value. In the ``install`` method and other methods that can
operate on the build environment directly through the ``env``
variable, test for environment variable existance before overriding
values to add compiler flags.
In rare circumstances such as compiling and running small unit tests, a
package developer may need to know what are the appropriate compiler
flags to enable features like ``OpenMP``, ``c++11``, ``c++14`` and