Introduce "generator expressions" to add_test()
[cmake.git] / Modules / CMakeDetermineCompilerId.cmake
blobdfbaefbb7d1c709e32823327fcacb3dc2d08c690
2 # Function to compile a source file to identify the compiler.  This is
3 # used internally by CMake and should not be included by user code.
4 # If successful, sets CMAKE_<lang>_COMPILER_ID and CMAKE_<lang>_PLATFORM_ID
6 FUNCTION(CMAKE_DETERMINE_COMPILER_ID lang flagvar src)
7   # Make sure the compiler arguments are clean.
8   STRING(STRIP "${CMAKE_${lang}_COMPILER_ARG1}" CMAKE_${lang}_COMPILER_ID_ARG1)
10   # Make sure user-specified compiler flags are used.
11   IF(CMAKE_${lang}_FLAGS)
12     SET(CMAKE_${lang}_COMPILER_ID_FLAGS ${CMAKE_${lang}_FLAGS})
13   ELSE(CMAKE_${lang}_FLAGS)
14     SET(CMAKE_${lang}_COMPILER_ID_FLAGS $ENV{${flagvar}})
15   ENDIF(CMAKE_${lang}_FLAGS)
16   STRING(REGEX REPLACE " " ";" CMAKE_${lang}_COMPILER_ID_FLAGS_LIST "${CMAKE_${lang}_COMPILER_ID_FLAGS}")
18   # Compute the directory in which to run the test.
19   SET(CMAKE_${lang}_COMPILER_ID_DIR ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CompilerId${lang})
21   # Try building with no extra flags and then try each set
22   # of helper flags.  Stop when the compiler is identified.
23   FOREACH(flags "" ${CMAKE_${lang}_COMPILER_ID_TEST_FLAGS})
24     IF(NOT CMAKE_${lang}_COMPILER_ID)
25       CMAKE_DETERMINE_COMPILER_ID_BUILD("${lang}" "${flags}" "${src}")
26       FOREACH(file ${COMPILER_${lang}_PRODUCED_FILES})
27         CMAKE_DETERMINE_COMPILER_ID_CHECK("${lang}" "${CMAKE_${lang}_COMPILER_ID_DIR}/${file}" "${src}")
28       ENDFOREACH(file)
29     ENDIF(NOT CMAKE_${lang}_COMPILER_ID)
30   ENDFOREACH(flags)
32   # if the format is unknown after all files have been checked, put "Unknown" in the cache
33   IF(NOT CMAKE_EXECUTABLE_FORMAT)
34     SET(CMAKE_EXECUTABLE_FORMAT "Unknown" CACHE INTERNAL "Executable file format")
35   ENDIF(NOT CMAKE_EXECUTABLE_FORMAT)
37   # Display the final identification result.
38   IF(CMAKE_${lang}_COMPILER_ID)
39     MESSAGE(STATUS "The ${lang} compiler identification is "
40       "${CMAKE_${lang}_COMPILER_ID}")
41   ELSE(CMAKE_${lang}_COMPILER_ID)
42     MESSAGE(STATUS "The ${lang} compiler identification is unknown")
43   ENDIF(CMAKE_${lang}_COMPILER_ID)
45   SET(CMAKE_${lang}_COMPILER_ID "${CMAKE_${lang}_COMPILER_ID}" PARENT_SCOPE)
46   SET(CMAKE_${lang}_PLATFORM_ID "${CMAKE_${lang}_PLATFORM_ID}" PARENT_SCOPE)
47 ENDFUNCTION(CMAKE_DETERMINE_COMPILER_ID)
49 #-----------------------------------------------------------------------------
50 # Function to write the compiler id source file.
51 FUNCTION(CMAKE_DETERMINE_COMPILER_ID_WRITE lang src)
52   FILE(READ ${CMAKE_ROOT}/Modules/${src}.in ID_CONTENT_IN)
53   STRING(CONFIGURE "${ID_CONTENT_IN}" ID_CONTENT_OUT @ONLY)
54   FILE(WRITE ${CMAKE_${lang}_COMPILER_ID_DIR}/${src} "${ID_CONTENT_OUT}")
55 ENDFUNCTION(CMAKE_DETERMINE_COMPILER_ID_WRITE)
57 #-----------------------------------------------------------------------------
58 # Function to build the compiler id source file and look for output
59 # files.
60 FUNCTION(CMAKE_DETERMINE_COMPILER_ID_BUILD lang testflags src)
61   # Create a clean working directory.
62   FILE(REMOVE_RECURSE ${CMAKE_${lang}_COMPILER_ID_DIR})
63   FILE(MAKE_DIRECTORY ${CMAKE_${lang}_COMPILER_ID_DIR})
64   CMAKE_DETERMINE_COMPILER_ID_WRITE("${lang}" "${src}")
66   # Construct a description of this test case.
67   SET(COMPILER_DESCRIPTION
68     "Compiler: ${CMAKE_${lang}_COMPILER} ${CMAKE_${lang}_COMPILER_ID_ARG1}
69 Build flags: ${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST}
70 Id flags: ${testflags}
73   # Compile the compiler identification source.
74   IF(COMMAND EXECUTE_PROCESS)
75     EXECUTE_PROCESS(
76       COMMAND ${CMAKE_${lang}_COMPILER}
77               ${CMAKE_${lang}_COMPILER_ID_ARG1}
78               ${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST}
79               ${testflags}
80               "${src}"
81       WORKING_DIRECTORY ${CMAKE_${lang}_COMPILER_ID_DIR}
82       OUTPUT_VARIABLE CMAKE_${lang}_COMPILER_ID_OUTPUT
83       ERROR_VARIABLE CMAKE_${lang}_COMPILER_ID_OUTPUT
84       RESULT_VARIABLE CMAKE_${lang}_COMPILER_ID_RESULT
85       )
86   ELSE(COMMAND EXECUTE_PROCESS)
87     EXEC_PROGRAM(
88       ${CMAKE_${lang}_COMPILER} ${CMAKE_${lang}_COMPILER_ID_DIR}
89       ARGS ${CMAKE_${lang}_COMPILER_ID_ARG1}
90            ${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST}
91            ${testflags}
92            \"${src}\"
93       OUTPUT_VARIABLE CMAKE_${lang}_COMPILER_ID_OUTPUT
94       RETURN_VALUE CMAKE_${lang}_COMPILER_ID_RESULT
95       )
96   ENDIF(COMMAND EXECUTE_PROCESS)
98   # Check the result of compilation.
99   IF(CMAKE_${lang}_COMPILER_ID_RESULT)
100     # Compilation failed.
101     SET(MSG
102       "Compiling the ${lang} compiler identification source file \"${src}\" failed.
103 ${COMPILER_DESCRIPTION}
104 The output was:
105 ${CMAKE_${lang}_COMPILER_ID_RESULT}
106 ${CMAKE_${lang}_COMPILER_ID_OUTPUT}
109     FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "${MSG}")
110     #IF(NOT CMAKE_${lang}_COMPILER_ID_ALLOW_FAIL)
111     #  MESSAGE(FATAL_ERROR "${MSG}")
112     #ENDIF(NOT CMAKE_${lang}_COMPILER_ID_ALLOW_FAIL)
114     # No output files should be inspected.
115     SET(COMPILER_${lang}_PRODUCED_FILES)
116   ELSE(CMAKE_${lang}_COMPILER_ID_RESULT)
117     # Compilation succeeded.
118     FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
119       "Compiling the ${lang} compiler identification source file \"${src}\" succeeded.
120 ${COMPILER_DESCRIPTION}
121 The output was:
122 ${CMAKE_${lang}_COMPILER_ID_RESULT}
123 ${CMAKE_${lang}_COMPILER_ID_OUTPUT}
127     # Find the executable produced by the compiler, try all files in the
128     # binary dir.
129     FILE(GLOB COMPILER_${lang}_PRODUCED_FILES
130       RELATIVE ${CMAKE_${lang}_COMPILER_ID_DIR}
131       ${CMAKE_${lang}_COMPILER_ID_DIR}/*)
132     LIST(REMOVE_ITEM COMPILER_${lang}_PRODUCED_FILES "${src}")
133     FOREACH(file ${COMPILER_${lang}_PRODUCED_FILES})
134       FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
135         "Compilation of the ${lang} compiler identification source \""
136         "${src}\" produced \"${file}\"\n\n")
137     ENDFOREACH(file)
139     IF(NOT COMPILER_${lang}_PRODUCED_FILES)
140       # No executable was found.
141       FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
142         "Compilation of the ${lang} compiler identification source \""
143         "${src}\" did not produce an executable in \""
144         "${CMAKE_${lang}_COMPILER_ID_DIR}\".\n\n")
145     ENDIF(NOT COMPILER_${lang}_PRODUCED_FILES)
146   ENDIF(CMAKE_${lang}_COMPILER_ID_RESULT)
148   # Return the files produced by the compilation.
149   SET(COMPILER_${lang}_PRODUCED_FILES "${COMPILER_${lang}_PRODUCED_FILES}" PARENT_SCOPE)
150 ENDFUNCTION(CMAKE_DETERMINE_COMPILER_ID_BUILD lang testflags src)
152 #-----------------------------------------------------------------------------
153 # Function to extract the compiler id from an executable.
154 FUNCTION(CMAKE_DETERMINE_COMPILER_ID_CHECK lang file)
155   # Look for a compiler id if not yet known.
156   IF(NOT CMAKE_${lang}_COMPILER_ID)
157     # Read the compiler identification string from the executable file.
158     SET(COMPILER_ID)
159     SET(PLATFORM_ID)
160     FILE(STRINGS ${file}
161       CMAKE_${lang}_COMPILER_ID_STRINGS LIMIT_COUNT 2 REGEX "INFO:")
162     SET(HAVE_COMPILER_TWICE 0)
163     FOREACH(info ${CMAKE_${lang}_COMPILER_ID_STRINGS})
164       IF("${info}" MATCHES ".*INFO:compiler\\[([^]\"]*)\\].*")
165         IF(COMPILER_ID)
166           SET(COMPILER_ID_TWICE 1)
167         ENDIF(COMPILER_ID)
168         STRING(REGEX REPLACE ".*INFO:compiler\\[([^]]*)\\].*" "\\1"
169           COMPILER_ID "${info}")
170       ENDIF("${info}" MATCHES ".*INFO:compiler\\[([^]\"]*)\\].*")
171       IF("${info}" MATCHES ".*INFO:platform\\[([^]\"]*)\\].*")
172         STRING(REGEX REPLACE ".*INFO:platform\\[([^]]*)\\].*" "\\1"
173           PLATFORM_ID "${info}")
174       ENDIF("${info}" MATCHES ".*INFO:platform\\[([^]\"]*)\\].*")
175     ENDFOREACH(info)
177     # Check if a valid compiler and platform were found.
178     IF(COMPILER_ID AND NOT COMPILER_ID_TWICE)
179       SET(CMAKE_${lang}_COMPILER_ID "${COMPILER_ID}")
180       SET(CMAKE_${lang}_PLATFORM_ID "${PLATFORM_ID}")
181     ENDIF(COMPILER_ID AND NOT COMPILER_ID_TWICE)
183     # Check the compiler identification string.
184     IF(CMAKE_${lang}_COMPILER_ID)
185       # The compiler identification was found.
186       FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
187         "The ${lang} compiler identification is ${CMAKE_${lang}_COMPILER_ID}, found in \""
188         "${file}\"\n\n")
189     ELSE(CMAKE_${lang}_COMPILER_ID)
190       # The compiler identification could not be found.
191       FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
192         "The ${lang} compiler identification could not be found in \""
193         "${file}\"\n\n")
194     ENDIF(CMAKE_${lang}_COMPILER_ID)
195   ENDIF(NOT CMAKE_${lang}_COMPILER_ID)
197   # try to figure out the executable format: ELF, COFF, Mach-O
198   IF(NOT CMAKE_EXECUTABLE_FORMAT)
199     FILE(READ ${file} CMAKE_EXECUTABLE_MAGIC LIMIT 4 HEX)
201     # ELF files start with 0x7f"ELF"
202     IF("${CMAKE_EXECUTABLE_MAGIC}" STREQUAL "7f454c46")
203       SET(CMAKE_EXECUTABLE_FORMAT "ELF" CACHE INTERNAL "Executable file format")
204     ENDIF("${CMAKE_EXECUTABLE_MAGIC}" STREQUAL "7f454c46")
206 #    # COFF (.exe) files start with "MZ"
207 #    IF("${CMAKE_EXECUTABLE_MAGIC}" MATCHES "4d5a....")
208 #      SET(CMAKE_EXECUTABLE_FORMAT "COFF" CACHE STRING "Executable file format")
209 #    ENDIF("${CMAKE_EXECUTABLE_MAGIC}" MATCHES "4d5a....")
211 #    # Mach-O files start with CAFEBABE or FEEDFACE, according to http://radio.weblogs.com/0100490/2003/01/28.html
212 #    IF("${CMAKE_EXECUTABLE_MAGIC}" MATCHES "cafebabe")
213 #      SET(CMAKE_EXECUTABLE_FORMAT "MACHO" CACHE STRING "Executable file format")
214 #    ENDIF("${CMAKE_EXECUTABLE_MAGIC}" MATCHES "cafebabe")
215 #    IF("${CMAKE_EXECUTABLE_MAGIC}" MATCHES "feedface")
216 #      SET(CMAKE_EXECUTABLE_FORMAT "MACHO" CACHE STRING "Executable file format")
217 #    ENDIF("${CMAKE_EXECUTABLE_MAGIC}" MATCHES "feedface")
219   ENDIF(NOT CMAKE_EXECUTABLE_FORMAT)
221   # Return the information extracted.
222   SET(CMAKE_${lang}_COMPILER_ID "${CMAKE_${lang}_COMPILER_ID}" PARENT_SCOPE)
223   SET(CMAKE_${lang}_PLATFORM_ID "${CMAKE_${lang}_PLATFORM_ID}" PARENT_SCOPE)
224   SET(CMAKE_EXECUTABLE_FORMAT "${CMAKE_EXECUTABLE_FORMAT}" PARENT_SCOPE)
225 ENDFUNCTION(CMAKE_DETERMINE_COMPILER_ID_CHECK lang)