[cmake-developers] cmake fails to identify C and CXX compiler when building universal

Ryan Schmidt cmake-2015 at ryandesign.com
Mon Sep 28 22:38:33 EDT 2015


Hello, I am a developer with the MacPorts package management system, and I want to report to you a bug in cmake 3.3.2 that affects OS X.

I was going to file a bug report in your issue tracker, but the bright yellow box at the top of the "report issue" page made it sound like I should send my report here instead.

The problem is that cmake cannot identify the compiler, when compiling any project (that uses cmake) universally (i.e. for more than one architecture, e.g. for both x86_64 and i386):

-- cmake version 3.3.2
-- The C compiler identification is unknown
-- The CXX compiler identification is unknown

This could cause programs that rely on identifying the compiler to either build incorrectly or even (e.g. in the case of x265) to fail to build at all. For cross-referencing purposes, this problem was previously reported to the MacPorts project here:

https://trac.macports.org/ticket/48331

The problem does not occur when compiling non-universally (i.e. for only a single architecture, e.g. for only x86_64):

-- The C compiler identification is AppleClang 7.0.0.7000072
-- The CXX compiler identification is AppleClang 7.0.0.7000072

I found that in CMakeDetermineCompilerId.cmake, cmake compiles a test program (CMAKE_DETERMINE_COMPILER_ID_BUILD) which defines certain strings that describe the compiler, and then examines the strings in the compiled a.out file (CMAKE_DETERMINE_COMPILER_ID_CHECK). If the file contains more than one "INFO:compiler[...]" string, cmake assumes something went wrong and sets COMPILER_ID_TWICE to 1 which causes the compiler id to be forgotten.

The problem is that when building universal, the a.out file produced by the test will contain multiple copies of the strings -- once for each architecture. What the compiler does for you when you use multiple -arch flags is to compile the file separately, once for each architecture, then glue the separate files together into a single file (using the lipo program), so naturally such a file will contain multiple copies of any strings. This is not a bug; this is how universal binaries work. The bug is that cmake considers this valid condition to be erroneous.

Here is an example of the duplicated strings:

$ lipo -info build/CMakeFiles/3.3.2/CompilerIdC/a.out 
Architectures in the fat file: work/build/CMakeFiles/3.3.2/CompilerIdC/a.out are: x86_64 i386
$ strings -arch all build/CMakeFiles/3.3.2/CompilerIdC/a.out 
INFO:compiler[AppleClang]
INFO:platform[Darwin]
INFO:arch[]
INFO:compiler_version[00000007.00000000.00000000.07000072]
INFO:compiler[AppleClang]
INFO:platform[Darwin]
INFO:arch[]
INFO:compiler_version[00000007.00000000.00000000.07000072]

(I know cmake uses its internal FILE(STRINGS) command, not the strings program, but I presume they are similar.)

I was able to get cmake to correctly identify the compilers even when building universal by simply removing the COMPILER_ID_TWICE stuff from CMakeDetermineCompilerId.cmake, but perhaps you want something more elegant that verifies that if there are multiple definitions of a particular info line, all the definitions are the same.



More information about the cmake-developers mailing list