From a28b197b11f4b647c67a6914c731077972449343 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 21 Jan 2008 18:30:17 -0500 Subject: [PATCH] ENH: Generalize the check for sizeof void* to detect more ABI information. --- Modules/CMakeCCompiler.cmake.in | 14 +++++-- Modules/CMakeCCompilerABI.c | 28 ++++++++++++++ Modules/CMakeCXXCompiler.cmake.in | 14 +++++-- Modules/CMakeCXXCompilerABI.cpp | 24 ++++++++++++ Modules/CMakeCompilerABI.h | 26 +++++++++++++ Modules/CMakeDetermineCompilerABI.cmake | 49 +++++++++++++++++++++++++ Modules/CMakeTestCCompiler.cmake | 17 +++++---- Modules/CMakeTestCXXCompiler.cmake | 9 +++++ Source/cmDocumentVariables.cxx | 21 +++++++++++ 9 files changed, 188 insertions(+), 14 deletions(-) create mode 100644 Modules/CMakeCCompilerABI.c create mode 100644 Modules/CMakeCXXCompilerABI.cpp create mode 100644 Modules/CMakeCompilerABI.h create mode 100644 Modules/CMakeDetermineCompilerABI.cmake diff --git a/Modules/CMakeCCompiler.cmake.in b/Modules/CMakeCCompiler.cmake.in index 6a7fef818..e334c471d 100644 --- a/Modules/CMakeCCompiler.cmake.in +++ b/Modules/CMakeCCompiler.cmake.in @@ -23,6 +23,14 @@ SET(CMAKE_C_SOURCE_FILE_EXTENSIONS c) SET(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) SET(CMAKE_C_LINKER_PREFERENCE 10) -# save the size of void* in case where cache is removed -# and the this file is still around -SET(CMAKE_SIZEOF_VOID_P @CMAKE_SIZEOF_VOID_P@) +# Save compiler ABI information. +SET(CMAKE_C_SIZEOF_DATA_PTR "@CMAKE_C_SIZEOF_DATA_PTR@") +SET(CMAKE_C_COMPILER_ABI "@CMAKE_C_COMPILER_ABI@") + +IF(CMAKE_C_SIZEOF_DATA_PTR) + SET(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}") +ENDIF(CMAKE_C_SIZEOF_DATA_PTR) + +IF(CMAKE_C_COMPILER_ABI) + SET(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}") +ENDIF(CMAKE_C_COMPILER_ABI) diff --git a/Modules/CMakeCCompilerABI.c b/Modules/CMakeCCompilerABI.c new file mode 100644 index 000000000..f73e7fcc3 --- /dev/null +++ b/Modules/CMakeCCompilerABI.c @@ -0,0 +1,28 @@ +#ifdef __cplusplus +# error "A C++ compiler has been selected for C." +#endif + +#ifdef __CLASSIC_C__ +# define const +#endif + +/*--------------------------------------------------------------------------*/ + +#include "CMakeCompilerABI.h" + +/*--------------------------------------------------------------------------*/ + +/* Make sure the information strings are referenced. */ +#define REQUIRE(x) (&x[0] != &require) + +int main() +{ + const char require = 0; + return + ( + REQUIRE(info_sizeof_dptr) +#if defined(ABI_ID) + && REQUIRE(info_abi) +#endif + ); +} diff --git a/Modules/CMakeCXXCompiler.cmake.in b/Modules/CMakeCXXCompiler.cmake.in index b3a84dd1d..81380c9ef 100644 --- a/Modules/CMakeCXXCompiler.cmake.in +++ b/Modules/CMakeCXXCompiler.cmake.in @@ -23,6 +23,14 @@ SET(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;H;o;O;obj;OBJ;def;DEF;rc;RC) SET(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm) SET(CMAKE_CXX_LINKER_PREFERENCE 30) -# save the size of void* in case where cache is removed -# and the this file is still around -SET(CMAKE_SIZEOF_VOID_P @CMAKE_SIZEOF_VOID_P@) +# Save compiler ABI information. +SET(CMAKE_CXX_SIZEOF_DATA_PTR "@CMAKE_CXX_SIZEOF_DATA_PTR@") +SET(CMAKE_CXX_COMPILER_ABI "@CMAKE_CXX_COMPILER_ABI@") + +IF(CMAKE_CXX_SIZEOF_DATA_PTR) + SET(CMAKE_SIZEOF_VOID_P "${CMAKE_CXX_SIZEOF_DATA_PTR}") +ENDIF(CMAKE_CXX_SIZEOF_DATA_PTR) + +IF(CMAKE_CXX_COMPILER_ABI) + SET(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_CXX_COMPILER_ABI}") +ENDIF(CMAKE_CXX_COMPILER_ABI) diff --git a/Modules/CMakeCXXCompilerABI.cpp b/Modules/CMakeCXXCompilerABI.cpp new file mode 100644 index 000000000..7fb361887 --- /dev/null +++ b/Modules/CMakeCXXCompilerABI.cpp @@ -0,0 +1,24 @@ +#ifndef __cplusplus +# error "A C compiler has been selected for C++." +#endif + +/*--------------------------------------------------------------------------*/ + +#include "CMakeCompilerABI.h" + +/*--------------------------------------------------------------------------*/ + +/* Make sure the information strings are referenced. */ +#define REQUIRE(x) (&x[0] != &require) + +int main() +{ + const char require = 0; + return + ( + REQUIRE(info_sizeof_dptr) +#if defined(ABI_ID) + && REQUIRE(info_abi) +#endif + ); +} diff --git a/Modules/CMakeCompilerABI.h b/Modules/CMakeCompilerABI.h new file mode 100644 index 000000000..8980abb5a --- /dev/null +++ b/Modules/CMakeCompilerABI.h @@ -0,0 +1,26 @@ +/*--------------------------------------------------------------------------*/ + +/* Size of a pointer-to-data in bytes. */ +#define SIZEOF_DPTR (sizeof(void*)) +const char info_sizeof_dptr[] = { + 'I', 'N', 'F', 'O', ':', 's', 'i', 'z', 'e', 'o', 'f', '_', 'd', 'p', 't', 'r', '[', + ('0' + ((SIZEOF_DPTR / 10)%10)), + ('0' + (SIZEOF_DPTR % 10)), + ']','\0'}; + +/*--------------------------------------------------------------------------*/ + +/* Application Binary Interface. */ +#if defined(__sgi) && defined(_ABIO32) +# define ABI_ID "ELF O32" +#elif defined(__sgi) && defined(_ABIN32) +# define ABI_ID "ELF N32" +#elif defined(__sgi) && defined(_ABI64) +# define ABI_ID "ELF 64" +#elif defined(__ELF__) +# define ABI_ID "ELF" +#endif + +#if defined(ABI_ID) +static char const info_abi[] = "INFO:abi[" ABI_ID "]"; +#endif diff --git a/Modules/CMakeDetermineCompilerABI.cmake b/Modules/CMakeDetermineCompilerABI.cmake new file mode 100644 index 000000000..0571dc664 --- /dev/null +++ b/Modules/CMakeDetermineCompilerABI.cmake @@ -0,0 +1,49 @@ + +# Function to compile a source file to identify the compiler ABI. +# This is used internally by CMake and should not be included by user +# code. + +FUNCTION(CMAKE_DETERMINE_COMPILER_ABI lang src) + IF(NOT DEFINED CMAKE_DETERMINE_${lang}_ABI_COMPILED) + MESSAGE(STATUS "Detecting ${lang} compiler info") + + # Compile the ABI identification source. + SET(BIN "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeDetermineCompilerABI_${lang}.bin") + TRY_COMPILE(CMAKE_DETERMINE_${lang}_ABI_COMPILED + ${CMAKE_BINARY_DIR} ${src} + OUTPUT_VARIABLE OUTPUT + COPY_FILE "${BIN}" + ) + + # Load the resulting information strings. + IF(CMAKE_DETERMINE_${lang}_ABI_COMPILED) + MESSAGE(STATUS "Detecting ${lang} compiler info - done") + FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Detecting ${lang} compiler info compiled with the following output:\n${OUTPUT}\n\n") + FILE(STRINGS "${BIN}" ABI_STRINGS LIMIT_COUNT 2 REGEX "INFO:[^[]*\\[") + FOREACH(info ${ABI_STRINGS}) + IF("${info}" MATCHES ".*INFO:sizeof_dptr\\[0*([^]]*)\\].*") + STRING(REGEX REPLACE ".*INFO:sizeof_dptr\\[0*([^]]*)\\].*" "\\1" ABI_SIZEOF_DPTR "${info}") + ENDIF("${info}" MATCHES ".*INFO:sizeof_dptr\\[0*([^]]*)\\].*") + IF("${info}" MATCHES ".*INFO:abi\\[([^]]*)\\].*") + STRING(REGEX REPLACE ".*INFO:abi\\[([^]]*)\\].*" "\\1" ABI_NAME "${info}") + ENDIF("${info}" MATCHES ".*INFO:abi\\[([^]]*)\\].*") + ENDFOREACH(info) + + IF(ABI_SIZEOF_DPTR) + SET(CMAKE_${lang}_SIZEOF_DATA_PTR "${ABI_SIZEOF_DPTR}" PARENT_SCOPE) + SET(CMAKE_SIZEOF_VOID_P "${ABI_SIZEOF_DPTR}" PARENT_SCOPE) + ENDIF(ABI_SIZEOF_DPTR) + + IF(ABI_NAME) + SET(CMAKE_${lang}_COMPILER_ABI "${ABI_NAME}" PARENT_SCOPE) + SET(CMAKE_INTERNAL_PLATFORM_ABI "${ABI_NAME}" PARENT_SCOPE) + ENDIF(ABI_NAME) + + ELSE(CMAKE_DETERMINE_${lang}_ABI_COMPILED) + MESSAGE(STATUS "Detecting ${lang} compiler info - failed") + FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log + "Detecting ${lang} compiler info failed to compile with the following output:\n${OUTPUT}\n\n") + ENDIF(CMAKE_DETERMINE_${lang}_ABI_COMPILED) + ENDIF(NOT DEFINED CMAKE_DETERMINE_${lang}_ABI_COMPILED) +ENDFUNCTION(CMAKE_DETERMINE_COMPILER_ABI) diff --git a/Modules/CMakeTestCCompiler.cmake b/Modules/CMakeTestCCompiler.cmake index 68c164048..2a64f7c0c 100644 --- a/Modules/CMakeTestCCompiler.cmake +++ b/Modules/CMakeTestCCompiler.cmake @@ -40,14 +40,15 @@ ELSE(NOT CMAKE_C_COMPILER_WORKS) "Determining if the C compiler works passed with " "the following output:\n${OUTPUT}\n\n") ENDIF(C_TEST_WAS_RUN) - INCLUDE (${CMAKE_ROOT}/Modules/CheckTypeSize.cmake) - # Check the size of void*. This used to be "void *" but icc expands the *. - CHECK_TYPE_SIZE("void*" CMAKE_SIZEOF_VOID_P) SET(CMAKE_C_COMPILER_WORKS 1 CACHE INTERNAL "") - # re-configure this file CMakeCCompiler.cmake so that it gets - # the value for CMAKE_SIZEOF_VOID_P - # configure variables set in this file for fast reload later on - CONFIGURE_FILE(${CMAKE_ROOT}/Modules/CMakeCCompiler.cmake.in - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeCCompiler.cmake IMMEDIATE) + + # Try to identify the ABI and configure it into CMakeCCompiler.cmake + INCLUDE(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerABI.cmake) + CMAKE_DETERMINE_COMPILER_ABI(C ${CMAKE_ROOT}/Modules/CMakeCCompilerABI.c) + CONFIGURE_FILE( + ${CMAKE_ROOT}/Modules/CMakeCCompiler.cmake.in + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeCCompiler.cmake + @ONLY + ) ENDIF(NOT CMAKE_C_COMPILER_WORKS) diff --git a/Modules/CMakeTestCXXCompiler.cmake b/Modules/CMakeTestCXXCompiler.cmake index 0b0fefcd8..44a67adb1 100644 --- a/Modules/CMakeTestCXXCompiler.cmake +++ b/Modules/CMakeTestCXXCompiler.cmake @@ -34,4 +34,13 @@ ELSE(NOT CMAKE_CXX_COMPILER_WORKS) "the following output:\n${OUTPUT}\n\n") ENDIF(CXX_TEST_WAS_RUN) SET(CMAKE_CXX_COMPILER_WORKS 1 CACHE INTERNAL "") + + # Try to identify the ABI and configure it into CMakeCXXCompiler.cmake + INCLUDE(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerABI.cmake) + CMAKE_DETERMINE_COMPILER_ABI(CXX ${CMAKE_ROOT}/Modules/CMakeCXXCompilerABI.cpp) + CONFIGURE_FILE( + ${CMAKE_ROOT}/Modules/CMakeCXXCompiler.cmake.in + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeCXXCompiler.cmake + @ONLY + ) ENDIF(NOT CMAKE_CXX_COMPILER_WORKS) diff --git a/Source/cmDocumentVariables.cxx b/Source/cmDocumentVariables.cxx index 99628f717..9fd48d95e 100644 --- a/Source/cmDocumentVariables.cxx +++ b/Source/cmDocumentVariables.cxx @@ -839,6 +839,27 @@ void cmDocumentVariables::DefineVariables(cmake* cm) false, "Variables for Languages"); + cm->DefineProperty + ("CMAKE__COMPILER_ABI", cmProperty::VARIABLE, + "An internal variable subject to change.", + "This is used in determining the compiler ABI and is subject to change.", + false, + "Variables for Languages"); + + cm->DefineProperty + ("CMAKE_INTERNAL_PLATFORM_ABI", cmProperty::VARIABLE, + "An internal variable subject to change.", + "This is used in determining the compiler ABI and is subject to change.", + false, + "Variables for Languages"); + + cm->DefineProperty + ("CMAKE__SIZEOF_DATA_PTR", cmProperty::VARIABLE, + "An internal variable subject to change.", + "This is used in determining the architecture and is subject to change.", + false, + "Variables for Languages"); + cm->DefineProperty ("CMAKE_COMPILER_IS_GNU", cmProperty::VARIABLE, "True if the compiler is GNU.",