Source code for spack.build_systems.meson

# Copyright 2013-2022 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)


import inspect
import os
from typing import List  # novm

from llnl.util.filesystem import working_dir

from spack.directives import depends_on, variant
from spack.package import PackageBase, run_after


[docs]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 = [] # type: List[str] install_targets = ['install'] build_time_test_callbacks = ['check'] variant('buildtype', default='debugoptimized', description='Meson build type', values=('plain', 'debug', 'debugoptimized', 'release', 'minsize')) variant('default_library', default='shared', values=('shared', 'static'), multi=True, description='Build shared libs, static libs or both') variant('strip', default=False, description='Strip targets on install') 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' strip = 'true' if '+strip' in pkg.spec else 'false' if 'default_library=static,shared' in pkg.spec: default_library = 'both' elif 'default_library=static' in pkg.spec: default_library = 'static' else: default_library = 'shared' args = [ '--prefix={0}'.format(pkg.prefix), # If we do not specify libdir explicitly, Meson chooses something # like lib/x86_64-linux-gnu, which causes problems when trying to # find libraries and pkg-config files. # See https://github.com/mesonbuild/meson/issues/2197 '--libdir={0}'.format(pkg.prefix.lib), '-Dbuildtype={0}'.format(build_type), '-Dstrip={0}'.format(strip), '-Ddefault_library={0}'.format(default_library) ] return args
[docs] 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')
[docs] def meson_args(self): """Produces a list containing all the arguments that must be passed to meson, except: * ``--prefix`` * ``--libdir`` * ``--buildtype`` * ``--strip`` * ``--default_library`` which will be set automatically. :return: list of arguments for meson """ return []
[docs] 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)
[docs] 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)
[docs] 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)
[docs] 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)