mcompile: add suffix as an additional parameter

Since the previous commit allows for more scenarios with name
collisions, it makes sense to expand the compile command so that it can
also take into account suffixes. i.e. meson compile -C build foo.exe can
now work if the executable has an exe suffix along with being named foo.
pull/12340/head
Dudemanguy 1 year ago committed by Dylan Baker
parent adb1a360b9
commit 03a0d3ddfb
  1. 7
      docs/markdown/Commands.md
  2. 7
      docs/markdown/snippets/meson_compile_suffixes.md
  3. 38
      mesonbuild/mcompile.py
  4. 9
      unittests/allplatformstests.py

@ -58,14 +58,17 @@ Builds a default or a specified target of a configured Meson project.
*(since 0.55.0)*
`TARGET` has the following syntax `[PATH/]NAME[:TYPE]`, where:
`TARGET` has the following syntax `[PATH/]NAME.SUFFIX[:TYPE]`, where:
- `NAME`: name of the target from `meson.build` (e.g. `foo` from `executable('foo', ...)`).
- `SUFFIX`: name of the suffix of the target from `meson.build` (e.g. `exe` from `executable('foo', suffix: 'exe', ...)`).
- `PATH`: path to the target relative to the root `meson.build` file. Note: relative path for a target specified in the root `meson.build` is `./`.
- `TYPE`: type of the target. Can be one of the following: 'executable', 'static_library', 'shared_library', 'shared_module', 'custom', 'alias', 'run', 'jar'.
`PATH` and/or `TYPE` can be omitted if the resulting `TARGET` can be
`PATH`, `SUFFIX`, and `TYPE` can all be omitted if the resulting `TARGET` can be
used to uniquely identify the target in `meson.build`.
Note that `SUFFIX` did not exist prior to 1.3.0.
#### Backend specific arguments
*(since 0.55.0)*

@ -0,0 +1,7 @@
## Meson compile command now accepts suffixes for TARGET
The syntax for specifying a target for meson compile is now
`[PATH_TO_TARGET/]TARGET_NAME.TARGET_SUFFIX[:TARGET_TYPE]` where
`TARGET_SUFFIX` is the suffix argument given in the build target
within meson.build. It is optional and `TARGET_NAME` remains
sufficient if it uniquely resolves to one single target.

@ -61,9 +61,11 @@ def parse_introspect_data(builddir: Path) -> T.Dict[str, T.List[dict]]:
class ParsedTargetName:
full_name = ''
base_name = ''
name = ''
type = ''
path = ''
suffix = ''
def __init__(self, target: str):
self.full_name = target
@ -80,6 +82,13 @@ class ParsedTargetName:
else:
self.name = split[0]
split = self.name.rsplit('.', 1)
if len(split) > 1:
self.base_name = split[0]
self.suffix = split[1]
else:
self.base_name = split[0]
@staticmethod
def _is_valid_type(type: str) -> bool:
# Amend docs in Commands.md when editing this list
@ -96,19 +105,32 @@ class ParsedTargetName:
return type in allowed_types
def get_target_from_intro_data(target: ParsedTargetName, builddir: Path, introspect_data: T.Dict[str, T.Any]) -> T.Dict[str, T.Any]:
if target.name not in introspect_data:
if target.name not in introspect_data and target.base_name not in introspect_data:
raise MesonException(f'Can\'t invoke target `{target.full_name}`: target not found')
intro_targets = introspect_data[target.name]
# if target.name doesn't find anything, try just the base name
if not intro_targets:
intro_targets = introspect_data[target.base_name]
found_targets: T.List[T.Dict[str, T.Any]] = []
resolved_bdir = builddir.resolve()
if not target.type and not target.path:
if not target.type and not target.path and not target.suffix:
found_targets = intro_targets
else:
for intro_target in intro_targets:
# Parse out the name from the id if needed
intro_target_name = intro_target['name']
split = intro_target['id'].rsplit('@', 1)
if len(split) > 1:
split = split[0].split('@@', 1)
if len(split) > 1:
intro_target_name = split[1]
else:
intro_target_name = split[0]
if ((target.type and target.type != intro_target['type'].replace(' ', '_')) or
(target.name != intro_target_name) or
(target.path and intro_target['filename'] != 'no_name' and
Path(target.path) != Path(intro_target['filename'][0]).relative_to(resolved_bdir).parent)):
continue
@ -119,7 +141,15 @@ def get_target_from_intro_data(target: ParsedTargetName, builddir: Path, introsp
elif len(found_targets) > 1:
suggestions: T.List[str] = []
for i in found_targets:
p = Path(i['filename'][0]).relative_to(resolved_bdir).parent / i['name']
i_name = i['name']
split = i['id'].rsplit('@', 1)
if len(split) > 1:
split = split[0].split('@@', 1)
if len(split) > 1:
i_name = split[1]
else:
i_name = split[0]
p = Path(i['filename'][0]).relative_to(resolved_bdir).parent / i_name
t = i['type'].replace(' ', '_')
suggestions.append(f'- ./{p}:{t}')
suggestions_str = '\n'.join(suggestions)
@ -278,7 +308,7 @@ def add_arguments(parser: 'argparse.ArgumentParser') -> None:
metavar='TARGET',
nargs='*',
default=None,
help='Targets to build. Target has the following format: [PATH_TO_TARGET/]TARGET_NAME[:TARGET_TYPE].')
help='Targets to build. Target has the following format: [PATH_TO_TARGET/]TARGET_NAME.TARGET_SUFFIX[:TARGET_TYPE].')
parser.add_argument(
'--clean',
action='store_true',

@ -2049,6 +2049,15 @@ class AllPlatformTests(BasePlatformTests):
self.assertPathExists(exe2)
self.assertNotEqual(exe1, exe2)
# Wipe and run the compile command against the target names
self.init(testdir, extra_args=['--wipe'])
self._run([*self.meson_command, 'compile', '-C', self.builddir, './foo'])
self._run([*self.meson_command, 'compile', '-C', self.builddir, './foo.bin'])
self.assertPathExists(exe1)
self.assertPathExists(exe2)
self.assertNotEqual(exe1, exe2)
def opt_has(self, name, value):
res = self.introspect('--buildoptions')
found = False

Loading…
Cancel
Save