From e0f19cf5204784c374f0a04926d2b3aa728480ed Mon Sep 17 00:00:00 2001 From: Daniel Mensinger Date: Wed, 20 Feb 2019 14:45:29 +0100 Subject: [PATCH 1/9] LLVM dependency refactoring --- mesonbuild/dependencies/dev.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/mesonbuild/dependencies/dev.py b/mesonbuild/dependencies/dev.py index 5ee85bf9c..2a8960693 100644 --- a/mesonbuild/dependencies/dev.py +++ b/mesonbuild/dependencies/dev.py @@ -192,7 +192,7 @@ class GMockDependency(ExternalDependency): return [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM] -class LLVMDependency(ConfigToolDependency): +class LLVMDependencyConfigTool(ConfigToolDependency): """ LLVM uses a special tool, llvm-config, which has arguments for getting c args, cxx args, and ldargs as well as version. @@ -399,6 +399,23 @@ class LLVMDependency(ConfigToolDependency): return 'modules: ' + ', '.join(self.module_details) return '' +class LLVMDependency(ExternalDependency): + def __init__(self, env, kwargs): + super().__init__('LLVM', env, 'cpp', kwargs) + + @classmethod + def _factory(cls, env, kwargs): + methods = cls._process_method_kw(kwargs) + candidates = [] + + if DependencyMethods.CONFIG_TOOL in methods: + candidates.append(functools.partial(LLVMDependencyConfigTool, env, kwargs)) + + return candidates + + @staticmethod + def get_methods(): + return [DependencyMethods.CONFIG_TOOL] class ValgrindDependency(PkgConfigDependency): ''' From 5086e34d3a7a06e2121fe4541e6919a784094343 Mon Sep 17 00:00:00 2001 From: Daniel Mensinger Date: Wed, 20 Feb 2019 15:12:30 +0100 Subject: [PATCH 2/9] cmake: Support different CMake files --- mesonbuild/dependencies/base.py | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py index 7a10d694f..5e1109dc4 100644 --- a/mesonbuild/dependencies/base.py +++ b/mesonbuild/dependencies/base.py @@ -971,6 +971,19 @@ class CMakeDependency(ExternalDependency): def _gen_exception(self, msg): return DependencyException('Dependency {} not found: {}'.format(self.name, msg)) + def _main_cmake_file(self): + return 'CMakeLists.txt' + + def _extra_cmake_opts(self): + return [] + + def _map_module_list(self, modules: List[str]) -> List[str]: + # Map the input module list to something else + # This function will only be executed AFTER the initial CMake + # interpreter pass has completed. Thus variables defined in the + # CMakeLists.txt can be accessed here. + return modules + def __init__(self, name: str, environment: Environment, kwargs, language=None): super().__init__('cmake', environment, language, kwargs) self.name = name @@ -1265,11 +1278,12 @@ class CMakeDependency(ExternalDependency): # Prepare options cmake_opts = ['--trace-expand', '-DNAME={}'.format(name), '-DARCHS={}'.format(';'.join(self.cmakeinfo['archs']))] + args + ['.'] + cmake_opts += self._extra_cmake_opts() if len(i) > 0: cmake_opts = ['-G', i] + cmake_opts # Run CMake - ret1, out1, err1 = self._call_cmake(cmake_opts, 'CMakeLists.txt') + ret1, out1, err1 = self._call_cmake(cmake_opts, self._main_cmake_file()) # Current generator was successful if ret1 == 0: @@ -1327,6 +1341,10 @@ class CMakeDependency(ExternalDependency): self.version = vers_raw[0] self.version.strip('"\' ') + # Post-process module list. Used in derived classes to modify the + # module list (append prepend a string, etc.). + modules = self._map_module_list(modules) + # Try guessing a CMake target if none is provided if len(modules) == 0: for i in self.targets: @@ -1340,11 +1358,12 @@ class CMakeDependency(ExternalDependency): # Failed to guess a target --> try the old-style method if len(modules) == 0: incDirs = self.get_first_cmake_var_of(['PACKAGE_INCLUDE_DIRS']) + defs = self.get_first_cmake_var_of(['PACKAGE_DEFINITIONS']) libs = self.get_first_cmake_var_of(['PACKAGE_LIBRARIES']) # Try to use old style variables if no module is specified if len(libs) > 0: - self.compile_args = list(map(lambda x: '-I{}'.format(x), incDirs)) + self.compile_args = list(map(lambda x: '-I{}'.format(x), incDirs)) + defs self.link_args = libs mlog.debug('using old-style CMake variables for dependency {}'.format(name)) return From a9930fe066b4fd7b36478e3962bb0ccdb6ed5241 Mon Sep 17 00:00:00 2001 From: Daniel Mensinger Date: Wed, 20 Feb 2019 17:34:38 +0100 Subject: [PATCH 3/9] LLVM: Added CMake backend --- .../dependencies/data/CMakeListsLLVM.txt | 70 +++++++++++++++++++ mesonbuild/dependencies/dev.py | 37 +++++++++- setup.py | 2 +- .../161 config tool variable/meson.build | 2 +- .../unit/47 native file binary/meson.build | 2 +- 5 files changed, 108 insertions(+), 5 deletions(-) create mode 100644 mesonbuild/dependencies/data/CMakeListsLLVM.txt diff --git a/mesonbuild/dependencies/data/CMakeListsLLVM.txt b/mesonbuild/dependencies/data/CMakeListsLLVM.txt new file mode 100644 index 000000000..3f064415a --- /dev/null +++ b/mesonbuild/dependencies/data/CMakeListsLLVM.txt @@ -0,0 +1,70 @@ +cmake_minimum_required(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION} ) + +set(PACKAGE_FOUND FALSE) + +while(TRUE) + find_package(LLVM REQUIRED CONFIG QUIET) + + # ARCHS has to be set via the CMD interface + if(LLVM_FOUND OR "${ARCHS}" STREQUAL "") + break() + endif() + + list(GET ARCHS 0 CMAKE_LIBRARY_ARCHITECTURE) + list(REMOVE_AT ARCHS 0) +endwhile() + +if(LLVM_FOUND) + set(PACKAGE_FOUND TRUE) + + llvm_map_components_to_libnames(llvm_libs ${LLVM_MESON_MODULES}) + set(MESON_RESOLVED_LLVM_MODULES ${llvm_libs}) + + # Check the following variables: + # LLVM_PACKAGE_VERSION + # LLVM_VERSION + # LLVM_VERSION_STRING + if(NOT DEFINED PACKAGE_VERSION) + if(DEFINED LLVM_PACKAGE_VERSION) + set(PACKAGE_VERSION "${LLVM_PACKAGE_VERSION}") + elseif(DEFINED LLVM_VERSION) + set(PACKAGE_VERSION "${LLVM_VERSION}") + elseif(DEFINED LLVM_VERSION_STRING) + set(PACKAGE_VERSION "${LLVM_VERSION_STRING}") + endif() + endif() + + # Check the following variables: + # LLVM_LIBRARIES + # LLVM_LIBS + set(libs) + if(DEFINED LLVM_LIBRARIES) + set(libs LLVM_LIBRARIES) + elseif(DEFINED LLVM_LIBS) + set(libs LLVM_LIBS) + endif() + + # Check the following variables: + # LLVM_INCLUDE_DIRS + # LLVM_INCLUDES + # LLVM_INCLUDE_DIR + set(includes) + if(DEFINED LLVM_INCLUDE_DIRS) + set(includes LLVM_INCLUDE_DIRS) + elseif(DEFINED LLVM_INCLUDES) + set(includes LLVM_INCLUDES) + elseif(DEFINED LLVM_INCLUDE_DIR) + set(includes LLVM_INCLUDE_DIR) + endif() + + # Check the following variables: + # LLVM_DEFINITIONS + set(definitions) + if(DEFINED LLVM_DEFINITIONS) + set(definitions LLVM_DEFINITIONS) + endif() + + set(PACKAGE_INCLUDE_DIRS "${${includes}}") + set(PACKAGE_DEFINITIONS "${${definitions}}") + set(PACKAGE_LIBRARIES "${${libs}}") +endif() diff --git a/mesonbuild/dependencies/dev.py b/mesonbuild/dependencies/dev.py index 2a8960693..74e1412c6 100644 --- a/mesonbuild/dependencies/dev.py +++ b/mesonbuild/dependencies/dev.py @@ -24,7 +24,7 @@ from .. import mesonlib from ..mesonlib import version_compare, stringlistify, extract_as_list, MachineChoice from .base import ( DependencyException, DependencyMethods, ExternalDependency, PkgConfigDependency, - strip_system_libdirs, ConfigToolDependency, + strip_system_libdirs, ConfigToolDependency, CMakeDependency ) from .misc import ThreadDependency @@ -399,6 +399,36 @@ class LLVMDependencyConfigTool(ConfigToolDependency): return 'modules: ' + ', '.join(self.module_details) return '' +class LLVMDependencyCMake(CMakeDependency): + def __init__(self, env, kwargs): + self.llvm_modules = kwargs.get('modules', []) + super().__init__(name='LLVM', environment=env, language='cpp', kwargs=kwargs) + + # Extract extra include directories and definitions + incDirs = self.get_cmake_var('PACKAGE_INCLUDE_DIRS') + defs = self.get_cmake_var('PACKAGE_DEFINITIONS') + temp = list(map(lambda x: '-I{}'.format(x), incDirs)) + defs + self.compile_args += [x for x in temp if x not in self.compile_args] + + def _main_cmake_file(self): + # Use a custom CMakeLists.txt for LLVM + return 'CMakeListsLLVM.txt' + + def _extra_cmake_opts(self): + return ['-DLLVM_MESON_MODULES={}'.format(';'.join(self.llvm_modules))] + + def _map_module_list(self, modules): + return self.get_cmake_var('MESON_RESOLVED_LLVM_MODULES') + + def need_threads(self): + return True + + def log_details(self): + modules = self.get_cmake_var('MESON_RESOLVED_LLVM_MODULES') + if modules: + return 'modules: ' + ', '.join(modules) + return '' + class LLVMDependency(ExternalDependency): def __init__(self, env, kwargs): super().__init__('LLVM', env, 'cpp', kwargs) @@ -408,6 +438,9 @@ class LLVMDependency(ExternalDependency): methods = cls._process_method_kw(kwargs) candidates = [] + if DependencyMethods.CMAKE in methods: + candidates.append(functools.partial(LLVMDependencyCMake, env, kwargs)) + if DependencyMethods.CONFIG_TOOL in methods: candidates.append(functools.partial(LLVMDependencyConfigTool, env, kwargs)) @@ -415,7 +448,7 @@ class LLVMDependency(ExternalDependency): @staticmethod def get_methods(): - return [DependencyMethods.CONFIG_TOOL] + return [DependencyMethods.CMAKE, DependencyMethods.CONFIG_TOOL] class ValgrindDependency(PkgConfigDependency): ''' diff --git a/setup.py b/setup.py index 07bd3dde5..aab740e93 100644 --- a/setup.py +++ b/setup.py @@ -35,7 +35,7 @@ packages = ['mesonbuild', 'mesonbuild.modules', 'mesonbuild.scripts', 'mesonbuild.wrap'] -package_data = {'mesonbuild.dependencies': ['data/CMakeLists.txt', 'data/CMakePathInfo.txt']} +package_data = {'mesonbuild.dependencies': ['data/CMakeLists.txt', 'data/CMakeListsLLVM.txt', 'data/CMakePathInfo.txt']} data_files = [] if sys.platform != 'win32': # Only useful on UNIX-like systems diff --git a/test cases/common/161 config tool variable/meson.build b/test cases/common/161 config tool variable/meson.build index 0643042d8..95841179c 100644 --- a/test cases/common/161 config tool variable/meson.build +++ b/test cases/common/161 config tool variable/meson.build @@ -15,7 +15,7 @@ project('config tool variable', 'cpp') -dep_llvm = dependency('llvm', required : false) +dep_llvm = dependency('llvm', method : 'config-tool', required : false) if not dep_llvm.found() error('MESON_SKIP_TEST LLVM not installed.') endif diff --git a/test cases/unit/47 native file binary/meson.build b/test cases/unit/47 native file binary/meson.build index 4489ac1e6..c9b6e5de4 100644 --- a/test cases/unit/47 native file binary/meson.build +++ b/test cases/unit/47 native file binary/meson.build @@ -8,7 +8,7 @@ if case == 'find_program' assert(result.stdout().strip().endswith('12345'), 'Didn\'t load bash from config file') elif case == 'config_dep' add_languages('cpp') - dep = dependency('llvm') + dep = dependency('llvm', method : 'config-tool') assert(dep.get_configtool_variable('version').endswith('12345'), 'Didn\'t load llvm from config file') elif case == 'python3' prog = import('python3').find_python() From 55379b7d0fcaaa3d8289710c8bbd501aebbbf9e2 Mon Sep 17 00:00:00 2001 From: Daniel Mensinger Date: Sun, 31 Mar 2019 12:57:50 +0200 Subject: [PATCH 4/9] CMake: optional modules support --- mesonbuild/dependencies/base.py | 14 +++++++++----- mesonbuild/dependencies/data/CMakeListsLLVM.txt | 6 ++++-- mesonbuild/dependencies/dev.py | 10 +++++++--- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py index 5e1109dc4..4ef3603f7 100644 --- a/mesonbuild/dependencies/base.py +++ b/mesonbuild/dependencies/base.py @@ -977,7 +977,7 @@ class CMakeDependency(ExternalDependency): def _extra_cmake_opts(self): return [] - def _map_module_list(self, modules: List[str]) -> List[str]: + def _map_module_list(self, modules: List[Tuple[str, bool]]) -> List[Tuple[str, bool]]: # Map the input module list to something else # This function will only be executed AFTER the initial CMake # interpreter pass has completed. Thus variables defined in the @@ -1074,7 +1074,8 @@ class CMakeDependency(ExternalDependency): if self.cmakeinfo is None: raise self._gen_exception('Unable to obtain CMake system information') - modules = kwargs.get('modules', []) + modules = [(x, True) for x in kwargs.get('modules', [])] + modules += [(x, False) for x in kwargs.get('optional_modules', [])] cm_path = kwargs.get('cmake_module_path', []) cm_args = kwargs.get('cmake_args', []) if not isinstance(modules, list): @@ -1255,7 +1256,7 @@ class CMakeDependency(ExternalDependency): return False - def _detect_dep(self, name: str, modules: List[str], args: List[str]): + def _detect_dep(self, name: str, modules: List[Tuple[str, bool]], args: List[str]): # Detect a dependency with CMake using the '--find-package' mode # and the trace output (stderr) # @@ -1352,7 +1353,7 @@ class CMakeDependency(ExternalDependency): lname = name.lower() if '{}::{}'.format(lname, lname) == tg or lname == tg.replace('::', ''): mlog.debug('Guessed CMake target \'{}\''.format(i)) - modules = [i] + modules = [(i, True)] break # Failed to guess a target --> try the old-style method @@ -1380,8 +1381,11 @@ class CMakeDependency(ExternalDependency): compileDefinitions = [] compileOptions = [] libraries = [] - for i in modules: + for i, required in modules: if i not in self.targets: + if not required: + mlog.warning('CMake: Optional CMake target', mlog.bold(i), 'for', mlog.bold(name), 'was not found') + continue raise self._gen_exception('CMake: invalid CMake target {} for {}.\n' 'Try to explicitly specify one or more targets with the "modules" property.\n' 'Valid targets are:\n{}'.format(i, name, list(self.targets.keys()))) diff --git a/mesonbuild/dependencies/data/CMakeListsLLVM.txt b/mesonbuild/dependencies/data/CMakeListsLLVM.txt index 3f064415a..d16e1b67b 100644 --- a/mesonbuild/dependencies/data/CMakeListsLLVM.txt +++ b/mesonbuild/dependencies/data/CMakeListsLLVM.txt @@ -17,8 +17,10 @@ endwhile() if(LLVM_FOUND) set(PACKAGE_FOUND TRUE) - llvm_map_components_to_libnames(llvm_libs ${LLVM_MESON_MODULES}) - set(MESON_RESOLVED_LLVM_MODULES ${llvm_libs}) + llvm_map_components_to_libnames(llvm_libs ${LLVM_MESON_MODULES}) + llvm_map_components_to_libnames(llvm_libs_opt ${LLVM_MESON_OPT_MODULES}) + set(MESON_RESOLVED_LLVM_MODULES ${llvm_libs}) + set(MESON_RESOLVED_LLVM_MODULES_OPT ${llvm_libs_opt}) # Check the following variables: # LLVM_PACKAGE_VERSION diff --git a/mesonbuild/dependencies/dev.py b/mesonbuild/dependencies/dev.py index 74e1412c6..8f0c2c5cd 100644 --- a/mesonbuild/dependencies/dev.py +++ b/mesonbuild/dependencies/dev.py @@ -401,7 +401,8 @@ class LLVMDependencyConfigTool(ConfigToolDependency): class LLVMDependencyCMake(CMakeDependency): def __init__(self, env, kwargs): - self.llvm_modules = kwargs.get('modules', []) + self.llvm_modules = stringlistify(extract_as_list(kwargs, 'modules')) + self.llvm_opt_modules = stringlistify(extract_as_list(kwargs, 'optional_modules')) super().__init__(name='LLVM', environment=env, language='cpp', kwargs=kwargs) # Extract extra include directories and definitions @@ -415,10 +416,13 @@ class LLVMDependencyCMake(CMakeDependency): return 'CMakeListsLLVM.txt' def _extra_cmake_opts(self): - return ['-DLLVM_MESON_MODULES={}'.format(';'.join(self.llvm_modules))] + return ['-DLLVM_MESON_MODULES={}'.format(';'.join(self.llvm_modules)), + '-DLLVM_MESON_OPT_MODULES={}'.format(';'.join(self.llvm_opt_modules))] def _map_module_list(self, modules): - return self.get_cmake_var('MESON_RESOLVED_LLVM_MODULES') + modules = [(x, True) for x in self.get_cmake_var('MESON_RESOLVED_LLVM_MODULES')] + modules += [(x, False) for x in self.get_cmake_var('MESON_RESOLVED_LLVM_MODULES_OPT')] + return modules def need_threads(self): return True From 1280ef238b65af3569f24f81f7c7e1863b50986f Mon Sep 17 00:00:00 2001 From: Daniel Mensinger Date: Sun, 31 Mar 2019 13:51:33 +0200 Subject: [PATCH 5/9] cmake: Fixed list unit test --- mesonbuild/dependencies/base.py | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py index 4ef3603f7..447a635dc 100644 --- a/mesonbuild/dependencies/base.py +++ b/mesonbuild/dependencies/base.py @@ -35,7 +35,7 @@ from .. import mesonlib from ..compilers import clib_langs from ..environment import BinaryTable, Environment, MachineInfo from ..mesonlib import MachineChoice, MesonException, OrderedSet, PerMachine -from ..mesonlib import Popen_safe, version_compare_many, version_compare, listify +from ..mesonlib import Popen_safe, version_compare_many, version_compare, listify, stringlistify, extract_as_list from ..mesonlib import Version, LibType # These must be defined in this file to avoid cyclical references. @@ -1074,16 +1074,10 @@ class CMakeDependency(ExternalDependency): if self.cmakeinfo is None: raise self._gen_exception('Unable to obtain CMake system information') - modules = [(x, True) for x in kwargs.get('modules', [])] - modules += [(x, False) for x in kwargs.get('optional_modules', [])] - cm_path = kwargs.get('cmake_module_path', []) - cm_args = kwargs.get('cmake_args', []) - if not isinstance(modules, list): - modules = [modules] - if not isinstance(cm_path, list): - cm_path = [cm_path] - if not isinstance(cm_args, list): - cm_args = [cm_args] + modules = [(x, True) for x in stringlistify(extract_as_list(kwargs, 'modules'))] + modules += [(x, False) for x in stringlistify(extract_as_list(kwargs, 'optional_modules'))] + cm_path = stringlistify(extract_as_list(kwargs, 'cmake_module_path')) + cm_args = stringlistify(extract_as_list(kwargs, 'cmake_args')) cm_path = [x if os.path.isabs(x) else os.path.join(environment.get_source_dir(), x) for x in cm_path] if cm_path: cm_args += ['-DCMAKE_MODULE_PATH={}'.format(';'.join(cm_path))] From 6a2faacdf9e5dff25c7a467d102811e3e7d1cf08 Mon Sep 17 00:00:00 2001 From: Daniel Mensinger Date: Tue, 2 Apr 2019 10:08:27 +0200 Subject: [PATCH 6/9] cmake: minor code fixes --- mesonbuild/dependencies/base.py | 4 ++-- mesonbuild/dependencies/dev.py | 16 +++++++++------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py index 447a635dc..b45836d46 100644 --- a/mesonbuild/dependencies/base.py +++ b/mesonbuild/dependencies/base.py @@ -971,10 +971,10 @@ class CMakeDependency(ExternalDependency): def _gen_exception(self, msg): return DependencyException('Dependency {} not found: {}'.format(self.name, msg)) - def _main_cmake_file(self): + def _main_cmake_file(self) -> str: return 'CMakeLists.txt' - def _extra_cmake_opts(self): + def _extra_cmake_opts(self) -> List[str]: return [] def _map_module_list(self, modules: List[Tuple[str, bool]]) -> List[Tuple[str, bool]]: diff --git a/mesonbuild/dependencies/dev.py b/mesonbuild/dependencies/dev.py index 8f0c2c5cd..deb7ef128 100644 --- a/mesonbuild/dependencies/dev.py +++ b/mesonbuild/dependencies/dev.py @@ -28,6 +28,8 @@ from .base import ( ) from .misc import ThreadDependency +from typing import List, Tuple + def get_shared_library_suffix(environment, native): """This is only gauranteed to work for languages that compile to machine @@ -406,28 +408,28 @@ class LLVMDependencyCMake(CMakeDependency): super().__init__(name='LLVM', environment=env, language='cpp', kwargs=kwargs) # Extract extra include directories and definitions - incDirs = self.get_cmake_var('PACKAGE_INCLUDE_DIRS') + inc_dirs = self.get_cmake_var('PACKAGE_INCLUDE_DIRS') defs = self.get_cmake_var('PACKAGE_DEFINITIONS') - temp = list(map(lambda x: '-I{}'.format(x), incDirs)) + defs + temp = ['-I' + x for x in inc_dirs] + defs self.compile_args += [x for x in temp if x not in self.compile_args] - def _main_cmake_file(self): + def _main_cmake_file(self) -> str: # Use a custom CMakeLists.txt for LLVM return 'CMakeListsLLVM.txt' - def _extra_cmake_opts(self): + def _extra_cmake_opts(self) -> List[str]: return ['-DLLVM_MESON_MODULES={}'.format(';'.join(self.llvm_modules)), '-DLLVM_MESON_OPT_MODULES={}'.format(';'.join(self.llvm_opt_modules))] - def _map_module_list(self, modules): + def _map_module_list(self, modules: List[Tuple[str, bool]]) -> List[Tuple[str, bool]]: modules = [(x, True) for x in self.get_cmake_var('MESON_RESOLVED_LLVM_MODULES')] modules += [(x, False) for x in self.get_cmake_var('MESON_RESOLVED_LLVM_MODULES_OPT')] return modules - def need_threads(self): + def need_threads(self) -> bool: return True - def log_details(self): + def log_details(self) -> str: modules = self.get_cmake_var('MESON_RESOLVED_LLVM_MODULES') if modules: return 'modules: ' + ', '.join(modules) From 3f539e01aedd1a3498c341efadb591a8a90e6995 Mon Sep 17 00:00:00 2001 From: Daniel Mensinger Date: Tue, 2 Apr 2019 10:40:17 +0200 Subject: [PATCH 7/9] cmake: revert module name mapping --- mesonbuild/dependencies/base.py | 25 ++++++++++++++++++++++--- mesonbuild/dependencies/dev.py | 20 ++++++++++++-------- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py index b45836d46..486f523ef 100644 --- a/mesonbuild/dependencies/base.py +++ b/mesonbuild/dependencies/base.py @@ -984,6 +984,11 @@ class CMakeDependency(ExternalDependency): # CMakeLists.txt can be accessed here. return modules + def _original_module_name(self, module: str) -> str: + # Reverse the module mapping done by _map_module_list for + # one module + return module + def __init__(self, name: str, environment: Environment, kwargs, language=None): super().__init__('cmake', environment, language, kwargs) self.name = name @@ -1003,6 +1008,9 @@ class CMakeDependency(ExternalDependency): # Where all CMake "build dirs" are located self.cmake_root_dir = environment.scratch_dir + # List of successfully found modules + self.found_modules = [] + # When finding dependencies for cross-compiling, we don't care about # the 'native' CMake binary # TODO: Test if this works as expected @@ -1339,6 +1347,7 @@ class CMakeDependency(ExternalDependency): # Post-process module list. Used in derived classes to modify the # module list (append prepend a string, etc.). modules = self._map_module_list(modules) + autodetected_module_list = False # Try guessing a CMake target if none is provided if len(modules) == 0: @@ -1348,6 +1357,7 @@ class CMakeDependency(ExternalDependency): if '{}::{}'.format(lname, lname) == tg or lname == tg.replace('::', ''): mlog.debug('Guessed CMake target \'{}\''.format(i)) modules = [(i, True)] + autodetected_module_list = True break # Failed to guess a target --> try the old-style method @@ -1378,13 +1388,16 @@ class CMakeDependency(ExternalDependency): for i, required in modules: if i not in self.targets: if not required: - mlog.warning('CMake: Optional CMake target', mlog.bold(i), 'for', mlog.bold(name), 'was not found') + mlog.warning('CMake: Optional module', mlog.bold(self._original_module_name(i)), 'for', mlog.bold(name), 'was not found') continue - raise self._gen_exception('CMake: invalid CMake target {} for {}.\n' + raise self._gen_exception('CMake: invalid module {} for {}.\n' 'Try to explicitly specify one or more targets with the "modules" property.\n' - 'Valid targets are:\n{}'.format(i, name, list(self.targets.keys()))) + 'Valid targets are:\n{}'.format(self._original_module_name(i), name, list(self.targets.keys()))) targets = [i] + if not autodetected_module_list: + self.found_modules += [i] + while len(targets) > 0: curr = targets.pop(0) @@ -1764,6 +1777,12 @@ set(CMAKE_SIZEOF_VOID_P "{}") def log_tried(self): return self.type_name + def log_details(self) -> str: + modules = [self._original_module_name(x) for x in self.found_modules] + if modules: + return 'modules: ' + ', '.join(modules) + return '' + class DubDependency(ExternalDependency): class_dubbin = None diff --git a/mesonbuild/dependencies/dev.py b/mesonbuild/dependencies/dev.py index deb7ef128..2ad506ed7 100644 --- a/mesonbuild/dependencies/dev.py +++ b/mesonbuild/dependencies/dev.py @@ -405,6 +405,7 @@ class LLVMDependencyCMake(CMakeDependency): def __init__(self, env, kwargs): self.llvm_modules = stringlistify(extract_as_list(kwargs, 'modules')) self.llvm_opt_modules = stringlistify(extract_as_list(kwargs, 'optional_modules')) + self.module_map = {} super().__init__(name='LLVM', environment=env, language='cpp', kwargs=kwargs) # Extract extra include directories and definitions @@ -422,19 +423,22 @@ class LLVMDependencyCMake(CMakeDependency): '-DLLVM_MESON_OPT_MODULES={}'.format(';'.join(self.llvm_opt_modules))] def _map_module_list(self, modules: List[Tuple[str, bool]]) -> List[Tuple[str, bool]]: - modules = [(x, True) for x in self.get_cmake_var('MESON_RESOLVED_LLVM_MODULES')] - modules += [(x, False) for x in self.get_cmake_var('MESON_RESOLVED_LLVM_MODULES_OPT')] + res_modules = self.get_cmake_var('MESON_RESOLVED_LLVM_MODULES') + res_opt_modules = self.get_cmake_var('MESON_RESOLVED_LLVM_MODULES_OPT') + modules = [(x, True) for x in res_modules] + modules += [(x, False) for x in res_opt_modules] + self.module_map = { + **dict(zip(res_modules, self.llvm_modules)), + **dict(zip(res_opt_modules, self.llvm_opt_modules)) + } return modules + def _original_module_name(self, module: str) -> str: + return self.module_map.get(module, module) + def need_threads(self) -> bool: return True - def log_details(self) -> str: - modules = self.get_cmake_var('MESON_RESOLVED_LLVM_MODULES') - if modules: - return 'modules: ' + ', '.join(modules) - return '' - class LLVMDependency(ExternalDependency): def __init__(self, env, kwargs): super().__init__('LLVM', env, 'cpp', kwargs) From 1fba945b61619a344c21468eb2bb36604f1cb975 Mon Sep 17 00:00:00 2001 From: Daniel Mensinger Date: Fri, 12 Apr 2019 13:08:47 +0200 Subject: [PATCH 8/9] cmake: LLVM better modules handling --- mesonbuild/dependencies/base.py | 5 +-- .../dependencies/data/CMakeListsLLVM.txt | 31 +++++++++++++++--- mesonbuild/dependencies/dev.py | 32 +++++++++++-------- test cases/frameworks/15 llvm/meson.build | 2 +- 4 files changed, 49 insertions(+), 21 deletions(-) diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py index 486f523ef..8f38d6c80 100644 --- a/mesonbuild/dependencies/base.py +++ b/mesonbuild/dependencies/base.py @@ -1462,7 +1462,7 @@ class CMakeDependency(ExternalDependency): self.compile_args = compileOptions + compileDefinitions + list(map(lambda x: '-I{}'.format(x), incDirs)) self.link_args = libraries - def get_first_cmake_var_of(self, var_list): + def get_first_cmake_var_of(self, var_list: List[str]) -> List[str]: # Return the first found CMake variable in list var_list for i in var_list: if i in self.vars: @@ -1470,7 +1470,7 @@ class CMakeDependency(ExternalDependency): return [] - def get_cmake_var(self, var): + def get_cmake_var(self, var: str) -> List[str]: # Return the value of the CMake variable var or an empty list if var does not exist if var in self.vars: return self.vars[var] @@ -1779,6 +1779,7 @@ set(CMAKE_SIZEOF_VOID_P "{}") def log_details(self) -> str: modules = [self._original_module_name(x) for x in self.found_modules] + modules = sorted(set(modules)) if modules: return 'modules: ' + ', '.join(modules) return '' diff --git a/mesonbuild/dependencies/data/CMakeListsLLVM.txt b/mesonbuild/dependencies/data/CMakeListsLLVM.txt index d16e1b67b..9d3e41234 100644 --- a/mesonbuild/dependencies/data/CMakeListsLLVM.txt +++ b/mesonbuild/dependencies/data/CMakeListsLLVM.txt @@ -17,10 +17,33 @@ endwhile() if(LLVM_FOUND) set(PACKAGE_FOUND TRUE) - llvm_map_components_to_libnames(llvm_libs ${LLVM_MESON_MODULES}) - llvm_map_components_to_libnames(llvm_libs_opt ${LLVM_MESON_OPT_MODULES}) - set(MESON_RESOLVED_LLVM_MODULES ${llvm_libs}) - set(MESON_RESOLVED_LLVM_MODULES_OPT ${llvm_libs_opt}) + foreach(mod IN LISTS LLVM_MESON_MODULES) + # Reset variables + set(out_mods) + set(real_mods) + + # Generate a lower and upper case version + string(TOLOWER "${mod}" mod_L) + string(TOUPPER "${mod}" mod_U) + + # Get the mapped components + llvm_map_components_to_libnames(out_mods ${mod} ${mod_L} ${mod_U}) + list(SORT out_mods) + list(REMOVE_DUPLICATES out_mods) + + # Make sure that the modules exist + foreach(i IN LISTS out_mods) + if(TARGET ${i}) + list(APPEND real_mods ${i}) + endif() + endforeach() + + # Set the output variables + set(MESON_LLVM_TARGETS_${mod} ${real_mods}) + foreach(i IN LISTS real_mods) + set(MESON_TARGET_TO_LLVM_${i} ${mod}) + endforeach() + endforeach() # Check the following variables: # LLVM_PACKAGE_VERSION diff --git a/mesonbuild/dependencies/dev.py b/mesonbuild/dependencies/dev.py index 2ad506ed7..646293b91 100644 --- a/mesonbuild/dependencies/dev.py +++ b/mesonbuild/dependencies/dev.py @@ -20,7 +20,7 @@ import glob import os import re -from .. import mesonlib +from .. import mesonlib, mlog from ..mesonlib import version_compare, stringlistify, extract_as_list, MachineChoice from .base import ( DependencyException, DependencyMethods, ExternalDependency, PkgConfigDependency, @@ -405,7 +405,6 @@ class LLVMDependencyCMake(CMakeDependency): def __init__(self, env, kwargs): self.llvm_modules = stringlistify(extract_as_list(kwargs, 'modules')) self.llvm_opt_modules = stringlistify(extract_as_list(kwargs, 'optional_modules')) - self.module_map = {} super().__init__(name='LLVM', environment=env, language='cpp', kwargs=kwargs) # Extract extra include directories and definitions @@ -419,22 +418,27 @@ class LLVMDependencyCMake(CMakeDependency): return 'CMakeListsLLVM.txt' def _extra_cmake_opts(self) -> List[str]: - return ['-DLLVM_MESON_MODULES={}'.format(';'.join(self.llvm_modules)), - '-DLLVM_MESON_OPT_MODULES={}'.format(';'.join(self.llvm_opt_modules))] + return ['-DLLVM_MESON_MODULES={}'.format(';'.join(self.llvm_modules + self.llvm_opt_modules))] def _map_module_list(self, modules: List[Tuple[str, bool]]) -> List[Tuple[str, bool]]: - res_modules = self.get_cmake_var('MESON_RESOLVED_LLVM_MODULES') - res_opt_modules = self.get_cmake_var('MESON_RESOLVED_LLVM_MODULES_OPT') - modules = [(x, True) for x in res_modules] - modules += [(x, False) for x in res_opt_modules] - self.module_map = { - **dict(zip(res_modules, self.llvm_modules)), - **dict(zip(res_opt_modules, self.llvm_opt_modules)) - } - return modules + res = [] + for mod, required in modules: + cm_targets = self.get_cmake_var('MESON_LLVM_TARGETS_{}'.format(mod)) + if not cm_targets: + if required: + raise self._gen_exception('LLVM module {} was not found'.format(mod)) + else: + mlog.warning('Optional LLVM module', mlog.bold(mod), 'was not found') + continue + for i in cm_targets: + res += [(i, required)] + return res def _original_module_name(self, module: str) -> str: - return self.module_map.get(module, module) + orig_name = self.get_cmake_var('MESON_TARGET_TO_LLVM_{}'.format(module)) + if orig_name: + return orig_name[0] + return module def need_threads(self) -> bool: return True diff --git a/test cases/frameworks/15 llvm/meson.build b/test cases/frameworks/15 llvm/meson.build index fc750842b..af94daeae 100644 --- a/test cases/frameworks/15 llvm/meson.build +++ b/test cases/frameworks/15 llvm/meson.build @@ -35,7 +35,7 @@ foreach static : [true, false] llvm_dep = dependency( 'llvm', modules : ['bitwriter', 'asmprinter', 'executionengine', 'target', - 'mcjit', 'nativecodegen'], + 'mcjit', 'nativecodegen', 'amdgpu'], required : false, static : static, ) From 25de6dd67568d1c02ad0ad5358cd3719c428b88b Mon Sep 17 00:00:00 2001 From: Daniel Mensinger Date: Fri, 12 Apr 2019 15:25:08 +0200 Subject: [PATCH 9/9] cmake: Fixed new thread dependency --- mesonbuild/dependencies/dev.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/mesonbuild/dependencies/dev.py b/mesonbuild/dependencies/dev.py index 646293b91..4d541a348 100644 --- a/mesonbuild/dependencies/dev.py +++ b/mesonbuild/dependencies/dev.py @@ -412,6 +412,7 @@ class LLVMDependencyCMake(CMakeDependency): defs = self.get_cmake_var('PACKAGE_DEFINITIONS') temp = ['-I' + x for x in inc_dirs] + defs self.compile_args += [x for x in temp if x not in self.compile_args] + self._add_sub_dependency(ThreadDependency, env, kwargs) def _main_cmake_file(self) -> str: # Use a custom CMakeLists.txt for LLVM @@ -440,9 +441,6 @@ class LLVMDependencyCMake(CMakeDependency): return orig_name[0] return module - def need_threads(self) -> bool: - return True - class LLVMDependency(ExternalDependency): def __init__(self, env, kwargs): super().__init__('LLVM', env, 'cpp', kwargs)