Add better generator support to CMakePackage (#4988)
* Add better generator support to CMakePackage * List valid CMake generators on error
This commit is contained in:
parent
db657d938d
commit
11b3ce27b7
@ -30,12 +30,15 @@
|
|||||||
import spack.build_environment
|
import spack.build_environment
|
||||||
from llnl.util.filesystem import working_dir, join_path
|
from llnl.util.filesystem import working_dir, join_path
|
||||||
from spack.directives import depends_on, variant
|
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):
|
class CMakePackage(PackageBase):
|
||||||
"""Specialized class for packages built using CMake
|
"""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:
|
This class provides three phases that can be overridden:
|
||||||
|
|
||||||
1. :py:meth:`~.CMakePackage.cmake`
|
1. :py:meth:`~.CMakePackage.cmake`
|
||||||
@ -69,6 +72,16 @@ class CMakePackage(PackageBase):
|
|||||||
|
|
||||||
build_time_test_callbacks = ['check']
|
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
|
# https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html
|
||||||
variant('build_type', default='RelWithDebInfo',
|
variant('build_type', default='RelWithDebInfo',
|
||||||
description='The build type to build',
|
description='The build type to build',
|
||||||
@ -100,14 +113,31 @@ def std_cmake_args(self):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def _std_args(pkg):
|
def _std_args(pkg):
|
||||||
"""Computes the standard cmake arguments for a generic package"""
|
"""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:
|
try:
|
||||||
build_type = pkg.spec.variants['build_type'].value
|
build_type = pkg.spec.variants['build_type'].value
|
||||||
except KeyError:
|
except KeyError:
|
||||||
build_type = 'RelWithDebInfo'
|
build_type = 'RelWithDebInfo'
|
||||||
|
|
||||||
args = ['-DCMAKE_INSTALL_PREFIX:PATH={0}'.format(pkg.prefix),
|
args = [
|
||||||
|
'-G', generator,
|
||||||
|
'-DCMAKE_INSTALL_PREFIX:PATH={0}'.format(pkg.prefix),
|
||||||
'-DCMAKE_BUILD_TYPE:STRING={0}'.format(build_type),
|
'-DCMAKE_BUILD_TYPE:STRING={0}'.format(build_type),
|
||||||
'-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON']
|
'-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON'
|
||||||
|
]
|
||||||
|
|
||||||
if platform.mac_ver()[0]:
|
if platform.mac_ver()[0]:
|
||||||
args.append('-DCMAKE_FIND_FRAMEWORK:STRING=LAST')
|
args.append('-DCMAKE_FIND_FRAMEWORK:STRING=LAST')
|
||||||
|
|
||||||
@ -158,12 +188,18 @@ def cmake(self, spec, prefix):
|
|||||||
def build(self, spec, prefix):
|
def build(self, spec, prefix):
|
||||||
"""Make the build targets"""
|
"""Make the build targets"""
|
||||||
with working_dir(self.build_directory):
|
with working_dir(self.build_directory):
|
||||||
|
if self.generator == 'Unix Makefiles':
|
||||||
inspect.getmodule(self).make(*self.build_targets)
|
inspect.getmodule(self).make(*self.build_targets)
|
||||||
|
elif self.generator == 'Ninja':
|
||||||
|
inspect.getmodule(self).ninja(*self.build_targets)
|
||||||
|
|
||||||
def install(self, spec, prefix):
|
def install(self, spec, prefix):
|
||||||
"""Make the install targets"""
|
"""Make the install targets"""
|
||||||
with working_dir(self.build_directory):
|
with working_dir(self.build_directory):
|
||||||
|
if self.generator == 'Unix Makefiles':
|
||||||
inspect.getmodule(self).make(*self.install_targets)
|
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)
|
run_after('build')(PackageBase._run_default_build_time_test_callbacks)
|
||||||
|
|
||||||
@ -172,7 +208,10 @@ def check(self):
|
|||||||
and runs it if found.
|
and runs it if found.
|
||||||
"""
|
"""
|
||||||
with working_dir(self.build_directory):
|
with working_dir(self.build_directory):
|
||||||
|
if self.generator == 'Unix Makefiles':
|
||||||
self._if_make_target_execute('test')
|
self._if_make_target_execute('test')
|
||||||
|
elif self.generator == 'Ninja':
|
||||||
|
self._if_ninja_target_execute('test')
|
||||||
|
|
||||||
# Check that self.prefix is there after installation
|
# Check that self.prefix is there after installation
|
||||||
run_after('install')(PackageBase.sanity_check_prefix)
|
run_after('install')(PackageBase.sanity_check_prefix)
|
||||||
|
@ -1091,12 +1091,30 @@ def _if_make_target_execute(self, target):
|
|||||||
matches = [line for line in f.readlines() if regex.match(line)]
|
matches = [line for line in f.readlines() if regex.match(line)]
|
||||||
|
|
||||||
if not matches:
|
if not matches:
|
||||||
tty.msg('Target \'' + target + ':\' not found in Makefile')
|
tty.msg("Target '" + target + ":' not found in Makefile")
|
||||||
return
|
return
|
||||||
|
|
||||||
# Execute target
|
# Execute target
|
||||||
inspect.getmodule(self).make(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):
|
def _get_needed_resources(self):
|
||||||
resources = []
|
resources = []
|
||||||
# Select the resources that are needed for this build
|
# Select the resources that are needed for this build
|
||||||
|
@ -36,22 +36,14 @@ class Archer(CMakePackage):
|
|||||||
|
|
||||||
depends_on('cmake@3.4.3:', type='build')
|
depends_on('cmake@3.4.3:', type='build')
|
||||||
depends_on('llvm')
|
depends_on('llvm')
|
||||||
depends_on('ninja', type='build')
|
depends_on('ninja@1.5:', type='build')
|
||||||
depends_on('llvm-openmp-ompt')
|
depends_on('llvm-openmp-ompt')
|
||||||
|
|
||||||
|
generator = 'Ninja'
|
||||||
|
|
||||||
def cmake_args(self):
|
def cmake_args(self):
|
||||||
return [
|
return [
|
||||||
'-G', 'Ninja',
|
|
||||||
'-DCMAKE_C_COMPILER=clang',
|
'-DCMAKE_C_COMPILER=clang',
|
||||||
'-DCMAKE_CXX_COMPILER=clang++',
|
'-DCMAKE_CXX_COMPILER=clang++',
|
||||||
'-DOMP_PREFIX:PATH=%s' % self.spec['llvm-openmp-ompt'].prefix,
|
'-DOMP_PREFIX:PATH=%s' % self.spec['llvm-openmp-ompt'].prefix,
|
||||||
]
|
]
|
||||||
|
|
||||||
# TODO: Add better ninja support to CMakePackage
|
|
||||||
def build(self, spec, prefix):
|
|
||||||
with working_dir(self.build_directory):
|
|
||||||
ninja()
|
|
||||||
|
|
||||||
def install(self, spec, prefix):
|
|
||||||
with working_dir(self.build_directory):
|
|
||||||
ninja('install')
|
|
||||||
|
@ -44,24 +44,15 @@ class LlvmOpenmpOmpt(CMakePackage):
|
|||||||
|
|
||||||
depends_on('cmake@2.8:', type='build')
|
depends_on('cmake@2.8:', type='build')
|
||||||
depends_on('llvm')
|
depends_on('llvm')
|
||||||
depends_on('ninja', type='build')
|
depends_on('ninja@1.5:', type='build')
|
||||||
|
|
||||||
|
generator = 'Ninja'
|
||||||
|
|
||||||
def cmake_args(self):
|
def cmake_args(self):
|
||||||
return [
|
return [
|
||||||
'-G', 'Ninja',
|
|
||||||
'-DCMAKE_C_COMPILER=clang',
|
'-DCMAKE_C_COMPILER=clang',
|
||||||
'-DCMAKE_CXX_COMPILER=clang++',
|
'-DCMAKE_CXX_COMPILER=clang++',
|
||||||
'-DCMAKE_BUILD_TYPE=Release',
|
|
||||||
'-DLIBOMP_OMPT_SUPPORT=on',
|
'-DLIBOMP_OMPT_SUPPORT=on',
|
||||||
'-DLIBOMP_OMPT_BLAME=on',
|
'-DLIBOMP_OMPT_BLAME=on',
|
||||||
'-DLIBOMP_OMPT_TRACE=on'
|
'-DLIBOMP_OMPT_TRACE=on'
|
||||||
]
|
]
|
||||||
|
|
||||||
# TODO: Add better ninja support to CMakePackage
|
|
||||||
def build(self, spec, prefix):
|
|
||||||
with working_dir(self.build_directory):
|
|
||||||
ninja()
|
|
||||||
|
|
||||||
def install(self, spec, prefix):
|
|
||||||
with working_dir(self.build_directory):
|
|
||||||
ninja('install')
|
|
||||||
|
Loading…
Reference in New Issue
Block a user