aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/markdown/Gnome-module.md25
-rw-r--r--docs/markdown/Pkgconfig-module.md1
-rw-r--r--docs/markdown/Reference-manual.md20
-rw-r--r--docs/markdown/Unity-builds.md2
-rw-r--r--docs/markdown/snippets/cross_find.md15
-rw-r--r--docs/markdown/snippets/get-supported-arguments.md23
-rw-r--r--mesonbuild/compilers/compilers.py7
-rw-r--r--mesonbuild/interpreter.py63
-rw-r--r--mesonbuild/mesonlib.py2
-rw-r--r--mesonbuild/modules/gnome.py16
-rw-r--r--mesonbuild/modules/pkgconfig.py2
-rw-r--r--mesonbuild/scripts/meson_install.py2
-rwxr-xr-xrun_unittests.py22
-rw-r--r--test cases/common/112 has arg/meson.build3
-rw-r--r--test cases/frameworks/7 gnome/gdbus/meson.build6
-rw-r--r--test cases/unit/12 cross prog/meson.build12
-rwxr-xr-xtest cases/unit/12 cross prog/some_cross_tool.py5
-rwxr-xr-xtest cases/unit/12 cross prog/sometool.py5
18 files changed, 206 insertions, 25 deletions
diff --git a/docs/markdown/Gnome-module.md b/docs/markdown/Gnome-module.md
index e81875a..3672761 100644
--- a/docs/markdown/Gnome-module.md
+++ b/docs/markdown/Gnome-module.md
@@ -220,14 +220,31 @@ useful when running the application locally for example during tests.
Compiles the given XML schema into gdbus source code. Takes two
positional arguments, the first one specifies the name of the source
-files and the second specifies the XML file name. There are three
-keyword arguments. `interface_prefix` and `namespace` map to
-corresponding features of the compiler while `object_manager` (since
-0.40.0), when set to true, generates object manager code.
+files and the second specifies the XML file name.
+
+* `interface_prefix`: prefix for the interface
+* `namespace`: namespace of the interface
+* `object_manager`: *(Added 0.40.0)* if true generates object manager code
+* `annotations`: *(Added 0.43.0)* list of lists of 3 strings for the annotation for `'ELEMENT', 'KEY', 'VALUE'`
Returns an opaque object containing the source files. Add it to a top
level target's source list.
+Example:
+
+```meson
+gnome = import('gnome')
+
+# The returned source would be passed to another target
+gdbus_src = gnome.gdbus_codegen('example-interface', 'com.example.Sample.xml',
+ interface_prefix : 'com.example.',
+ namespace : 'Sample',
+ annotations : [
+ ['com.example.Hello()', 'org.freedesktop.DBus.Deprecated', 'true']
+ ]
+)
+```
+
### gnome.generate_vapi()
Creates a VAPI file from gir. The first argument is the name of the
diff --git a/docs/markdown/Pkgconfig-module.md b/docs/markdown/Pkgconfig-module.md
index 8814d19..5a660fd 100644
--- a/docs/markdown/Pkgconfig-module.md
+++ b/docs/markdown/Pkgconfig-module.md
@@ -34,6 +34,7 @@ keyword arguments.
- `requires` list of strings to put in the `Requires` field
- `requires_private` list of strings to put in the `Requires.private`
field
+- `url` a string with a url for the library
- `variables` a list of strings with custom variables to add to the
generated file. The strings must be in the form `name=value` and may
reference other pkgconfig variables,
diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md
index 91f7edd..34b473d 100644
--- a/docs/markdown/Reference-manual.md
+++ b/docs/markdown/Reference-manual.md
@@ -466,6 +466,12 @@ Keyword arguments are the following:
then use the `.found()` method on the returned object to check
whether it was found or not.
+- `native` defines how this executable should be searched. By default
+ it is set to `false`, which causes Meson to first look for the
+ executable in the cross file (when cross building) and if it is not
+ defined there, then from the system. If set to `true`, the cross
+ file is ignored and the program is only searched from the system.
+
Meson will also autodetect scripts with a shebang line and run them
with the executable/interpreter specified in it both on Windows
(because the command invocator will reject the command otherwise) and
@@ -1260,6 +1266,12 @@ the following methods:
the positional argument, you can specify external dependencies to
use with `dependencies` keyword argument.
+- `compiles(code)` returns true if the code fragment given in the
+ positional argument compiles, you can specify external dependencies
+ to use with `dependencies` keyword argument, `code` can be either a
+ string containing source code or a `file` object pointing to the
+ source code.
+
- `compute_int(expr, ...')` computes the value of the given expression
(as an example `1 + 2`). When cross compiling this is evaluated with
an iterative algorithm, you can specify keyword arguments `low`
@@ -1286,11 +1298,9 @@ the following methods:
- `get_id()` returns a string identifying the compiler. For example,
`gcc`, `msvc`, [and more](Compiler-properties.md#compiler-id).
-- `compiles(code)` returns true if the code fragment given in the
- positional argument compiles, you can specify external dependencies
- to use with `dependencies` keyword argument, `code` can be either a
- string containing source code or a `file` object pointing to the
- source code.
+- `get_supported_arguments(list_of_string)` returns an array
+ containing only the arguments supported by the compiler, as if
+ `has_argument` were called on them individually.
- `has_argument(argument_name)` returns true if the compiler accepts
the specified command line argument, that is, can compile code
diff --git a/docs/markdown/Unity-builds.md b/docs/markdown/Unity-builds.md
index 9f939f5..533a421 100644
--- a/docs/markdown/Unity-builds.md
+++ b/docs/markdown/Unity-builds.md
@@ -16,4 +16,4 @@ This is then compiled rather than the individual files. The exact speedup depend
The downside is that incremental builds are as slow as full rebuilds (because that is what they are). Unity compiles also use more memory, which may become an issue in certain scenarios. There may also be some bugs in the source that need to be fixed before Unity compiles work. As an example, if both `src1.c` and `src2.c` contain a static function or variable of the same name, there will be a clash.
-Meson has built-in support for unity builds. To enable them, just pass the `--unity` command line argument or enable unity builds with the GUI. No code changes are necessary apart from the potential clash issue discussed above. Meson will automatically generate all the necessary inclusion files for you.
+Meson has built-in support for unity builds. To enable them, just pass `--unity on` on the command line or enable unity builds with the GUI. No code changes are necessary apart from the potential clash issue discussed above. Meson will automatically generate all the necessary inclusion files for you.
diff --git a/docs/markdown/snippets/cross_find.md b/docs/markdown/snippets/cross_find.md
new file mode 100644
index 0000000..b16d64d
--- /dev/null
+++ b/docs/markdown/snippets/cross_find.md
@@ -0,0 +1,15 @@
+# Can override executables in the cross file
+
+The cross file can now be used for overriding the result of
+`find_program`. As an example if you want to find the `objdump`
+command and have the following definition in your cross file:
+
+ [binaries]
+ ...
+ objdump = '/usr/bin/arm-linux-gnueabihf-objdump-6'
+
+Then issuing the command `find_program('objdump')` will return the
+version specified in the cross file. If you need the build machine's
+objdump, you can specify the `native` keyword like this:
+
+ native_objdump = find_program('objdump', native : true)
diff --git a/docs/markdown/snippets/get-supported-arguments.md b/docs/markdown/snippets/get-supported-arguments.md
new file mode 100644
index 0000000..c0cc9bf
--- /dev/null
+++ b/docs/markdown/snippets/get-supported-arguments.md
@@ -0,0 +1,23 @@
+# Easier handling of supported compiler arguments
+
+A common pattern for handling multiple desired compiler arguments, was to
+test their presence and add them to an array one-by-one, e.g.:
+
+ warning_flags_maybe = [
+ '-Wsomething',
+ '-Wanother-thing',
+ '-Wno-the-other-thing',
+ ]
+ warning_flags = []
+ foreach flag : warning_flags_maybe
+ if cc.has_argument(flag)
+ warning_flags += flag
+ endif
+ endforeach
+ cc.add_project_argument(warning_flags)
+
+A helper has been added for the foreach/has_argument pattern, so you can
+now simply do:
+
+ warning_flags = [ ... ]
+ flags = cc.get_supported_flags(warning_flags)
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py
index 5077a6e..c431194 100644
--- a/mesonbuild/compilers/compilers.py
+++ b/mesonbuild/compilers/compilers.py
@@ -712,6 +712,13 @@ class Compiler:
'Language {} does not support has_multi_arguments.'.format(
self.get_display_language()))
+ def get_supported_arguments(self, args, env):
+ supported_args = []
+ for arg in args:
+ if self.has_argument(arg, env):
+ supported_args.append(arg)
+ return supported_args
+
def get_cross_extra_flags(self, environment, link):
extra_flags = []
if self.is_cross and environment:
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index 0157c2e..23f5907 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -652,6 +652,7 @@ class CompilerHolder(InterpreterObject):
'find_library': self.find_library_method,
'has_argument': self.has_argument_method,
'has_multi_arguments': self.has_multi_arguments_method,
+ 'get_supported_arguments': self.get_supported_arguments_method,
'first_supported_argument': self.first_supported_argument_method,
'unittest_args': self.unittest_args_method,
'symbols_have_underscore_prefix': self.symbols_have_underscore_prefix_method,
@@ -1013,6 +1014,22 @@ class CompilerHolder(InterpreterObject):
h)
return result
+ def get_supported_arguments_method(self, args, kwargs):
+ args = mesonlib.stringlistify(args)
+ result = self.compiler.get_supported_arguments(args, self.environment)
+ if len(result) == len(args):
+ h = mlog.green('YES')
+ elif len(result) > 0:
+ h = mlog.yellow('SOME')
+ else:
+ h = mlog.red('NO')
+ mlog.log(
+ 'Compiler for {} supports arguments {}:'.format(
+ self.compiler.get_display_language(), ' '.join(args)),
+ h)
+ return result
+
+
def first_supported_argument_method(self, args, kwargs):
for i in mesonlib.stringlistify(args):
if self.compiler.has_argument(i, self.environment):
@@ -1300,7 +1317,7 @@ permitted_kwargs = {'add_global_arguments': {'language'},
'custom_target': {'input', 'output', 'command', 'install', 'install_dir', 'build_always', 'capture', 'depends', 'depend_files', 'depfile', 'build_by_default'},
'declare_dependency': {'include_directories', 'link_with', 'sources', 'dependencies', 'compile_args', 'link_args', 'version'},
'executable': exe_kwargs,
- 'find_program': {'required'},
+ 'find_program': {'required', 'native'},
'generator': {'arguments', 'output', 'depfile'},
'include_directories': {'is_system'},
'install_data': {'install_dir', 'install_mode', 'sources'},
@@ -1946,13 +1963,22 @@ class Interpreter(InterpreterBase):
break
self.coredata.base_options[optname] = oobj
- @permittedKwargs(permitted_kwargs['find_program'])
- def func_find_program(self, node, args, kwargs):
- if not args:
- raise InterpreterException('No program name specified.')
- required = kwargs.get('required', True)
- if not isinstance(required, bool):
- raise InvalidArguments('"required" argument must be a boolean.')
+ def program_from_cross_file(self, prognames):
+ bins = self.environment.cross_info.config['binaries']
+ for p in prognames:
+ if hasattr(p, 'held_object'):
+ p = p.held_object
+ if isinstance(p, mesonlib.File):
+ continue # Always points to a local (i.e. self generated) file.
+ if not isinstance(p, str):
+ raise InterpreterException('Executable name must be a string.')
+ if p in bins:
+ exename = bins[p]
+ extprog = dependencies.ExternalProgram(exename)
+ progobj = ExternalProgramHolder(extprog)
+ return progobj
+
+ def program_from_system(self, args):
# Search for scripts relative to current subdir.
# Do not cache found programs because find_program('foobar')
# might give different results when run from different source dirs.
@@ -1975,8 +2001,27 @@ class Interpreter(InterpreterBase):
progobj = ExternalProgramHolder(extprog)
if progobj.found():
return progobj
- if required and not progobj.found():
+
+ @permittedKwargs(permitted_kwargs['find_program'])
+ def func_find_program(self, node, args, kwargs):
+ if not args:
+ raise InterpreterException('No program name specified.')
+ required = kwargs.get('required', True)
+ if not isinstance(required, bool):
+ raise InvalidArguments('"required" argument must be a boolean.')
+ progobj = None
+ if self.build.environment.is_cross_build():
+ use_native = kwargs.get('native', False)
+ if not isinstance(use_native, bool):
+ raise InvalidArguments('Argument to "native" must be a boolean.')
+ if not use_native:
+ progobj = self.program_from_cross_file(args)
+ if progobj is None:
+ progobj = self.program_from_system(args)
+ if required and (progobj is None or not progobj.found()):
raise InvalidArguments('Program "%s" not found or not executable' % exename)
+ if progobj is None:
+ return ExternalProgramHolder(dependencies.ExternalProgram('nonexistingprogram'))
return progobj
def func_find_library(self, node, args, kwargs):
diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py
index 9a019c6..305f600 100644
--- a/mesonbuild/mesonlib.py
+++ b/mesonbuild/mesonlib.py
@@ -255,7 +255,7 @@ def detect_vcs(source_dir):
def grab_leading_numbers(vstr, strict=False):
result = []
- for x in vstr.split('.'):
+ for x in vstr.rstrip('.').split('.'):
try:
result.append(int(x))
except ValueError as e:
diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py
index 3f1b016..cb8f560 100644
--- a/mesonbuild/modules/gnome.py
+++ b/mesonbuild/modules/gnome.py
@@ -423,7 +423,7 @@ class GnomeModule(ExtensionModule):
raise MesonException('gobject-introspection dependency was not found, gir cannot be generated.')
ns = kwargs.pop('namespace')
nsversion = kwargs.pop('nsversion')
- libsources = kwargs.pop('sources')
+ libsources = mesonlib.flatten(kwargs.pop('sources'))
girfile = '%s-%s.gir' % (ns, nsversion)
srcdir = os.path.join(state.environment.get_source_dir(), state.subdir)
builddir = os.path.join(state.environment.get_build_dir(), state.subdir)
@@ -850,7 +850,7 @@ class GnomeModule(ExtensionModule):
return []
- @permittedKwargs({'interface_prefix', 'namespace', 'object_manager', 'build_by_default'})
+ @permittedKwargs({'interface_prefix', 'namespace', 'object_manager', 'build_by_default', 'annotations'})
def gdbus_codegen(self, state, args, kwargs):
if len(args) != 2:
raise MesonException('Gdbus_codegen takes two arguments, name and xml file.')
@@ -865,6 +865,18 @@ class GnomeModule(ExtensionModule):
if kwargs.get('object_manager', False):
cmd += ['--c-generate-object-manager']
+ # Annotations are a bit ugly in that they are a list of lists of strings...
+ annotations = kwargs.pop('annotations', [])
+ if not isinstance(annotations, list):
+ raise MesonException('annotations takes a list')
+ if annotations and isinstance(annotations, list) and not isinstance(annotations[0], list):
+ annotations = [annotations]
+
+ for annotation in annotations:
+ if len(annotation) != 3 or not all(isinstance(i, str) for i in annotation):
+ raise MesonException('Annotations must be made up of 3 strings for ELEMENT, KEY, and VALUE')
+ cmd += ['--annotate'] + annotation
+
# https://git.gnome.org/browse/glib/commit/?id=ee09bb704fe9ccb24d92dd86696a0e6bb8f0dc1a
if mesonlib.version_compare(self._get_native_glib_version(state), '>= 2.51.3'):
cmd += ['--output-directory', '@OUTDIR@', '--generate-c-code', namebase, '@INPUT@']
diff --git a/mesonbuild/modules/pkgconfig.py b/mesonbuild/modules/pkgconfig.py
index 5d98167..0a0498c 100644
--- a/mesonbuild/modules/pkgconfig.py
+++ b/mesonbuild/modules/pkgconfig.py
@@ -121,7 +121,7 @@ class PkgConfigModule(ExtensionModule):
@permittedKwargs({'libraries', 'version', 'name', 'description', 'filebase',
'subdirs', 'requires', 'requires_private', 'libraries_private',
- 'install_dir', 'extra_cflags', 'variables'})
+ 'install_dir', 'extra_cflags', 'variables', 'url'})
def generate(self, state, args, kwargs):
if len(args) > 0:
raise mesonlib.MesonException('Pkgconfig_gen takes no positional arguments.')
diff --git a/mesonbuild/scripts/meson_install.py b/mesonbuild/scripts/meson_install.py
index b05ffbc..f978be4 100644
--- a/mesonbuild/scripts/meson_install.py
+++ b/mesonbuild/scripts/meson_install.py
@@ -101,7 +101,7 @@ def restore_selinux_context(to_file):
use_selinux = False
msg = "{!r}: Failed to restore SELinux context, ignoring SELinux context for all remaining files..."
print(msg.format(to_file, e.returncode))
- except (FileNotFoundError, subprocess.CalledProcessError) as e:
+ except (FileNotFoundError, PermissionError, subprocess.CalledProcessError) as e:
# If we don't have selinux or selinuxenabled returned 1, failure
# is ignored quietly.
use_selinux = False
diff --git a/run_unittests.py b/run_unittests.py
index f33824a..08ec774 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -1925,6 +1925,28 @@ class LinuxlikeTests(BasePlatformTests):
self.run_tests()
self.run_target('coverage-html')
+ def test_cross_find_program(self):
+ testdir = os.path.join(self.unit_test_dir, '12 cross prog')
+ crossfile = tempfile.NamedTemporaryFile(mode='w')
+ print(os.path.join(testdir, 'some_cross_tool.py'))
+ crossfile.write('''[binaries]
+c = '/usr/bin/cc'
+ar = '/usr/bin/ar'
+strip = '/usr/bin/ar'
+sometool.py = '%s'
+
+[properties]
+
+[host_machine]
+system = 'linux'
+cpu_family = 'arm'
+cpu = 'armv7' # Not sure if correct.
+endian = 'little'
+''' % os.path.join(testdir, 'some_cross_tool.py'))
+ crossfile.flush()
+ self.init(testdir, ['--cross-file='+crossfile.name])
+
+
class LinuxArmCrossCompileTests(BasePlatformTests):
'''
Tests that verify cross-compilation to Linux/ARM
diff --git a/test cases/common/112 has arg/meson.build b/test cases/common/112 has arg/meson.build
index a89b59e..27290a1 100644
--- a/test cases/common/112 has arg/meson.build
+++ b/test cases/common/112 has arg/meson.build
@@ -19,6 +19,9 @@ assert(not cc.has_argument(isnt_arg), 'Arg that should be broken is not.')
assert(cpp.has_argument(is_arg), 'Arg that should have worked does not work.')
assert(not cpp.has_argument(isnt_arg), 'Arg that should be broken is not.')
+assert(cc.get_supported_arguments([is_arg, isnt_arg, useless]) == [is_arg, useless], 'Arg filtering returned different result.')
+assert(cpp.get_supported_arguments([is_arg, isnt_arg, useless]) == [is_arg, useless], 'Arg filtering returned different result.')
+
# Have useless at the end to ensure that the search goes from front to back.
l1 = cc.first_supported_argument([isnt_arg, is_arg, isnt_arg, useless])
l2 = cc.first_supported_argument(isnt_arg, isnt_arg, isnt_arg)
diff --git a/test cases/frameworks/7 gnome/gdbus/meson.build b/test cases/frameworks/7 gnome/gdbus/meson.build
index 7f7c97b..f8a8eba 100644
--- a/test cases/frameworks/7 gnome/gdbus/meson.build
+++ b/test cases/frameworks/7 gnome/gdbus/meson.build
@@ -1,6 +1,10 @@
gdbus_src = gnome.gdbus_codegen('generated-gdbus', 'com.example.Sample.xml',
interface_prefix : 'com.example.',
- namespace : 'Sample')
+ namespace : 'Sample',
+ annotations : [
+ ['com.example.Hello()', 'org.freedesktop.DBus.Deprecated', 'true']
+ ]
+)
gdbus_exe = executable('gdbus-test', 'gdbusprog.c',
gdbus_src,
diff --git a/test cases/unit/12 cross prog/meson.build b/test cases/unit/12 cross prog/meson.build
new file mode 100644
index 0000000..e628701
--- /dev/null
+++ b/test cases/unit/12 cross prog/meson.build
@@ -0,0 +1,12 @@
+project('cross find program', 'c')
+
+native_exe = find_program('sometool.py', native : true)
+cross_exe = find_program('sometool.py')
+
+native_out = run_command(native_exe).stdout().strip()
+cross_out = run_command(cross_exe).stdout().strip()
+
+assert(native_out == 'native',
+ 'Native output incorrect:' + native_out)
+assert(cross_out == 'cross',
+ 'Cross output incorrect:' + cross_out)
diff --git a/test cases/unit/12 cross prog/some_cross_tool.py b/test cases/unit/12 cross prog/some_cross_tool.py
new file mode 100755
index 0000000..1edd10f
--- /dev/null
+++ b/test cases/unit/12 cross prog/some_cross_tool.py
@@ -0,0 +1,5 @@
+#!/usr/bin/env python
+
+from __future__ import print_function
+
+print('cross')
diff --git a/test cases/unit/12 cross prog/sometool.py b/test cases/unit/12 cross prog/sometool.py
new file mode 100755
index 0000000..4c0e3b1
--- /dev/null
+++ b/test cases/unit/12 cross prog/sometool.py
@@ -0,0 +1,5 @@
+#!/usr/bin/env python
+
+from __future__ import print_function
+
+print('native')