From 3c2ecbe74eb0d01dc276b98b1307b2580b81adc6 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 1 Feb 2010 09:03:05 -0500 Subject: [PATCH] Add alternate per-vendor compiler id detection At least one Fortran compiler does not provide a preprocessor symbol to identify itself. Instead we try running unknown compilers with version query flags known for each vendor and look for known output. Future commits will add vendor-specific flags/output table entries. --- Modules/CMakeDetermineCompilerId.cmake | 40 +++++++++++++++++++ Tests/CMakeTests/CMakeLists.txt | 1 + .../CMakeTests/CompilerIdVendorTest.cmake.in | 31 ++++++++++++++ 3 files changed, 72 insertions(+) create mode 100644 Tests/CMakeTests/CompilerIdVendorTest.cmake.in diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake index a70c6ab92..bddd6a1e8 100644 --- a/Modules/CMakeDetermineCompilerId.cmake +++ b/Modules/CMakeDetermineCompilerId.cmake @@ -42,6 +42,11 @@ FUNCTION(CMAKE_DETERMINE_COMPILER_ID lang flagvar src) ENDIF(NOT CMAKE_${lang}_COMPILER_ID) ENDFOREACH(flags) + # If the compiler is still unknown, try to query its vendor. + IF(NOT CMAKE_${lang}_COMPILER_ID) + CMAKE_DETERMINE_COMPILER_ID_VENDOR(${lang}) + ENDIF() + # if the format is unknown after all files have been checked, put "Unknown" in the cache IF(NOT CMAKE_EXECUTABLE_FORMAT) SET(CMAKE_EXECUTABLE_FORMAT "Unknown" CACHE INTERNAL "Executable file format") @@ -245,3 +250,38 @@ FUNCTION(CMAKE_DETERMINE_COMPILER_ID_CHECK lang file) PARENT_SCOPE) SET(CMAKE_EXECUTABLE_FORMAT "${CMAKE_EXECUTABLE_FORMAT}" PARENT_SCOPE) ENDFUNCTION(CMAKE_DETERMINE_COMPILER_ID_CHECK lang) + +#----------------------------------------------------------------------------- +# Function to query the compiler vendor. +# This uses a table with entries of the form +# list(APPEND CMAKE_${lang}_COMPILER_ID_VENDORS ${vendor}) +# set(CMAKE_${lang}_COMPILER_ID_VENDOR_FLAGS_${vendor} -some-vendor-flag) +# set(CMAKE_${lang}_COMPILER_ID_VENDOR_REGEX_${vendor} "Some Vendor Output") +# We try running the compiler with the flag for each vendor and +# matching its regular expression in the output. +FUNCTION(CMAKE_DETERMINE_COMPILER_ID_VENDOR lang) + FOREACH(vendor ${CMAKE_${lang}_COMPILER_ID_VENDORS}) + SET(flags ${CMAKE_${lang}_COMPILER_ID_VENDOR_FLAGS_${vendor}}) + SET(regex ${CMAKE_${lang}_COMPILER_ID_VENDOR_REGEX_${vendor}}) + EXECUTE_PROCESS( + COMMAND ${CMAKE_${lang}_COMPILER} + ${CMAKE_${lang}_COMPILER_ID_ARG1} + ${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST} + ${flags} + WORKING_DIRECTORY ${CMAKE_${lang}_COMPILER_ID_DIR} + OUTPUT_VARIABLE output ERROR_VARIABLE output + RESULT_VARIABLE result + ) + IF("${output}" MATCHES "${regex}") + FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Checking whether the ${lang} compiler is ${vendor} using \"${flags}\" " + "matched \"${regex}\":\n${output}") + SET(CMAKE_${lang}_COMPILER_ID "${vendor}" PARENT_SCOPE) + BREAK() + ELSE() + FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log + "Checking whether the ${lang} compiler is ${vendor} using \"${flags}\" " + "did not match \"${regex}\":\n${output}") + ENDIF() + ENDFOREACH() +ENDFUNCTION(CMAKE_DETERMINE_COMPILER_ID_VENDOR) diff --git a/Tests/CMakeTests/CMakeLists.txt b/Tests/CMakeTests/CMakeLists.txt index 161ca4499..6df026e0b 100644 --- a/Tests/CMakeTests/CMakeLists.txt +++ b/Tests/CMakeTests/CMakeLists.txt @@ -26,6 +26,7 @@ AddCMakeTest(If "") AddCMakeTest(String "") AddCMakeTest(Math "") AddCMakeTest(CMakeMinimumRequired "") +AddCMakeTest(CompilerIdVendor "") if(HAVE_ELF_H) AddCMakeTest(ELF "") diff --git a/Tests/CMakeTests/CompilerIdVendorTest.cmake.in b/Tests/CMakeTests/CompilerIdVendorTest.cmake.in new file mode 100644 index 000000000..68f646212 --- /dev/null +++ b/Tests/CMakeTests/CompilerIdVendorTest.cmake.in @@ -0,0 +1,31 @@ +# This is not supposed to be included by user code, but we need to +# test it. +include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerId.cmake) + +set(MY_BINARY_DIR "@CMAKE_CURRENT_BINARY_DIR@/CompilerIdVendor") +file(REMOVE_RECURSE ${MY_BINARY_DIR}) +file(MAKE_DIRECTORY ${MY_BINARY_DIR}) + +set(CMAKE_MyLang_COMPILER ${CMAKE_COMMAND}) +set(CMAKE_MyLang_COMPILER_ID_ARG1) +set(CMAKE_MyLang_COMPILER_ID_FLAGS_LIST) +set(CMAKE_MyLang_COMPILER_ID_DIR ${MY_BINARY_DIR}) + +file(WRITE "${MY_BINARY_DIR}/BogusVendor.cmake" "message(\"This is a BogusVendor compiler\")") +list(APPEND CMAKE_MyLang_COMPILER_ID_VENDORS BogusVendor) +set(CMAKE_MyLang_COMPILER_ID_VENDOR_FLAGS_BogusVendor -P BogusVendor.cmake) +set(CMAKE_MyLang_COMPILER_ID_VENDOR_REGEX_BogusVendor ThisDoesNotMatch_BogusVendor) + +file(WRITE "${MY_BINARY_DIR}/MyVendor.cmake" "message(\"This is a MyVendor compiler\")") +list(APPEND CMAKE_MyLang_COMPILER_ID_VENDORS MyVendor) +set(CMAKE_MyLang_COMPILER_ID_VENDOR_FLAGS_MyVendor -P MyVendor.cmake) +set(CMAKE_MyLang_COMPILER_ID_VENDOR_REGEX_MyVendor MyVendor) + +set(CMAKE_BINARY_DIR ${MY_BINARY_DIR}) +cmake_determine_compiler_id_vendor(MyLang) + +if("${CMAKE_MyLang_COMPILER_ID}" STREQUAL "MyVendor") + message(STATUS "Found MyVendor compiler id!") +else() + message(FATAL_ERROR "Did not find MyVendor compiler id: [${CMAKE_MyLang_COMPILER_ID}]") +endif()