Skip to content

Commit cfd5718

Browse files
stspdcbaker
authored andcommitted
implement @PLAINNAME0@ and @BASENAME0@
@Plainname@ and @basename@ cannot be used in custom_target() with multiple inputs. For those, similar macros are needed with an index. Fixes mesonbuild#13164
1 parent f8aefe2 commit cfd5718

File tree

6 files changed

+39
-4
lines changed

6 files changed

+39
-4
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
## Support of indexed `@PLAINNAME@` and `@BASENAME@`
2+
3+
In `custom_target()` and `configure_file()` with multiple inputs,
4+
it is now possible to specify index for `@PLAINNAME@` and `@BASENAME@`
5+
macros in `output`:
6+
```
7+
custom_target('target_name',
8+
output: '@[email protected]',
9+
input: [dep1, dep2],
10+
command: cmd)
11+
```

docs/yaml/functions/configure_file.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,9 @@ kwargs:
123123
type: str
124124
description: |
125125
The output file name. *(since 0.41.0)* may contain
126-
`@PLAINNAME@` or `@BASENAME@` substitutions. In configuration mode,
126+
`@PLAINNAME@` or `@BASENAME@` substitutions, as well as *(since 1.5.0)*
127+
their indexed versions, like `@PLAINNAME0@` or `@BASENAME0@`.
128+
In configuration mode,
127129
the permissions of the input file (if it is specified) are copied to
128130
the output file.
129131

docs/yaml/functions/custom_target.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ description: |
3131
- `@OUTDIR@`: the full path to the directory where the output(s) must be written
3232
- `@DEPFILE@`: the full path to the dependency file passed to `depfile`
3333
- `@PLAINNAME@`: the input filename, without a path
34+
- `@PLAINNAME0@` `@PLAINNAME1@` `...` *(since 1.5.0)*: the input filename without a path, with the specified array index in `input`
3435
- `@BASENAME@`: the input filename, with extension removed
36+
- `@BASENAME0@` `@BASENAME1@` `...` *(since 1.5.0)*: the input filename with extension removed, with the specified array index in `input`
3537
- `@PRIVATE_DIR@` *(since 0.50.1)*: path to a directory where the custom target must store all its intermediate files.
3638
- `@SOURCE_ROOT@`: the path to the root of the source tree. Depending on the backend,
3739
this may be an absolute or a relative to current workdir path.

