Handle cmake dependencies which require a specified version

Some CMake packages fail to find at all if no version is specified.
This commit adds a cmake_version parameter to dependency() to allow you
to specify the requested version.
pull/8014/head
Jason Ekstrand 4 years ago committed by Dylan Baker
parent 9dab27f814
commit 15bbf1ea75
  1. 5
      docs/markdown/Dependencies.md
  2. 5
      docs/markdown/snippets/cmake_package_version.md
  3. 8
      mesonbuild/dependencies/base.py
  4. 6
      mesonbuild/dependencies/data/CMakeLists.txt
  5. 2
      mesonbuild/interpreter.py
  6. 8
      mesonbuild/mesondata.py
  7. 9
      test cases/linuxlike/13 cmake dependency/cmake_pref_env/lib/cmake/cmMesonVersionedTestDep/cmMesonVersionedTestDepConfig.cmake
  8. 12
      test cases/linuxlike/13 cmake dependency/cmake_pref_env/lib/cmake/cmMesonVersionedTestDep/cmMesonVersionedTestDepConfigVersion.cmake
  9. 6
      test cases/linuxlike/13 cmake dependency/meson.build

@ -177,6 +177,11 @@ Support for adding additional `COMPONENTS` for the CMake `find_package` lookup
is provided with the `components` kwarg (*introduced in 0.54.0*). All specified
componets will be passed directly to `find_package(COMPONENTS)`.
Support for packages which require a specified version for CMake
`find_package` to succeed is provided with the `cmake_package_version` kwarg
(*introduced in 0.57.0*). The specified `cmake_package_version` will be
passed directly as the second parameter to `find_package`.
It is also possible to reuse existing `Find<name>.cmake` files with the
`cmake_module_path` property. Using this property is equivalent to setting the
`CMAKE_MODULE_PATH` variable in CMake. The path(s) given to `cmake_module_path`

@ -0,0 +1,5 @@
## CMake find_package version support
It is now possible to specify a requested package version to the CMake
dependency backend via the new `cmake_package_version` kwarg in the
`dependency` function.

@ -1111,6 +1111,9 @@ class CMakeDependency(ExternalDependency):
if self.cmakeinfo is None:
raise self._gen_exception('Unable to obtain CMake system information')
package_version = kwargs.get('cmake_package_version', '')
if not isinstance(package_version, str):
raise DependencyException('Keyword "cmake_package_version" must be a string.')
components = [(x, True) for x in stringlistify(extract_as_list(kwargs, 'components'))]
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'))]
@ -1121,7 +1124,7 @@ class CMakeDependency(ExternalDependency):
if not self._preliminary_find_check(name, cm_path, self.cmakebin.get_cmake_prefix_paths(), environment.machines[self.for_machine]):
mlog.debug('Preliminary CMake check failed. Aborting.')
return
self._detect_dep(name, modules, components, cm_args)
self._detect_dep(name, package_version, modules, components, cm_args)
def __repr__(self):
s = '<{0} {1}: {2} {3}>'
@ -1307,7 +1310,7 @@ class CMakeDependency(ExternalDependency):
return False
def _detect_dep(self, name: str, modules: T.List[T.Tuple[str, bool]], components: T.List[T.Tuple[str, bool]], args: T.List[str]):
def _detect_dep(self, name: str, package_version: str, modules: T.List[T.Tuple[str, bool]], components: T.List[T.Tuple[str, bool]], args: T.List[str]):
# Detect a dependency with CMake using the '--find-package' mode
# and the trace output (stderr)
#
@ -1337,6 +1340,7 @@ class CMakeDependency(ExternalDependency):
cmake_opts = []
cmake_opts += ['-DNAME={}'.format(name)]
cmake_opts += ['-DARCHS={}'.format(';'.join(self.cmakeinfo['archs']))]
cmake_opts += ['-DVERSION={}'.format(package_version)]
cmake_opts += ['-DCOMPS={}'.format(';'.join([x[0] for x in comp_mapped]))]
cmake_opts += args
cmake_opts += self.traceparser.trace_args()

@ -9,7 +9,11 @@ set(_packageName "${NAME}")
string(TOUPPER "${_packageName}" PACKAGE_NAME)
while(TRUE)
find_package("${NAME}" QUIET COMPONENTS ${COMPS})
if ("${VERSION}" STREQUAL "")
find_package("${NAME}" QUIET COMPONENTS ${COMPS})
else()
find_package("${NAME}" "${VERSION}" QUIET COMPONENTS ${COMPS})
endif()
# ARCHS has to be set via the CMD interface
if(${_packageName}_FOUND OR ${PACKAGE_NAME}_FOUND OR "${ARCHS}" STREQUAL "")

@ -2334,6 +2334,7 @@ permitted_kwargs = {'add_global_arguments': {'language', 'native'},
'version',
'private_headers',
'cmake_args',
'cmake_package_version',
'include_type',
},
'declare_dependency': {'include_directories',
@ -3716,6 +3717,7 @@ external dependencies (including libraries) must go to "dependencies".''')
elif name == 'openmp':
FeatureNew.single_use('OpenMP Dependency', '0.46.0', self.subproject)
@FeatureNewKwargs('dependency', '0.57.0', ['cmake_package_version'])
@FeatureNewKwargs('dependency', '0.54.0', ['components'])
@FeatureNewKwargs('dependency', '0.52.0', ['include_type'])
@FeatureNewKwargs('dependency', '0.50.0', ['not_found_message', 'cmake_module_path', 'cmake_args'])

@ -174,7 +174,11 @@ set(_packageName "${NAME}")
string(TOUPPER "${_packageName}" PACKAGE_NAME)
while(TRUE)
find_package("${NAME}" QUIET COMPONENTS ${COMPS})
if ("${VERSION}" STREQUAL "")
find_package("${NAME}" QUIET COMPONENTS ${COMPS})
else()
find_package("${NAME}" "${VERSION}" QUIET COMPONENTS ${COMPS})
endif()
# ARCHS has to be set via the CMD interface
if(${_packageName}_FOUND OR ${PACKAGE_NAME}_FOUND OR "${ARCHS}" STREQUAL "")
@ -379,7 +383,7 @@ mesondata = {
),
'dependencies/data/CMakeLists.txt': DataFile(
Path('dependencies/data/CMakeLists.txt'),
'71a2d58381f912bbfb1c8709884d34d721f682edf2fca001e1f582f0bffd0da7',
'4dca24afa13e9311f0598a6ac29690490819bd7d82cfdaa0a2fe5eea3c0fa0d5',
file_2_data_CMakeLists_txt,
),
'cmake/data/preload.cmake': DataFile(

@ -0,0 +1,9 @@
find_package(ZLIB)
if(ZLIB_FOUND OR ZLIB_Found)
set(cmMesonVersionedTestDep_FOUND ON)
set(cmMesonVersionedTestDep_LIBRARIES ${ZLIB_LIBRARY})
set(cmMesonVersionedTestDep_INCLUDE_DIRS ${ZLIB_INCLUDE_DIR})
else()
set(cmMesonVersionedTestDep_FOUND OFF)
endif()

@ -0,0 +1,12 @@
set(PACKAGE_VERSION 3.1.4)
if (${PACKAGE_FIND_VERSION_MAJOR} EQUAL 3)
if (${PACKAGE_FIND_VERSION} VERSION_LESS 3.1.4)
set(PACKAGE_VERSION_COMPATIBLE 1)
endif()
if (${PACKAGE_FIND_VERSION} VERSION_EQUAL 3.1.4)
set(PACKAGE_VERSION_EXACT 1)
endif()
else()
set(PACKAGE_VERSION_UNSUITABLE 1)
endif()

@ -64,6 +64,12 @@ if cm_vers.version_compare('>=3.15')
test('testFlagSetTest2', testFlagSet2)
endif
# Try to find a dependency with a cmake module which requires a package version
# test.json sets CMAKE_PREFIX_PATH to include ./cmake_pref_env/
verdep1 = dependency('cmMesonVersionedTestDep', required : true, method : 'cmake', cmake_package_version : '3.0')
verdep2 = dependency('cmMesonVersionedTestDep', required : false, method : 'cmake', cmake_package_version : '200.0')
assert(not verdep2.found(), 'found a version dep we shouldnt have')
# Try to compile a test that takes a dep and an include_directories
cc = meson.get_compiler('c')

Loading…
Cancel
Save