Repository: mesonbuild/meson

Issue:
Failure to find linker for custom_target
Meson failes to determine linker if multiple languages are used and a custom_target is the sole source file of a shared library:

== meson.build ==
project ('Showcase for custom_target source', ['c', 'cpp'])
Foo_cc = custom_target ('Foo.cc', command : [ 'touch', '@OUTPUT@' ], output : 'Foo.cc')
Somelib = shared_library ('Somelib', [ Foo_cc ])

== build result ==
  File "/tmp/meson/mesonbuild/backend/backends.py", line 290, in determine_linker
    raise RuntimeError('Unreachable code')
RuntimeError: Unreachable code



Discussion:

Resolving patch:
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -264,10 +264,12 @@ def generate_target(self, target, outfile):
         unity_src = []
         unity_deps = [] # Generated sources that must be built before compiling a Unity target.
         header_deps += self.get_generated_headers(target)
+        generator_output_sources = [] # Needed to determine the linker
         for gensource in target.get_generated_sources():
             if isinstance(gensource, build.CustomTarget):
                 for src in gensource.output:
                     src = os.path.join(self.get_target_dir(gensource), src)
+                    generator_output_sources.append(src)
                     if self.environment.is_source(src) and not self.environment.is_header(src):
                         if is_unity:
                             unity_deps.append(os.path.join(self.environment.get_build_dir(), RawFilename(src)))
@@ -285,6 +287,7 @@ def generate_target(self, target, outfile):
                         header_deps.append(RawFilename(src))
             else:
                 for src in gensource.get_outfilelist():
+                    generator_output_sources.append(src)
                     if self.environment.is_object(src):
                         obj_list.append(os.path.join(self.get_target_private_dir(target), src))
                     elif not self.environment.is_header(src):
@@ -330,7 +333,7 @@ def generate_target(self, target, outfile):
         if is_unity:
             for src in self.generate_unity_files(target, unity_src):
                 obj_list.append(self.generate_single_compile(target, outfile, src, True, unity_deps + header_deps))
-        linker = self.determine_linker(target, src_list)
+        linker = self.determine_linker(target, src_list + generator_output_sources)
         elem = self.generate_link(target, outfile, outname, obj_list, linker, pch_objects)
         self.generate_shlib_aliases(target, self.get_target_dir(target))
         elem.write(outfile)


Test patch:
diff --git a/test cases/common/118 allgenerate/converter.py b/test cases/common/118 allgenerate/converter.py
new file mode 100755
--- /dev/null
+++ b/test cases/common/118 allgenerate/converter.py	
@@ -0,0 +1,8 @@
+#!/usr/bin/env python3
+
+import sys
+
+ifile = sys.argv[1]
+ofile = sys.argv[2]
+
+open(ofile, 'w').write(open(ifile).read())
diff --git a/test cases/common/118 allgenerate/foobar.cpp.in b/test cases/common/118 allgenerate/foobar.cpp.in
new file mode 100644
--- /dev/null
+++ b/test cases/common/118 allgenerate/foobar.cpp.in	
@@ -0,0 +1,6 @@
+#include<stdio.h>
+
+int main(int argc, char **argv) {
+  printf("I am a program.\n");
+  return 0;
+}
diff --git a/test cases/common/118 allgenerate/meson.build b/test cases/common/118 allgenerate/meson.build
new file mode 100644
--- /dev/null
+++ b/test cases/common/118 allgenerate/meson.build	
@@ -0,0 +1,20 @@
+# Must have two languages here to exercise linker language
+# selection bug
+project('all sources generated', 'c', 'cpp')
+
+comp = find_program('converter.py')
+
+g = generator(comp,
+  output : '@BASENAME@.cpp',
+  arguments : ['@INPUT@', '@OUTPUT@'])
+
+c = g.process('foobar.cpp.in')
+
+prog = executable('genexe', c)
+
+c2 = custom_target('c2gen',
+  output : 'c2gen.cpp',
+  input : 'foobar.cpp.in',
+  command : [comp, '@INPUT@', '@OUTPUT@'])
+
+prog2 = executable('genexe2', c2)
\ No newline at end of file