Repository: mesonbuild/meson

Issue:
mintro: AttributeError: 'str' object has no attribute 'subdir'
Running this in [Mesa](/mesa3d/mesa) breaks meson:

```
$ meson -v
0.44.0

$ meson introspect --target-files egd_tables.h@cus 
Traceback (most recent call last):
  File "/usr/bin/meson", line 37, in <module>
    sys.exit(main())
  File "/usr/bin/meson", line 34, in main
    return mesonmain.run(sys.argv[1:], launcher)
  File "/usr/lib/python3.6/site-packages/mesonbuild/mesonmain.py", line 297, in run
    return mintro.run(remaining_args)
  File "/usr/lib/python3.6/site-packages/mesonbuild/mintro.py", line 236, in run
    list_target_files(options.target_files, coredata, builddata)
  File "/usr/lib/python3.6/site-packages/mesonbuild/mintro.py", line 118, in list_target_files
    sources = [os.path.join(i.subdir, i.fname) for i in sources]
  File "/usr/lib/python3.6/site-packages/mesonbuild/mintro.py", line 118, in <listcomp>
    sources = [os.path.join(i.subdir, i.fname) for i in sources]
AttributeError: 'str' object has no attribute 'subdir'
```


Discussion:

Resolving patch:
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -3231,6 +3231,12 @@ def _func_custom_target_impl(self, node, args, kwargs):
         'Implementation-only, without FeatureNew checks, for internal use'
         name = args[0]
         kwargs['install_mode'] = self._get_kwarg_install_mode(kwargs)
+        if 'input' in kwargs:
+            try:
+                kwargs['input'] = self.source_strings_to_files(extract_as_list(kwargs, 'input'))
+            except mesonlib.MesonException:
+                mlog.warning('''Custom target input \'%s\' can\'t be converted to File object(s).
+This will become a hard error in the future.''' % kwargs['input'])
         tg = CustomTargetHolder(build.CustomTarget(name, self.subdir, self.subproject, kwargs), self)
         self.add_target(name, tg.held_object)
         return tg
@@ -3908,7 +3914,7 @@ def source_strings_to_files(self, sources):
             sources = [sources]
         for s in sources:
             if isinstance(s, (mesonlib.File, GeneratedListHolder,
-                              CustomTargetHolder, CustomTargetIndexHolder)):
+                              TargetHolder, CustomTargetIndexHolder)):
                 pass
             elif isinstance(s, str):
                 self.validate_within_subproject(self.subdir, s)
diff --git a/run_unittests.py b/run_unittests.py
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -2372,6 +2372,38 @@ def test_cross_file_system_paths(self):
                 self.init(testdir, ['--cross-file=' + name], inprocess=True)
                 self.wipe()
 
+    def test_introspect_target_files(self):
+        '''
+        Tests that mesonintrospect --target-files returns expected output.
+        '''
+        testdir = os.path.join(self.common_test_dir, '8 install')
+        self.init(testdir)
+        expected = {
+            'stat@sta': ['stat.c'],
+            'prog@exe': ['prog.c'],
+        }
+        t_intro = self.introspect('--targets')
+        self.assertCountEqual([t['id'] for t in t_intro], expected)
+        for t in t_intro:
+            id = t['id']
+            tf_intro = self.introspect(['--target-files', id])
+            self.assertEqual(tf_intro, expected[id])
+        self.wipe()
+
+        testdir = os.path.join(self.common_test_dir, '53 custom target')
+        self.init(testdir)
+        expected = {
+            'bindat@cus': ['data_source.txt'],
+            'depfile@cus': [],
+        }
+        t_intro = self.introspect('--targets')
+        self.assertCountEqual([t['id'] for t in t_intro], expected)
+        for t in t_intro:
+            id = t['id']
+            tf_intro = self.introspect(['--target-files', id])
+            self.assertEqual(tf_intro, expected[id])
+        self.wipe()
+
     def test_compiler_run_command(self):
         '''
         The test checks that the compiler object can be passed to


Test patch: