Repository: mesonbuild/meson

Issue:
Exec format error when cross compiling
So when I try to cross compile with meson, I get this error:

```
Traceback (most recent call last):
  File "/home/pfultz/.local/lib/python3.5/site-packages/mesonbuild/mesonmain.py", line 364, in run
    app.generate()
  File "/home/pfultz/.local/lib/python3.5/site-packages/mesonbuild/mesonmain.py", line 135, in generate
    self._generate(env)
  File "/home/pfultz/.local/lib/python3.5/site-packages/mesonbuild/mesonmain.py", line 174, in _generate
    intr = interpreter.Interpreter(b, g)
  File "/home/pfultz/.local/lib/python3.5/site-packages/mesonbuild/interpreter.py", line 1616, in __init__
    self.parse_project()
  File "/home/pfultz/.local/lib/python3.5/site-packages/mesonbuild/interpreterbase.py", line 201, in parse_project
    self.evaluate_codeblock(self.ast, end=1)
  File "/home/pfultz/.local/lib/python3.5/site-packages/mesonbuild/interpreterbase.py", line 239, in evaluate_codeblock
    raise e
  File "/home/pfultz/.local/lib/python3.5/site-packages/mesonbuild/interpreterbase.py", line 231, in evaluate_codeblock
    self.evaluate_statement(cur)
  File "/home/pfultz/.local/lib/python3.5/site-packages/mesonbuild/interpreterbase.py", line 244, in evaluate_statement
    return self.function_call(cur)
  File "/home/pfultz/.local/lib/python3.5/site-packages/mesonbuild/interpreterbase.py", line 504, in function_call
    return func(node, posargs, kwargs)
  File "/home/pfultz/.local/lib/python3.5/site-packages/mesonbuild/interpreterbase.py", line 71, in wrapped
    return f(self, node, args, kwargs)
  File "/home/pfultz/.local/lib/python3.5/site-packages/mesonbuild/interpreterbase.py", line 99, in wrapped
    return f(s, node_or_state, args, kwargs)
  File "/home/pfultz/.local/lib/python3.5/site-packages/mesonbuild/interpreter.py", line 2142, in func_project
    self.add_languages(proj_langs, True)
  File "/home/pfultz/.local/lib/python3.5/site-packages/mesonbuild/interpreter.py", line 2273, in add_languages
    (comp, cross_comp) = self.detect_compilers(lang, need_cross_compiler)
  File "/home/pfultz/.local/lib/python3.5/site-packages/mesonbuild/interpreter.py", line 2242, in detect_compilers
    comp.sanity_check(self.environment.get_scratch_dir(), self.environment)
  File "/home/pfultz/.local/lib/python3.5/site-packages/mesonbuild/compilers/cpp.py", line 48, in sanity_check
    return self.sanity_check_impl(work_dir, environment, 'sanitycheckcpp.cc', code)
  File "/home/pfultz/.local/lib/python3.5/site-packages/mesonbuild/compilers/c.py", line 260, in sanity_check_impl
    pe = subprocess.Popen(cmdlist)
  File "/usr/lib/python3.5/subprocess.py", line 947, in __init__
    restore_signals, start_new_session)
  File "/usr/lib/python3.5/subprocess.py", line 1551, in _execute_child
    raise child_exception_type(errno_num, err_msg)
OSError: [Errno 8] Exec format error
```

This is the cross file I am using:

```
[binaries]
c = '/usr/bin/x86_64-w64-mingw32-gcc'
cpp = '/usr/bin/x86_64-w64-mingw32-g++'
ar = '/usr/bin/x86_64-w64-mingw32-ar'
pkgconfig = '/usr/bin/pkg-config'


[properties]
root = '/usr/x86_64-w64-mingw32'


sizeof_int = 4
sizeof_wchar_t = 2
sizeof_void* = 8

alignment_char = 1
alignment_void* = 8
alignment_double = 8

has_function_printf = true

c_args = ['-isystem', '/home/pfultz/github/pfultz2/cget/scheme-test/mingw/include', '-isystem', '/usr/x86_64-w64-mingw32/include', '-isystem', '/usr/local/x86_64-w64-mingw32/include', '-isystem', '/home/pfultz/github/pfultz2/cget/scheme-test/mingw/include', '-isystem', '/usr/x86_64-w64-mingw32/include', '-isystem', '/usr/local/x86_64-w64-mingw32/include']
c_link_args = []

[target_machine]
system = 'windows'
cpu_family = 'x86'
cpu = 'x86_64'
endian = 'little'
```

Maybe there is something wrong with one of the settings, but it would be nice if meson would let me know which one failed.


