From 11b3ce27b7dbd76014955f36f8d6097498bf58be Mon Sep 17 00:00:00 2001 From: "Adam J. Stewart" Date: Wed, 16 Aug 2017 12:25:37 -0500 Subject: Add better generator support to CMakePackage (#4988) * Add better generator support to CMakePackage * List valid CMake generators on error --- lib/spack/spack/build_systems/cmake.py | 53 +++++++++++++++++++++++++++++----- lib/spack/spack/package.py | 20 ++++++++++++- 2 files changed, 65 insertions(+), 8 deletions(-) (limited to 'lib') diff --git a/lib/spack/spack/build_systems/cmake.py b/lib/spack/spack/build_systems/cmake.py index db3240e8a5..f643320b10 100644 --- a/lib/spack/spack/build_systems/cmake.py +++ b/lib/spack/spack/build_systems/cmake.py @@ -30,12 +30,15 @@ import platform import spack.build_environment from llnl.util.filesystem import working_dir, join_path from spack.directives import depends_on, variant -from spack.package import PackageBase, run_after +from spack.package import PackageBase, InstallError, run_after class CMakePackage(PackageBase): """Specialized class for packages built using CMake + For more information on the CMake build system, see: + https://cmake.org/cmake/help/latest/ + This class provides three phases that can be overridden: 1. :py:meth:`~.CMakePackage.cmake` @@ -69,6 +72,16 @@ class CMakePackage(PackageBase): build_time_test_callbacks = ['check'] + #: The build system generator to use. + #: + #: See ``cmake --help`` for a list of valid generators. + #: Currently, "Unix Makefiles" and "Ninja" are the only generators + #: that Spack supports. Defaults to "Unix Makefiles". + #: + #: See https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html + #: for more information. + generator = 'Unix Makefiles' + # https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html variant('build_type', default='RelWithDebInfo', description='The build type to build', @@ -100,14 +113,31 @@ class CMakePackage(PackageBase): @staticmethod def _std_args(pkg): """Computes the standard cmake arguments for a generic package""" + try: + generator = pkg.generator + except AttributeError: + generator = 'Unix Makefiles' + + # Make sure a valid generator was chosen + valid_generators = ['Unix Makefiles', 'Ninja'] + if generator not in valid_generators: + msg = "Invalid CMake generator: '{0}'\n".format(generator) + msg += "CMakePackage currently supports the following " + msg += "generators: '{0}'".format("', '".join(valid_generators)) + raise InstallError(msg) + try: build_type = pkg.spec.variants['build_type'].value except KeyError: build_type = 'RelWithDebInfo' - args = ['-DCMAKE_INSTALL_PREFIX:PATH={0}'.format(pkg.prefix), - '-DCMAKE_BUILD_TYPE:STRING={0}'.format(build_type), - '-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON'] + args = [ + '-G', generator, + '-DCMAKE_INSTALL_PREFIX:PATH={0}'.format(pkg.prefix), + '-DCMAKE_BUILD_TYPE:STRING={0}'.format(build_type), + '-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON' + ] + if platform.mac_ver()[0]: args.append('-DCMAKE_FIND_FRAMEWORK:STRING=LAST') @@ -158,12 +188,18 @@ class CMakePackage(PackageBase): def build(self, spec, prefix): """Make the build targets""" with working_dir(self.build_directory): - inspect.getmodule(self).make(*self.build_targets) + if self.generator == 'Unix Makefiles': + inspect.getmodule(self).make(*self.build_targets) + elif self.generator == 'Ninja': + inspect.getmodule(self).ninja(*self.build_targets) def install(self, spec, prefix): """Make the install targets""" with working_dir(self.build_directory): - inspect.getmodule(self).make(*self.install_targets) + if self.generator == 'Unix Makefiles': + inspect.getmodule(self).make(*self.install_targets) + elif self.generator == 'Ninja': + inspect.getmodule(self).ninja(*self.install_targets) run_after('build')(PackageBase._run_default_build_time_test_callbacks) @@ -172,7 +208,10 @@ class CMakePackage(PackageBase): and runs it if found. """ with working_dir(self.build_directory): - self._if_make_target_execute('test') + if self.generator == 'Unix Makefiles': + self._if_make_target_execute('test') + elif self.generator == 'Ninja': + self._if_ninja_target_execute('test') # Check that self.prefix is there after installation run_after('install')(PackageBase.sanity_check_prefix) diff --git a/lib/spack/spack/package.py b/lib/spack/spack/package.py index 8c849573a7..cbf7d92ea6 100644 --- a/lib/spack/spack/package.py +++ b/lib/spack/spack/package.py @@ -1091,12 +1091,30 @@ class PackageBase(with_metaclass(PackageMeta, object)): matches = [line for line in f.readlines() if regex.match(line)] if not matches: - tty.msg('Target \'' + target + ':\' not found in Makefile') + tty.msg("Target '" + target + ":' not found in Makefile") return # Execute target inspect.getmodule(self).make(target) + def _if_ninja_target_execute(self, target): + # Check if we have a ninja build script + if not os.path.exists('build.ninja'): + tty.msg('No ninja build script found in the build directory') + return + + # Check if 'target' is in the ninja build script + regex = re.compile('^build ' + target + ':') + with open('build.ninja', 'r') as f: + matches = [line for line in f.readlines() if regex.match(line)] + + if not matches: + tty.msg("Target 'build " + target + ":' not found in build.ninja") + return + + # Execute target + inspect.getmodule(self).ninja(target) + def _get_needed_resources(self): resources = [] # Select the resources that are needed for this build -- cgit v1.2.3-60-g2f50