Repository: mesonbuild/meson

Issue:
meson can't find dependency via cmake
Digging through the log files, I found out cmake failed with:

```
CMake Error at /usr/share/cmake-3.14/Modules/CheckIncludeFile.cmake:93 (try_compile):
 Unknown extension ".c" for file

   [snip]/meson-private/cmake_prometheus-cpp/CMakeFiles/CMakeTmp/CheckIncludeFile.c

 try_compile() works only for enabled languages.  Currently these are:

   C CXX

 See project() command to enable other languages.
```

Which is a really absurd error.

Going into the mentioned directory then run cmake manually works.

meson version is 0.51.0


Discussion:
Could you please attach the full log (via pastebin etc.) and the name of the dependency?
This is how you reproduce this problem: https://gist.github.com/yshui/f203c379f501cecf4923000bcecc804c

Note, if you comment out the `find_dependency(Threads)` line in the `.cmake`, this problem goes away.

@mensinda 
I can confirm that this is also affecting me with meson 0.51.0 on Windows 10. I can provide logs if it would be helpful.

Resolving patch:
diff --git a/mesonbuild/cmake/executor.py b/mesonbuild/cmake/executor.py
--- a/mesonbuild/cmake/executor.py
+++ b/mesonbuild/cmake/executor.py
@@ -24,7 +24,7 @@
 if TYPE_CHECKING:
     from ..dependencies.base import ExternalProgram
 
-import re, os, ctypes
+import re, os, shutil, ctypes
 
 class CMakeExecutor:
     # The class's copy of the CMake path. Avoids having to search for it
@@ -162,6 +162,41 @@ def call_with_fake_build(self, args: List[str], build_dir: str, env=None):
 
         os.makedirs(build_dir, exist_ok=True)
 
+        # Try to set the correct compiler for C and C++
+        # This step is required to make try_compile work inside CMake
+        fallback = os.path.realpath(__file__)  # A file used as a fallback wehen everything else fails
+        compilers = self.environment.coredata.compilers[MachineChoice.BUILD]
+
+        def make_abs(exe: str, lang: str):
+            if os.path.isabs(exe):
+                return exe
+
+            p = shutil.which(exe)
+            if p is None:
+                mlog.debug('Failed to find a {} compiler for CMake. This might cause CMake to fail.'.format(lang))
+                p = fallback
+            return p
+
+        def choose_compiler(lang: str):
+            exe_list = []
+            if lang in compilers:
+                exe_list = compilers[lang].get_exelist()
+            else:
+                comp_obj = self.environment.compiler_from_language(lang, MachineChoice.BUILD)
+                if comp_obj is not None:
+                    exe_list = comp_obj.get_exelist()
+
+            if len(exe_list) == 1:
+                return make_abs(exe_list[0], lang), ''
+            elif len(exe_list) == 2:
+                return make_abs(exe_list[1], lang), make_abs(exe_list[0], lang)
+            else:
+                mlog.debug('Failed to find a {} compiler for CMake. This might cause CMake to fail.'.format(lang))
+                return fallback, ''
+
+        c_comp, c_launcher = choose_compiler('c')
+        cxx_comp, cxx_launcher = choose_compiler('cpp')
+
         # Reset the CMake cache
         with open('{}/CMakeCache.txt'.format(build_dir), 'w') as fp:
             fp.write('CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1\n')
@@ -170,32 +205,38 @@ def call_with_fake_build(self, args: List[str], build_dir: str, env=None):
         comp_dir = '{}/CMakeFiles/{}'.format(build_dir, self.cmakevers)
         os.makedirs(comp_dir, exist_ok=True)
 
-        c_comp = '{}/CMakeCCompiler.cmake'.format(comp_dir)
-        cxx_comp = '{}/CMakeCXXCompiler.cmake'.format(comp_dir)
+        c_comp_file = '{}/CMakeCCompiler.cmake'.format(comp_dir)
+        cxx_comp_file = '{}/CMakeCXXCompiler.cmake'.format(comp_dir)
 
-        if not os.path.exists(c_comp):
-            with open(c_comp, 'w') as fp:
+        if not os.path.exists(c_comp_file):
+            with open(c_comp_file, 'w') as fp:
                 fp.write('''# Fake CMake file to skip the boring and slow stuff
-set(CMAKE_C_COMPILER "{}") # Just give CMake a valid full path to any file
+set(CMAKE_C_COMPILER "{}") # Should be a valid compiler for try_compile, etc.
+set(CMAKE_C_COMPILER_LAUNCHER "{}") # The compiler launcher (if presentt)
 set(CMAKE_C_COMPILER_ID "GNU") # Pretend we have found GCC
 set(CMAKE_COMPILER_IS_GNUCC 1)
 set(CMAKE_C_COMPILER_LOADED 1)
 set(CMAKE_C_COMPILER_WORKS TRUE)
 set(CMAKE_C_ABI_COMPILED TRUE)
+set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m)
+set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC)
 set(CMAKE_SIZEOF_VOID_P "{}")
-'''.format(os.path.realpath(__file__), ctypes.sizeof(ctypes.c_voidp)))
+'''.format(c_comp, c_launcher, ctypes.sizeof(ctypes.c_voidp)))
 
-        if not os.path.exists(cxx_comp):
-            with open(cxx_comp, 'w') as fp:
+        if not os.path.exists(cxx_comp_file):
+            with open(cxx_comp_file, 'w') as fp:
                 fp.write('''# Fake CMake file to skip the boring and slow stuff
-set(CMAKE_CXX_COMPILER "{}") # Just give CMake a valid full path to any file
+set(CMAKE_CXX_COMPILER "{}") # Should be a valid compiler for try_compile, etc.
+set(CMAKE_CXX_COMPILER_LAUNCHER "{}") # The compiler launcher (if presentt)
 set(CMAKE_CXX_COMPILER_ID "GNU") # Pretend we have found GCC
 set(CMAKE_COMPILER_IS_GNUCXX 1)
 set(CMAKE_CXX_COMPILER_LOADED 1)
 set(CMAKE_CXX_COMPILER_WORKS TRUE)
 set(CMAKE_CXX_ABI_COMPILED TRUE)
+set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC)
+set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;mm;CPP)
 set(CMAKE_SIZEOF_VOID_P "{}")
-'''.format(os.path.realpath(__file__), ctypes.sizeof(ctypes.c_voidp)))
+'''.format(cxx_comp, cxx_launcher, ctypes.sizeof(ctypes.c_voidp)))
 
         return self.call(args, build_dir, env)
 


Test patch:
diff --git a/test cases/linuxlike/13 cmake dependency/cmake/FindSomethingLikeZLIB.cmake b/test cases/linuxlike/13 cmake dependency/cmake/FindSomethingLikeZLIB.cmake
--- a/test cases/linuxlike/13 cmake dependency/cmake/FindSomethingLikeZLIB.cmake	
+++ b/test cases/linuxlike/13 cmake dependency/cmake/FindSomethingLikeZLIB.cmake	
@@ -1,5 +1,8 @@
 find_package(ZLIB)
 
+include(CMakeFindDependencyMacro)
+find_dependency(Threads)
+
 if(ZLIB_FOUND OR ZLIB_Found)
   set(SomethingLikeZLIB_FOUND        ON)
   set(SomethingLikeZLIB_LIBRARIES    ${ZLIB_LIBRARY})