Discussion:
What is happening here is that Meson is trying to use your C++ compiler to compile a test application to see that it is working. For some reason the executable for the compiler you have specified is not a valid executable. Common reasons for this include having a corrupted executable (maybe because it is an empty file for some reason) or that the executable is of incorrect format. These include running x86 _64 (or ARM) executables on 32 bit platforms, trying to run Windows apps on Linux without Wine and the requisite binfmt magic or mixing Cygwin/MinGW/VS/etc/etc binaries on Windows by accident (or by running Cygwin Python from Windows command shell or vice versa).

Further debug would need more system information. The only advice I can give you right now is to try to run `/usr/bin/x86_64-w64-mingw32-g++` from the same command prompt that you tried to run Meson from.

Unrelated to this, you can delete all entries in your cross file between `[properties]` and `c_args`. You probably just copied those from the sample cross file, but they are there only to demonstrate how they would be used. They are not actually needed in this case.

Also, your values for `cpu_family` and `cpu` do not match. One of them is 32 bits and the other is 64 bits. You should either have both at `x86_64` or change the cpu to `i686` or something. 
> What is happening here is that Meson is trying to use your C++ compiler to compile a test application to see that it is working. For some reason the executable for the compiler you have specified is not a valid executable.

That would be good to say when this error happens.

> The only advice I can give you right now is to try to run /usr/bin/x86_64-w64-mingw32-g++ from the same command prompt that you tried to run Meson from.

I did, the compiler works. Is there a way to see the command its using to invoke the compiler? I couldn't find any flags to see a log or verbose mode.
Ok, so I see a meson-log.txt file in the build, which shows this:

```
Sanity testing C++ compiler: /usr/bin/x86_64-w64-mingw32-g++
Is cross compiler: False.
Sanity check compiler command line: /usr/bin/x86_64-w64-mingw32-g++ /home/pfultz/github/pfultz2/cget/scheme-test/mingw/cget/build/tmp-b989928d0c9d46e4b63289f76e7121f5/build/build/meson-private/sanitycheckcpp.cc -o /home/pfultz/github/pfultz2/cget/scheme-test/mingw/cget/build/tmp-b989928d0c9d46e4b63289f76e7121f5/build/build/meson-private/sanitycheckcpp.exe
Sanity check compile stdout:

-----
Sanity check compile stderr:

-----
Running test binary command: /home/pfultz/github/pfultz2/cget/scheme-test/mingw/cget/build/tmp-b989928d0c9d46e4b63289f76e7121f5/build/build/meson-private/sanitycheckcpp.exe
```

Which is interesting. Why does it say the `Is cross compiler: False`? It also looks like it tries to run the binary, which should fail, especially, since I haven't defined a `exe_wrapper`.
Are you setting `CC` or `CXX` to the cross compiler? Those env vars are for the native compiler only.

Resolving patch:
diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py
--- a/mesonbuild/compilers/c.py
+++ b/mesonbuild/compilers/c.py
@@ -281,7 +281,10 @@ def sanity_check_impl(self, work_dir, environment, sname, code):
         else:
             cmdlist = [binary_name]
         mlog.debug('Running test binary command: ' + ' '.join(cmdlist))
-        pe = subprocess.Popen(cmdlist)
+        try:
+            pe = subprocess.Popen(cmdlist)
+        except Exception as e:
+            raise EnvironmentException('Could not invoke sanity test executable: %s.' % str(e))
         pe.wait()
         if pe.returncode != 0:
             raise EnvironmentException('Executables created by {0} compiler {1} are not runnable.'.format(self.language, self.name_string()))
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py
--- a/mesonbuild/environment.py
+++ b/mesonbuild/environment.py
@@ -448,6 +448,12 @@ def get_gnu_compiler_type(defines):
             return GCC_CYGWIN
         return GCC_STANDARD
 
+    def warn_about_lang_pointing_to_cross(self, compiler_exe, evar):
+        evar_str = os.environ.get(evar, 'WHO_WOULD_CALL_THEIR_COMPILER_WITH_THIS_NAME')
+        if evar_str == compiler_exe:
+            mlog.warning('''Env var %s seems to point to the cross compiler.
+This is probably wrong, it should always point to the native compiler.''' % evar)
+
     def _get_compilers(self, lang, evar, want_cross):
         '''
         The list of compilers is detected in the exact same way for
@@ -461,6 +467,7 @@ def _get_compilers(self, lang, evar, want_cross):
                 ccache = self.detect_ccache()
             else:
                 ccache = []
+            self.warn_about_lang_pointing_to_cross(compilers[0], evar)
             # Return value has to be a list of compiler 'choices'
             compilers = [compilers]
             is_cross = True


Test patch: