Add better generator support to CMakePackage (#4988)
* Add better generator support to CMakePackage * List valid CMake generators on error
This commit is contained in:
		| @@ -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 = [ | ||||||
|                 '-DCMAKE_BUILD_TYPE:STRING={0}'.format(build_type), |             '-G', generator, | ||||||
|                 '-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON'] |             '-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]: |         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): | ||||||
|             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): |     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): | ||||||
|             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) |     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): | ||||||
|             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 |     # 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') |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Adam J. Stewart
					Adam J. Stewart