MantisBT - CMake
View Issue Details
0014635CMake(No Category)public2013-12-06 19:182016-06-06 13:37
Ted Kremenek 
Brad King 
urgentmajoralways
closedfixed 
OSX10.9
CMake 2.8.12 
CMake 2.8.12.2CMake 2.8.12.2 
0014635: CMake with Xcode generator breaks with Xcode 5.1 DP due to brittle regex in CMakeDetermineCompilerId.cmake
Logic in CMakeDetermineCompilerId.cmake tries to determine the compiler version number by scraping the output of xcodebuild. Cleanups in the output of Xcode 5.1 (Developer Preview) causes this regex to break. The fix is very simple:

diff --git a/CMakeDetermineCompilerId.cmake b/CMakeDetermineCompilerId.cmake
index 8ca5334..dd0c2bd 100644
--- a/CMakeDetermineCompilerId.cmake
+++ b/CMakeDetermineCompilerId.cmake
@@ -209,7 +209,7 @@ Id flags: ${testflags}
     # ...
     # /path/to/cc ...CompilerId${lang}/...
     # to extract the compiler front-end for the language.
- if("${CMAKE_${lang}_COMPILER_ID_OUTPUT}" MATCHES "\nLd[^\n]*(\n[ \t]+[^\n]*)*\n[ \t]+([^ \t\r\n]+)[^\r\n]*-o[^\r\n]*CompilerId${lang}/\\./CompilerId${lang}[ \t\n\\\"]")
+ if("${CMAKE_${lang}_COMPILER_ID_OUTPUT}" MATCHES "\nLd[^\n]*(\n[ \t]+[^\n]*)*\n[ \t]+([^ \t\r\n]+)[^\r\n]*-o[^\r\n]*CompilerId${lang}/(\\./)?CompilerId${lang}[ \t\n\\\"]")
       set(_comp "${CMAKE_MATCH_2}")
       if(EXISTS "${_comp}")
         set(CMAKE_${lang}_COMPILER_ID_TOOL "${_comp}" PARENT_SCOPE)

Essentially this makes matching the "./" before the project name optional. Making this match optional fixes the problem.
No tags attached.
related to 0014836closed  find_package(Threads) fails on Mac OS X with Xcode 5.1. 
Issue History
2013-12-06 19:18Ted KremenekNew Issue
2013-12-09 10:48Brad KingNote Added: 0034760
2013-12-09 11:22Brad KingNote Added: 0034761
2013-12-18 13:12Ted KremenekNote Added: 0034795
2013-12-18 15:19Brad KingNote Added: 0034801
2013-12-18 15:39Ted KremenekNote Added: 0034803
2013-12-18 15:47Brad KingNote Added: 0034805
2013-12-23 10:08Brad KingNote Added: 0034857
2013-12-23 10:08Brad KingAssigned To => Brad King
2013-12-23 10:08Brad KingStatusnew => resolved
2013-12-23 10:08Brad KingResolutionopen => fixed
2013-12-23 10:08Brad KingFixed in Version => CMake 2.8.12.2
2013-12-23 10:08Brad KingTarget Version => CMake 2.8.12.2
2014-03-26 08:51Brad KingRelationship addedrelated to 0014836
2014-10-06 10:33Robert MaynardNote Added: 0036954
2014-10-06 10:33Robert MaynardStatusresolved => closed
2016-06-06 13:37Brad KingView Statusprivate => public

Notes
(0034760)
Brad King   
2013-12-09 10:48   
Thanks, applied:

 CMakeDetermineCompilerId: Fix compiler line match for Xcode 5.1
 http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=65ee85d0 [^]

> tries to determine the compiler version number by scraping the output of xcodebuild

Actually CMake is trying to detect the full path to the compiler tool that Xcode invokes internally. The logic was added by these commits:

 Xcode: Detect the compiler id and tool location
 http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=965a69dc [^]

 Xcode: Implement generator toolset selection
 http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f980a804 [^]

I would love to find another way to do this. Basically we need to know the full path to the compiler tool that Xcode launches for a given GCC_VERSION project attribute setting.
(0034761)
Brad King   
2013-12-09 11:22   
Re 34760:

> I would love to find another way to do this

BTW, I am aware of commands like

 xcrun -n -l --toolchain llvm.clang.1_0 cc

However, the output parsing method works with older versions of Xcode that do not have xcrun. Also, we do not know for a given toolchain and language what Xcode will call the compiler tool: cc, CC, c++, clang, clang++, etc.
(0034795)
Ted Kremenek   
2013-12-18 13:12   
The problem with using xcrun is that clang theoretically isn't guaranteed to be your default compiler, although I don't see that ever changing.

You could always use the xcrun trick if the version of Xcode is fairly recent. You can query xcodebuild for the version number.
(0034801)
Brad King   
2013-12-18 15:19   
Re 0014635:0034795: We're getting the version number from a reliable source, not from this regex match. The regex is a hack to discover exactly what compiler tool will Xcode run to compile code in the project. Xcode launches the tool as "clang" or "gcc" instead of "cc" but there seems to be no way to know that without scraping it from xcodebuild output. Using "xcrun" requires us to pass the command-line tool name, which we do not know. If we did know it then xcrun could be used to get the full path to the tool.

Side question: Does xcrun's --toolchain option exactly correspond to the GCC_VERSION Xcode setting such that (1) the set of possible values are the same and (2) the same toolchain is selected when the option/setting is not specified explicitly?
(0034803)
Ted Kremenek   
2013-12-18 15:39   
I think you are using the toolchain option incorrectly. This:

  xcrun -n -l --toolchain llvm.clang.1_0 cc

Doesn't do what you think it does. If you replace 'llvm.clang.1_0' with something else, e.g.:

    xcrun -n -l --toolchain Mordor cc

you will get the same result.

Xcode has the notion of "toolchains", which allows separate copies of the command line tools to be installed side-by-side in the same Xcode installation. Xcode ships with only one toolchain, the XcodeDefault toolchain, but others could exist.

Within Apple, we use toolchains to allow Xcode to be used in contexts where different versions of the command-line tools are needed. A variant of the SDK can say "prefer to use this toolchain for building" when using that SDK, and Xcode will then look to see if that toolchain exists and use the tools from there. If that toolchain does not exist, it falls back to the XcodeDefault toolchain.

So effectively, what you have written is effectively the same as:

 xcrun -n -l cc
(0034805)
Brad King   
2013-12-18 15:47   
Re 0014635:0034803: Okay, thanks. That means xcrun is even less suitable to solve this problem than I thought.

We're still left with the original problem for which the fragile regex scraping xcodebuild output seems to be the only solution. It would be pretty easy to solve if the "Run Script Build Phase" were to have the same environment as that used when invoking the compiler, especially with $CC and $CXX set to the compiler locations (e.g. for Visual Studio we search %PATH% for cl.exe in a custom build step). When I last experimented with that approach the Run Script build phase knew nothing about the compiler.
(0034857)
Brad King   
2013-12-23 10:08   
Without having established a better way to find this information we can at least use the regex fix commit linked in 0014635:0034760.
(0036954)
Robert Maynard   
2014-10-06 10:33   
Closing resolved issues that have not been updated in more than 4 months.