Repository: mesonbuild/meson

Issue:
Allow passing a list of File objects to custom_target
Currently the following code fails with a python assertion about unknown type:

```meson
foo = custom_target(
  'foo',
  input : [files('foo'), files('bar')],
  output : 'foo.h',
  command : [my_prog, '@INPUT0@', '@INTPUT1@', '-o', '@OUTPUT@'],
)
```
However, replacing `[files('foo'), files('bar')]` with `files('foo') + files('bar')` does work. So this is probably pretty trivial to fix.

I'll have a look at it soon if on one else gets to it before then.
link_with: isn't flattened
extracted from xserver meson.build, with the maze of conditionals removed for clarity:

```meson
project('test', 'c')

libxserver_dri3 = []
libxserver = [ libxserver_dri3 ]

executable('Xephyr', 'xephyr.c', link_with: [ libxserver ])
````

fails with

```
Meson encountered an error in file meson.build, line 6, column 0:
Link target [] is not library.

```


Discussion:

Resolving patch:
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -638,9 +638,7 @@ def process_kwargs(self, kwargs, environment):
             self.vala_gir = kwargs.get('vala_gir', None)
         dlist = stringlistify(kwargs.get('d_args', []))
         self.add_compiler_args('d', dlist)
-        self.link_args = kwargs.get('link_args', [])
-        if not isinstance(self.link_args, list):
-            self.link_args = [self.link_args]
+        self.link_args = flatten(kwargs.get('link_args', []))
         for i in self.link_args:
             if not isinstance(i, str):
                 raise InvalidArguments('Link_args arguments must be strings.')
@@ -813,9 +811,7 @@ def get_external_deps(self):
         return self.external_deps
 
     def link(self, target):
-        if not isinstance(target, list):
-            target = [target]
-        for t in target:
+        for t in flatten(target):
             if hasattr(t, 'held_object'):
                 t = t.held_object
             if not isinstance(t, (StaticLibrary, SharedLibrary)):
@@ -829,9 +825,7 @@ def link(self, target):
             self.link_targets.append(t)
 
     def link_whole(self, target):
-        if not isinstance(target, list):
-            target = [target]
-        for t in target:
+        for t in flatten(target):
             if hasattr(t, 'held_object'):
                 t = t.held_object
             if not isinstance(t, StaticLibrary):
@@ -1443,8 +1437,7 @@ def flatten_command(self, cmd):
     def process_kwargs(self, kwargs):
         super().process_kwargs(kwargs)
         self.sources = kwargs.get('input', [])
-        if not isinstance(self.sources, list):
-            self.sources = [self.sources]
+        self.sources = flatten(self.sources)
         if 'output' not in kwargs:
             raise InvalidArguments('Missing keyword argument "output".')
         self.outputs = kwargs['output']
diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py
--- a/mesonbuild/mesonlib.py
+++ b/mesonbuild/mesonlib.py
@@ -203,7 +203,7 @@ def classify_unity_sources(compilers, sources):
 
 def flatten(item):
     if not isinstance(item, list):
-        return item
+        return [item]
     result = []
     for i in item:
         if isinstance(i, list):


Test patch:
diff --git a/test cases/common/150 nested links/meson.build b/test cases/common/150 nested links/meson.build
new file mode 100644
--- /dev/null
+++ b/test cases/common/150 nested links/meson.build	
@@ -0,0 +1,8 @@
+project('test', 'c')
+
+libxserver_dri3 = []
+libxserver = [ libxserver_dri3 ]
+
+executable('Xephyr', 'xephyr.c', link_with: [ libxserver ])
+
+executable('Zephyr', 'xephyr.c', link_args: [[], []])
diff --git a/test cases/common/150 nested links/xephyr.c b/test cases/common/150 nested links/xephyr.c
new file mode 100644
--- /dev/null
+++ b/test cases/common/150 nested links/xephyr.c	
@@ -0,0 +1,3 @@
+int main() {
+    return 0;
+}
diff --git a/test cases/common/151 list of file sources/foo b/test cases/common/151 list of file sources/foo
new file mode 100644
--- /dev/null
+++ b/test cases/common/151 list of file sources/foo	
@@ -0,0 +1 @@
+some text
diff --git a/test cases/common/151 list of file sources/gen.py b/test cases/common/151 list of file sources/gen.py
new file mode 100644
--- /dev/null
+++ b/test cases/common/151 list of file sources/gen.py	
@@ -0,0 +1,7 @@
+import shutil
+import sys
+
+if __name__ == '__main__':
+    if len(sys.argv) != 3:
+        raise Exception('Requires exactly 2 args')
+    shutil.copy2(sys.argv[1], sys.argv[2])
diff --git a/test cases/common/151 list of file sources/meson.build b/test cases/common/151 list of file sources/meson.build
new file mode 100644
--- /dev/null
+++ b/test cases/common/151 list of file sources/meson.build	
@@ -0,0 +1,12 @@
+project('test', 'c')
+
+mod_py = import('python3')
+python = mod_py.find_python()
+
+test_target = custom_target(
+  'test_target',
+  input : [files('gen.py'), files('foo')],
+  output : 'bar',
+  command : [python, '@INPUT0@', '@INPUT1@', '@OUTPUT@'],
+  build_by_default : true,
+)