Repository: mesonbuild/meson

Issue:
custom_target() doesn't accept SharedLibrary as command argument
When using a library as command argument, you get a RuntimeError:
is of unknown type <class 'mesonbuild.build.SharedLibrary'>

```
lib = library('foo', sources)
abidw = find_program('abidw')

custom_target('abi',
  output : 'libfoo.abi',
  command : [abidw, lib]
)
```

That seems enough:
```diff
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py
index 687b12265..b220bc730 100644
--- a/mesonbuild/backend/backends.py
+++ b/mesonbuild/backend/backends.py
@@ -960,7 +960,7 @@ class Backend:
         # Evaluate the command list
         cmd = []
         for i in target.command:
-            if isinstance(i, build.Executable):
+            if isinstance(i, (build.SharedLibrary, build.SharedModule, build.Executable)):
                 cmd += self.exe_object_to_cmd_array(i)
                 continue
             elif isinstance(i, build.CustomTarget):
```


Discussion:
This won't work in cross build case, see `exe_object_to_cmd_array()` implementation.

I think you should check here if it's a build.BuildTarget instance, and modify `exe_object_to_cmd_array()`(also rename) to do the for_machine checks only when it's a build.Executable.

Resolving patch:
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py
--- a/mesonbuild/backend/backends.py
+++ b/mesonbuild/backend/backends.py
@@ -817,9 +817,9 @@ def check_clock_skew(self, file_list):
             if delta > 0.001:
                 raise MesonException('Clock skew detected. File {} has a time stamp {:.4f}s in the future.'.format(absf, delta))
 
-    def exe_object_to_cmd_array(self, exe):
-        if isinstance(exe, build.BuildTarget):
-            if exe.for_machine is not MachineChoice.BUILD:
+    def build_target_to_cmd_array(self, bt):
+        if isinstance(bt, build.BuildTarget):
+            if isinstance(bt, build.Executable) and bt.for_machine is not MachineChoice.BUILD:
                 if (self.environment.is_cross_build() and
                         self.environment.exe_wrapper is None and
                         self.environment.need_exe_wrapper()):
@@ -827,12 +827,12 @@ def exe_object_to_cmd_array(self, exe):
                         Cannot use target {} as a generator because it is built for the
                         host machine and no exe wrapper is defined or needs_exe_wrapper is
                         true. You might want to set `native: true` instead to build it for
-                        the build machine.'''.format(exe.name))
+                        the build machine.'''.format(bt.name))
                     raise MesonException(s)
-            exe_arr = [os.path.join(self.environment.get_build_dir(), self.get_target_filename(exe))]
+            arr = [os.path.join(self.environment.get_build_dir(), self.get_target_filename(bt))]
         else:
-            exe_arr = exe.get_command()
-        return exe_arr
+            arr = bt.get_command()
+        return arr
 
     def replace_extra_args(self, args, genlist):
         final_args = []
@@ -960,8 +960,8 @@ def eval_custom_target_command(self, target, absolute_outputs=False):
         # Evaluate the command list
         cmd = []
         for i in target.command:
-            if isinstance(i, build.Executable):
-                cmd += self.exe_object_to_cmd_array(i)
+            if isinstance(i, build.BuildTarget):
+                cmd += self.build_target_to_cmd_array(i)
                 continue
             elif isinstance(i, build.CustomTarget):
                 # GIR scanner will attempt to execute this binary but
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -1771,7 +1771,7 @@ def generate_genlist_for_target(self, genlist, target):
         generator = genlist.get_generator()
         subdir = genlist.subdir
         exe = generator.get_exe()
-        exe_arr = self.exe_object_to_cmd_array(exe)
+        exe_arr = self.build_target_to_cmd_array(exe)
         infilelist = genlist.get_inputs()
         outfilelist = genlist.get_outputs()
         extra_dependencies = self.get_custom_target_depend_files(genlist)
diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py
--- a/mesonbuild/backend/vs2010backend.py
+++ b/mesonbuild/backend/vs2010backend.py
@@ -119,7 +119,7 @@ def generate_custom_generator_commands(self, target, parent_node):
                 infilelist = genlist.get_inputs()
                 outfilelist = genlist.get_outputs()
                 source_dir = os.path.join(down, self.build_to_src, genlist.subdir)
-                exe_arr = self.exe_object_to_cmd_array(exe)
+                exe_arr = self.build_target_to_cmd_array(exe)
                 idgroup = ET.SubElement(parent_node, 'ItemGroup')
                 for i in range(len(infilelist)):
                     if len(infilelist) == len(outfilelist):


Test patch:
diff --git a/test cases/common/93 selfbuilt custom/checkarg.cpp b/test cases/common/93 selfbuilt custom/checkarg.cpp
new file mode 100644
--- /dev/null
+++ b/test cases/common/93 selfbuilt custom/checkarg.cpp	
@@ -0,0 +1,6 @@
+#include <cassert>
+
+int main(int argc, char *[]) {
+    assert(argc == 2);
+    return 0;
+}
diff --git a/test cases/common/93 selfbuilt custom/meson.build b/test cases/common/93 selfbuilt custom/meson.build
--- a/test cases/common/93 selfbuilt custom/meson.build	
+++ b/test cases/common/93 selfbuilt custom/meson.build	
@@ -14,3 +14,14 @@ hfile = custom_target('datah',
 main = executable('mainprog', 'mainprog.cpp', hfile)
 
 test('maintest', main)
+
+lib = library('libtool', 'tool.cpp')
+
+checkarg = executable('checkarg', 'checkarg.cpp')
+
+ctlib = custom_target('ctlib',
+  output : 'ctlib.out',
+  capture : true,
+  command : [checkarg, lib],
+  build_by_default : true,
+)