Merge pull request #7231 from mensinda/cmOverride

cmake: Add more advanced subproject configuration options
This commit is contained in:
Jussi Pakkanen 2020-07-01 00:04:08 +03:00 committed by GitHub
commit 64f36613ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 470 additions and 23 deletions

View File

@ -48,8 +48,6 @@ The `subproject` method is almost identical to the normal meson
`subproject` function. The only difference is that a CMake project `subproject` function. The only difference is that a CMake project
instead of a meson project is configured. 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. The returned `sub_proj` supports the same options as a "normal" subproject.
Meson automatically detects CMake build targets, which can be accessed with Meson automatically detects CMake build targets, which can be accessed with
the methods listed [below](#subproject-object). 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 safest approach would still be to create a `meson.build` for the
subprojects in question. 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 ### `subproject` object
This object is returned by the `subproject` function described above 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 the subproject. Usually `dependency()` or `target()` should be
preferred to extract build targets. preferred to extract build targets.
- `found` returns true if the subproject is available, otherwise false - `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 ## CMake configuration files

View File

@ -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.

View File

@ -24,11 +24,14 @@ __all__ = [
'CMakeTarget', 'CMakeTarget',
'CMakeTraceLine', 'CMakeTraceLine',
'CMakeTraceParser', 'CMakeTraceParser',
'SingleTargetOptions',
'TargetOptions',
'parse_generator_expressions', 'parse_generator_expressions',
'language_map', '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 .client import CMakeClient
from .executor import CMakeExecutor from .executor import CMakeExecutor
from .fileapi import CMakeFileAPI from .fileapi import CMakeFileAPI

View File

@ -60,6 +60,26 @@ def _flags_to_list(raw: str) -> T.List[str]:
res = list(filter(lambda x: len(x) > 0, res)) res = list(filter(lambda x: len(x) > 0, res))
return 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: class CMakeFileGroup:
def __init__(self, data: dict): def __init__(self, data: dict):
self.defines = data.get('defines', '') self.defines = data.get('defines', '')
@ -163,3 +183,78 @@ class CMakeConfiguration:
mlog.log('Project {}:'.format(idx)) mlog.log('Project {}:'.format(idx))
with mlog.nested(): with mlog.nested():
i.log() 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

View File

@ -17,7 +17,7 @@
import pkg_resources import pkg_resources
from .common import CMakeException, CMakeTarget from .common import CMakeException, CMakeTarget, TargetOptions
from .client import CMakeClient, RequestCMakeInputs, RequestConfigure, RequestCompute, RequestCodeModel from .client import CMakeClient, RequestCMakeInputs, RequestConfigure, RequestCompute, RequestCodeModel
from .fileapi import CMakeFileAPI from .fileapi import CMakeFileAPI
from .executor import CMakeExecutor 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.') 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: if not self.project_name:
raise CMakeException('CMakeInterpreter was not analysed') raise CMakeException('CMakeInterpreter was not analysed')
@ -1154,21 +1154,26 @@ class CMakeInterpreter:
dep_var = '{}_dep'.format(tgt.name) dep_var = '{}_dep'.format(tgt.name)
tgt_var = tgt.name tgt_var = tgt.name
install_tgt = options.get_install(tgt.cmake_name, tgt.install)
# Generate target kwargs # Generate target kwargs
tgt_kwargs = { tgt_kwargs = {
'build_by_default': tgt.install, 'build_by_default': install_tgt,
'link_args': tgt.link_flags + tgt.link_libraries, 'link_args': options.get_link_args(tgt.cmake_name, tgt.link_flags + tgt.link_libraries),
'link_with': link_with, 'link_with': link_with,
'include_directories': id_node(inc_var), 'include_directories': id_node(inc_var),
'install': tgt.install, 'install': install_tgt,
'install_dir': tgt.install_dir, 'override_options': options.get_override_options(tgt.cmake_name, tgt.override_options),
'override_options': tgt.override_options,
'objects': [method(x, 'extract_all_objects') for x in objec_libs], '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 # Handle compiler args
for key, val in tgt.compile_opts.items(): 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 # Handle -fPCI, etc
if tgt_func == 'executable': if tgt_func == 'executable':

View File

@ -2444,7 +2444,7 @@ class Interpreter(InterpreterBase):
if isinstance(item, build.CustomTarget): if isinstance(item, build.CustomTarget):
return CustomTargetHolder(item, self) 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 return item
elif isinstance(item, build.Executable): elif isinstance(item, build.Executable):
return ExecutableHolder(item, self) return ExecutableHolder(item, self)
@ -2867,13 +2867,21 @@ external dependencies (including libraries) must go to "dependencies".''')
with mlog.nested(): with mlog.nested():
new_build = self.build.copy() new_build = self.build.copy()
prefix = self.coredata.builtins['prefix'].value 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 = 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 = CMakeInterpreter(new_build, subdir, subdir_abs, prefix, new_build.environment, self.backend)
cm_int.initialise(cmake_options) cm_int.initialise(cmake_options)
cm_int.analyse() cm_int.analyse()
# Generate a meson ast and execute it with the normal do_subproject_meson # 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() mlog.log()
with mlog.nested(): with mlog.nested():

View File

@ -14,12 +14,28 @@
import re import re
import os, os.path, pathlib import os, os.path, pathlib
import shutil import shutil
import typing as T
from . import ExtensionModule, ModuleReturnValue from . import ExtensionModule, ModuleReturnValue
from .. import build, dependencies, mesonlib, mlog 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 ..interpreter import ConfigurationDataHolder, InterpreterException, SubprojectHolder
from ..interpreterbase import (
InterpreterObject,
ObjectHolder,
FeatureNew,
FeatureNewKwargs,
FeatureDeprecatedKwargs,
stringArgs,
permittedKwargs,
noPosargs,
noKwargs,
InvalidArguments,
)
COMPATIBILITIES = ['AnyNewerVersion', 'SameMajorVersion', 'SameMinorVersion', 'ExactVersion'] 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']])) assert(all([x in res for x in ['inc', 'src', 'dep', 'tgt', 'func']]))
return res return res
@permittedKwargs({}) @noKwargs
@stringArgs
def get_variable(self, args, kwargs): def get_variable(self, args, kwargs):
return self.held_object.get_variable_method(args, kwargs) return self.held_object.get_variable_method(args, kwargs)
@permittedKwargs({}) @noKwargs
@stringArgs
def dependency(self, args, kwargs): def dependency(self, args, kwargs):
info = self._args_to_info(args) info = self._args_to_info(args)
return self.get_variable([info['dep']], kwargs) return self.get_variable([info['dep']], kwargs)
@permittedKwargs({}) @noKwargs
@stringArgs
def include_directories(self, args, kwargs): def include_directories(self, args, kwargs):
info = self._args_to_info(args) info = self._args_to_info(args)
return self.get_variable([info['inc']], kwargs) return self.get_variable([info['inc']], kwargs)
@permittedKwargs({}) @noKwargs
@stringArgs
def target(self, args, kwargs): def target(self, args, kwargs):
info = self._args_to_info(args) info = self._args_to_info(args)
return self.get_variable([info['tgt']], kwargs) return self.get_variable([info['tgt']], kwargs)
@permittedKwargs({}) @noKwargs
@stringArgs
def target_type(self, args, kwargs): def target_type(self, args, kwargs):
info = self._args_to_info(args) info = self._args_to_info(args)
return info['func'] return info['func']
@noPosargs @noPosargs
@permittedKwargs({}) @noKwargs
def target_list(self, args, kwargs): def target_list(self, args, kwargs):
return self.held_object.cm_interpreter.target_list() return self.held_object.cm_interpreter.target_list()
@noPosargs @noPosargs
@permittedKwargs({}) @noKwargs
@FeatureNew('CMakeSubproject.found()', '0.53.2') @FeatureNew('CMakeSubproject.found()', '0.53.2')
def found_method(self, args, kwargs): def found_method(self, args, kwargs):
return self.held_object is not None 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): class CmakeModule(ExtensionModule):
cmake_detected = False cmake_detected = False
cmake_root = None cmake_root = None
@ -286,16 +367,27 @@ class CmakeModule(ExtensionModule):
return res return res
@FeatureNew('subproject', '0.51.0') @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 @stringArgs
def subproject(self, interpreter, state, args, kwargs): def subproject(self, interpreter, state, args, kwargs):
if len(args) != 1: if len(args) != 1:
raise InterpreterException('Subproject takes exactly one argument') 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] dirname = args[0]
subp = interpreter.do_subproject(dirname, 'cmake', kwargs) subp = interpreter.do_subproject(dirname, 'cmake', kwargs)
if not subp.held_object: if not subp.held_object:
return subp return subp
return CMakeSubprojectHolder(subp, dirname) 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): def initialize(*args, **kwargs):
return CmakeModule(*args, **kwargs) return CmakeModule(*args, **kwargs)

View File

@ -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;
}

View File

@ -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)

View File

@ -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)

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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;
}

View File

@ -0,0 +1,3 @@
#pragma once
int getTestInt();

View File

@ -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;
}

View File

@ -0,0 +1,8 @@
{
"installed": [
{"type": "exe", "file": "usr/bin/cm_testEXE"}
],
"tools": {
"cmake": ">=3.11"
}
}