mesonbuild/interpreter/interpreter.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1983,17 +1983,23 @@ def func_vcs_tag(self, node: mparser.BaseNode, args: T.List['TYPE_var'], kwargs:
19831983
def func_subdir_done(self, node: mparser.BaseNode, args: TYPE_var, kwargs: TYPE_kwargs) -> T.NoReturn:
19841984
raise SubdirDoneRequest()
19851985

1986-
@staticmethod
1987-
def _validate_custom_target_outputs(has_multi_in: bool, outputs: T.Iterable[str], name: str) -> None:
1986+
def _validate_custom_target_outputs(self, has_multi_in: bool, outputs: T.Iterable[str], name: str) -> None:
19881987
"""Checks for additional invalid values in a custom_target output.
19891988
19901989
This cannot be done with typed_kwargs because it requires the number of
19911990
inputs.
19921991
"""
1992+
inregex: T.List[str] = ['@PLAINNAME[0-9]+@', '@BASENAME[0-9]+@']
1993+
from ..utils.universal import iter_regexin_iter
19931994
for out in outputs:
1995+
match = iter_regexin_iter(inregex, [out])
19941996
if has_multi_in and ('@PLAINNAME@' in out or '@BASENAME@' in out):
19951997
raise InvalidArguments(f'{name}: output cannot contain "@PLAINNAME@" or "@BASENAME@" '
19961998
'when there is more than one input (we can\'t know which to use)')
1999+
elif match:
2000+
FeatureNew.single_use(
2001+
f'{match} in output', '1.5.0',
2002+
self.subproject)
19972003

19982004
@typed_pos_args('custom_target', optargs=[str])
19992005
@typed_kwargs(

mesonbuild/utils/universal.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1744,6 +1744,8 @@ def get_filenames_templates_dict(inputs: T.List[str], outputs: T.List[str]) -> T
17441744
If there is more than one input file, the following keys are also created:
17451745
17461746
@INPUT0@, @INPUT1@, ... one for each input file
1747+
@PLAINNAME0@, @PLAINNAME1@, ... one for each input file
1748+
@BASENAME0@, @BASENAME1@, ... one for each input file
17471749
17481750
If there is more than one output file, the following keys are also created:
17491751
@@ -1757,6 +1759,9 @@ def get_filenames_templates_dict(inputs: T.List[str], outputs: T.List[str]) -> T
17571759
for (ii, vv) in enumerate(inputs):
17581760
# Write out @INPUT0@, @INPUT1@, ...
17591761
values[f'@INPUT{ii}@'] = vv
1762+
plain = os.path.basename(vv)
1763+
values[f'@PLAINNAME{ii}@'] = plain
1764+
values[f'@BASENAME{ii}@'] = os.path.splitext(plain)[0]
17601765
if len(inputs) == 1:
17611766
# Just one value, substitute @PLAINNAME@ and @BASENAME@
17621767
values['@PLAINNAME@'] = plain = os.path.basename(inputs[0])

unittests/internaltests.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@ def test_string_templates_substitution(self):
287287
outputs = []
288288
ret = dictfunc(inputs, outputs)
289289
d = {'@INPUT@': inputs, '@INPUT0@': inputs[0],
290+
'@PLAINNAME0@': 'foo.c.in', '@BASENAME0@': 'foo.c',
290291
'@PLAINNAME@': 'foo.c.in', '@BASENAME@': 'foo.c'}
291292
# Check dictionary
292293
self.assertEqual(ret, d)
@@ -309,6 +310,7 @@ def test_string_templates_substitution(self):
309310
outputs = ['out.c']
310311
ret = dictfunc(inputs, outputs)
311312
d = {'@INPUT@': inputs, '@INPUT0@': inputs[0],
313+
'@PLAINNAME0@': 'foo.c.in', '@BASENAME0@': 'foo.c',
312314
'@PLAINNAME@': 'foo.c.in', '@BASENAME@': 'foo.c',
313315
'@OUTPUT@': outputs, '@OUTPUT0@': outputs[0], '@OUTDIR@': '.'}
314316
# Check dictionary
@@ -330,6 +332,7 @@ def test_string_templates_substitution(self):
330332
outputs = ['dir/out.c']
331333
ret = dictfunc(inputs, outputs)
332334
d = {'@INPUT@': inputs, '@INPUT0@': inputs[0],
335+
'@PLAINNAME0@': 'foo.c.in', '@BASENAME0@': 'foo.c',
333336
'@PLAINNAME@': 'foo.c.in', '@BASENAME@': 'foo.c',
334337
'@OUTPUT@': outputs, '@OUTPUT0@': outputs[0], '@OUTDIR@': 'dir'}
335338
# Check dictionary
@@ -339,7 +342,9 @@ def test_string_templates_substitution(self):
339342
inputs = ['bar/foo.c.in', 'baz/foo.c.in']
340343
outputs = []
341344
ret = dictfunc(inputs, outputs)
342-
d = {'@INPUT@': inputs, '@INPUT0@': inputs[0], '@INPUT1@': inputs[1]}
345+
d = {'@INPUT@': inputs, '@INPUT0@': inputs[0], '@INPUT1@': inputs[1],
346+
'@PLAINNAME0@': 'foo.c.in', '@PLAINNAME1@': 'foo.c.in',
347+
'@BASENAME0@': 'foo.c', '@BASENAME1@': 'foo.c'}
343348
# Check dictionary
344349
self.assertEqual(ret, d)
345350
# Check substitutions
@@ -376,6 +381,8 @@ def test_string_templates_substitution(self):
376381
outputs = ['dir/out.c']
377382
ret = dictfunc(inputs, outputs)
378383
d = {'@INPUT@': inputs, '@INPUT0@': inputs[0], '@INPUT1@': inputs[1],
384+
'@PLAINNAME0@': 'foo.c.in', '@PLAINNAME1@': 'foo.c.in',
385+
'@BASENAME0@': 'foo.c', '@BASENAME1@': 'foo.c',
379386
'@OUTPUT@': outputs, '@OUTPUT0@': outputs[0], '@OUTDIR@': 'dir'}
380387
# Check dictionary
381388
self.assertEqual(ret, d)
@@ -402,6 +409,8 @@ def test_string_templates_substitution(self):
402409
outputs = ['dir/out.c', 'dir/out2.c']
403410
ret = dictfunc(inputs, outputs)
404411
d = {'@INPUT@': inputs, '@INPUT0@': inputs[0], '@INPUT1@': inputs[1],
412+
'@PLAINNAME0@': 'foo.c.in', '@PLAINNAME1@': 'foo.c.in',
413+
'@BASENAME0@': 'foo.c', '@BASENAME1@': 'foo.c',
405414
'@OUTPUT@': outputs, '@OUTPUT0@': outputs[0], '@OUTPUT1@': outputs[1],
406415
'@OUTDIR@': 'dir'}
407416
# Check dictionary

0 commit comments

Comments
 (0)