From b1182741d43c20c10d2c58d07941322df67c646b Mon Sep 17 00:00:00 2001 From: Tom Merrick Date: Fri, 10 Aug 2018 12:52:09 -0500 Subject: 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 --- lib/spack/docs/build_systems.rst | 1 + lib/spack/docs/build_systems/mesonpackage.rst | 85 ++++++++++++ lib/spack/spack/build_environment.py | 19 +++ lib/spack/spack/build_systems/meson.py | 184 ++++++++++++++++++++++++++ lib/spack/spack/cmd/build.py | 2 + lib/spack/spack/cmd/configure.py | 2 + lib/spack/spack/cmd/create.py | 14 ++ lib/spack/spack/pkgkit.py | 1 + lib/spack/spack/test/build_system_guess.py | 1 + 9 files changed, 309 insertions(+) create mode 100644 lib/spack/docs/build_systems/mesonpackage.rst create mode 100644 lib/spack/spack/build_systems/meson.py diff --git a/lib/spack/docs/build_systems.rst b/lib/spack/docs/build_systems.rst index 562e5c9fd0..b84c9fe450 100644 --- a/lib/spack/docs/build_systems.rst +++ b/lib/spack/docs/build_systems.rst @@ -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:: diff --git a/lib/spack/docs/build_systems/mesonpackage.rst b/lib/spack/docs/build_systems/mesonpackage.rst new file mode 100644 index 0000000000..a3379d7772 --- /dev/null +++ b/lib/spack/docs/build_systems/mesonpackage.rst @@ -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 + + +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 diff --git a/lib/spack/spack/build_environment.py b/lib/spack/spack/build_environment.py index 01a5a9ed17..7a47da13f7 100644 --- a/lib/spack/spack/build_environment.py +++ b/lib/spack/spack/build_environment.py @@ -66,6 +66,7 @@ from llnl.util.tty.color import cescape, colorize 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 diff --git a/lib/spack/spack/build_systems/meson.py b/lib/spack/spack/build_systems/meson.py new file mode 100644 index 0000000000..442c836391 --- /dev/null +++ b/lib/spack/spack/build_systems/meson.py @@ -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) diff --git a/lib/spack/spack/cmd/build.py b/lib/spack/spack/cmd/build.py index 7aa02a8747..d544d1c43e 100644 --- a/lib/spack/spack/cmd/build.py +++ b/lib/spack/spack/cmd/build.py @@ -31,6 +31,7 @@ from spack.build_systems.scons import SConsPackage 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 @@ build_system_to_phase = { WafPackage: 'build', PythonPackage: 'build', PerlPackage: 'build', + MesonPackage: 'build', } diff --git a/lib/spack/spack/cmd/configure.py b/lib/spack/spack/cmd/configure.py index 04ce8641e4..8135bfb994 100644 --- a/lib/spack/spack/cmd/configure.py +++ b/lib/spack/spack/cmd/configure.py @@ -34,6 +34,7 @@ from spack.build_systems.qmake import QMakePackage 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 @@ build_system_to_phase = { WafPackage: 'configure', PerlPackage: 'configure', IntelPackage: 'configure', + MesonPackage: 'meson', } diff --git a/lib/spack/spack/cmd/create.py b/lib/spack/spack/cmd/create.py index eae6e6da3a..a9d0a8e999 100644 --- a/lib/spack/spack/cmd/create.py +++ b/lib/spack/spack/cmd/create.py @@ -195,6 +195,18 @@ class CMakePackageTemplate(PackageTemplate): 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 @@ templates = { 'octave': OctavePackageTemplate, 'makefile': MakefilePackageTemplate, 'intel': IntelPackageTemplate, + 'meson': MesonPackageTemplate, 'generic': PackageTemplate, } @@ -459,6 +472,7 @@ class BuildSystemGuesser: (r'/.*\.pro$', 'qmake'), (r'/(GNU)?[Mm]akefile$', 'makefile'), (r'/DESCRIPTION$', 'octave'), + (r'/meson\.build$', 'meson'), ] # Peek inside the compressed file. diff --git a/lib/spack/spack/pkgkit.py b/lib/spack/spack/pkgkit.py index 563fe0f64a..bb688d1acd 100644 --- a/lib/spack/spack/pkgkit.py +++ b/lib/spack/spack/pkgkit.py @@ -44,6 +44,7 @@ from spack.build_systems.python import PythonPackage 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 diff --git a/lib/spack/spack/test/build_system_guess.py b/lib/spack/spack/test/build_system_guess.py index 88c788f587..53bfa4ffb6 100644 --- a/lib/spack/spack/test/build_system_guess.py +++ b/lib/spack/spack/test/build_system_guess.py @@ -45,6 +45,7 @@ import spack.stage ('GNUmakefile', 'makefile'), ('makefile', 'makefile'), ('Makefile', 'makefile'), + ('meson.build', 'meson'), ('foobar', 'generic') ] ) -- cgit v1.2.3-60-g2f50