summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/markdown/Commands.md7
-rw-r--r--docs/markdown/snippets/meson_compile_suffixes.md7
-rw-r--r--mesonbuild/mcompile.py40
-rw-r--r--unittests/allplatformstests.py9
4 files changed, 56 insertions, 7 deletions
diff --git a/docs/markdown/Commands.md b/docs/markdown/Commands.md
index efc316ce7..3fcdedd03 100644
--- a/docs/markdown/Commands.md
+++ b/docs/markdown/Commands.md
@@ -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)*
diff --git a/docs/markdown/snippets/meson_compile_suffixes.md b/docs/markdown/snippets/meson_compile_suffixes.md
new file mode 100644
index 000000000..481e8adf4
--- /dev/null
+++ b/docs/markdown/snippets/meson_compile_suffixes.md
@@ -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.
diff --git a/mesonbuild/mcompile.py b/mesonbuild/mcompile.py
index 19875c22a..6721beb0b 100644
--- a/mesonbuild/mcompile.py
+++ b/mesonbuild/mcompile.py
@@ -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,12 +141,20 @@ 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)
raise MesonException(f'Can\'t invoke target `{target.full_name}`: ambiguous name.'
- f'Add target type and/or path:\n{suggestions_str}')
+ f' Add target type and/or path:\n{suggestions_str}')
return found_targets[0]
@@ -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',
diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py
index 030b216d7..f5048837f 100644
--- a/unittests/allplatformstests.py
+++ b/unittests/allplatformstests.py
@@ -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