Branch with the meson build-system (#8467)

* Branch with the meson build-system

* Fix build_environment for dual loads and add create code

* Add documentation

* Fixed option list

* Update build_system_guess for meson

* Fixed documentation errors

* Added meson to build and configure and updated documentation

* fix typos
This commit is contained in:
Tom Merrick 2018-08-10 12:52:09 -05:00 committed by Adam J. Stewart
parent 2a94d59433
commit b1182741d4
9 changed files with 309 additions and 0 deletions

View File

@ -33,6 +33,7 @@ on these ideas for each distinct build system that Spack supports:
build_systems/autotoolspackage
build_systems/cmakepackage
build_systems/mesonpackage
build_systems/qmakepackage
.. toctree::

View File

@ -0,0 +1,85 @@
.. _mesonpackage:
------------
MesonPackage
------------
Much like Autotools and CMake, Meson is a build system. But it is
meant to be both fast and as user friendly as possible. GNOME's goal
is to port modules to use the Meson build system.
^^^^^^
Phases
^^^^^^
The ``MesonPackage`` base class comes with the following phases:
#. ``meson`` - generate ninja files
#. ``build`` - build the project
#. ``install`` - install the project
By default, these phases run:
.. code-block:: console
$ mkdir spack-build
$ cd spack-build
$ meson .. --prefix=/path/to/installation/prefix
$ ninja
$ ninja test # optional
$ ninja install
Any of these phases can be overridden in your package as necessary.
There is also a ``check`` method that looks for a ``test`` target
in the build file. If a ``test`` target exists and the user runs:
.. code-block:: console
$ spack install --test=root <meson-package>
Spack will run ``ninja test`` after the build phase.
^^^^^^^^^^^^^^^
Important files
^^^^^^^^^^^^^^^
Packages that use the Meson build system can be identified by the
presence of a ``meson.build`` file. This file declares things
like build instructions and dependencies.
^^^^^^^^^^^^^^^^^^^^^^^^^
Build system dependencies
^^^^^^^^^^^^^^^^^^^^^^^^^
At the bare minimum, packages that use the Meson build system need
``meson`` and ```ninja``` dependencies. Since this is always the case,
the ``MesonPackage`` base class already contains:
.. code-block:: python
depends_on('meson', type='build')
depends_on('ninja', type='build')
^^^^^^^^^^^^^^^^^^^^^^^^^^
Passing arguments to meson
^^^^^^^^^^^^^^^^^^^^^^^^^^
If you need to pass any arguments to the ``meson`` call, you can
override the ``meson_args`` method like so:
.. code-block:: python
def meson_args(self):
return ['--default-library=both']
This method can be used to pass flags as well as variables.
^^^^^^^^^^^^^^^^^^^^^^
External documentation
^^^^^^^^^^^^^^^^^^^^^^
For more information on the Meson build system, see:
https://mesonbuild.com/index.html

View File

@ -66,6 +66,7 @@
from llnl.util.filesystem import mkdirp, install, install_tree
import spack.build_systems.cmake
import spack.build_systems.meson
import spack.config
import spack.main
import spack.paths
@ -384,11 +385,13 @@ def set_module_variables_for_package(pkg, module):
# Don't use which for this; we want to find it in the current dir.
m.configure = Executable('./configure')
m.meson = Executable('meson')
m.cmake = Executable('cmake')
m.ctest = Executable('ctest')
# Standard CMake arguments
m.std_cmake_args = spack.build_systems.cmake.CMakePackage._std_args(pkg)
m.std_meson_args = spack.build_systems.meson.MesonPackage._std_args(pkg)
# Put spack compiler paths in module scope.
link_dir = spack.paths.build_env_path
@ -557,6 +560,22 @@ def get_std_cmake_args(pkg):
return spack.build_systems.cmake.CMakePackage._std_args(pkg)
def get_std_meson_args(pkg):
"""List of standard arguments used if a package is a MesonPackage.
Returns:
list of str: standard arguments that would be used if this
package were a MesonPackage instance.
Args:
pkg (PackageBase): package under consideration
Returns:
list of str: arguments for meson
"""
return spack.build_systems.meson.MesonPackage._std_args(pkg)
def parent_class_modules(cls):
"""
Get list of superclass modules that descend from spack.package.PackageBase

View File

@ -0,0 +1,184 @@
##############################################################################
# Copyright (c) 2013-2018, Lawrence Livermore National Security, LLC.
# Produced at the Lawrence Livermore National Laboratory.
#
# This file is part of Spack.
# Created by Todd Gamblin, tgamblin@llnl.gov, All rights reserved.
# LLNL-CODE-647188
#
# For details, see https://github.com/spack/spack
# Please also see the NOTICE and LICENSE files for our notice and the LGPL.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License (as
# published by the Free Software Foundation) version 2.1, February 1999.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and
# conditions of the GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##############################################################################
import inspect
import os
from llnl.util.filesystem import working_dir
from spack.directives import depends_on, variant
from spack.package import PackageBase, run_after
class MesonPackage(PackageBase):
"""Specialized class for packages built using Meson
For more information on the Meson build system, see:
https://mesonbuild.com/
This class provides three phases that can be overridden:
1. :py:meth:`~.MesonPackage.meson`
2. :py:meth:`~.MesonPackage.build`
3. :py:meth:`~.MesonPackage.install`
They all have sensible defaults and for many packages the only thing
necessary will be to override :py:meth:`~.MesonPackage.meson_args`.
For a finer tuning you may also override:
+-----------------------------------------------+--------------------+
| **Method** | **Purpose** |
+===============================================+====================+
| :py:meth:`~.MesonPackage.root_mesonlists_dir` | Location of the |
| | root MesonLists.txt|
+-----------------------------------------------+--------------------+
| :py:meth:`~.MesonPackage.build_directory` | Directory where to |
| | build the package |
+-----------------------------------------------+--------------------+
"""
#: Phases of a Meson package
phases = ['meson', 'build', 'install']
#: This attribute is used in UI queries that need to know the build
#: system base class
build_system_class = 'MesonPackage'
build_targets = []
install_targets = ['install']
build_time_test_callbacks = ['check']
variant('buildtype', default='release',
description='Meson build type',
values=('plain', 'debug', 'debugoptimized', 'release', 'minsize'))
depends_on('meson', type='build')
depends_on('ninja', type='build')
@property
def archive_files(self):
"""Files to archive for packages based on Meson"""
return [os.path.join(self.build_directory, 'meson-logs/meson-log.txt')]
@property
def root_mesonlists_dir(self):
"""The relative path to the directory containing meson.build
This path is relative to the root of the extracted tarball,
not to the ``build_directory``. Defaults to the current directory.
:return: directory containing meson.build
"""
return self.stage.source_path
@property
def std_meson_args(self):
"""Standard meson arguments provided as a property for
convenience of package writers
:return: standard meson arguments
"""
# standard Meson arguments
std_meson_args = MesonPackage._std_args(self)
std_meson_args += getattr(self, 'meson_flag_args', [])
return std_meson_args
@staticmethod
def _std_args(pkg):
"""Computes the standard meson arguments for a generic package"""
try:
build_type = pkg.spec.variants['buildtype'].value
except KeyError:
build_type = 'release'
args = [
'--prefix={0}'.format(pkg.prefix),
'--buildtype={0}'.format(build_type),
'--strip',
]
return args
def flags_to_build_system_args(self, flags):
"""Produces a list of all command line arguments to pass the specified
compiler flags to meson."""
# Has to be dynamic attribute due to caching
setattr(self, 'meson_flag_args', [])
@property
def build_directory(self):
"""Returns the directory to use when building the package
:return: directory where to build the package
"""
return os.path.join(self.stage.source_path, 'spack-build')
def meson_args(self):
"""Produces a list containing all the arguments that must be passed to
meson, except:
* ``--prefix``
* ``--buildtype``
* ``--strip``
which will be set automatically.
:return: list of arguments for meson
"""
return []
def meson(self, spec, prefix):
"""Runs ``meson`` in the build directory"""
options = [os.path.abspath(self.root_mesonlists_dir)]
options += self.std_meson_args
options += self.meson_args()
with working_dir(self.build_directory, create=True):
inspect.getmodule(self).meson(*options)
def build(self, spec, prefix):
"""Make the build targets"""
options = ['-v']
options += self.build_targets
with working_dir(self.build_directory):
inspect.getmodule(self).ninja(*options)
def install(self, spec, prefix):
"""Make the install targets"""
with working_dir(self.build_directory):
inspect.getmodule(self).ninja(*self.install_targets)
run_after('build')(PackageBase._run_default_build_time_test_callbacks)
def check(self):
"""Searches the Meson-generated file for the target ``test``
and runs it if found.
"""
with working_dir(self.build_directory):
self._if_ninja_target_execute('test')
self._if_ninja_target_execute('check')
# Check that self.prefix is there after installation
run_after('install')(PackageBase.sanity_check_prefix)

View File

@ -31,6 +31,7 @@
from spack.build_systems.waf import WafPackage
from spack.build_systems.python import PythonPackage
from spack.build_systems.perl import PerlPackage
from spack.build_systems.meson import MesonPackage
description = 'stops at build stage when installing a package, if possible'
section = "build"
@ -45,6 +46,7 @@
WafPackage: 'build',
PythonPackage: 'build',
PerlPackage: 'build',
MesonPackage: 'build',
}

View File

@ -34,6 +34,7 @@
from spack.build_systems.waf import WafPackage
from spack.build_systems.perl import PerlPackage
from spack.build_systems.intel import IntelPackage
from spack.build_systems.meson import MesonPackage
description = 'stage and configure a package but do not install'
section = "build"
@ -47,6 +48,7 @@
WafPackage: 'configure',
PerlPackage: 'configure',
IntelPackage: 'configure',
MesonPackage: 'meson',
}

View File

@ -195,6 +195,18 @@ def cmake_args(self):
return args"""
class MesonPackageTemplate(PackageTemplate):
"""Provides appropriate overrides for meson-based packages"""
base_class_name = 'MesonPackage'
body = """\
def meson_args(self):
# FIXME: If not needed delete this function
args = []
return args"""
class QMakePackageTemplate(PackageTemplate):
"""Provides appropriate overrides for QMake-based packages"""
@ -389,6 +401,7 @@ class IntelPackageTemplate(PackageTemplate):
'octave': OctavePackageTemplate,
'makefile': MakefilePackageTemplate,
'intel': IntelPackageTemplate,
'meson': MesonPackageTemplate,
'generic': PackageTemplate,
}
@ -459,6 +472,7 @@ def __call__(self, stage, url):
(r'/.*\.pro$', 'qmake'),
(r'/(GNU)?[Mm]akefile$', 'makefile'),
(r'/DESCRIPTION$', 'octave'),
(r'/meson\.build$', 'meson'),
]
# Peek inside the compressed file.

View File

@ -44,6 +44,7 @@
from spack.build_systems.r import RPackage
from spack.build_systems.perl import PerlPackage
from spack.build_systems.intel import IntelPackage
from spack.build_systems.meson import MesonPackage
from spack.mixins import filter_compiler_wrappers

View File

@ -45,6 +45,7 @@
('GNUmakefile', 'makefile'),
('makefile', 'makefile'),
('Makefile', 'makefile'),
('meson.build', 'meson'),
('foobar', 'generic')
]
)