Repository: mesonbuild/meson

Issue:
@BASENAME@ and @PLAINNAME@ not supported as generator arguments
Considering the following meson.build line

```
generator(glsl2h, output: '@PLAINNAME@.h', arguments: ['@INPUT@', '@OUTPUT@', '@PLAINNAME@'])
```

I would expect the third argument to the generator to be the name of the input file but it is just the string `@PLAINNAME@`.


Discussion:
Oh and BTW, something like `'@PLAINNAME@'.underscorify()` works even less because the substitution happens after the call to underscorify.
Just another thought: Maybe the string formatting could support named variables or expressions so something like `'@x@'.format(x: 'foo')` or `'@x + 2@'.format(x: 5)` or `'@PLAINNAME.underscorify()@'.format(PLAINNAME: 'foo.txt')` would be possible.

Resolving patch:
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -1784,7 +1784,6 @@ def generate_genlist_for_target(self, genlist, target, outfile):
         exe_arr = self.exe_object_to_cmd_array(exe)
         infilelist = genlist.get_inputs()
         outfilelist = genlist.get_outputs()
-        base_args = generator.get_arglist()
         extra_dependencies = [os.path.join(self.build_to_src, i) for i in genlist.extra_depends]
         source_target_dir = self.get_target_source_dir(target)
         for i in range(len(infilelist)):
@@ -1794,6 +1793,7 @@ def generate_genlist_for_target(self, genlist, target, outfile):
                 sole_output = ''
             curfile = infilelist[i]
             infilename = curfile.rel_to_builddir(self.build_to_src)
+            base_args = generator.get_arglist(infilename)
             outfiles = genlist.get_outputs_for(curfile)
             outfiles = [os.path.join(self.get_target_private_dir(target), of) for of in outfiles]
             if generator.depfile is None:
diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py
--- a/mesonbuild/backend/vs2010backend.py
+++ b/mesonbuild/backend/vs2010backend.py
@@ -106,7 +106,6 @@ def generate_custom_generator_commands(self, target, parent_node):
                 infilelist = genlist.get_inputs()
                 outfilelist = genlist.get_outputs()
                 exe_arr = self.exe_object_to_cmd_array(exe)
-                base_args = generator.get_arglist()
                 idgroup = ET.SubElement(parent_node, 'ItemGroup')
                 for i in range(len(infilelist)):
                     if len(infilelist) == len(outfilelist):
@@ -115,6 +114,7 @@ def generate_custom_generator_commands(self, target, parent_node):
                         sole_output = ''
                     curfile = infilelist[i]
                     infilename = os.path.join(down, curfile.rel_to_builddir(self.build_to_src))
+                    base_args = generator.get_arglist(infilename)
                     outfiles_rel = genlist.get_outputs_for(curfile)
                     outfiles = [os.path.join(target_private_dir, of) for of in outfiles_rel]
                     generator_output_files += outfiles
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -1075,8 +1075,10 @@ def get_dep_outname(self, inname):
         basename = os.path.splitext(plainname)[0]
         return self.depfile.replace('@BASENAME@', basename).replace('@PLAINNAME@', plainname)
 
-    def get_arglist(self):
-        return self.arglist
+    def get_arglist(self, inname):
+        plainname = os.path.split(inname)[1]
+        basename = os.path.splitext(plainname)[0]
+        return [x.replace('@BASENAME@', basename).replace('@PLAINNAME@', plainname) for x in self.arglist]
 
     def process_files(self, name, files, state, extra_args=[]):
         output = GeneratedList(self, extra_args=extra_args)


Test patch:
diff --git a/test cases/common/98 gen extra/meson.build b/test cases/common/98 gen extra/meson.build
--- a/test cases/common/98 gen extra/meson.build	
+++ b/test cases/common/98 gen extra/meson.build	
@@ -11,3 +11,20 @@ g2 = gen.process('name.dat', extra_args: '--upper')
 
 test('basic', executable('basic', 'plain.c', g1))
 test('upper', executable('upper', 'upper.c', g2))
+
+prog2 = find_program('srcgen2.py')
+basename_gen = generator(prog2,
+  output : ['@BASENAME@.tab.c', '@BASENAME@.tab.h'],
+  arguments : ['@BUILD_DIR@', '@BASENAME@', '@INPUT@'])
+
+basename_src = basename_gen.process('name.l')
+
+test('basename', executable('basename', basename_src))
+
+plainname_gen = generator(prog2,
+  output : ['@PLAINNAME@.tab.c', '@PLAINNAME@.tab.h'],
+  arguments : ['@BUILD_DIR@', '@PLAINNAME@', '@INPUT@'])
+
+plainname_src = plainname_gen.process('name.l')
+
+test('plainname', executable('plainname', plainname_src))
diff --git a/test cases/common/98 gen extra/name.l b/test cases/common/98 gen extra/name.l
new file mode 100644
--- /dev/null
+++ b/test cases/common/98 gen extra/name.l	
@@ -0,0 +1,3 @@
+int main() {
+return 0;
+}
diff --git a/test cases/common/98 gen extra/srcgen2.py b/test cases/common/98 gen extra/srcgen2.py
new file mode 100644
--- /dev/null
+++ b/test cases/common/98 gen extra/srcgen2.py	
@@ -0,0 +1,32 @@
+#!/usr/bin/env python3
+
+import os
+import sys
+import argparse
+
+parser = argparse.ArgumentParser()
+parser.add_argument('target_dir',
+                    help='the target dir')
+parser.add_argument('stem',
+                    help='the stem')
+parser.add_argument('input',
+                    help='the input file')
+
+options = parser.parse_args(sys.argv[1:])
+
+with open(options.input) as f:
+    content = f.read()
+
+
+output_c = os.path.join(options.target_dir, options.stem + ".tab.c")
+with open(output_c, 'w') as f:
+    f.write(content)
+
+
+output_h = os.path.join(options.target_dir, options.stem + ".tab.h")
+h_content = '''#pragma once
+
+int myfun(void);
+'''
+with open(output_h, 'w') as f:
+    f.write(h_content)