diff options
47 files changed, 383 insertions, 97 deletions
diff --git a/data/syntax-highlighting/vim/syntax/meson.vim b/data/syntax-highlighting/vim/syntax/meson.vim index d0d15d9..1100113 100644 --- a/data/syntax-highlighting/vim/syntax/meson.vim +++ b/data/syntax-highlighting/vim/syntax/meson.vim @@ -32,8 +32,9 @@ set cpo&vim " http://mesonbuild.com/Syntax.html syn keyword mesonConditional elif else if endif -syn keyword mesonRepeat foreach endforeach +syn keyword mesonRepeat foreach endforeach syn keyword mesonOperator and not or in +syn keyword mesonStatement continue break syn match mesonComment "#.*$" contains=mesonTodo,@Spell syn keyword mesonTodo FIXME NOTE NOTES TODO XXX contained diff --git a/docs/markdown/Builtin-options.md b/docs/markdown/Builtin-options.md index e7101d5..6234ecf 100644 --- a/docs/markdown/Builtin-options.md +++ b/docs/markdown/Builtin-options.md @@ -59,27 +59,27 @@ Options that are labeled "per machine" in the table are set per machine. See the [specifying options per machine](#Specifying-options-per-machine) section for details. -| Option | Default value | Description | Is per machine | -| ------ | ------------- | ----------- | -------------- | -| auto_features {enabled, disabled, auto} | auto | Override value of all 'auto' features | no | -| backend {ninja, vs,<br>vs2010, vs2015, vs2017, vs2019, xcode} | ninja | Backend to use | no | -| buildtype {plain, debug,<br>debugoptimized, release, minsize, custom} | debug | Build type to use | no | -| debug | true | Debug | no | -| default_library {shared, static, both} | shared | Default library type | no | -| errorlogs | true | Whether to print the logs from failing tests. | no | -| install_umask {preserve, 0000-0777} | 022 | Default umask to apply on permissions of installed files | no | -| layout {mirror,flat} | mirror | Build directory layout | no | -| optimization {0, g, 1, 2, 3, s} | 0 | Optimization level | no | -| pkg_config_path {OS separated path} | '' | Additional paths for pkg-config to search before builtin paths | yes | -| cmake_prefix_path | [] | Additional prefixes for cmake to search before builtin paths | yes | -| stdsplit | true | Split stdout and stderr in test logs | no | -| strip | false | Strip targets on install | no | -| unity {on, off, subprojects} | off | Unity build | no | -| unity_size {>=2} | 4 | Unity file block size | no | -| warning_level {0, 1, 2, 3} | 1 | Set the warning level. From 0 = none to 3 = highest | no | -| werror | false | Treat warnings as errors | no | -| wrap_mode {default, nofallback,<br>nodownload, forcefallback} | default | Wrap mode to use | no | -| force_fallback_for | [] | Force fallback for those dependencies | no | +| Option | Default value | Description | Is per machine | Is per subproject | +| ------ | ------------- | ----------- | -------------- | ----------------- | +| auto_features {enabled, disabled, auto} | auto | Override value of all 'auto' features | no | no | +| backend {ninja, vs,<br>vs2010, vs2015, vs2017, vs2019, xcode} | ninja | Backend to use | no | no | +| buildtype {plain, debug,<br>debugoptimized, release, minsize, custom} | debug | Build type to use | no | no | +| debug | true | Debug | no | no | +| default_library {shared, static, both} | shared | Default library type | no | yes | +| errorlogs | true | Whether to print the logs from failing tests. | no | no | +| install_umask {preserve, 0000-0777} | 022 | Default umask to apply on permissions of installed files | no | no | +| layout {mirror,flat} | mirror | Build directory layout | no | no | +| optimization {0, g, 1, 2, 3, s} | 0 | Optimization level | no | no | +| pkg_config_path {OS separated path} | '' | Additional paths for pkg-config to search before builtin paths | yes | no | +| cmake_prefix_path | [] | Additional prefixes for cmake to search before builtin paths | yes | no | +| stdsplit | true | Split stdout and stderr in test logs | no | no | +| strip | false | Strip targets on install | no | no | +| unity {on, off, subprojects} | off | Unity build | no | no | +| unity_size {>=2} | 4 | Unity file block size | no | no | +| warning_level {0, 1, 2, 3} | 1 | Set the warning level. From 0 = none to 3 = highest | no | yes | +| werror | false | Treat warnings as errors | no | yes | +| wrap_mode {default, nofallback,<br>nodownload, forcefallback} | default | Wrap mode to use | no | no | +| force_fallback_for | [] | Force fallback for those dependencies | no | no | <a name="build-type-options"></a> For setting optimization levels and toggling debug, you can either set the @@ -215,3 +215,22 @@ the command line, as there was no `build.` prefix. Similarly named fields in the `[properties]` section of the cross file would effect cross compilers, but the code paths were fairly different allowing differences in behavior to crop out. + +## Specifying options per subproject + +Since *0.54.0* `default_library` and `werror` built-in options can be defined +per subproject. This is useful for example when building shared libraries in the +main project, but static link a subproject, or when the main project must build +with no warnings but some subprojects cannot. + +Most of the time this would be used either by the parent project by setting +subproject's default_options (e.g. `subproject('foo', default_options: 'default_library=static')`), +or by the user using the command line `-Dfoo:default_library=static`. + +The value is overriden in this order: +- Value from parent project +- Value from subproject's default_options if set +- Value from subproject() default_options if set +- Value from command line if set + +Since 0.56.0 `warning_level` can also be defined per subproject. diff --git a/docs/markdown/Dependencies.md b/docs/markdown/Dependencies.md index a8f6d8a..b89a0aa 100644 --- a/docs/markdown/Dependencies.md +++ b/docs/markdown/Dependencies.md @@ -288,8 +288,12 @@ You can call `dependency` multiple times with different modules and use those to link against your targets. If your boost headers or libraries are in non-standard locations you -can set the BOOST_ROOT, BOOST_INCLUDEDIR, and/or BOOST_LIBRARYDIR -environment variables. +can set the `BOOST_ROOT`, or the `BOOST_INCLUDEDIR` and `BOOST_LIBRARYDIR` +environment variables. *(added in 0.56.0)* You can also set these +parameters as `boost_root`, `boost_include`, and `boost_librarydir` in your +native or cross machine file. Note that machine file variables are +preferred to environment variables, and that specifying any of these +disables system-wide search for boost. You can set the argument `threading` to `single` to use boost libraries that have been compiled for single-threaded use instead. diff --git a/docs/markdown/Keyval-module.md b/docs/markdown/Keyval-module.md index 643265e..afc48fa 100644 --- a/docs/markdown/Keyval-module.md +++ b/docs/markdown/Keyval-module.md @@ -1,5 +1,5 @@ --- -short-description: Unstable keyval module +short-description: Keyval module authors: - name: Mark Schulte, Paolo Bonzini years: [2017, 2019] @@ -23,7 +23,7 @@ chosen the configuration options), output a ".config" file. The module may be imported as follows: ``` meson -keyval = import('unstable-keyval') +keyval = import('keyval') ``` The following functions will then be available as methods on the object diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md index 966d408..080fe3e 100644 --- a/docs/markdown/Reference-manual.md +++ b/docs/markdown/Reference-manual.md @@ -1977,6 +1977,9 @@ are immutable, all operations return their results as a new string. - `startswith(string)`: returns true if string starts with the string specified as the argument +- `substring(start,end)` *(since 0.56.0)*: returns a substring specified from start to end. + Both `start` and `end` arguments are optional, so, for example, `'foobar'.substring()` will return `'foobar'`. + - `strip()`: removes whitespace at the beginning and end of the string. *(since 0.43.0)* Optionally can take one positional string argument, and all characters in that string will be stripped. diff --git a/docs/markdown/Syntax.md b/docs/markdown/Syntax.md index 7cb39e9..bbe3dbb 100644 --- a/docs/markdown/Syntax.md +++ b/docs/markdown/Syntax.md @@ -220,6 +220,26 @@ is_x86 = target.startswith('x86') # boolean value 'true' is_bsd = target.to_lower().endswith('bsd') # boolean value 'true' ``` +#### .substring() + +Since 0.56.0, you can extract a substring from a string. + +```meson +# Similar to the Python str[start:end] syntax +target = 'x86_FreeBSD' +platform = target.substring(0, 3) # prefix string value 'x86' +system = target.substring(4) # suffix string value 'FreeBSD' +``` + +The method accepts negative values where negative `start` is relative to the end of +string `len(string) - start` as well as negative `end`. + +```meson +string = 'foobar' +target.substring(-5, -3) # => 'oo' +target.substring(1, -1) # => 'ooba' +``` + #### .split(), .join() ```meson diff --git a/docs/markdown/Vala.md b/docs/markdown/Vala.md index cbb58a9..0a29847 100644 --- a/docs/markdown/Vala.md +++ b/docs/markdown/Vala.md @@ -237,7 +237,7 @@ dependencies = [ dependency('glib-2.0'), dependency('gobject-2.0'), meson.get_compiler('c').find_library('foo'), - meson.get_compiler('vala').find_library('foo', dir: vapi_dir), + meson.get_compiler('vala').find_library('foo', dirs: vapi_dir), ] sources = files('app.vala') diff --git a/docs/markdown/snippets/keyval.md b/docs/markdown/snippets/keyval.md new file mode 100644 index 0000000..895de9b --- /dev/null +++ b/docs/markdown/snippets/keyval.md @@ -0,0 +1,7 @@ +## `unstable-keyval` is now stable `keyval` + +The `unstable-keyval` has been renamed to `keyval` and now promises stability +guarantees. + +Meson will print a warning when you load an `unstable-` module that has been +stabilised (so `unstable-keyval` is still accepted for example). diff --git a/docs/markdown/snippets/per_subproject.md b/docs/markdown/snippets/per_subproject.md new file mode 100644 index 0000000..6de6068 --- /dev/null +++ b/docs/markdown/snippets/per_subproject.md @@ -0,0 +1,4 @@ +## Per subproject `warning_level` option + +`warning_level` can now be defined per subproject, in the same way as +`default_library` and `werror`. diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 065da00..3b4a4bd 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -348,7 +348,7 @@ class NinjaBuildElement: use_rspfile = self._should_use_rspfile() if use_rspfile: rulename = self.rulename + '_RSP' - mlog.log("Command line for building %s is long, using a response file" % self.outfilenames) + mlog.debug("Command line for building %s is long, using a response file" % self.outfilenames) else: rulename = self.rulename line = 'build {}{}: {} {}'.format(outs, implicit_outs, rulename, ins) @@ -459,7 +459,7 @@ int dummy; # different locales have different messages with a different # number of colons. Match up to the the drive name 'd:\'. # When used in cross compilation, the path separator is a - # backslash rather than a forward slash so handle both. + # forward slash rather than a backslash so handle both. matchre = re.compile(rb"^(.*\s)([a-zA-Z]:\\|\/).*stdio.h$") def detect_prefix(out): diff --git a/mesonbuild/build.py b/mesonbuild/build.py index d7f3b66..a06979c 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -819,7 +819,8 @@ class BuildTarget(Target): def get_link_dep_subdirs(self): result = OrderedSet() for i in self.link_targets: - result.add(i.get_subdir()) + if not isinstance(i, StaticLibrary): + result.add(i.get_subdir()) result.update(i.get_link_dep_subdirs()) return result diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index 478a68c..f5b0c05 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -577,7 +577,7 @@ class VisualStudioCPPCompiler(CPP11AsCPP14Mixin, VisualStudioLikeCPPCompilerMixi is_cross: bool, info: 'MachineInfo', exe_wrap, target, **kwargs): CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, info, exe_wrap, **kwargs) MSVCCompiler.__init__(self, target) - self.base_options = ['b_pch', 'b_vscrt'] # FIXME add lto, pgo and the like + self.base_options = ['b_pch', 'b_vscrt', 'b_ndebug'] # FIXME add lto, pgo and the like self.id = 'msvc' def get_options(self): diff --git a/mesonbuild/compilers/mixins/gnu.py b/mesonbuild/compilers/mixins/gnu.py index 3526a91..83f7047 100644 --- a/mesonbuild/compilers/mixins/gnu.py +++ b/mesonbuild/compilers/mixins/gnu.py @@ -362,7 +362,7 @@ class GnuCompiler(GnuLikeCompiler): # For some compiler command line arguments, the GNU compilers will # emit a warning on stderr indicating that an option is valid for a # another language, but still complete with exit_success - with self._build_wrapper(code, env, args, None, mode, disable_cache=False, want_output=True) as p: + with self._build_wrapper(code, env, args, None, mode) as p: result = p.returncode == 0 if self.language in {'cpp', 'objcpp'} and 'is valid for C/ObjC' in p.stde: result = False diff --git a/mesonbuild/compilers/mixins/visualstudio.py b/mesonbuild/compilers/mixins/visualstudio.py index 4dfd8b4..93101b5 100644 --- a/mesonbuild/compilers/mixins/visualstudio.py +++ b/mesonbuild/compilers/mixins/visualstudio.py @@ -114,7 +114,7 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta): # See: https://ninja-build.org/manual.html#_deps always_args = ['/nologo', '/showIncludes'] warn_args = { - '0': ['/W1'], + '0': [], '1': ['/W2'], '2': ['/W3'], '3': ['/W4'], diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 26f33f1..e2a6954 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -19,8 +19,9 @@ from itertools import chain from pathlib import PurePath from collections import OrderedDict, defaultdict from .mesonlib import ( - MesonException, MachineChoice, PerMachine, OrderedSet, - default_libdir, default_libexecdir, default_prefix, split_args + MesonException, EnvironmentException, MachineChoice, PerMachine, + OrderedSet, default_libdir, default_libexecdir, default_prefix, + split_args ) from .envconfig import get_env_var_pair from .wrap import WrapMode @@ -1181,7 +1182,7 @@ builtin_options = OrderedDict([ ('strip', BuiltinOption(UserBooleanOption, 'Strip targets on install', False)), ('unity', BuiltinOption(UserComboOption, 'Unity build', 'off', choices=['on', 'off', 'subprojects'])), ('unity_size', BuiltinOption(UserIntegerOption, 'Unity block size', (2, None, 4))), - ('warning_level', BuiltinOption(UserComboOption, 'Compiler warning level to use', '1', choices=['0', '1', '2', '3'])), + ('warning_level', BuiltinOption(UserComboOption, 'Compiler warning level to use', '1', choices=['0', '1', '2', '3'], yielding=False)), ('werror', BuiltinOption(UserBooleanOption, 'Treat warnings as errors', False, yielding=False)), ('wrap_mode', BuiltinOption(UserComboOption, 'Wrap mode', 'default', choices=['default', 'nofallback', 'nodownload', 'forcefallback'])), ('force_fallback_for', BuiltinOption(UserArrayOption, 'Force fallback for those subprojects', [])), diff --git a/mesonbuild/dependencies/boost.py b/mesonbuild/dependencies/boost.py index 907c0c2..3ad534e 100644 --- a/mesonbuild/dependencies/boost.py +++ b/mesonbuild/dependencies/boost.py @@ -20,6 +20,7 @@ from pathlib import Path from .. import mlog from .. import mesonlib +from ..envconfig import get_env_var from ..environment import Environment from .base import DependencyException, ExternalDependency, PkgConfigDependency @@ -163,8 +164,8 @@ class BoostLibraryFile(): if not tags: return - # Without any tags mt is assumed, however, an absents of mt in the name - # with tags present indicates that the lib was build without mt support + # Without any tags mt is assumed, however, an absence of mt in the name + # with tags present indicates that the lib was built without mt support self.mt = False for i in tags: if i == 'mt': @@ -367,36 +368,27 @@ class BoostDependency(ExternalDependency): self.arch = environment.machines[self.for_machine].cpu_family self.arch = boost_arch_map.get(self.arch, None) - # Prefere BOOST_INCLUDEDIR and BOOST_LIBRARYDIR if preset - boost_manual_env = [x in os.environ for x in ['BOOST_INCLUDEDIR', 'BOOST_LIBRARYDIR']] - if all(boost_manual_env): - inc_dir = Path(os.environ['BOOST_INCLUDEDIR']) - lib_dir = Path(os.environ['BOOST_LIBRARYDIR']) - mlog.debug('Trying to find boost with:') - mlog.debug(' - BOOST_INCLUDEDIR = {}'.format(inc_dir)) - mlog.debug(' - BOOST_LIBRARYDIR = {}'.format(lib_dir)) - - boost_inc_dir = None - for j in [inc_dir / 'version.hpp', inc_dir / 'boost' / 'version.hpp']: - if j.is_file(): - boost_inc_dir = self._include_dir_from_version_header(j) - break - if not boost_inc_dir: - self.is_found = False - return + # First, look for paths specified in a machine file + props = self.env.properties[self.for_machine] + boost_property_env = [props.get('boost_includedir'), props.get('boost_librarydir'), props.get('boost_root')] + if any(boost_property_env): + self.detect_boost_machine_file(props) + return - self.is_found = self.run_check([boost_inc_dir], [lib_dir]) + # Next, look for paths in the environment + boost_manual_env_list = ['BOOST_INCLUDEDIR', 'BOOST_LIBRARYDIR', 'BOOST_ROOT', 'BOOSTROOT'] + boost_manual_env = [get_env_var(self.for_machine, self.env.is_cross_build, x) for x in boost_manual_env_list] + if any(boost_manual_env): + self.detect_boost_env() return - elif any(boost_manual_env): - mlog.warning('Both BOOST_INCLUDEDIR *and* BOOST_LIBRARYDIR have to be set (one is not enough). Ignoring.') - # A) Detect potential boost root directories (uses also BOOST_ROOT env var) - roots = self.detect_roots() - roots = list(mesonlib.OrderedSet(roots)) + # Finally, look for paths from .pc files and from searching the filesystem + self.detect_roots() - # B) Foreach candidate + def check_and_set_roots(self, roots) -> None: + roots = list(mesonlib.OrderedSet(roots)) for j in roots: - # 1. Look for the boost headers (boost/version.pp) + # 1. Look for the boost headers (boost/version.hpp) mlog.debug('Checking potential boost root {}'.format(j.as_posix())) inc_dirs = self.detect_inc_dirs(j) inc_dirs = sorted(inc_dirs, reverse=True) # Prefer the newer versions @@ -411,6 +403,74 @@ class BoostDependency(ExternalDependency): self.boost_root = j break + def detect_boost_machine_file(self, props) -> None: + incdir = props.get('boost_includedir') + libdir = props.get('boost_librarydir') + + if incdir and libdir: + inc_dir = Path(props['boost_includedir']) + lib_dir = Path(props['boost_librarydir']) + + if not inc_dir.is_absolute() or not lib_dir.is_absolute(): + raise DependencyException('Paths given for boost_includedir and boost_librarydir in machine file must be absolute') + + mlog.debug('Trying to find boost with:') + mlog.debug(' - boost_includedir = {}'.format(inc_dir)) + mlog.debug(' - boost_librarydir = {}'.format(lib_dir)) + + return self.detect_split_root(inc_dir, lib_dir) + + elif incdir or libdir: + raise DependencyException('Both boost_includedir *and* boost_librarydir have to be set in your machine file (one is not enough)') + + rootdir = props.get('boost_root') + # It shouldn't be possible to get here without something in boost_root + assert(rootdir) + + raw_paths = mesonlib.stringlistify(rootdir) + paths = [Path(x) for x in raw_paths] + if paths and any([not x.is_absolute() for x in paths]): + raise DependencyException('boost_root path given in machine file must be absolute') + + self.check_and_set_roots(paths) + + def detect_boost_env(self): + boost_includedir = get_env_var(self.for_machine, self.env.is_cross_build, 'BOOST_INCLUDEDIR') + boost_librarydir = get_env_var(self.for_machine, self.env.is_cross_build, 'BOOST_LIBRARYDIR') + + boost_manual_env = [boost_includedir, boost_librarydir] + if all(boost_manual_env): + inc_dir = Path(boost_includedir) + lib_dir = Path(boost_librarydir) + + if not inc_dir.is_absolute() or not lib_dir.is_absolute(): + raise DependencyException('Paths given in BOOST_INCLUDEDIR and BOOST_LIBRARYDIR must be absolute') + + mlog.debug('Trying to find boost with:') + mlog.debug(' - BOOST_INCLUDEDIR = {}'.format(inc_dir)) + mlog.debug(' - BOOST_LIBRARYDIR = {}'.format(lib_dir)) + + return self.detect_split_root(inc_dir, lib_dir) + + elif any(boost_manual_env): + raise DependencyException('Both BOOST_INCLUDEDIR *and* BOOST_LIBRARYDIR have to be set (one is not enough). Ignoring.') + + boost_root = get_env_var(self.for_machine, self.env.is_cross_build, 'BOOST_ROOT') + boostroot = get_env_var(self.for_machine, self.env.is_cross_build, 'BOOSTROOT') + + # It shouldn't be possible to get here without something in BOOST_ROOT or BOOSTROOT + assert(boost_root or boostroot) + + for path, name in [(boost_root, 'BOOST_ROOT'), (boostroot, 'BOOSTROOT')]: + if path: + raw_paths = path.split(os.pathsep) + paths = [Path(x) for x in raw_paths] + if paths and any([not x.is_absolute() for x in paths]): + raise DependencyException('Paths in {} must be absolute'.format(name)) + break + + self.check_and_set_roots(paths) + def run_check(self, inc_dirs: T.List[BoostIncludeDir], lib_dirs: T.List[Path]) -> bool: mlog.debug(' - potential library dirs: {}'.format([x.as_posix() for x in lib_dirs])) mlog.debug(' - potential include dirs: {}'.format([x.path.as_posix() for x in inc_dirs])) @@ -560,6 +620,12 @@ class BoostDependency(ExternalDependency): except (KeyError, IndexError, AttributeError): pass + # mlog.debug(' - static: {}'.format(self.static)) + # mlog.debug(' - not explicit static: {}'.format(not self.explicit_static)) + # mlog.debug(' - mt: {}'.format(self.multithreading)) + # mlog.debug(' - version: {}'.format(lib_vers)) + # mlog.debug(' - arch: {}'.format(self.arch)) + # mlog.debug(' - vscrt: {}'.format(vscrt)) libs = [x for x in libs if x.static == self.static or not self.explicit_static] libs = [x for x in libs if x.mt == self.multithreading] libs = [x for x in libs if x.version_matches(lib_vers)] @@ -592,20 +658,22 @@ class BoostDependency(ExternalDependency): libs += [BoostLibraryFile(i)] return [x for x in libs if x.is_boost()] # Filter out no boost libraries - def detect_roots(self) -> T.List[Path]: - roots = [] # type: T.List[Path] + def detect_split_root(self, inc_dir, lib_dir) -> None: + boost_inc_dir = None + for j in [inc_dir / 'version.hpp', inc_dir / 'boost' / 'version.hpp']: + if j.is_file(): + boost_inc_dir = self._include_dir_from_version_header(j) + break + if not boost_inc_dir: + self.is_found = False + return - # Add roots from the environment - for i in ['BOOST_ROOT', 'BOOSTROOT']: - if i in os.environ: - raw_paths = os.environ[i].split(os.pathsep) - paths = [Path(x) for x in raw_paths] - if paths and any([not x.is_absolute() for x in paths]): - raise DependencyException('Paths in {} must be absolute'.format(i)) - roots += paths - return roots # Do not add system paths if BOOST_ROOT is present + self.is_found = self.run_check([boost_inc_dir], [lib_dir]) + + def detect_roots(self) -> None: + roots = [] # type: T.List[Path] - # Try getting the BOOST_ROOT from a boost.pc if it exists. This primarely + # Try getting the BOOST_ROOT from a boost.pc if it exists. This primarily # allows BoostDependency to find boost from Conan. See #5438 try: boost_pc = PkgConfigDependency('boost', self.env, {'required': False}) @@ -660,7 +728,7 @@ class BoostDependency(ExternalDependency): tmp = [x.resolve() for x in tmp] roots += tmp - return roots + self.check_and_set_roots(roots) def log_details(self) -> str: res = '' diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index 11dac38..df81569 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -1844,10 +1844,18 @@ class Summary: if bool_yn and isinstance(i, bool): formatted_values.append(mlog.green('YES') if i else mlog.red('NO')) else: - formatted_values.append(i) + formatted_values.append(str(i)) self.sections[section][k] = (formatted_values, list_sep) self.max_key_len = max(self.max_key_len, len(k)) + def text_len(self, v): + if isinstance(v, str): + return len(v) + elif isinstance(v, mlog.AnsiDecorator): + return len(v.text) + else: + raise RuntimeError('Expecting only strings or AnsiDecorator') + def dump(self): mlog.log(self.project_name, mlog.normal_cyan(self.project_version)) for section, values in self.sections.items(): @@ -1859,12 +1867,28 @@ class Summary: indent = self.max_key_len - len(k) + 3 end = ' ' if v else '' mlog.log(' ' * indent, k + ':', end=end) - if list_sep is None: - indent = self.max_key_len + 6 - list_sep = '\n' + ' ' * indent - mlog.log(*v, sep=list_sep) + indent = self.max_key_len + 6 + self.dump_value(v, list_sep, indent) mlog.log('') # newline + def dump_value(self, arr, list_sep, indent): + lines_sep = '\n' + ' ' * indent + if list_sep is None: + mlog.log(*arr, sep=lines_sep) + return + max_len = shutil.get_terminal_size().columns + line = [] + line_len = indent + lines_sep = list_sep.rstrip() + lines_sep + for v in arr: + v_len = self.text_len(v) + len(list_sep) + if line and line_len + v_len > max_len: + mlog.log(*line, sep=list_sep, end=lines_sep) + line_len = indent + line = [] + line.append(v) + line_len += v_len + mlog.log(*line, sep=list_sep) class MesonMain(InterpreterObject): def __init__(self, build, interpreter): @@ -2559,6 +2583,15 @@ class Interpreter(InterpreterBase): except InvalidArguments: pass + def import_module(self, modname): + if modname in self.modules: + return + try: + module = importlib.import_module('mesonbuild.modules.' + modname) + except ImportError: + raise InvalidArguments('Module "%s" does not exist' % (modname, )) + self.modules[modname] = module.initialize(self) + @stringArgs @noKwargs def func_import(self, node, args, kwargs): @@ -2567,14 +2600,15 @@ class Interpreter(InterpreterBase): modname = args[0] if modname.startswith('unstable-'): plainname = modname.split('-', 1)[1] - mlog.warning('Module %s has no backwards or forwards compatibility and might not exist in future releases.' % modname, location=node) - modname = 'unstable_' + plainname - if modname not in self.modules: try: - module = importlib.import_module('mesonbuild.modules.' + modname) - except ImportError: - raise InvalidArguments('Module "%s" does not exist' % (modname, )) - self.modules[modname] = module.initialize(self) + # check if stable module exists + self.import_module(plainname) + mlog.warning('Module %s is now stable, please use the %s module instead.' % (modname, plainname)) + modname = plainname + except InvalidArguments: + mlog.warning('Module %s has no backwards or forwards compatibility and might not exist in future releases.' % modname, location=node) + modname = 'unstable_' + plainname + self.import_module(modname) return ModuleHolder(modname, self.modules[modname], self) @stringArgs diff --git a/mesonbuild/interpreterbase.py b/mesonbuild/interpreterbase.py index 634f4f2..9f35601 100644 --- a/mesonbuild/interpreterbase.py +++ b/mesonbuild/interpreterbase.py @@ -1026,6 +1026,20 @@ The result of this is undefined and will become a hard error in a future Meson r if not isinstance(cmpr, str): raise InterpreterException('Version_compare() argument must be a string.') return mesonlib.version_compare(obj, cmpr) + elif method_name == 'substring': + if len(posargs) > 2: + raise InterpreterException('substring() takes maximum two arguments.') + start = 0 + end = len(obj) + if len (posargs) > 0: + if not isinstance(posargs[0], int): + raise InterpreterException('substring() argument must be an int') + start = posargs[0] + if len (posargs) > 1: + if not isinstance(posargs[1], int): + raise InterpreterException('substring() argument must be an int') + end = posargs[1] + return obj[start:end] raise InterpreterException('Unknown method "%s" for a string.' % method_name) def format_string(self, templ: str, args: T.List[TYPE_nvar]) -> str: diff --git a/mesonbuild/modules/unstable_keyval.py b/mesonbuild/modules/keyval.py index 3da2992..3da2992 100644 --- a/mesonbuild/modules/unstable_keyval.py +++ b/mesonbuild/modules/keyval.py diff --git a/run_meson_command_tests.py b/run_meson_command_tests.py index 6ed3d8f..7bc6185 100755 --- a/run_meson_command_tests.py +++ b/run_meson_command_tests.py @@ -129,6 +129,10 @@ class CommandTests(unittest.TestCase): os.environ['PYTHONPATH'] = os.path.join(str(pylibdir), '') os.environ['PATH'] = str(bindir) + os.pathsep + os.environ['PATH'] self._run(python_command + ['setup.py', 'install', '--prefix', str(prefix)]) + # Fix importlib-metadata by appending all dirs in pylibdir + PYTHONPATHS = [pylibdir] + [x for x in pylibdir.iterdir()] + PYTHONPATHS = [os.path.join(str(x), '') for x in PYTHONPATHS] + os.environ['PYTHONPATH'] = os.pathsep.join(PYTHONPATHS) # Check that all the files were installed correctly self.assertTrue(bindir.is_dir()) self.assertTrue(pylibdir.is_dir()) diff --git a/run_project_tests.py b/run_project_tests.py index 9487a04..56b7e2a 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -41,6 +41,7 @@ from mesonbuild import compilers from mesonbuild import mesonlib from mesonbuild import mlog from mesonbuild import mtest +from mesonbuild.build import ConfigurationData from mesonbuild.mesonlib import MachineChoice, Popen_safe from mesonbuild.coredata import backendlist, version as meson_version @@ -475,6 +476,28 @@ def create_deterministic_builddir(test: TestDef, use_tmpdir: bool) -> str: os.mkdir(abs_pathname) return abs_pathname +def format_parameter_file(file_basename: str, test: TestDef, test_build_dir: str) -> Path: + confdata = ConfigurationData() + confdata.values = {'MESON_TEST_ROOT': (str(test.path.absolute()), 'base directory of current test')} + + template = test.path / (file_basename + '.in') + destination = Path(test_build_dir) / file_basename + mesonlib.do_conf_file(str(template), str(destination), confdata, 'meson') + + return destination + +def detect_parameter_files(test: TestDef, test_build_dir: str) -> (Path, Path): + nativefile = test.path / 'nativefile.ini' + crossfile = test.path / 'crossfile.ini' + + if os.path.exists(str(test.path / 'nativefile.ini.in')): + nativefile = format_parameter_file('nativefile.ini', test, test_build_dir) + + if os.path.exists(str(test.path / 'crossfile.ini.in')): + crossfile = format_parameter_file('crossfile.ini', test, test_build_dir) + + return nativefile, crossfile + def run_test(test: TestDef, extra_args, compiler, backend, flags, commands, should_fail, use_tmp: bool): if test.skip: return None @@ -497,8 +520,9 @@ def _run_test(test: TestDef, test_build_dir: str, install_dir: str, extra_args, if 'libdir' not in test.do_not_set_opts: gen_args += ['--libdir', 'lib'] gen_args += [test.path.as_posix(), test_build_dir] + flags + extra_args - nativefile = test.path / 'nativefile.ini' - crossfile = test.path / 'crossfile.ini' + + nativefile, crossfile = detect_parameter_files(test, test_build_dir) + if nativefile.exists(): gen_args.extend(['--native-file', nativefile.as_posix()]) if crossfile.exists(): diff --git a/run_unittests.py b/run_unittests.py index 820b705..ff6bb9c 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -4635,6 +4635,10 @@ recommended as it is not supported on some platforms''') no: NO coma list: a, b, c + Plugins + long coma list: alpha, alphacolor, apetag, audiofx, audioparsers, auparse, + autodetect, avi + Subprojects sub: YES sub2: NO Problem encountered: This subproject failed @@ -7030,6 +7034,13 @@ c = ['{0}'] windows_proof_rmtree(os.path.join(testdir, 'subprojects', 'foo')) os.unlink(wrap_filename) + def test_no_rpath_for_static(self): + testdir = os.path.join(self.common_test_dir, '5 linkstatic') + self.init(testdir) + self.build() + build_rpath = get_rpath(os.path.join(self.builddir, 'prog')) + self.assertIsNone(build_rpath) + class BaseLinuxCrossTests(BasePlatformTests): # Don't pass --libdir when cross-compiling. We have tests that diff --git a/test cases/common/222 source set realistic example/meson.build b/test cases/common/222 source set realistic example/meson.build index 106b81d..d986b99 100644 --- a/test cases/common/222 source set realistic example/meson.build +++ b/test cases/common/222 source set realistic example/meson.build @@ -9,7 +9,7 @@ if cppid == 'pgi' endif ss = import('sourceset') -keyval = import('unstable-keyval') +keyval = import('keyval') zlib = declare_dependency(compile_args: '-DZLIB=1') another = declare_dependency(compile_args: '-DANOTHER=1') diff --git a/test cases/common/230 persubproject options/meson.build b/test cases/common/230 persubproject options/meson.build index 20dff90..f76a70c 100644 --- a/test cases/common/230 persubproject options/meson.build +++ b/test cases/common/230 persubproject options/meson.build @@ -1,9 +1,11 @@ project('persubproject options', 'c', default_options : ['default_library=both', - 'werror=true']) + 'werror=true', + 'warning_level=3']) assert(get_option('default_library') == 'both', 'Parent default_library should be "both"') assert(get_option('werror')) +assert(get_option('warning_level') == '3') # Check it build both by calling a method only both_libraries target implement lib = library('lib1', 'foo.c') diff --git a/test cases/common/230 persubproject options/subprojects/sub1/foo.c b/test cases/common/230 persubproject options/subprojects/sub1/foo.c index 63e4de6..82ad2c2 100644 --- a/test cases/common/230 persubproject options/subprojects/sub1/foo.c +++ b/test cases/common/230 persubproject options/subprojects/sub1/foo.c @@ -1,5 +1,8 @@ int foo(void); int foo(void) { + /* This is built with -Werror, it would error if warning_level=3 was inherited + * from main project and not overridden by this subproject's default_options. */ + int x; return 0; } diff --git a/test cases/common/230 persubproject options/subprojects/sub1/meson.build b/test cases/common/230 persubproject options/subprojects/sub1/meson.build index 7afc934..4e4bc1b 100644 --- a/test cases/common/230 persubproject options/subprojects/sub1/meson.build +++ b/test cases/common/230 persubproject options/subprojects/sub1/meson.build @@ -1,6 +1,8 @@ -project('sub1', 'c') +project('sub1', 'c', + default_options : ['warning_level=0']) assert(get_option('default_library') == 'both', 'Should inherit parent project default_library') +assert(get_option('warning_level') == '0') # Check it build both by calling a method only both_libraries target implement lib = library('lib1', 'foo.c') diff --git a/test cases/common/38 string operations/meson.build b/test cases/common/38 string operations/meson.build index 6596142..8a06a82 100644 --- a/test cases/common/38 string operations/meson.build +++ b/test cases/common/38 string operations/meson.build @@ -101,3 +101,18 @@ assert('\\\\n' == bs_bs_n, 'Four backslash broken before n') assert('\\\\\n' == bs_bs_nl, 'Five backslash broken before n') assert('\\\\' == bs_bs, 'Double-backslash broken') assert('\\' == bs, 'Backslash broken') + +mysubstring='foobarbaz' +assert(mysubstring.substring() == 'foobarbaz', 'substring is broken') +assert(mysubstring.substring(0) == 'foobarbaz', 'substring is broken') +assert(mysubstring.substring(1) == 'oobarbaz', 'substring is broken') +assert(mysubstring.substring(-5) == 'arbaz', 'substring is broken') +assert(mysubstring.substring(1, 4) == 'oob', 'substring is broken') +assert(mysubstring.substring(1,-5) == 'oob', 'substring is broken') +assert(mysubstring.substring(1, 0) == '', 'substring is broken') +assert(mysubstring.substring(0, 100) == 'foobarbaz', 'substring is broken') +assert(mysubstring.substring(-1, -5) == '', 'substring is broken') +assert(mysubstring.substring(10, -25) == '', 'substring is broken') +assert(mysubstring.substring(-4, 2) == '', 'substring is broken') +assert(mysubstring.substring(10, 9) == '', 'substring is broken') +assert(mysubstring.substring(8, 10) == 'z', 'substring is broken') diff --git a/test cases/frameworks/32 boost root/boost/include/boost/version.hpp b/test cases/frameworks/32 boost root/boost/include/boost/version.hpp new file mode 100644 index 0000000..65e4fab --- /dev/null +++ b/test cases/frameworks/32 boost root/boost/include/boost/version.hpp @@ -0,0 +1,3 @@ +#define BOOST_VERSION 100 + +#error This is not a real version of boost diff --git a/test cases/frameworks/32 boost root/boost/lib/boost_regex-vc142-mt-gd-x32-0_1.lib b/test cases/frameworks/32 boost root/boost/lib/boost_regex-vc142-mt-gd-x32-0_1.lib new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test cases/frameworks/32 boost root/boost/lib/boost_regex-vc142-mt-gd-x32-0_1.lib diff --git a/test cases/frameworks/32 boost root/boost/lib/boost_regex-vc142-mt-gd-x64-0_1.lib b/test cases/frameworks/32 boost root/boost/lib/boost_regex-vc142-mt-gd-x64-0_1.lib new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test cases/frameworks/32 boost root/boost/lib/boost_regex-vc142-mt-gd-x64-0_1.lib diff --git a/test cases/frameworks/32 boost root/boost/lib/libboost_regex.so.0.1.0 b/test cases/frameworks/32 boost root/boost/lib/libboost_regex.so.0.1.0 new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test cases/frameworks/32 boost root/boost/lib/libboost_regex.so.0.1.0 diff --git a/test cases/frameworks/32 boost root/meson.build b/test cases/frameworks/32 boost root/meson.build new file mode 100644 index 0000000..50d2f0d --- /dev/null +++ b/test cases/frameworks/32 boost root/meson.build @@ -0,0 +1,6 @@ +project('boosttest', 'cpp') + +dep = dependency('boost', modules : 'regex', required: false) + +assert(dep.found(), 'expected to find a fake version of boost') +assert(dep.version() == '0.1.0', 'expected to find version 0.1.0') diff --git a/test cases/frameworks/32 boost root/nativefile.ini.in b/test cases/frameworks/32 boost root/nativefile.ini.in new file mode 100644 index 0000000..54510d7 --- /dev/null +++ b/test cases/frameworks/32 boost root/nativefile.ini.in @@ -0,0 +1,2 @@ +[properties] +boost_root = '@MESON_TEST_ROOT@/boost' diff --git a/test cases/frameworks/33 boost split root/boost/extra-dir/include/boost/version.hpp b/test cases/frameworks/33 boost split root/boost/extra-dir/include/boost/version.hpp new file mode 100644 index 0000000..3ba19ee --- /dev/null +++ b/test cases/frameworks/33 boost split root/boost/extra-dir/include/boost/version.hpp @@ -0,0 +1,3 @@ +#define BOOST_VERSION 200 + +#error This is not a real version of boost diff --git a/test cases/frameworks/33 boost split root/boost/lib/boost_regex-vc142-mt-gd-x32-0_2.lib b/test cases/frameworks/33 boost split root/boost/lib/boost_regex-vc142-mt-gd-x32-0_2.lib new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test cases/frameworks/33 boost split root/boost/lib/boost_regex-vc142-mt-gd-x32-0_2.lib diff --git a/test cases/frameworks/33 boost split root/boost/lib/boost_regex-vc142-mt-gd-x64-0_2.lib b/test cases/frameworks/33 boost split root/boost/lib/boost_regex-vc142-mt-gd-x64-0_2.lib new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test cases/frameworks/33 boost split root/boost/lib/boost_regex-vc142-mt-gd-x64-0_2.lib diff --git a/test cases/frameworks/33 boost split root/boost/lib/libboost_regex.so.0.2.0 b/test cases/frameworks/33 boost split root/boost/lib/libboost_regex.so.0.2.0 new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test cases/frameworks/33 boost split root/boost/lib/libboost_regex.so.0.2.0 diff --git a/test cases/frameworks/33 boost split root/meson.build b/test cases/frameworks/33 boost split root/meson.build new file mode 100644 index 0000000..a2353bb --- /dev/null +++ b/test cases/frameworks/33 boost split root/meson.build @@ -0,0 +1,6 @@ +project('boosttest', 'cpp') + +dep = dependency('boost', modules : 'regex', required: false) + +assert(dep.found(), 'expected to find a fake version of boost') +assert(dep.version() == '0.2.0', 'expected to find version 0.2.0') diff --git a/test cases/frameworks/33 boost split root/nativefile.ini.in b/test cases/frameworks/33 boost split root/nativefile.ini.in new file mode 100644 index 0000000..7bd5ac2 --- /dev/null +++ b/test cases/frameworks/33 boost split root/nativefile.ini.in @@ -0,0 +1,3 @@ +[properties] +boost_includedir = '@MESON_TEST_ROOT@/boost/extra-dir/include' +boost_librarydir = '@MESON_TEST_ROOT@/boost/lib' diff --git a/test cases/keyval/1 basic/meson.build b/test cases/keyval/1 basic/meson.build index fc7ddb3..4207b8e 100644 --- a/test cases/keyval/1 basic/meson.build +++ b/test cases/keyval/1 basic/meson.build @@ -1,6 +1,6 @@ project('keyval basic test') -k = import('unstable-keyval') +k = import('keyval') conf = k.load('.config') if not conf.has_key('CONFIG_VAL1') @@ -14,3 +14,5 @@ endif if conf.get('CONFIG_VAL_VAL').to_int() != 4 error('Expected CONFIG_VAL_VAL to be 4') endif + +k = import('unstable-keyval') diff --git a/test cases/keyval/1 basic/test.json b/test cases/keyval/1 basic/test.json new file mode 100644 index 0000000..dbdc5af --- /dev/null +++ b/test cases/keyval/1 basic/test.json @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "WARNING: Module unstable-keyval is now stable, please use the keyval module instead." + } + ] +} diff --git a/test cases/keyval/2 subdir/dir/meson.build b/test cases/keyval/2 subdir/dir/meson.build index dc1b478..291ad93 100644 --- a/test cases/keyval/2 subdir/dir/meson.build +++ b/test cases/keyval/2 subdir/dir/meson.build @@ -1,5 +1,5 @@ -k = import('unstable-keyval') +k = import('keyval') conf = k.load(meson.source_root() / '.config') diff --git a/test cases/keyval/3 load_config files/dir/meson.build b/test cases/keyval/3 load_config files/dir/meson.build index 43fba13..adc5289 100644 --- a/test cases/keyval/3 load_config files/dir/meson.build +++ b/test cases/keyval/3 load_config files/dir/meson.build @@ -1,5 +1,5 @@ -k = import('unstable-keyval') +k = import('keyval') conf = k.load(files('config')) diff --git a/test cases/keyval/4 load_config builddir/meson.build b/test cases/keyval/4 load_config builddir/meson.build index 1bb0285..6bd83db 100644 --- a/test cases/keyval/4 load_config builddir/meson.build +++ b/test cases/keyval/4 load_config builddir/meson.build @@ -1,6 +1,6 @@ project('keyval builddir test') -k = import('unstable-keyval') +k = import('keyval') out_conf = configure_file(input: 'config', output: 'out-config', copy: true) conf = k.load(out_conf) diff --git a/test cases/unit/73 summary/meson.build b/test cases/unit/73 summary/meson.build index df4540d..1bc05ca 100644 --- a/test cases/unit/73 summary/meson.build +++ b/test cases/unit/73 summary/meson.build @@ -13,3 +13,4 @@ summary('A number', 1, section: 'Configuration') summary('yes', true, bool_yn : true, section: 'Configuration') summary('no', false, bool_yn : true, section: 'Configuration') summary('coma list', ['a', 'b', 'c'], list_sep: ', ', section: 'Configuration') +summary('long coma list', ['alpha', 'alphacolor', 'apetag', 'audiofx', 'audioparsers', 'auparse', 'autodetect', 'avi'], list_sep: ', ', section: 'Plugins') diff --git a/test cases/windows/17 msvc ndebug/main.cpp b/test cases/windows/17 msvc ndebug/main.cpp new file mode 100644 index 0000000..d647d71 --- /dev/null +++ b/test cases/windows/17 msvc ndebug/main.cpp @@ -0,0 +1,9 @@ +int main() { +#ifdef NDEBUG + // NDEBUG is defined + return 0; +#else + // NDEBUG is not defined + return 1; +#endif +}
\ No newline at end of file diff --git a/test cases/windows/17 msvc ndebug/meson.build b/test cases/windows/17 msvc ndebug/meson.build new file mode 100644 index 0000000..78eaf89 --- /dev/null +++ b/test cases/windows/17 msvc ndebug/meson.build @@ -0,0 +1,7 @@ +project('msvc_ndebug', 'cpp', + default_options : [ 'b_ndebug=true' ] +) + +exe = executable('exe', 'main.cpp') + +test('ndebug', exe) |