From 29c2b44a29cea47696b4026673874260ac547ab7 Mon Sep 17 00:00:00 2001 From: Daniel Mensinger Date: Sat, 4 Sep 2021 13:40:09 +0200 Subject: [PATCH] cmake: Implement support for interpreting link "keywords" CMakes `target_link_libraries()` supports certain keywords to only enable specific libraries for specific CMake configurations. We now try our best to replicate this for Meson dependencies. Fixes #9197 --- mesonbuild/dependencies/cmake.py | 42 ++++++++++++++----- .../cmake_fake1/cmMesonTestF1Config.cmake | 2 +- .../linuxlike/13 cmake dependency/meson.build | 4 ++ 3 files changed, 37 insertions(+), 11 deletions(-) diff --git a/mesonbuild/dependencies/cmake.py b/mesonbuild/dependencies/cmake.py index 3fe5b8f28..1f1c1e12b 100644 --- a/mesonbuild/dependencies/cmake.py +++ b/mesonbuild/dependencies/cmake.py @@ -433,6 +433,18 @@ class CMakeDependency(ExternalDependency): modules = self._map_module_list(modules, components) autodetected_module_list = False + # Check if we need a DEBUG or RELEASE CMake dependencies + is_debug = False + if OptionKey('b_vscrt') in self.env.coredata.options: + is_debug = self.env.coredata.get_option(OptionKey('buildtype')) == 'debug' + if self.env.coredata.options[OptionKey('b_vscrt')].value in {'mdd', 'mtd'}: + is_debug = True + else: + # Don't directly assign to is_debug to make mypy happy + debug_opt = self.env.coredata.get_option(OptionKey('debug')) + assert isinstance(debug_opt, bool) + is_debug = debug_opt + # Try guessing a CMake target if none is provided if len(modules) == 0: for i in self.traceparser.targets: @@ -479,7 +491,26 @@ class CMakeDependency(ExternalDependency): incDirs = [x for x in self.traceparser.get_cmake_var('PACKAGE_INCLUDE_DIRS') if x] defs = [x for x in self.traceparser.get_cmake_var('PACKAGE_DEFINITIONS') if x] - libs = [x for x in self.traceparser.get_cmake_var('PACKAGE_LIBRARIES') if x] + libs_raw = [x for x in self.traceparser.get_cmake_var('PACKAGE_LIBRARIES') if x] + + # CMake has a "fun" API, where certain keywords describing + # configurations can be in the *_LIBRARIES vraiables. See: + # - https://github.com/mesonbuild/meson/issues/9197 + # - https://gitlab.freedesktop.org/libnice/libnice/-/issues/140 + # - https://cmake.org/cmake/help/latest/command/target_link_libraries.html#overview (the last point in the section) + libs: T.List[str] = [] + cfg_matches = True + cm_tag_map = {'debug': is_debug, 'optimized': not is_debug, 'general': True} + for i in libs_raw: + if i.lower() in cm_tag_map: + cfg_matches = cm_tag_map[i.lower()] + continue + if cfg_matches: + libs += [i] + # According to the CMake docs, a keyword only works for the + # directly the following item and all items without a keyword + # are implizitly `general` + cfg_matches = True # Try to use old style variables if no module is specified if len(libs) > 0: @@ -545,15 +576,6 @@ class CMakeDependency(ExternalDependency): cfgs = [x for x in tgt.properties['IMPORTED_CONFIGURATIONS'] if x] cfg = cfgs[0] - if OptionKey('b_vscrt') in self.env.coredata.options: - is_debug = self.env.coredata.get_option(OptionKey('buildtype')) == 'debug' - if self.env.coredata.options[OptionKey('b_vscrt')].value in {'mdd', 'mtd'}: - is_debug = True - else: - # Don't directly assign to is_debug to make mypy happy - debug_opt = self.env.coredata.get_option(OptionKey('debug')) - assert isinstance(debug_opt, bool) - is_debug = debug_opt if is_debug: if 'DEBUG' in cfgs: cfg = 'DEBUG' diff --git a/test cases/linuxlike/13 cmake dependency/cmake_fake1/cmMesonTestF1Config.cmake b/test cases/linuxlike/13 cmake dependency/cmake_fake1/cmMesonTestF1Config.cmake index 938c7061b..4b3f81479 100644 --- a/test cases/linuxlike/13 cmake dependency/cmake_fake1/cmMesonTestF1Config.cmake +++ b/test cases/linuxlike/13 cmake dependency/cmake_fake1/cmMesonTestF1Config.cmake @@ -2,7 +2,7 @@ find_package(ZLIB) if(ZLIB_FOUND OR ZLIB_Found) set(cmMesonTestF1_FOUND ON) - set(cmMesonTestF1_LIBRARIES ${ZLIB_LIBRARY}) + set(cmMesonTestF1_LIBRARIES general ${ZLIB_LIBRARY}) set(cmMesonTestF1_INCLUDE_DIRS ${ZLIB_INCLUDE_DIR}) add_library(CMMesonTESTf1::evil_non_standard_trget UNKNOWN IMPORTED) diff --git a/test cases/linuxlike/13 cmake dependency/meson.build b/test cases/linuxlike/13 cmake dependency/meson.build index 67d53cf45..b82f9b7f5 100644 --- a/test cases/linuxlike/13 cmake dependency/meson.build +++ b/test cases/linuxlike/13 cmake dependency/meson.build @@ -48,6 +48,10 @@ depPrefEnv1 = dependency('cmMesonTestF1', required : true, method : 'cmake') depPrefEnv2 = dependency('cmMesonTestF2', required : true, method : 'cmake') depPrefEnv3 = dependency('cmMesonTestF3', required : true, method : 'cmake') +# Try to actually link with depPrefEnv1, since we are doing "fun" stuff there +exe3 = executable('zlibprog3', 'prog.c', dependencies : depPrefEnv1) +test('zlibtest3', exe3) + # Try to find a dependency with a custom CMake module depm1 = dependency('SomethingLikeZLIB', required : true, components : 'required_comp', method : 'cmake', cmake_module_path : 'cmake')