Merge pull request #7231 from mensinda/cmOverride
cmake: Add more advanced subproject configuration options
This commit is contained in:
commit
64f36613ef
|
@ -48,8 +48,6 @@ The `subproject` method is almost identical to the normal meson
|
|||
`subproject` function. The only difference is that a CMake project
|
||||
instead of a meson project is configured.
|
||||
|
||||
Also, project specific CMake options can be added with the `cmake_options` key.
|
||||
|
||||
The returned `sub_proj` supports the same options as a "normal" subproject.
|
||||
Meson automatically detects CMake build targets, which can be accessed with
|
||||
the methods listed [below](#subproject-object).
|
||||
|
@ -87,6 +85,49 @@ It should be noted that not all projects are guaranteed to work. The
|
|||
safest approach would still be to create a `meson.build` for the
|
||||
subprojects in question.
|
||||
|
||||
### Configuration options
|
||||
|
||||
*New in meson 0.55.0*
|
||||
|
||||
Meson also supports passing configuration options to CMake and overriding
|
||||
certain build details extracted from the CMake subproject.
|
||||
|
||||
```meson
|
||||
cmake = import('cmake')
|
||||
opt_var = cmake.subproject_options()
|
||||
|
||||
# Call CMake with `-DSOME_OTHER_VAR=ON`
|
||||
opt_var.add_cmake_defines({'SOME_OTHER_VAR': true})
|
||||
|
||||
# Globally override the C++ standard to c++11
|
||||
opt_var.set_override_option('cpp_std', 'c++11')
|
||||
|
||||
# Override the previous global C++ standard
|
||||
# with c++14 only for the CMake target someLib
|
||||
opt_var.set_override_option('cpp_std', 'c++14', target: 'someLib')
|
||||
|
||||
sub_pro = cmake.subproject('someLibProject', options: opt_var)
|
||||
|
||||
# Further changes to opt_var have no effect
|
||||
```
|
||||
|
||||
See [the CMake options object](#cmake-options-object) for a complete reference
|
||||
of all supported functions.
|
||||
|
||||
The CMake configuration options object is very similar to the
|
||||
[configuration data object](Reference-manual.md#configuration-data-object) object
|
||||
returned by [`configuration_data`](Reference-manual.md#configuration_data). It
|
||||
is generated by the `subproject_options` function
|
||||
|
||||
All configuration options have to be set *before* the subproject is configured
|
||||
and must be passed to the `subproject` method via the `options` key. Altering
|
||||
the configuration object won't have any effect on previous `cmake.subproject`
|
||||
calls.
|
||||
|
||||
In earlier meson versions CMake command-line parameters could be set with the
|
||||
`cmake_options` kwarg. However, this feature is deprecated since 0.55.0 and only
|
||||
kept for compatibility. It will not work together with the `options` kwarg.
|
||||
|
||||
### `subproject` object
|
||||
|
||||
This object is returned by the `subproject` function described above
|
||||
|
@ -103,7 +144,37 @@ and supports the following methods:
|
|||
the subproject. Usually `dependency()` or `target()` should be
|
||||
preferred to extract build targets.
|
||||
- `found` returns true if the subproject is available, otherwise false
|
||||
*new in in 0.53.2*
|
||||
*new in meson 0.53.2*
|
||||
|
||||
### `cmake options` object
|
||||
|
||||
This object is returned by the `subproject_options()` function and consumed by
|
||||
the `options` kwarg of the `subproject` function. The following methods are
|
||||
supported:
|
||||
|
||||
- `add_cmake_defines({'opt1': val1, ...})` add additional CMake commandline defines
|
||||
- `set_override_option(opt, val)` set specific [build options](Build-options.md)
|
||||
for targets. This will effectively add `opt=val` to the `override_options`
|
||||
array of the [build target](Reference-manual.md#executable)
|
||||
- `set_install(bool)` override wether targets should be installed or not
|
||||
- `append_compile_args(lang, arg1, ...)` append compile flags for a specific
|
||||
language to the targets
|
||||
- `append_link_args(arg1, ...)` append linger args to the targets
|
||||
- `clear()` reset all data in the `cmake options` object
|
||||
|
||||
The methods `set_override_option`, `set_install`, `append_compile_args` and
|
||||
`append_link_args` support the optional `target` kwarg. If specified, the set
|
||||
options affect the specific target. The effect of the option is global for the
|
||||
subproject otherwise.
|
||||
|
||||
If, for instance, `opt_var.set_install(false)` is called, no target will be
|
||||
installed regardless of what is set by CMake. However, it is still possible to
|
||||
install specific targets (here `foo`) by setting the `target` kwarg:
|
||||
`opt_var.set_install(true, target: 'foo')`
|
||||
|
||||
Options that are not set won't affect the generated subproject. So, if for
|
||||
instance, `set_install` was not called then the values extracted from CMake will
|
||||
be used.
|
||||
|
||||
## CMake configuration files
|
||||
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
## Configure CMake subprojects with meson.subproject_options
|
||||
|
||||
Meson now supports passing configuration options to CMake and overriding
|
||||
certain build details extracted from the CMake subproject.
|
||||
|
||||
The new CMake configuration options object is very similar to the
|
||||
[configuration data object](Reference-manual.md#configuration-data-object) object
|
||||
returned by [`configuration_data`](Reference-manual.md#configuration_data). It
|
||||
is generated by the `subproject_options` function
|
||||
|
||||
All configuration options have to be set *before* the subproject is configured
|
||||
and must be passed to the `subproject` method via the `options` key. Altering
|
||||
the configuration object won't have any effect on previous `cmake.subproject`
|
||||
calls.
|
||||
|
||||
**Note:** The `cmake_options` kwarg for the `subproject` function is now
|
||||
deprecated since it is replaced by the new `options` system.
|
|
@ -24,11 +24,14 @@ __all__ = [
|
|||
'CMakeTarget',
|
||||
'CMakeTraceLine',
|
||||
'CMakeTraceParser',
|
||||
'SingleTargetOptions',
|
||||
'TargetOptions',
|
||||
'parse_generator_expressions',
|
||||
'language_map',
|
||||
'cmake_defines_to_args',
|
||||
]
|
||||
|
||||
from .common import CMakeException
|
||||
from .common import CMakeException, SingleTargetOptions, TargetOptions, cmake_defines_to_args
|
||||
from .client import CMakeClient
|
||||
from .executor import CMakeExecutor
|
||||
from .fileapi import CMakeFileAPI
|
||||
|
|
|
@ -60,6 +60,26 @@ def _flags_to_list(raw: str) -> T.List[str]:
|
|||
res = list(filter(lambda x: len(x) > 0, res))
|
||||
return res
|
||||
|
||||
def cmake_defines_to_args(raw: T.Any, permissive: bool = False) -> T.List[str]:
|
||||
res = [] # type: T.List[str]
|
||||
if not isinstance(raw, list):
|
||||
raw = [raw]
|
||||
|
||||
for i in raw:
|
||||
if not isinstance(i, dict):
|
||||
raise MesonException('Invalid CMake defines. Expected a dict, but got a {}'.format(type(i).__name__))
|
||||
for key, val in i.items():
|
||||
assert isinstance(key, str)
|
||||
if isinstance(val, (str, int, float)):
|
||||
res += ['-D{}={}'.format(key, val)]
|
||||
elif isinstance(val, bool):
|
||||
val_str = 'ON' if val else 'OFF'
|
||||
res += ['-D{}={}'.format(key, val_str)]
|
||||
else:
|
||||
raise MesonException('Type "{}" of "{}" is not supported as for a CMake define value'.format(type(val).__name__, key))
|
||||
|
||||
return res
|
||||
|
||||
class CMakeFileGroup:
|
||||
def __init__(self, data: dict):
|
||||
self.defines = data.get('defines', '')
|
||||
|
@ -163,3 +183,78 @@ class CMakeConfiguration:
|
|||
mlog.log('Project {}:'.format(idx))
|
||||
with mlog.nested():
|
||||
i.log()
|
||||
|
||||
class SingleTargetOptions:
|
||||
def __init__(self) -> None:
|
||||
self.opts = {} # type: T.Dict[str, str]
|
||||
self.lang_args = {} # type: T.Dict[str, T.List[str]]
|
||||
self.link_args = [] # type: T.List[str]
|
||||
self.install = 'preserve'
|
||||
|
||||
def set_opt(self, opt: str, val: str) -> None:
|
||||
self.opts[opt] = val
|
||||
|
||||
def append_args(self, lang: str, args: T.List[str]) -> None:
|
||||
if lang not in self.lang_args:
|
||||
self.lang_args[lang] = []
|
||||
self.lang_args[lang] += args
|
||||
|
||||
def append_link_args(self, args: T.List[str]) -> None:
|
||||
self.link_args += args
|
||||
|
||||
def set_install(self, install: bool) -> None:
|
||||
self.install = 'true' if install else 'false'
|
||||
|
||||
def get_override_options(self, initial: T.List[str]) -> T.List[str]:
|
||||
res = [] # type: T.List[str]
|
||||
for i in initial:
|
||||
opt = i[:i.find('=')]
|
||||
if opt not in self.opts:
|
||||
res += [i]
|
||||
res += ['{}={}'.format(k, v) for k, v in self.opts.items()]
|
||||
return res
|
||||
|
||||
def get_compile_args(self, lang: str, initial: T.List[str]) -> T.List[str]:
|
||||
if lang in self.lang_args:
|
||||
return initial + self.lang_args[lang]
|
||||
return initial
|
||||
|
||||
def get_link_args(self, initial: T.List[str]) -> T.List[str]:
|
||||
return initial + self.link_args
|
||||
|
||||
def get_install(self, initial: bool) -> bool:
|
||||
return {'preserve': initial, 'true': True, 'false': False}[self.install]
|
||||
|
||||
class TargetOptions:
|
||||
def __init__(self) -> None:
|
||||
self.global_options = SingleTargetOptions()
|
||||
self.target_options = {} # type: T.Dict[str, SingleTargetOptions]
|
||||
|
||||
def __getitem__(self, tgt: str) -> SingleTargetOptions:
|
||||
if tgt not in self.target_options:
|
||||
self.target_options[tgt] = SingleTargetOptions()
|
||||
return self.target_options[tgt]
|
||||
|
||||
def get_override_options(self, tgt: str, initial: T.List[str]) -> T.List[str]:
|
||||
initial = self.global_options.get_override_options(initial)
|
||||
if tgt in self.target_options:
|
||||
initial = self.target_options[tgt].get_override_options(initial)
|
||||
return initial
|
||||
|
||||
def get_compile_args(self, tgt: str, lang: str, initial: T.List[str]) -> T.List[str]:
|
||||
initial = self.global_options.get_compile_args(lang, initial)
|
||||
if tgt in self.target_options:
|
||||
initial = self.target_options[tgt].get_compile_args(lang, initial)
|
||||
return initial
|
||||
|
||||
def get_link_args(self, tgt: str, initial: T.List[str]) -> T.List[str]:
|
||||
initial = self.global_options.get_link_args(initial)
|
||||
if tgt in self.target_options:
|
||||
initial = self.target_options[tgt].get_link_args(initial)
|
||||
return initial
|
||||
|
||||
def get_install(self, tgt: str, initial: bool) -> bool:
|
||||
initial = self.global_options.get_install(initial)
|
||||
if tgt in self.target_options:
|
||||
initial = self.target_options[tgt].get_install(initial)
|
||||
return initial
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
import pkg_resources
|
||||
|
||||
from .common import CMakeException, CMakeTarget
|
||||
from .common import CMakeException, CMakeTarget, TargetOptions
|
||||
from .client import CMakeClient, RequestCMakeInputs, RequestConfigure, RequestCompute, RequestCodeModel
|
||||
from .fileapi import CMakeFileAPI
|
||||
from .executor import CMakeExecutor
|
||||
|
@ -993,7 +993,7 @@ class CMakeInterpreter:
|
|||
|
||||
mlog.log('CMake project', mlog.bold(self.project_name), 'has', mlog.bold(str(len(self.targets) + len(self.custom_targets))), 'build targets.')
|
||||
|
||||
def pretend_to_be_meson(self) -> CodeBlockNode:
|
||||
def pretend_to_be_meson(self, options: TargetOptions) -> CodeBlockNode:
|
||||
if not self.project_name:
|
||||
raise CMakeException('CMakeInterpreter was not analysed')
|
||||
|
||||
|
@ -1154,21 +1154,26 @@ class CMakeInterpreter:
|
|||
dep_var = '{}_dep'.format(tgt.name)
|
||||
tgt_var = tgt.name
|
||||
|
||||
install_tgt = options.get_install(tgt.cmake_name, tgt.install)
|
||||
|
||||
# Generate target kwargs
|
||||
tgt_kwargs = {
|
||||
'build_by_default': tgt.install,
|
||||
'link_args': tgt.link_flags + tgt.link_libraries,
|
||||
'build_by_default': install_tgt,
|
||||
'link_args': options.get_link_args(tgt.cmake_name, tgt.link_flags + tgt.link_libraries),
|
||||
'link_with': link_with,
|
||||
'include_directories': id_node(inc_var),
|
||||
'install': tgt.install,
|
||||
'install_dir': tgt.install_dir,
|
||||
'override_options': tgt.override_options,
|
||||
'install': install_tgt,
|
||||
'override_options': options.get_override_options(tgt.cmake_name, tgt.override_options),
|
||||
'objects': [method(x, 'extract_all_objects') for x in objec_libs],
|
||||
}
|
||||
|
||||
# Only set if installed and only override if it is set
|
||||
if install_tgt and tgt.install_dir:
|
||||
tgt_kwargs['install_dir'] = tgt.install_dir
|
||||
|
||||
# Handle compiler args
|
||||
for key, val in tgt.compile_opts.items():
|
||||
tgt_kwargs['{}_args'.format(key)] = val
|
||||
tgt_kwargs['{}_args'.format(key)] = options.get_compile_args(tgt.cmake_name, key, val)
|
||||
|
||||
# Handle -fPCI, etc
|
||||
if tgt_func == 'executable':
|
||||
|
|
|
@ -2444,7 +2444,7 @@ class Interpreter(InterpreterBase):
|
|||
|
||||
if isinstance(item, build.CustomTarget):
|
||||
return CustomTargetHolder(item, self)
|
||||
elif isinstance(item, (int, str, bool, Disabler)) or item is None:
|
||||
elif isinstance(item, (int, str, bool, Disabler, InterpreterObject)) or item is None:
|
||||
return item
|
||||
elif isinstance(item, build.Executable):
|
||||
return ExecutableHolder(item, self)
|
||||
|
@ -2867,13 +2867,21 @@ external dependencies (including libraries) must go to "dependencies".''')
|
|||
with mlog.nested():
|
||||
new_build = self.build.copy()
|
||||
prefix = self.coredata.builtins['prefix'].value
|
||||
|
||||
from .modules.cmake import CMakeSubprojectOptions
|
||||
options = kwargs.get('options', CMakeSubprojectOptions())
|
||||
if not isinstance(options, CMakeSubprojectOptions):
|
||||
raise InterpreterException('"options" kwarg must be CMakeSubprojectOptions'
|
||||
' object (created by cmake.subproject_options())')
|
||||
|
||||
cmake_options = mesonlib.stringlistify(kwargs.get('cmake_options', []))
|
||||
cmake_options += options.cmake_options
|
||||
cm_int = CMakeInterpreter(new_build, subdir, subdir_abs, prefix, new_build.environment, self.backend)
|
||||
cm_int.initialise(cmake_options)
|
||||
cm_int.analyse()
|
||||
|
||||
# Generate a meson ast and execute it with the normal do_subproject_meson
|
||||
ast = cm_int.pretend_to_be_meson()
|
||||
ast = cm_int.pretend_to_be_meson(options.target_options)
|
||||
|
||||
mlog.log()
|
||||
with mlog.nested():
|
||||
|
|
|
@ -14,12 +14,28 @@
|
|||
import re
|
||||
import os, os.path, pathlib
|
||||
import shutil
|
||||
import typing as T
|
||||
|
||||
from . import ExtensionModule, ModuleReturnValue
|
||||
|
||||
from .. import build, dependencies, mesonlib, mlog
|
||||
from ..interpreterbase import permittedKwargs, FeatureNew, stringArgs, InterpreterObject, ObjectHolder, noPosargs
|
||||
from ..cmake import SingleTargetOptions, TargetOptions, cmake_defines_to_args
|
||||
from ..interpreter import ConfigurationDataHolder, InterpreterException, SubprojectHolder
|
||||
from ..interpreterbase import (
|
||||
InterpreterObject,
|
||||
ObjectHolder,
|
||||
|
||||
FeatureNew,
|
||||
FeatureNewKwargs,
|
||||
FeatureDeprecatedKwargs,
|
||||
|
||||
stringArgs,
|
||||
permittedKwargs,
|
||||
noPosargs,
|
||||
noKwargs,
|
||||
|
||||
InvalidArguments,
|
||||
)
|
||||
|
||||
|
||||
COMPATIBILITIES = ['AnyNewerVersion', 'SameMajorVersion', 'SameMinorVersion', 'ExactVersion']
|
||||
|
@ -82,42 +98,107 @@ class CMakeSubprojectHolder(InterpreterObject, ObjectHolder):
|
|||
assert(all([x in res for x in ['inc', 'src', 'dep', 'tgt', 'func']]))
|
||||
return res
|
||||
|
||||
@permittedKwargs({})
|
||||
@noKwargs
|
||||
@stringArgs
|
||||
def get_variable(self, args, kwargs):
|
||||
return self.held_object.get_variable_method(args, kwargs)
|
||||
|
||||
@permittedKwargs({})
|
||||
@noKwargs
|
||||
@stringArgs
|
||||
def dependency(self, args, kwargs):
|
||||
info = self._args_to_info(args)
|
||||
return self.get_variable([info['dep']], kwargs)
|
||||
|
||||
@permittedKwargs({})
|
||||
@noKwargs
|
||||
@stringArgs
|
||||
def include_directories(self, args, kwargs):
|
||||
info = self._args_to_info(args)
|
||||
return self.get_variable([info['inc']], kwargs)
|
||||
|
||||
@permittedKwargs({})
|
||||
@noKwargs
|
||||
@stringArgs
|
||||
def target(self, args, kwargs):
|
||||
info = self._args_to_info(args)
|
||||
return self.get_variable([info['tgt']], kwargs)
|
||||
|
||||
@permittedKwargs({})
|
||||
@noKwargs
|
||||
@stringArgs
|
||||
def target_type(self, args, kwargs):
|
||||
info = self._args_to_info(args)
|
||||
return info['func']
|
||||
|
||||
@noPosargs
|
||||
@permittedKwargs({})
|
||||
@noKwargs
|
||||
def target_list(self, args, kwargs):
|
||||
return self.held_object.cm_interpreter.target_list()
|
||||
|
||||
@noPosargs
|
||||
@permittedKwargs({})
|
||||
@noKwargs
|
||||
@FeatureNew('CMakeSubproject.found()', '0.53.2')
|
||||
def found_method(self, args, kwargs):
|
||||
return self.held_object is not None
|
||||
|
||||
|
||||
class CMakeSubprojectOptions(InterpreterObject):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self.cmake_options = [] # type: T.List[str]
|
||||
self.target_options = TargetOptions()
|
||||
|
||||
self.methods.update(
|
||||
{
|
||||
'add_cmake_defines': self.add_cmake_defines,
|
||||
'set_override_option': self.set_override_option,
|
||||
'set_install': self.set_install,
|
||||
'append_compile_args': self.append_compile_args,
|
||||
'append_link_args': self.append_link_args,
|
||||
'clear': self.clear,
|
||||
}
|
||||
)
|
||||
|
||||
def _get_opts(self, kwargs: dict) -> SingleTargetOptions:
|
||||
if 'target' in kwargs:
|
||||
return self.target_options[kwargs['target']]
|
||||
return self.target_options.global_options
|
||||
|
||||
@noKwargs
|
||||
def add_cmake_defines(self, args, kwargs) -> None:
|
||||
self.cmake_options += cmake_defines_to_args(args)
|
||||
|
||||
@stringArgs
|
||||
@permittedKwargs({'target'})
|
||||
def set_override_option(self, args, kwargs) -> None:
|
||||
if len(args) != 2:
|
||||
raise InvalidArguments('set_override_option takes exactly 2 positional arguments')
|
||||
self._get_opts(kwargs).set_opt(args[0], args[1])
|
||||
|
||||
@permittedKwargs({'target'})
|
||||
def set_install(self, args, kwargs) -> None:
|
||||
if len(args) != 1 or not isinstance(args[0], bool):
|
||||
raise InvalidArguments('set_install takes exactly 1 boolean argument')
|
||||
self._get_opts(kwargs).set_install(args[0])
|
||||
|
||||
@stringArgs
|
||||
@permittedKwargs({'target'})
|
||||
def append_compile_args(self, args, kwargs) -> None:
|
||||
if len(args) < 2:
|
||||
raise InvalidArguments('append_compile_args takes at least 2 positional arguments')
|
||||
self._get_opts(kwargs).append_args(args[0], args[1:])
|
||||
|
||||
@stringArgs
|
||||
@permittedKwargs({'target'})
|
||||
def append_link_args(self, args, kwargs) -> None:
|
||||
if not args:
|
||||
raise InvalidArguments('append_link_args takes at least 1 positional argument')
|
||||
self._get_opts(kwargs).append_link_args(args)
|
||||
|
||||
@noPosargs
|
||||
@noKwargs
|
||||
def clear(self, args, kwargs) -> None:
|
||||
self.cmake_options.clear()
|
||||
self.target_options = TargetOptions()
|
||||
|
||||
|
||||
class CmakeModule(ExtensionModule):
|
||||
cmake_detected = False
|
||||
cmake_root = None
|
||||
|
@ -286,16 +367,27 @@ class CmakeModule(ExtensionModule):
|
|||
return res
|
||||
|
||||
@FeatureNew('subproject', '0.51.0')
|
||||
@permittedKwargs({'cmake_options', 'required'})
|
||||
@FeatureNewKwargs('subproject', '0.55.0', ['options'])
|
||||
@FeatureDeprecatedKwargs('subproject', '0.55.0', ['cmake_options'])
|
||||
@permittedKwargs({'cmake_options', 'required', 'options'})
|
||||
@stringArgs
|
||||
def subproject(self, interpreter, state, args, kwargs):
|
||||
if len(args) != 1:
|
||||
raise InterpreterException('Subproject takes exactly one argument')
|
||||
if 'cmake_options' in kwargs and 'options' in kwargs:
|
||||
raise InterpreterException('"options" cannot be used together with "cmake_options"')
|
||||
dirname = args[0]
|
||||
subp = interpreter.do_subproject(dirname, 'cmake', kwargs)
|
||||
if not subp.held_object:
|
||||
return subp
|
||||
return CMakeSubprojectHolder(subp, dirname)
|
||||
|
||||
@FeatureNew('subproject_options', '0.55.0')
|
||||
@noKwargs
|
||||
@noPosargs
|
||||
def subproject_options(self, state, args, kwargs) -> ModuleReturnValue:
|
||||
opts = CMakeSubprojectOptions()
|
||||
return ModuleReturnValue(opts, [])
|
||||
|
||||
def initialize(*args, **kwargs):
|
||||
return CmakeModule(*args, **kwargs)
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
#include <iostream>
|
||||
#include <cmMod.hpp>
|
||||
#include <cmTest.hpp>
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main(void) {
|
||||
cmModClass obj("Hello");
|
||||
cout << obj.getStr() << endl;
|
||||
|
||||
int v1 = obj.getInt();
|
||||
int v2 = getTestInt();
|
||||
if (v1 != ((1 + v2) * 2)) {
|
||||
cerr << "Number test failed" << endl;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
project('cmake_set_opt', ['c', 'cpp'])
|
||||
|
||||
comp = meson.get_compiler('cpp')
|
||||
if comp.get_argument_syntax() == 'msvc'
|
||||
error('MESON_SKIP_TEST: MSVC is not supported because it does not support C++11')
|
||||
endif
|
||||
|
||||
cm = import('cmake')
|
||||
opts = cm.subproject_options()
|
||||
|
||||
opts.add_cmake_defines({'SOME_CMAKE_VAR': 'something', 'SOME_OTHER_VAR': true})
|
||||
|
||||
opts.set_override_option('cpp_std', 'c++11') # Global is C++11
|
||||
opts.set_override_option('cpp_std', 'c++14', target: 'cmModLib++') # Override it with C++14 for cmModLib++
|
||||
|
||||
opts.append_compile_args('cpp', '-DMESON_GLOBAL_FLAG=1')
|
||||
opts.append_compile_args('cpp', ['-DMESON_SPECIAL_FLAG1=1', ['-DMESON_SPECIAL_FLAG2=1']], target: 'cmModLib++')
|
||||
opts.append_compile_args('cpp', '-DMESON_MAGIC_INT=42', target: 'cmModLib++')
|
||||
opts.append_compile_args('cpp', [[[['-DMESON_MAGIC_INT=20']]]], target: 'cmTestLib')
|
||||
|
||||
opts.set_install(false)
|
||||
opts.set_install(true, target: 'testEXE')
|
||||
|
||||
sp = cm.subproject('cmOpts', options: opts)
|
||||
dep1 = sp.dependency('cmModLib++')
|
||||
dep2 = sp.dependency('cmTestLib')
|
||||
|
||||
exe1 = executable('main', ['main.cpp'], dependencies: [dep1, dep2])
|
||||
test('test1', exe1)
|
|
@ -0,0 +1,18 @@
|
|||
cmake_minimum_required(VERSION 3.7)
|
||||
|
||||
project(CmOpts)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 98)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
if(NOT "${SOME_CMAKE_VAR}" STREQUAL "something")
|
||||
message(FATAL_ERROR "Setting the CMake var failed")
|
||||
endif()
|
||||
|
||||
add_library(cmModLib++ STATIC cmMod.cpp)
|
||||
add_library(cmTestLib STATIC cmTest.cpp)
|
||||
add_executable(testEXE main.cpp)
|
||||
|
||||
target_link_libraries(testEXE cmModLib++)
|
||||
|
||||
install(TARGETS cmTestLib ARCHIVE DESTINATION lib RUNTIME DESTINATION bin)
|
|
@ -0,0 +1,31 @@
|
|||
#include "cmMod.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
#if __cplusplus < 201402L
|
||||
#error "At least C++14 is required"
|
||||
#endif
|
||||
|
||||
#ifndef MESON_GLOBAL_FLAG
|
||||
#error "MESON_GLOBAL_FLAG was not set"
|
||||
#endif
|
||||
|
||||
#ifndef MESON_SPECIAL_FLAG1
|
||||
#error "MESON_SPECIAL_FLAG1 was not set"
|
||||
#endif
|
||||
|
||||
#ifndef MESON_SPECIAL_FLAG2
|
||||
#error "MESON_SPECIAL_FLAG2 was not set"
|
||||
#endif
|
||||
|
||||
cmModClass::cmModClass(string foo) {
|
||||
str = foo + " World";
|
||||
}
|
||||
|
||||
string cmModClass::getStr() const {
|
||||
return str;
|
||||
}
|
||||
|
||||
int cmModClass::getInt() const {
|
||||
return MESON_MAGIC_INT;
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
class cmModClass {
|
||||
private:
|
||||
std::string str;
|
||||
|
||||
public:
|
||||
cmModClass(std::string foo);
|
||||
|
||||
std::string getStr() const;
|
||||
int getInt() const;
|
||||
};
|
|
@ -0,0 +1,25 @@
|
|||
#include "cmTest.hpp"
|
||||
|
||||
#if __cplusplus < 201103L
|
||||
#error "At least C++11 is required"
|
||||
#endif
|
||||
|
||||
#if __cplusplus >= 201402L
|
||||
#error "At most C++11 is required"
|
||||
#endif
|
||||
|
||||
#ifndef MESON_GLOBAL_FLAG
|
||||
#error "MESON_GLOBAL_FLAG was not set"
|
||||
#endif
|
||||
|
||||
#ifdef MESON_SPECIAL_FLAG1
|
||||
#error "MESON_SPECIAL_FLAG1 *was* set"
|
||||
#endif
|
||||
|
||||
#ifdef MESON_SPECIAL_FLAG2
|
||||
#error "MESON_SPECIAL_FLAG2 *was* set"
|
||||
#endif
|
||||
|
||||
int getTestInt() {
|
||||
return MESON_MAGIC_INT;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
int getTestInt();
|
|
@ -0,0 +1,10 @@
|
|||
#include <iostream>
|
||||
#include "cmMod.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main(void) {
|
||||
cmModClass obj("Hello (LIB TEST)");
|
||||
cout << obj.getStr() << endl;
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"installed": [
|
||||
{"type": "exe", "file": "usr/bin/cm_testEXE"}
|
||||
],
|
||||
"tools": {
|
||||
"cmake": ">=3.11"
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue