cmake: add project language to cmakelists.txt

cmake: get language from Meson project if not specified as depedency(..., langugage: ...)

deps: add threads method:cmake

dependency('threads', method: 'cmake') is useful for cmake unit tests
or those who just want to find threads using cmake.

cmake: project(... Fortran) generally also requires C language
pull/6321/head
Michael Hirsch, Ph.D 5 years ago committed by Michael Hirsch, Ph.D
parent 419a7a8f51
commit 98fd4e5557
  1. 53
      mesonbuild/dependencies/base.py
  2. 6
      mesonbuild/dependencies/data/CMakeLists.txt
  3. 38
      mesonbuild/dependencies/misc.py
  4. 4
      mesonbuild/mesonlib.py
  5. 9
      test cases/cmake/14 fortran threads/meson.build
  6. 1
      test cases/frameworks/1 boost/meson.build
  7. 1
      test cases/frameworks/2 gtest/meson.build
  8. 4
      test cases/linuxlike/13 cmake dependency/meson.build

@ -1037,7 +1037,23 @@ class CMakeDependency(ExternalDependency):
# one module
return module
def __init__(self, name: str, environment: Environment, kwargs, language=None):
def __init__(self, name: str, environment: Environment, kwargs, language: str = None):
if language is None:
if kwargs.get('native', False):
if 'c' in environment.coredata.compilers.build.keys():
language = 'c'
elif 'cpp' in environment.coredata.compilers.build.keys():
language = 'cpp'
elif 'fortran' in environment.coredata.compilers.build.keys():
language = 'fortran'
else:
if 'c' in environment.coredata.compilers.host.keys():
language = 'c'
elif 'cpp' in environment.coredata.compilers.host.keys():
language = 'cpp'
elif 'fortran' in environment.coredata.compilers.host.keys():
language = 'fortran'
super().__init__('cmake', environment, language, kwargs)
self.name = name
self.is_libtool = False
@ -1460,9 +1476,40 @@ class CMakeDependency(ExternalDependency):
build_dir = Path(self.cmake_root_dir) / 'cmake_{}'.format(self.name)
build_dir.mkdir(parents=True, exist_ok=True)
# Copy the CMakeLists.txt
# Insert language parameters into the CMakeLists.txt and write new CMakeLists.txt
src_cmake = Path(__file__).parent / 'data' / cmake_file
shutil.copyfile(str(src_cmake), str(build_dir / 'CMakeLists.txt')) # str() is for Python 3.5
cmake_txt = src_cmake.read_text()
# In general, some Fortran CMake find_package() also require C language enabled,
# even if nothing from C is directly used. An easy Fortran example that fails
# without C language is
# find_package(Threads)
# To make this general to
# any other language that might need this, we use a list for all
# languages and expand in the cmake Project(... LANGUAGES ...) statement.
if self.language is None:
cmake_language = ['NONE']
elif self.language == 'c':
cmake_language = ['C']
elif self.language == 'cpp':
cmake_language = ['CXX']
elif self.language == 'cs':
cmake_language = ['CSharp']
elif self.language == 'cuda':
cmake_language = ['CUDA']
elif self.language == 'fortran':
cmake_language = ['C', 'Fortran']
elif self.language == 'objc':
cmake_language = ['OBJC']
elif self.language == 'objcpp':
cmake_language = ['OBJCXX']
cmake_txt = """
cmake_minimum_required(VERSION ${{CMAKE_VERSION}})
project(MesonTemp LANGUAGES {})
""".format(' '.join(cmake_language)) + cmake_txt
(build_dir / 'CMakeLists.txt').write_text(cmake_txt)
return str(build_dir)

@ -1,4 +1,8 @@
cmake_minimum_required(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION} )
# fail noisily if attempt to use this file without setting:
# cmake_minimum_required(VERSION ${CMAKE_VERSION})
# project(... LANGUAGES ...)
cmake_policy(SET CMP0000 NEW)
set(PACKAGE_FOUND FALSE)
set(_packageName "${NAME}")

@ -22,6 +22,7 @@ import sysconfig
from .. import mlog
from .. import mesonlib
from ..environment import detect_cpu_family
from ..mesonlib import listify
from .base import (
DependencyException, DependencyMethods, ExternalDependency,
@ -109,15 +110,34 @@ class ThreadDependency(ExternalDependency):
def __init__(self, environment, kwargs):
super().__init__('threads', environment, None, kwargs)
self.name = 'threads'
self.is_found = True
# Happens if you are using a language with threads
# concept without C, such as plain Cuda.
if self.clib_compiler is None:
self.compile_args = []
self.link_args = []
else:
self.compile_args = self.clib_compiler.thread_flags(environment)
self.link_args = self.clib_compiler.thread_link_flags(environment)
self.is_found = False
methods = listify(self.methods)
if DependencyMethods.AUTO in methods:
self.is_found = True
# Happens if you are using a language with threads
# concept without C, such as plain Cuda.
if self.clib_compiler is None:
self.compile_args = []
self.link_args = []
else:
self.compile_args = self.clib_compiler.thread_flags(environment)
self.link_args = self.clib_compiler.thread_link_flags(environment)
return
if DependencyMethods.CMAKE in methods:
# for unit tests and for those who simply want
# dependency('threads', method: 'cmake')
cmakedep = CMakeDependency('Threads', environment, kwargs)
if cmakedep.found():
self.compile_args = cmakedep.get_compile_args()
self.link_args = cmakedep.get_link_args()
self.version = cmakedep.get_version()
self.is_found = True
return
@staticmethod
def get_methods():
return [DependencyMethods.AUTO, DependencyMethods.CMAKE]
class BlocksDependency(ExternalDependency):

@ -976,7 +976,9 @@ def replace_if_different(dst, dst_tmp):
else:
os.unlink(dst_tmp)
def listify(item, flatten=True, unholder=False):
def listify(item: typing.Any,
flatten: bool = True,
unholder: bool = False) -> typing.List[typing.Any]:
'''
Returns a list with all args embedded in a list if they are not a list.
This function preserves order.

@ -0,0 +1,9 @@
project('FortranThreads')
if not add_languages('fortran', required: false)
error('MESON_SKIP_TEST: Fortran language not available.')
endif
# want to be sure that CMake can find dependencies where even if the
# project isn't C, the C language is required to find the library.
threads = dependency('threads', method: 'cmake', required: true)

@ -1,3 +1,4 @@
# this test requires the following on Ubuntu: libboost-{system,python,log,thread,test}-dev
project('boosttest', 'cpp',
default_options : ['cpp_std=c++11'])

@ -1,3 +1,4 @@
# on Ubuntu this test requires libgtest-dev
project('gtest', 'cpp')
gtest = dependency('gtest', main : true, required : false)

@ -1,3 +1,5 @@
# this test can ONLY be run successfully from run_project_test.py
# due to use of setup_env.json
project('external CMake dependency', 'c')
if not find_program('cmake', required: false).found()
@ -37,7 +39,7 @@ depf2 = dependency('ZLIB', required : false, method : 'cmake', modules : 'dfggh:
assert(depf2.found() == false, 'Invalid CMake targets should fail')
# Try to find cmMesonTestDep in a custom prefix
# setup_env.json is used by run_project_tests.py:_run_test to point to ./cmake_pref_env/
depPrefEnv = dependency('cmMesonTestDep', required : true, method : 'cmake')
# Try to find a dependency with a custom CMake module

Loading…
Cancel
Save