diff options
-rw-r--r-- | docs/markdown/Reference-manual.md | 26 | ||||
-rw-r--r-- | docs/markdown/snippets/compiler-object-run_command.md | 10 | ||||
-rw-r--r-- | docs/markdown/snippets/improved-help.md | 6 | ||||
-rw-r--r-- | mesonbuild/interpreter.py | 11 | ||||
-rw-r--r-- | mesonbuild/mesonmain.py | 7 | ||||
-rwxr-xr-x | run_unittests.py | 24 | ||||
-rw-r--r-- | test cases/unit/23 compiler run_command/meson.build | 10 |
7 files changed, 84 insertions, 10 deletions
diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md index 6f6cb36..5b22fec 100644 --- a/docs/markdown/Reference-manual.md +++ b/docs/markdown/Reference-manual.md @@ -982,9 +982,13 @@ Project supports the following keyword arguments. runresult run_command(command, list_of_args) ``` -Runs the command specified in positional arguments. Returns [an opaque -object](#run-result-object) containing the result of the -invocation. The script is run from an *unspecified* directory, and +Runs the command specified in positional arguments. +`command` can be a string, or the output of [`find_program()`](#find_program), +[`files()`](#files) or [`configure_file()`](#configure_file), or +[a compiler object](#compiler-object). + +Returns [an opaque object](#run-result-object) containing the result of the +invocation. The command is run from an *unspecified* directory, and Meson will set three environment variables `MESON_SOURCE_ROOT`, `MESON_BUILD_ROOT` and `MESON_SUBDIR` that specify the source directory, build directory and subdirectory the target was defined in, @@ -1199,10 +1203,18 @@ be up to date on every build. Keywords are similar to `custom_target`. Meson will read the contents of `input`, substitute the `replace_string` with the detected revision number, and write the -result to `output`. This method returns an opaque -[`custom_target`](#custom_target) object that can be used as -source. If you desire more specific behavior than what this command -provides, you should use `custom_target`. +result to `output`. This method returns a +[`custom_target`](#custom_target) object that (as usual) should be +used to signal dependencies if other targets use the file outputted +by this. + +For example, if you generate a header with this and want to use that in +a build target, you must add the return value to the sources of that +build target. Without that, Meson will not know the order in which to +build the targets. + +If you desire more specific behavior than what this command provides, +you should use `custom_target`. ## Built-in objects diff --git a/docs/markdown/snippets/compiler-object-run_command.md b/docs/markdown/snippets/compiler-object-run_command.md new file mode 100644 index 0000000..0308416 --- /dev/null +++ b/docs/markdown/snippets/compiler-object-run_command.md @@ -0,0 +1,10 @@ +## Compiler object can now be passed to run_command() + +This can be used to run the current compiler with the specified arguments +to obtain additional information from it. +One of the use cases is to get the location of development files for the +GCC plugins: + + cc = meson.get_compiler('c') + result = run_command(cc, '-print-file-name=plugin') + plugin_dev_path = result.stdout().strip() diff --git a/docs/markdown/snippets/improved-help.md b/docs/markdown/snippets/improved-help.md new file mode 100644 index 0000000..db7e852 --- /dev/null +++ b/docs/markdown/snippets/improved-help.md @@ -0,0 +1,6 @@ +## "meson help" now shows command line help + +Command line parsing is now less surprising. "meson help" is now +equivalent to "meson --help" and "meson help <subcommand>" is +equivalent to "meson <subcommand> --help", instead of creating a build +directory called "help" in these cases. diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index 8421d70..f9f25e4 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -1680,10 +1680,17 @@ external dependencies (including libraries) must go to "dependencies".''') cargs = args[1:] srcdir = self.environment.get_source_dir() builddir = self.environment.get_build_dir() - m = 'must be a string, or the output of find_program(), files(), or ' \ - 'configure_file(); not {!r}' + m = 'must be a string, or the output of find_program(), files() '\ + 'or configure_file(), or a compiler object; not {!r}' if isinstance(cmd, ExternalProgramHolder): cmd = cmd.held_object + elif isinstance(cmd, CompilerHolder): + cmd = cmd.compiler.get_exelist()[0] + prog = ExternalProgram(cmd, silent=True) + if not prog.found(): + raise InterpreterException('Program {!r} not found ' + 'or not executable'.format(cmd)) + cmd = prog else: if isinstance(cmd, mesonlib.File): cmd = cmd.absolute_path(srcdir, builddir) diff --git a/mesonbuild/mesonmain.py b/mesonbuild/mesonmain.py index e354cce..69b4e31 100644 --- a/mesonbuild/mesonmain.py +++ b/mesonbuild/mesonmain.py @@ -284,6 +284,13 @@ def run(original_args, mainfile=None): # First check if we want to run a subcommand. cmd_name = args[0] remaining_args = args[1:] + # "help" is a special case: Since printing of the help may be + # delegated to a subcommand, we edit cmd_name before executing + # the rest of the logic here. + if cmd_name == 'help': + remaining_args += ['--help'] + args = remaining_args + cmd_name = args[0] if cmd_name == 'test': return mtest.run(remaining_args) elif cmd_name == 'setup': diff --git a/run_unittests.py b/run_unittests.py index 8f69077..cbae559 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -25,7 +25,7 @@ import unittest from unittest import mock from configparser import ConfigParser from glob import glob -from pathlib import PurePath +from pathlib import (PurePath, Path) import mesonbuild.mlog import mesonbuild.compilers @@ -429,6 +429,20 @@ class InternalTests(unittest.TestCase): kwargs = {'sources': [1, 2, 3], 'pch_sources': [4, 5, 6]} self.assertEqual([[1, 2, 3], [4, 5, 6]], extract(kwargs, 'sources', 'pch_sources')) + def test_snippets(self): + hashcounter = re.compile('^ *(#)+') + snippet_dir = Path('docs/markdown/snippets') + self.assertTrue(snippet_dir.is_dir()) + for f in snippet_dir.glob('*'): + self.assertTrue(f.is_file()) + if f.suffix == '.md': + for line in f.open(): + m = re.match(hashcounter, line) + if m: + self.assertEqual(len(m.group(0)), 2, 'All headings in snippets must have two hash symbols: ' + f.name) + else: + if f.name != 'add_release_note_snippets_here': + self.assertTrue(False, 'A file without .md suffix in snippets dir: ' + f.name) class BasePlatformTests(unittest.TestCase): def setUp(self): @@ -1836,6 +1850,14 @@ int main(int argc, char **argv) { self.init(testdir, ['--cross-file=' + name], inprocess=True) self.wipe() + def test_compiler_run_command(self): + ''' + The test checks that the compiler object can be passed to + run_command(). + ''' + testdir = os.path.join(self.unit_test_dir, '23 compiler run_command') + self.init(testdir) + class FailureTests(BasePlatformTests): ''' diff --git a/test cases/unit/23 compiler run_command/meson.build b/test cases/unit/23 compiler run_command/meson.build new file mode 100644 index 0000000..6d9e0b9 --- /dev/null +++ b/test cases/unit/23 compiler run_command/meson.build @@ -0,0 +1,10 @@ +project('compiler_object_in_run_command', 'c') +cc = meson.get_compiler('c') + +# This test only checks that the compiler object can be passed to +# run_command(). If the compiler has been launched, it is expected +# to output something either to stdout or to stderr. +result = run_command(cc, '--version') +if result.stdout() == '' and result.stderr() == '' + error('No output in stdout and stderr. Did the compiler run at all?') +endif |