Merge pull request #8812 from mensinda/cmakeToolchain

CMake toolchain file improvements (fixes #8293)
pull/8724/head
Jussi Pakkanen 4 years ago committed by GitHub
commit 99452dde26
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      mesonbuild/cmake/__init__.py
  2. 20
      mesonbuild/cmake/common.py
  3. 4
      mesonbuild/cmake/generator.py
  4. 18
      mesonbuild/cmake/interpreter.py
  5. 163
      mesonbuild/cmake/toolchain.py
  6. 54
      mesonbuild/cmake/traceparser.py
  7. 32
      mesonbuild/coredata.py
  8. 4
      mesonbuild/dependencies/base.py
  9. 2
      test cases/cmake/16 threads/subprojects/cmMod/CMakeLists.txt
  10. 6
      test cases/cmake/23 cmake toolchain/meson.build
  11. 1
      test cases/cmake/23 cmake toolchain/nativefile.ini.in
  12. 6
      test cases/cmake/23 cmake toolchain/subprojects/cmMod/CMakeLists.txt
  13. 19
      test cases/cmake/23 cmake toolchain/subprojects/cmModFortran/CMakeLists.txt

@ -30,11 +30,13 @@ __all__ = [
'TargetOptions',
'parse_generator_expressions',
'language_map',
'backend_generator_map',
'cmake_get_generator_args',
'cmake_defines_to_args',
'check_cmake_args',
]
from .common import CMakeException, SingleTargetOptions, TargetOptions, cmake_defines_to_args, language_map, check_cmake_args
from .common import CMakeException, SingleTargetOptions, TargetOptions, cmake_defines_to_args, language_map, backend_generator_map, cmake_get_generator_args, check_cmake_args
from .client import CMakeClient
from .executor import CMakeExecutor
from .fileapi import CMakeFileAPI

@ -15,11 +15,14 @@
# This class contains the basic functionality needed to run any interpreter
# or an interpreter-based tool.
from ..mesonlib import MesonException
from ..mesonlib import MesonException, OptionKey
from .. import mlog
from pathlib import Path
import typing as T
if T.TYPE_CHECKING:
from ..environment import Environment
language_map = {
'c': 'C',
'cpp': 'CXX',
@ -32,6 +35,15 @@ language_map = {
'swift': 'Swift',
}
backend_generator_map = {
'ninja': 'Ninja',
'xcode': 'Xcode',
'vs2010': 'Visual Studio 10 2010',
'vs2015': 'Visual Studio 15 2017',
'vs2017': 'Visual Studio 15 2017',
'vs2019': 'Visual Studio 16 2019',
}
blacklist_cmake_defs = [
'CMAKE_TOOLCHAIN_FILE',
'CMAKE_PROJECT_INCLUDE',
@ -87,6 +99,12 @@ def _flags_to_list(raw: str) -> T.List[str]:
res = list(filter(lambda x: len(x) > 0, res))
return res
def cmake_get_generator_args(env: 'Environment') -> T.List[str]:
backend_name = env.coredata.get_option(OptionKey('backend'))
assert isinstance(backend_name, str)
assert backend_name in backend_generator_map
return ['-G', backend_generator_map[backend_name]]
def cmake_defines_to_args(raw: T.Any, permissive: bool = False) -> T.List[str]:
res = [] # type: T.List[str]
if not isinstance(raw, list):

@ -23,6 +23,10 @@ def parse_generator_expressions(raw: str) -> str:
use cases.
'''
# Early abort if no generator expression present
if '$<' not in raw:
return raw
out = '' # type: str
i = 0 # type: int

@ -15,7 +15,7 @@
# This class contains the basic functionality needed to run any interpreter
# or an interpreter-based tool.
from .common import CMakeException, CMakeTarget, TargetOptions, CMakeConfiguration, language_map, check_cmake_args
from .common import CMakeException, CMakeTarget, TargetOptions, CMakeConfiguration, language_map, backend_generator_map, cmake_get_generator_args, check_cmake_args
from .client import CMakeClient, RequestCMakeInputs, RequestConfigure, RequestCompute, RequestCodeModel, ReplyCMakeInputs, ReplyCodeModel
from .fileapi import CMakeFileAPI
from .executor import CMakeExecutor
@ -74,15 +74,6 @@ disable_policy_warnings = [
'CMP0102',
]
backend_generator_map = {
'ninja': 'Ninja',
'xcode': 'Xcode',
'vs2010': 'Visual Studio 10 2010',
'vs2015': 'Visual Studio 15 2017',
'vs2017': 'Visual Studio 15 2017',
'vs2019': 'Visual Studio 16 2019',
}
target_type_map = {
'STATIC_LIBRARY': 'static_library',
'MODULE_LIBRARY': 'shared_module',
@ -892,15 +883,14 @@ class CMakeInterpreter:
self.trace = CMakeTraceParser(cmake_exe.version(), self.build_dir, permissive=True)
preload_file = mesondata['cmake/data/preload.cmake'].write_to_private(self.env)
toolchain = CMakeToolchain(self.env, self.for_machine, CMakeExecScope.SUBPROJECT, self.build_dir.parent, preload_file)
toolchain = CMakeToolchain(cmake_exe, self.env, self.for_machine, CMakeExecScope.SUBPROJECT, self.build_dir, preload_file)
toolchain_file = toolchain.write()
# TODO: drop this check once the deprecated `cmake_args` kwarg is removed
extra_cmake_options = check_cmake_args(extra_cmake_options)
generator = backend_generator_map[self.backend_name]
cmake_args = []
cmake_args += ['-G', generator]
cmake_args += cmake_get_generator_args(self.env)
cmake_args += [f'-DCMAKE_INSTALL_PREFIX={self.install_prefix}']
cmake_args += extra_cmake_options
trace_args = self.trace.trace_args()
@ -953,6 +943,7 @@ class CMakeInterpreter:
cmake_files = self.fileapi.get_cmake_sources()
self.bs_files = [x.file for x in cmake_files if not x.is_cmake and not x.is_temp]
self.bs_files = [relative_to_if_possible(x, Path(self.env.get_source_dir())) for x in self.bs_files]
self.bs_files = [x for x in self.bs_files if not path_is_in_root(x, Path(self.env.get_build_dir()), resolve=True)]
self.bs_files = list(OrderedSet(self.bs_files))
# Load the codemodel configurations
@ -980,6 +971,7 @@ class CMakeInterpreter:
src_dir = bs_reply.src_dir
self.bs_files = [x.file for x in bs_reply.build_files if not x.is_cmake and not x.is_temp]
self.bs_files = [relative_to_if_possible(src_dir / x, Path(self.env.get_source_dir()), resolve=True) for x in self.bs_files]
self.bs_files = [x for x in self.bs_files if not path_is_in_root(x, Path(self.env.get_build_dir()), resolve=True)]
self.bs_files = list(OrderedSet(self.bs_files))
self.codemodel_configs = cm_reply.configs

@ -13,9 +13,10 @@
# limitations under the License.
from pathlib import Path
from .traceparser import CMakeTraceParser
from ..envconfig import CMakeSkipCompilerTest
from ..mesonlib import MachineChoice
from .common import language_map
from .common import language_map, cmake_get_generator_args
from .. import mlog
import shutil
@ -24,53 +25,49 @@ from enum import Enum
from textwrap import dedent
if T.TYPE_CHECKING:
from .executor import CMakeExecutor
from ..envconfig import MachineInfo, Properties, CMakeVariables
from ..environment import Environment
from ..compilers import Compiler
_MESON_TO_CMAKE_MAPPING = {
'arm': 'ARMCC',
'armclang': 'ARMClang',
'clang': 'Clang',
'clang-cl': 'MSVC',
'flang': 'Flang',
'g95': 'G95',
'gcc': 'GNU',
'intel': 'Intel',
'intel-cl': 'MSVC',
'msvc': 'MSVC',
'pathscale': 'PathScale',
'pgi': 'PGI',
'sun': 'SunPro',
}
class CMakeExecScope(Enum):
SUBPROJECT = 'subproject'
DEPENDENCY = 'dependency'
class CMakeToolchain:
def __init__(self, env: 'Environment', for_machine: MachineChoice, exec_scope: CMakeExecScope, out_dir: Path, preload_file: T.Optional[Path] = None) -> None:
def __init__(self, cmakebin: 'CMakeExecutor', env: 'Environment', for_machine: MachineChoice, exec_scope: CMakeExecScope, build_dir: Path, preload_file: T.Optional[Path] = None) -> None:
self.env = env
self.cmakebin = cmakebin
self.for_machine = for_machine
self.exec_scope = exec_scope
self.preload_file = preload_file
self.toolchain_file = out_dir / 'CMakeMesonToolchainFile.cmake'
self.toolchain_file = self.toolchain_file.resolve()
self.build_dir = build_dir
self.build_dir = self.build_dir.resolve()
self.toolchain_file = build_dir / 'CMakeMesonToolchainFile.cmake'
self.cmcache_file = build_dir / 'CMakeCache.txt'
self.minfo = self.env.machines[self.for_machine]
self.properties = self.env.properties[self.for_machine]
self.compilers = self.env.coredata.compilers[self.for_machine]
self.cmakevars = self.env.cmakevars[self.for_machine]
self.cmakestate = self.env.coredata.cmake_cache[self.for_machine]
self.variables = self.get_defaults()
self.variables.update(self.cmakevars.get_variables())
# Determine whether CMake the compiler test should be skipped
skip_status = self.properties.get_cmake_skip_compiler_test()
self.skip_check = skip_status == CMakeSkipCompilerTest.ALWAYS
if skip_status == CMakeSkipCompilerTest.DEP_ONLY and self.exec_scope == CMakeExecScope.DEPENDENCY:
self.skip_check = True
if not self.properties.get_cmake_defaults():
self.skip_check = False
assert self.toolchain_file.is_absolute()
def write(self) -> Path:
if not self.toolchain_file.parent.exists():
self.toolchain_file.parent.mkdir(parents=True)
self.toolchain_file.write_text(self.generate())
self.cmcache_file.write_text(self.generate_cache())
mlog.cmd_ci_include(self.toolchain_file.as_posix())
return self.toolchain_file
@ -80,6 +77,16 @@ class CMakeToolchain:
args += ['-DMESON_PRELOAD_FILE=' + self.preload_file.as_posix()]
return args
@staticmethod
def _print_vars(vars: T.Dict[str, T.List[str]]) -> str:
res = ''
for key, value in vars.items():
res += 'set(' + key
for i in value:
res += f' "{i}"'
res += ')\n'
return res
def generate(self) -> str:
res = dedent('''\
######################################
@ -100,14 +107,19 @@ class CMakeToolchain:
for key, value in self.variables.items():
self.variables[key] = [x.replace('\\', '/') for x in value]
# Set compiler
if self.skip_check:
self.update_cmake_compiler_state()
res += '# CMake compiler state variables\n'
for lang, vars in self.cmakestate:
res += f'# -- Variables for language {lang}\n'
res += self._print_vars(vars)
res += '\n'
res += '\n'
# Set variables from the current machine config
res += '# Variables from meson\n'
for key, value in self.variables.items():
res += 'set(' + key
for i in value:
res += f' "{i}"'
res += ')\n'
res += self._print_vars(self.variables)
res += '\n'
# Add the user provided toolchain file
@ -121,6 +133,15 @@ class CMakeToolchain:
return res
def generate_cache(self) -> str:
if not self.skip_check:
return ''
res = ''
for name, v in self.cmakestate.cmake_cache.items():
res += f'{name}:{v.type}={";".join(v.value)}\n'
return res
def get_defaults(self) -> T.Dict[str, T.List[str]]:
defaults = {} # type: T.Dict[str, T.List[str]]
@ -151,11 +172,6 @@ class CMakeToolchain:
if sys_root:
defaults['CMAKE_SYSROOT'] = [sys_root]
# Determine whether CMake the compiler test should be skipped
skip_check = self.properties.get_cmake_skip_compiler_test() == CMakeSkipCompilerTest.ALWAYS
if self.properties.get_cmake_skip_compiler_test() == CMakeSkipCompilerTest.DEP_ONLY and self.exec_scope == CMakeExecScope.DEPENDENCY:
skip_check = True
def make_abs(exe: str) -> str:
if Path(exe).is_absolute():
return exe
@ -168,9 +184,6 @@ class CMakeToolchain:
# Set the compiler variables
for lang, comp_obj in self.compilers.items():
exe_list = [make_abs(x) for x in comp_obj.get_exelist()]
comp_id = CMakeToolchain.meson_compiler_to_cmake_id(comp_obj)
comp_version = comp_obj.version.upper()
prefix = 'CMAKE_{}_'.format(language_map.get(lang, lang.upper()))
if not exe_list:
@ -183,35 +196,53 @@ class CMakeToolchain:
if comp_obj.get_id() == 'clang-cl':
defaults['CMAKE_LINKER'] = comp_obj.get_linker_exelist()
# Setting the variables after this check cause CMake to skip
# validating the compiler
if not skip_check:
continue
defaults[prefix + 'COMPILER_ID'] = [comp_id]
defaults[prefix + 'COMPILER_VERSION'] = [comp_version]
#defaults[prefix + 'COMPILER_LOADED'] = ['1']
defaults[prefix + 'COMPILER_FORCED'] = ['1']
defaults[prefix + 'COMPILER_WORKS'] = ['TRUE']
#defaults[prefix + 'ABI_COMPILED'] = ['TRUE']
return defaults
@staticmethod
def meson_compiler_to_cmake_id(cobj: 'Compiler') -> str:
"""Translate meson compiler's into CMAKE compiler ID's.
Most of these can be handled by a simple table lookup, with a few
exceptions.
Clang and Apple's Clang are both identified as "clang" by meson. To make
things more complicated gcc and vanilla clang both use Apple's ld64 on
macOS. The only way to know for sure is to do an isinstance() check.
"""
from ..compilers import (AppleClangCCompiler, AppleClangCPPCompiler,
AppleClangObjCCompiler, AppleClangObjCPPCompiler)
if isinstance(cobj, (AppleClangCCompiler, AppleClangCPPCompiler,
AppleClangObjCCompiler, AppleClangObjCPPCompiler)):
return 'AppleClang'
# If no mapping, try GNU and hope that the build files don't care
return _MESON_TO_CMAKE_MAPPING.get(cobj.get_id(), 'GNU')
def update_cmake_compiler_state(self) -> None:
# Check if all variables are already cached
if self.cmakestate.languages.issuperset(self.compilers.keys()):
return
# Generate the CMakeLists.txt
mlog.debug('CMake Toolchain: Calling CMake once to generate the compiler state')
languages = list(self.compilers.keys())
lang_ids = [language_map.get(x, x.upper()) for x in languages]
cmake_content = dedent(f'''
cmake_minimum_required(VERSION 3.7)
project(CompInfo {' '.join(lang_ids)})
''')
build_dir = Path(self.env.scratch_dir) / '__CMake_compiler_info__'
build_dir.mkdir(parents=True, exist_ok=True)
cmake_file = build_dir / 'CMakeLists.txt'
cmake_file.write_text(cmake_content)
# Generate the temporary toolchain file
temp_toolchain_file = build_dir / 'CMakeMesonTempToolchainFile.cmake'
temp_toolchain_file.write_text(CMakeToolchain._print_vars(self.variables))
# Configure
trace = CMakeTraceParser(self.cmakebin.version(), build_dir)
self.cmakebin.set_exec_mode(print_cmout=False, always_capture_stderr=trace.requires_stderr())
cmake_args = []
cmake_args += trace.trace_args()
cmake_args += cmake_get_generator_args(self.env)
cmake_args += [f'-DCMAKE_TOOLCHAIN_FILE={temp_toolchain_file.as_posix()}', '.']
rc, _, raw_trace = self.cmakebin.call(cmake_args, build_dir=build_dir, disable_cache=True)
if rc != 0:
mlog.warning('CMake Toolchain: Failed to determine CMake compilers state')
return
# Parse output
trace.parse(raw_trace)
self.cmakestate.cmake_cache = {**trace.cache}
vars_by_file = {k.name: v for (k, v) in trace.vars_by_file.items()}
for lang in languages:
lang_cmake = language_map.get(lang, lang.upper())
file_name = f'CMake{lang_cmake}Compiler.cmake'
vars = vars_by_file.setdefault(file_name, {})
vars[f'CMAKE_{lang_cmake}_COMPILER_FORCED'] = ['1']
self.cmakestate.update(lang, vars)

@ -22,21 +22,31 @@ from ..mesonlib import version_compare
import typing as T
from pathlib import Path
from functools import lru_cache
import re
import json
import textwrap
class CMakeTraceLine:
def __init__(self, file: Path, line: int, func: str, args: T.List[str]) -> None:
self.file = file
def __init__(self, file_str: str, line: int, func: str, args: T.List[str]) -> None:
self.file = CMakeTraceLine._to_path(file_str)
self.line = line
self.func = func.lower()
self.args = args
@staticmethod
@lru_cache(maxsize=None)
def _to_path(file_str: str) -> Path:
return Path(file_str)
def __repr__(self) -> str:
s = 'CMake TRACE: {0}:{1} {2}({3})'
return s.format(self.file, self.line, self.func, self.args)
class CMakeCacheEntry(T.NamedTuple):
value: T.List[str]
type: str
class CMakeTarget:
def __init__(
self,
@ -81,8 +91,10 @@ class CMakeGeneratorTarget(CMakeTarget):
class CMakeTraceParser:
def __init__(self, cmake_version: str, build_dir: Path, permissive: bool = True) -> None:
self.vars = {} # type: T.Dict[str, T.List[str]]
self.targets = {} # type: T.Dict[str, CMakeTarget]
self.vars: T.Dict[str, T.List[str]] = {}
self.vars_by_file: T.Dict[Path, T.Dict[str, T.List[str]]] = {}
self.targets: T.Dict[str, CMakeTarget] = {}
self.cache: T.Dict[str, CMakeCacheEntry] = {}
self.explicit_headers = set() # type: T.Set[Path]
@ -234,6 +246,14 @@ class CMakeTraceParser:
"""
# DOC: https://cmake.org/cmake/help/latest/command/set.html
cache_type = None
cache_force = 'FORCE' in tline.args
try:
cache_idx = tline.args.index('CACHE')
cache_type = tline.args[cache_idx + 1]
except (ValueError, IndexError):
pass
# 1st remove PARENT_SCOPE and CACHE from args
args = []
for i in tline.args:
@ -256,12 +276,19 @@ class CMakeTraceParser:
identifier = args.pop(0)
value = ' '.join(args)
# Write to the CMake cache instead
if cache_type:
# Honor how the CMake FORCE parameter works
if identifier not in self.cache or cache_force:
self.cache[identifier] = CMakeCacheEntry(value.split(';'), cache_type)
if not value:
# Same as unset
if identifier in self.vars:
del self.vars[identifier]
else:
self.vars[identifier] = value.split(';')
self.vars_by_file.setdefault(tline.file, {})[identifier] = value.split(';')
def _cmake_unset(self, tline: CMakeTraceLine) -> None:
# DOC: https://cmake.org/cmake/help/latest/command/unset.html
@ -437,17 +464,18 @@ class CMakeTraceParser:
if not value:
return
def do_target(tgt: str) -> None:
if i not in self.targets:
return self._gen_exception('set_property', f'TARGET {i} not found', tline)
def do_target(t: str) -> None:
if t not in self.targets:
return self._gen_exception('set_property', f'TARGET {t} not found', tline)
if identifier not in self.targets[i].properties:
self.targets[i].properties[identifier] = []
tgt = self.targets[t]
if identifier not in tgt.properties:
tgt.properties[identifier] = []
if append:
self.targets[i].properties[identifier] += value
tgt.properties[identifier] += value
else:
self.targets[i].properties[identifier] = value
tgt.properties[identifier] = value
def do_source(src: str) -> None:
if identifier != 'HEADER_FILE_ONLY' or not self._str_to_bool(value):
@ -652,7 +680,7 @@ class CMakeTraceParser:
argl = args.split(' ')
argl = list(map(lambda x: x.strip(), argl))
yield CMakeTraceLine(Path(file), int(line), func, argl)
yield CMakeTraceLine(file, int(line), func, argl)
def _lex_trace_json(self, trace: str) -> T.Generator[CMakeTraceLine, None, None]:
lines = trace.splitlines(keepends=False)
@ -667,7 +695,7 @@ class CMakeTraceParser:
for j in args:
assert isinstance(j, str)
args = [parse_generator_expressions(x) for x in args]
yield CMakeTraceLine(Path(data['file']), data['line'], data['cmd'], args)
yield CMakeTraceLine(data['file'], data['line'], data['cmd'], args)
def _flatten_args(self, args: T.List[str]) -> T.List[str]:
# Split lists in arguments

@ -36,6 +36,7 @@ if T.TYPE_CHECKING:
from .compilers.compilers import Compiler, CompileResult # noqa: F401
from .environment import Environment
from .mesonlib import OptionOverrideProxy
from .cmake.traceparser import CMakeCacheEntry
OptionDictType = T.Union[T.Dict[str, 'UserOption[T.Any]'], OptionOverrideProxy]
KeyedOptionDictType = T.Union[T.Dict['OptionKey', 'UserOption[T.Any]'], OptionOverrideProxy]
@ -374,6 +375,34 @@ class DependencyCache:
def clear(self) -> None:
self.__cache.clear()
class CMakeStateCache:
"""Class that stores internal CMake compiler states.
This cache is used to reduce the startup overhead of CMake by caching
all internal CMake compiler variables.
"""
def __init__(self) -> None:
self.__cache: T.Dict[str, T.Dict[str, T.List[str]]] = {}
self.cmake_cache: T.Dict[str, 'CMakeCacheEntry'] = {}
def __iter__(self) -> T.Iterator[T.Tuple[str, T.Dict[str, T.List[str]]]]:
return iter(self.__cache.items())
def items(self) -> T.Iterator[T.Tuple[str, T.Dict[str, T.List[str]]]]:
return iter(self.__cache.items())
def update(self, language: str, variables: T.Dict[str, T.List[str]]):
if language not in self.__cache:
self.__cache[language] = {}
self.__cache[language].update(variables)
@property
def languages(self) -> T.Set[str]:
return set(self.__cache.keys())
# Can't bind this near the class method it seems, sadly.
_V = T.TypeVar('_V')
@ -414,6 +443,9 @@ class CoreData:
self.compiler_check_cache = OrderedDict() # type: T.Dict[CompilerCheckCacheKey, compiler.CompileResult]
# CMake cache
self.cmake_cache: PerMachine[CMakeStateCache] = PerMachine(CMakeStateCache(), CMakeStateCache())
# Only to print a warning if it changes between Meson invocations.
self.config_files = self.__load_config_files(options, scratch_dir, 'native')
self.builtin_options_libdir_cross_fixup()

@ -1146,7 +1146,7 @@ class CMakeDependency(ExternalDependency):
gen_list += CMakeDependency.class_cmake_generators
temp_parser = CMakeTraceParser(self.cmakebin.version(), self._get_build_dir())
toolchain = CMakeToolchain(self.env, self.for_machine, CMakeExecScope.DEPENDENCY, self._get_build_dir())
toolchain = CMakeToolchain(self.cmakebin, self.env, self.for_machine, CMakeExecScope.DEPENDENCY, self._get_build_dir())
toolchain.write()
for i in gen_list:
@ -1346,7 +1346,7 @@ class CMakeDependency(ExternalDependency):
# Map the components
comp_mapped = self._map_component_list(modules, components)
toolchain = CMakeToolchain(self.env, self.for_machine, CMakeExecScope.DEPENDENCY, self._get_build_dir())
toolchain = CMakeToolchain(self.cmakebin, self.env, self.for_machine, CMakeExecScope.DEPENDENCY, self._get_build_dir())
toolchain.write()
for i in gen_list:

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.5)
project(cmMod CXX)
project(cmMod C CXX)
set (CMAKE_CXX_STANDARD 14)
if(NOT USE_PTHREAD STREQUAL NOT_SET)

@ -1,4 +1,4 @@
project('cmake toolchain test', ['c', 'cpp'])
project('cmake toolchain test', ['c'])
if meson.is_cross_build()
error('MESON_SKIP_TEST: skip this on cross builds')
@ -7,3 +7,7 @@ endif
cm = import('cmake')
sub_pro = cm.subproject('cmMod')
add_languages('cpp')
sub_pro = cm.subproject('cmModFortran')

@ -1,6 +1,7 @@
[properties]
cmake_toolchain_file = '@MESON_TEST_ROOT@/CMakeToolchain.cmake'
cmake_skip_compiler_test = 'always'
[cmake]

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.5)
project(cmMod)
project(cmMod NONE)
if(NOT "${MESON_TEST_VAR1}" STREQUAL "VAR1 space")
message(FATAL_ERROR "MESON_TEST_VAR1 -- '${MESON_TEST_VAR1}' != 'VAR1 space'")
@ -9,3 +9,7 @@ endif()
if(NOT "${MESON_TEST_VAR2}" STREQUAL "VAR2")
message(FATAL_ERROR "MESON_TEST_VAR2 -- '${MESON_TEST_VAR2}' != 'VAR2'")
endif()
if(NOT DEFINED CMAKE_C_COMPILER_VERSION)
message(FATAL_ERROR "CMAKE_C_COMPILER_VERSION was not defined")
endif()

@ -0,0 +1,19 @@
cmake_minimum_required(VERSION 3.5)
project(cmMod NONE)
if(NOT "${MESON_TEST_VAR1}" STREQUAL "VAR1 space")
message(FATAL_ERROR "MESON_TEST_VAR1 -- '${MESON_TEST_VAR1}' != 'VAR1 space'")
endif()
if(NOT "${MESON_TEST_VAR2}" STREQUAL "VAR2")
message(FATAL_ERROR "MESON_TEST_VAR2 -- '${MESON_TEST_VAR2}' != 'VAR2'")
endif()
if(NOT DEFINED CMAKE_C_COMPILER_VERSION)
message(FATAL_ERROR "CMAKE_C_COMPILER_VERSION was not defined")
endif()
if(NOT DEFINED CMAKE_CXX_COMPILER_VERSION)
message(FATAL_ERROR "CMAKE_CXX_COMPILER_VERSION was not defined")
endif()
Loading…
Cancel
Save