Skip to content

Commit

Permalink
Add "meson run" command
Browse files Browse the repository at this point in the history
  • Loading branch information
xclaesse committed Nov 8, 2024
1 parent dc4483b commit d6c5449
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 1 deletion.
16 changes: 16 additions & 0 deletions docs/markdown/Commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,22 @@ format should be used. There are currently 3 formats supported:

{{ devenv_arguments.inc }}

### run

*Since 1.7.0*

{{ run_usage.inc }}

Compile and run a target inside Meson's [`devenv`](#devenv).

In the case the project installs more than one executable, `--bin <target>`
argument can be used to specify which one to run. See [`compile`](#compile)
command for `target` syntax.

The remainder of the command line are arguments passed to the target executable:
```
meson run -C builddir --bin gst-launch-1.0 videotestsrc ! glimagesink
```

### format

Expand Down
13 changes: 13 additions & 0 deletions docs/markdown/snippets/run.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
## Build and run the project

[`Meson run`](Commands.md#run) compiles and runs a target inside Meson's
[`devenv`](Commands.md#devenv).

In the case the project installs more than one executable, `--bin <target>`
argument can be used to specify which one to run. See [`compile`](#compile)
command for `target` syntax.

The remainder of the command line are arguments passed to the target executable:
```
meson run -C builddir --bin gst-launch-1.0 videotestsrc ! glimagesink
```
27 changes: 27 additions & 0 deletions mesonbuild/mcompile.py
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,33 @@ def add_arguments(parser: 'argparse.ArgumentParser') -> None:
help='Arguments to pass to `xcodebuild` (applied only on `xcode` backend).'
)

# Used by mrun.py
def compile_single_executable(environment: Environment, target: T.Optional[str]) -> T.Tuple[T.Optional[str], int]:
builddir = Path(environment.build_dir)
intro_data = parse_introspect_data(builddir)
if target:
intro_target = get_target_from_intro_data(target, builddir, intro_data)
if intro_target['type'] != 'executable':
raise MesonException('--bin argument must be an executable')
else:
found_targets: T.List[IntroTarget] = []
for name, targets in intro_data.items():
for intro_target in targets:
# Restrict the search to installable executables.
if intro_target['type'] == 'executable' and intro_target['installed']:
found_targets.append(intro_target)
if not found_targets:
raise MesonException('No executable targets found.')
elif len(found_targets) > 1:
suggestions_str = get_suggestions(builddir, found_targets)
raise MesonException('Multiple executable targets found.'
f' Specify --bin argument:\n{suggestions_str}')
intro_target = found_targets[0]
returncode = run_compile(environment, [intro_target])
if returncode != 0:
return None, returncode
return intro_target['filename'][0], 0

def run_compile(environment: Environment, targets: T.List[IntroTarget],
jobs: int = 0, load_average: int = 0, verbose: bool = False,
clean: bool = False, ninja_args: T.Optional[T.List[str]] = None,
Expand Down
5 changes: 4 additions & 1 deletion mesonbuild/mesonmain.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ def errorhandler(e: Exception, command: str) -> int:
class CommandLineParser:
def __init__(self) -> None:
# only import these once we do full argparse processing
from . import mconf, mdist, minit, minstall, mintro, msetup, mtest, rewriter, msubprojects, munstable_coredata, mcompile, mdevenv, mformat
from . import (mconf, mdist, minit, minstall, mintro, msetup, mtest, rewriter, msubprojects, munstable_coredata,
mcompile, mdevenv, mformat, mrun)
from .scripts import env2mfile, reprotest
from .wrap import wraptool
import shutil
Expand Down Expand Up @@ -101,6 +102,8 @@ def __init__(self) -> None:
help_msg='Build the project')
self.add_command('devenv', mdevenv.add_arguments, mdevenv.run,
help_msg='Run commands in developer environment')
self.add_command('run', mrun.add_arguments, mrun.run,
help_msg='Compile and run an executable')
self.add_command('env2mfile', env2mfile.add_arguments, env2mfile.run,
help_msg='Convert current environment to a cross or native file')
self.add_command('reprotest', reprotest.add_arguments, reprotest.run,
Expand Down
39 changes: 39 additions & 0 deletions mesonbuild/mrun.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from __future__ import annotations

import argparse
import typing as T

from pathlib import Path
from . import build
from .mesonlib import setup_vsenv, MesonException
from .options import OptionKey
from .mcompile import compile_single_executable
from .mdevenv import run_cmd


# Note: when adding arguments, please also add them to the completion
# scripts in $MESONSRC/data/shell-completions/
def add_arguments(parser: argparse.ArgumentParser) -> None:
parser.add_argument('-C', dest='builddir', type=Path, default='.',
help='Path to build directory')
parser.add_argument('--bin', default=None,
help='Executable target to build and run')
parser.add_argument('arguments', nargs=argparse.REMAINDER,
help='Arguments to pass to the executable')


def run(options: argparse.Namespace) -> int:
buildfile = Path(options.builddir, 'meson-private', 'build.dat')
if not buildfile.is_file():
raise MesonException(f'Directory {options.builddir!r} does not seem to be a Meson build directory.')
b = build.load(options.builddir)

need_vsenv = T.cast('bool', b.environment.coredata.get_option(OptionKey('vsenv')))
setup_vsenv(need_vsenv)

path, returncode = compile_single_executable(b.environment, options.bin)
if returncode != 0:
return returncode

cmd = [path] + options.arguments
return run_cmd(b, cmd)

0 comments on commit d6c5449

Please sign in to comment.