Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CMake identifies MSVC (both C and CXX), but still throws 'No CMAKE_*_COMPILER found'

Tags:

c++

cmake

I've been searching around, and this issue seems to come up a lot in various forms. It was most often caused by a missing compiler, which would say C and CXX compilers are unknown.

In my case however, that's not what's happening. I have C and C++ compilers on my machine, and e.g. through Visual Studio everything compiles fine. Through cmake however, this happens:

> cmake .

Output:

-- Building for: Visual Studio 14 2015
-- The C compiler identification is MSVC 19.0.24215.1
-- The CXX compiler identification is MSVC 19.0.24215.1

CMake Error at CMakeLists.txt:12 (project):
  No CMAKE_C_COMPILER could be found.

CMake Error at CMakeLists.txt:12 (project):
  No CMAKE_CXX_COMPILER could be found.

-- Configuring incomplete, errors occurred!

I'm a bit confused. How can it find the compiler, but then forget about it? There are also no errors in the output log (or if there are, I don't recognize them).

These are the very last lines in CMakeOutput.log:

Compilation of the CXX compiler identification source "CMakeCXXCompilerId.cpp" produced "CompilerIdCXX.exe"
Compilation of the CXX compiler identification source "CMakeCXXCompilerId.cpp" produced "CompilerIdCXX.vcxproj"
The CXX compiler identification is MSVC, found in "[...]/CMakeFiles/3.9.1/CompilerIdCXX/CompilerIdCXX.exe"

The source CMakeLists.txt is part of an existing, working project, so I'm led to believe this is a local configuration issue.


Update

Manually specifying these compilers as the following will make cmake discover them and generate the project (real paths are used here on purpose, as I suspect the paths themselves can be perhaps the cause of this error, note the foreign characters):

SET(CMAKE_C_COMPILER "D:/Programfájlok (x86)/Microsoft Visual Studio 14.0/VC/bin")
SET(CMAKE_CXX_COMPILER "D:/Programfájlok (x86)/Microsoft Visual Studio 14.0/VC/bin")

Note: these go at the top of the CmakeLists.txt file.

The question still stands as in why can't cmake determine these paths automatically, when it can determine the correct generator.

Update 2

According to the FAQ, it is not recommended to set compiler paths in CmakeLists.txt, so another approach can be the following:

cmake
    -D CMAKE_C_COMPILER="path/to/compiler"
    -D CMAKE_CXX_COMPILER="path/to/compiler"
    ..
like image 435
John Weisz Avatar asked Aug 28 '17 21:08

John Weisz


1 Answers

There have been previous reports of CMake's Visual Studio generators breaking due to unicode paths (here, here), and while this issue seems to be long fixed (CMake commit), it could indicate that Unicode paths may be still causing trouble in some cases.

Based on your description, it doesn't sound like an installation issue - a fresh Visual Studio installation, that otherwise works properly. Since when specifying CMAKE_CXX_COMPILER manually, the build is working, my best guess would be that there's may be something to do with CMake's compiler detection involving Unicode paths.

The above is just an educated guess. However, if it's your own project, and/or you have control on how CMake is invoked, specifying the compilers to CMake with -DCMAKE_C_COMPILER and -DCMAKE_CXX_COMPILER is perfectly fine.

How can it find the compiler, but then forget about it?

The macro in charge of determining the compiler version is called CMAKE_DETERMINE_COMPILER_ID (in CMakeDetermineCompilerId.cmake). Going through the macro code, there are several defines that should be set during normal operation, namely CMAKE_CXX_COMPILER_ID, CMAKE_CXX_COMPILER_VERSION and CMAKE_CXX_COMPILER_ID_TOOL. In your case, it seems that CMAKE_CXX_COMPILER_ID and CMAKE_CXX_COMPILER_VERSION are set, but for some reason CMAKE_CXX_COMPILER_ID_TOOL isn't:

  # Display the final identification result.
  if(CMAKE_${lang}_COMPILER_ID)
    if(CMAKE_${lang}_COMPILER_VERSION)
      set(_version " ${CMAKE_${lang}_COMPILER_VERSION}")
    else()
      set(_version "")
    endif()
    message(STATUS "The ${lang} compiler identification is "
      "${CMAKE_${lang}_COMPILER_ID}${_version}")
  else()
    message(STATUS "The ${lang} compiler identification is unknown")
  endif()

  # Check if compiler id detection gave us the compiler tool.
  if(CMAKE_${lang}_COMPILER_ID_TOOL)
    set(CMAKE_${lang}_COMPILER "${CMAKE_${lang}_COMPILER_ID_TOOL}" PARENT_SCOPE)
  elseif(NOT CMAKE_${lang}_COMPILER)
    set(CMAKE_${lang}_COMPILER "CMAKE_${lang}_COMPILER-NOTFOUND" PARENT_SCOPE)
  endif()

CMAKE_CXX_COMPILER_ID_TOOL is set by the CMAKE_DETERMINE_COMPILER_ID_BUILD macro, in that same file. There's quite some code involved in setting CMAKE_CXX_COMPILER_ID_TOOL (running a process, capturing its output, regex matching, etc.), so it's theoretically possible that some of it (or even the invoked Visual Studio commands) doesn't behave well with Unicode paths.

like image 132
valiano Avatar answered Oct 15 '22 20:10

valiano