Repository: mesonbuild/meson

Issue:
Compilation of generated LLVM IR sources is broken
1. Usage a generator to generate LLVM IR
2. Compile the resulting LLVM IR
3. Compilation succeeds, but the binary doesn't contain any output

Example: https://github.com/npmccallum/whitfield/blob/master/meson.build


Discussion:
I have a fix for this, will open a PR soon.

Resolving patch:
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -1758,9 +1758,9 @@ def generate_single_compile(self, target, outfile, src, is_generated=False, head
         Compiles C/C++, ObjC/ObjC++, Fortran, and D sources
         """
         if isinstance(src, str) and src.endswith('.h'):
-            raise AssertionError('BUG: sources should not contain headers')
+            raise AssertionError('BUG: sources should not contain headers {!r}'.format(src))
         if isinstance(src, RawFilename) and src.fname.endswith('.h'):
-            raise AssertionError('BUG: sources should not contain headers')
+            raise AssertionError('BUG: sources should not contain headers {!r}'.format(src.fname))
         extra_orderdeps = []
         compiler = get_compiler_for_source(target.compilers.values(), src)
         commands = []
diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py
--- a/mesonbuild/compilers.py
+++ b/mesonbuild/compilers.py
@@ -53,9 +53,10 @@
 clike_suffixes = ()
 for l in clike_langs:
     clike_suffixes += lang_suffixes[l]
-clike_suffixes += ('h',)
+clike_suffixes += ('h', 'll', 's')
+
+# All these are only for C-like languages; see `clike_langs` above.
 
-# These are used in backend/backends.py:generated_target()
 def is_header(fname):
     if hasattr(fname, 'fname'):
         fname = fname.fname
@@ -65,7 +66,7 @@ def is_header(fname):
 def is_source(fname):
     if hasattr(fname, 'fname'):
         fname = fname.fname
-    suffix = fname.split('.')[-1]
+    suffix = fname.split('.')[-1].lower()
     return suffix in clike_suffixes
 
 def is_assembly(fname):


Test patch:
diff --git a/test cases/common/134 generated llvm ir/copy.py b/test cases/common/134 generated llvm ir/copy.py
new file mode 100644
--- /dev/null
+++ b/test cases/common/134 generated llvm ir/copy.py	
@@ -0,0 +1,6 @@
+#!/usr/bin/env python
+
+import sys
+import shutil
+
+shutil.copyfile(sys.argv[1], sys.argv[2])
diff --git a/test cases/common/134 generated llvm ir/main.c b/test cases/common/134 generated llvm ir/main.c
new file mode 100644
--- /dev/null
+++ b/test cases/common/134 generated llvm ir/main.c	
@@ -0,0 +1,14 @@
+#include <stdio.h>
+
+unsigned square_unsigned (unsigned a);
+
+int
+main (int argc, char * argv[])
+{
+  unsigned int ret = square_unsigned (2);
+  if (ret != 4) {
+    printf("Got %u instead of 4\n", ret);
+    return 1;
+  }
+  return 0;
+}
diff --git a/test cases/common/134 generated llvm ir/meson.build b/test cases/common/134 generated llvm ir/meson.build
new file mode 100644
--- /dev/null
+++ b/test cases/common/134 generated llvm ir/meson.build	
@@ -0,0 +1,24 @@
+project('generated llvm ir', 'c')
+
+if meson.get_compiler('c').get_id() != 'clang'
+  error('MESON_SKIP_TEST: LLVM IR files can only be built with clang')
+endif
+
+copy = find_program('copy.py')
+
+copygen = generator(copy,
+  arguments : ['@INPUT@', '@OUTPUT@'],
+  output : '@BASENAME@')
+
+l = shared_library('square-gen', copygen.process('square.ll.in'))
+
+test('square-gen-test', executable('square-gen-test', 'main.c', link_with : l))
+
+copyct = custom_target('square',
+  input : 'square.ll.in',
+  output : 'square.ll',
+  command : [copy, '@INPUT@', '@OUTPUT@'])
+
+l = shared_library('square-ct', copyct)
+
+test('square-ct-test', executable('square-ct-test', 'main.c', link_with : l))
diff --git a/test cases/common/134 generated llvm ir/square.ll.in b/test cases/common/134 generated llvm ir/square.ll.in
new file mode 100644
--- /dev/null
+++ b/test cases/common/134 generated llvm ir/square.ll.in	
@@ -0,0 +1,4 @@
+define i32 @square_unsigned(i32 %a) {
+  %1 = mul i32 %a, %a
+  ret i32 %1
+}
diff --git a/test cases/common/135 generated assembly/copy.py b/test cases/common/135 generated assembly/copy.py
new file mode 100644
--- /dev/null
+++ b/test cases/common/135 generated assembly/copy.py	
@@ -0,0 +1,6 @@
+#!/usr/bin/env python
+
+import sys
+import shutil
+
+shutil.copyfile(sys.argv[1], sys.argv[2])
diff --git a/test cases/common/135 generated assembly/main.c b/test cases/common/135 generated assembly/main.c
new file mode 100644
--- /dev/null
+++ b/test cases/common/135 generated assembly/main.c	
@@ -0,0 +1,14 @@
+#include <stdio.h>
+
+unsigned square_unsigned (unsigned a);
+
+int
+main (int argc, char * argv[])
+{
+  unsigned int ret = square_unsigned (2);
+  if (ret != 4) {
+    printf("Got %u instead of 4\n", ret);
+    return 1;
+  }
+  return 0;
+}
diff --git a/test cases/common/135 generated assembly/meson.build b/test cases/common/135 generated assembly/meson.build
new file mode 100644
--- /dev/null
+++ b/test cases/common/135 generated assembly/meson.build	
@@ -0,0 +1,39 @@
+project('generated assembly', 'c')
+
+cc = meson.get_compiler('c')
+
+if cc.get_id() == 'msvc'
+  error('MESON_SKIP_TEST: assembly files cannot be compiled directly by MSVC')
+endif
+
+cpu = host_machine.cpu_family()
+supported_cpus = ['arm', 'x86', 'x86_64']
+
+if not supported_cpus.contains(cpu)
+  error('MESON_SKIP_TEST: unsupported cpu family: ' + cpu)
+endif
+
+if cc.symbols_have_underscore_prefix()
+  add_project_arguments('-DMESON_TEST__UNDERSCORE_SYMBOL', language : 'c')
+endif
+
+copy = find_program('copy.py')
+output = 'square-@0@.S'.format(cpu)
+input = output + '.in'
+
+copygen = generator(copy,
+  arguments : ['@INPUT@', '@OUTPUT@'],
+  output : '@BASENAME@')
+
+l = shared_library('square-gen', copygen.process(input))
+
+test('square-gen-test', executable('square-gen-test', 'main.c', link_with : l))
+
+copyct = custom_target('square',
+  input : input,
+  output : output,
+  command : [copy, '@INPUT@', '@OUTPUT@'])
+
+l = shared_library('square-ct', copyct)
+
+test('square-ct-test', executable('square-ct-test', 'main.c', link_with : l))
diff --git a/test cases/common/135 generated assembly/square-arm.S.in b/test cases/common/135 generated assembly/square-arm.S.in
new file mode 100644
--- /dev/null
+++ b/test cases/common/135 generated assembly/square-arm.S.in	
@@ -0,0 +1,12 @@
+#include "symbol-underscore.h"
+
+.text
+.globl SYMBOL_NAME(square_unsigned)
+#ifndef __APPLE__
+.type	square_unsigned,%function
+#endif
+
+SYMBOL_NAME(square_unsigned):
+	mul	r1, r0, r0
+	mov	r0, r1
+	mov	pc, lr
diff --git a/test cases/common/135 generated assembly/square-x86.S.in b/test cases/common/135 generated assembly/square-x86.S.in
new file mode 100644
--- /dev/null
+++ b/test cases/common/135 generated assembly/square-x86.S.in	
@@ -0,0 +1,33 @@
+#include "symbol-underscore.h"
+
+#ifdef _MSC_VER
+
+.386
+.MODEL FLAT, C
+
+PUBLIC square_unsigned
+_TEXT   SEGMENT
+
+square_unsigned PROC var1:DWORD
+        mov     eax, var1
+	imul	eax, eax
+	ret
+square_unsigned ENDP
+
+_TEXT   ENDS
+END
+
+#else
+
+.text
+.globl SYMBOL_NAME(square_unsigned)
+# ifndef __APPLE__
+.type  square_unsigned,@function
+# endif
+
+SYMBOL_NAME(square_unsigned):
+	movl	4(%esp), %eax
+	imull	%eax, %eax
+	retl
+
+#endif
diff --git a/test cases/common/135 generated assembly/square-x86_64.S.in b/test cases/common/135 generated assembly/square-x86_64.S.in
new file mode 100644
--- /dev/null
+++ b/test cases/common/135 generated assembly/square-x86_64.S.in	
@@ -0,0 +1,39 @@
+#include "symbol-underscore.h"
+
+#include "symbol-underscore.h"
+
+#ifdef _MSC_VER /* MSVC on Windows */
+
+PUBLIC SYMBOL_NAME(square_unsigned)
+_TEXT   SEGMENT
+
+SYMBOL_NAME(square_unsigned) PROC
+        mov     eax, ecx
+	imul	eax, eax
+	ret
+SYMBOL_NAME(square_unsigned) ENDP
+
+_TEXT   ENDS
+END
+
+#else
+
+.text
+.globl SYMBOL_NAME(square_unsigned)
+# ifndef __APPLE__
+.type  square_unsigned,@function
+# endif
+
+# ifdef _WIN32 /* MinGW */
+SYMBOL_NAME(square_unsigned):
+	imull	%ecx, %ecx
+	movl	%ecx, %eax
+	retq
+# else /* Linux and OS X */
+SYMBOL_NAME(square_unsigned):
+	imull	%edi, %edi
+	movl	%edi, %eax
+	retq
+# endif
+
+#endif
diff --git a/test cases/common/135 generated assembly/symbol-underscore.h b/test cases/common/135 generated assembly/symbol-underscore.h
new file mode 100644
--- /dev/null
+++ b/test cases/common/135 generated assembly/symbol-underscore.h	
@@ -0,0 +1,5 @@
+#if defined(MESON_TEST__UNDERSCORE_SYMBOL)
+# define SYMBOL_NAME(name) _##name
+#else
+# define SYMBOL_NAME(name) name
+#endif
diff --git a/test cases/frameworks/4 qt/meson.build b/test cases/frameworks/4 qt/meson.build
--- a/test cases/frameworks/4 qt/meson.build	
+++ b/test cases/frameworks/4 qt/meson.build	
@@ -1,4 +1,6 @@
-project('qt4 and 5 build test', 'cpp')
+project('qt4 and 5 build test', 'cpp',
+  # Qt5 now requires C++ 11 support
+  default_options : ['cpp_std=c++11'])
 
 qt5_modules = ['Widgets']
 foreach qt : ['qt4', 'qt5']