summaryrefslogtreecommitdiff
path: root/Modules/CheckTypeSize.cmake
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2009-12-17 15:14:47 -0500
committerBrad King <brad.king@kitware.com>2009-12-17 15:14:47 -0500
commitc9b726c314c9c399975fbea3c673852310ee45e6 (patch)
tree7b2b02c917d8bcb846f179b1a05043c3c017a1e5 /Modules/CheckTypeSize.cmake
parent6c9f678098ff40a994529d81ab81936bff891ee1 (diff)
downloadcmake-c9b726c314c9c399975fbea3c673852310ee45e6.tar.gz
New CheckTypeSize for OS X Universal Binaries
We re-implement this module to support architecture-dependent type sizes. In the mixed-size case we generate C preprocessor code to select the detected type size for each architecture.
Diffstat (limited to 'Modules/CheckTypeSize.cmake')
-rw-r--r--Modules/CheckTypeSize.cmake252
1 files changed, 163 insertions, 89 deletions
diff --git a/Modules/CheckTypeSize.cmake b/Modules/CheckTypeSize.cmake
index 3701467dc2..6f4b437604 100644
--- a/Modules/CheckTypeSize.cmake
+++ b/Modules/CheckTypeSize.cmake
@@ -1,16 +1,29 @@
# - Check sizeof a type
# CHECK_TYPE_SIZE(TYPE VARIABLE [BUILTIN_TYPES_ONLY])
-# Check if the type exists and determine size of type. if the type
-# exists, the size will be stored to the variable. This also
-# calls check_include_file for sys/types.h stdint.h
-# and stddef.h, setting HAVE_SYS_TYPES_H, HAVE_STDINT_H,
-# and HAVE_STDDEF_H. This is because many types are stored
-# in these include files.
-# VARIABLE - variable to store size if the type exists.
-# HAVE_${VARIABLE} - does the variable exists or not
-# BUILTIN_TYPES_ONLY - The third argument is optional and if
-# it is set to the string BUILTIN_TYPES_ONLY
-# this macro will not check for any header files.
+# Check if the type exists and determine its size.
+# On return, "HAVE_${VARIABLE}" holds the existence of the type,
+# and "${VARIABLE}" holds one of the following:
+# <size> = type has non-zero size <size>
+# "0" = type has arch-dependent size (see below)
+# "" = type does not exist
+# Furthermore, the variable "${VARIABLE}_CODE" holds C preprocessor
+# code to define the macro "${VARIABLE}" to the size of the type, or
+# leave the macro undefined if the type does not exist.
+#
+# The variable "${VARIABLE}" may be "0" when CMAKE_OSX_ARCHITECTURES
+# has multiple architectures for building OS X universal binaries.
+# This indicates that the type size varies across architectures.
+# In this case "${VARIABLE}_CODE" contains C preprocessor tests
+# mapping from each architecture macro to the corresponding type size.
+# The list of architecture macros is stored in "${VARIABLE}_KEYS", and
+# the value for each key is stored in "${VARIABLE}-${KEY}".
+#
+# If the BUILTIN_TYPES_ONLY option is not given, the macro checks for
+# headers <sys/types.h>, <stdint.h>, and <stddef.h>, and saves results
+# in HAVE_SYS_TYPES_H, HAVE_STDINT_H, and HAVE_STDDEF_H. The type
+# size check automatically includes the available headers, thus
+# supporting checks of types defined in the headers.
+#
# The following variables may be set before calling this macro to
# modify the way the check is run:
#
@@ -18,9 +31,7 @@
# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
# CMAKE_REQUIRED_INCLUDES = list of include directories
# CMAKE_REQUIRED_LIBRARIES = list of libraries to link
-
-# These variables are referenced in CheckTypeSizeC.c so we have
-# to check for them.
+# CMAKE_EXTRA_INCLUDE_FILES = list of extra headers to include
#=============================================================================
# Copyright 2002-2009 Kitware, Inc.
@@ -37,81 +48,144 @@
include(CheckIncludeFile)
-MACRO(CHECK_TYPE_SIZE TYPE VARIABLE)
- IF(NOT "${ARGV2}" STREQUAL "BUILTIN_TYPES_ONLY")
+cmake_policy(PUSH)
+cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
+
+get_filename_component(__check_type_size_dir "${CMAKE_CURRENT_LIST_FILE}" PATH)
+
+#-----------------------------------------------------------------------------
+# Helper function. DO NOT CALL DIRECTLY.
+function(__check_type_size_impl type var map builtin)
+ message(STATUS "Check size of ${type}")
+
+ # Include header files.
+ set(headers)
+ if(builtin)
+ if(HAVE_SYS_TYPES_H)
+ set(headers "${headers}#include <sys/types.h>\n")
+ endif()
+ if(HAVE_STDINT_H)
+ set(headers "${headers}#include <stdint.h>\n")
+ endif()
+ if(HAVE_STDDEF_H)
+ set(headers "${headers}#include <stddef.h>\n")
+ endif()
+ endif()
+ foreach(h ${CMAKE_EXTRA_INCLUDE_FILES})
+ set(headers "${headers}#include \"${h}\"\n")
+ endforeach()
+
+ # Perform the check.
+ set(src ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckTypeSize/${var}.c)
+ set(bin ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckTypeSize/${var}.bin)
+ configure_file(${__check_type_size_dir}/CheckTypeSize.c.in ${src} @ONLY)
+ try_compile(HAVE_${var} ${CMAKE_BINARY_DIR} ${src}
+ COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
+ CMAKE_FLAGS
+ "-DCOMPILE_DEFINITIONS:STRING=${CMAKE_REQUIRED_FLAGS}"
+ "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}"
+ "-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}"
+ OUTPUT_VARIABLE output
+ COPY_FILE ${bin}
+ )
+
+ if(HAVE_${var})
+ # The check compiled. Load information from the binary.
+ file(STRINGS ${bin} strings LIMIT_COUNT 10 REGEX "INFO:size")
+
+ # Parse the information strings.
+ set(regex_size ".*INFO:size\\[0*([^]]*)\\].*")
+ set(regex_key " key\\[([^]]*)\\]")
+ set(keys)
+ set(code)
+ set(mismatch)
+ set(first 1)
+ foreach(info ${strings})
+ if("${info}" MATCHES "${regex_size}")
+ # Get the type size.
+ string(REGEX REPLACE "${regex_size}" "\\1" size "${info}")
+ if(first)
+ set(${var} ${size})
+ elseif(NOT "${size}" STREQUAL "${${var}}")
+ set(mismatch 1)
+ endif()
+ set(first 0)
+
+ # Get the architecture map key.
+ string(REGEX MATCH "${regex_key}" key "${info}")
+ string(REGEX REPLACE "${regex_key}" "\\1" key "${key}")
+ if(key)
+ set(code "${code}\nset(${var}-${key} \"${size}\")")
+ list(APPEND keys ${key})
+ endif()
+ endif()
+ endforeach()
+
+ # Update the architecture-to-size map.
+ if(mismatch AND keys)
+ configure_file(${__check_type_size_dir}/CheckTypeSizeMap.cmake.in ${map} @ONLY)
+ set(${var} 0)
+ else()
+ file(REMOVE ${map})
+ endif()
+
+ if(mismatch AND NOT keys)
+ message(SEND_ERROR "CHECK_TYPE_SIZE found different results, consider setting CMAKE_OSX_ARCHITECTURES or CMAKE_TRY_COMPILE_OSX_ARCHITECTURES to one or no architecture !")
+ endif()
+
+ message(STATUS "Check size of ${type} - done")
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+ "Determining size of ${type} passed with the following output:\n${output}\n\n")
+ set(${var} "${${var}}" CACHE INTERNAL "CHECK_TYPE_SIZE: sizeof(${type})")
+ else(HAVE_${var})
+ # The check failed to compile.
+ message(STATUS "Check size of ${type} - failed")
+ file(READ ${src} content)
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
+ "Determining size of ${type} failed with the following output:\n${output}\n${src}:\n${content}\n\n")
+ set(${var} "" CACHE INTERNAL "CHECK_TYPE_SIZE: ${type} unknown")
+ file(REMOVE ${map})
+ endif(HAVE_${var})
+endfunction()
+
+#-----------------------------------------------------------------------------
+macro(CHECK_TYPE_SIZE TYPE VARIABLE)
+ # Optionally check for standard headers.
+ if("${ARGV2}" STREQUAL "BUILTIN_TYPES_ONLY")
+ set(_builtin 0)
+ else()
+ set(_builtin 1)
check_include_file(sys/types.h HAVE_SYS_TYPES_H)
check_include_file(stdint.h HAVE_STDINT_H)
check_include_file(stddef.h HAVE_STDDEF_H)
- ENDIF(NOT "${ARGV2}" STREQUAL "BUILTIN_TYPES_ONLY")
-
- IF("HAVE_${VARIABLE}" MATCHES "^HAVE_${VARIABLE}$")
- MESSAGE(STATUS "Check size of ${TYPE}")
- SET(CHECK_TYPE_SIZE_TYPE "${TYPE}")
- SET(MACRO_CHECK_TYPE_SIZE_FLAGS
- "${CMAKE_REQUIRED_FLAGS}")
- FOREACH(def HAVE_SYS_TYPES_H HAVE_STDINT_H HAVE_STDDEF_H)
- IF("${def}")
- SET(MACRO_CHECK_TYPE_SIZE_FLAGS
- "${MACRO_CHECK_TYPE_SIZE_FLAGS} -D${def}")
- ENDIF("${def}")
- ENDFOREACH(def)
- SET(CHECK_TYPE_SIZE_PREINCLUDE)
- SET(CHECK_TYPE_SIZE_PREMAIN)
- SET(CHECK_TYPE_SIZE_ADD_LIBRARIES)
- SET(CHECK_TYPE_SIZE_ADD_INCLUDES)
-
- FOREACH(def ${CMAKE_EXTRA_INCLUDE_FILES})
- SET(CHECK_TYPE_SIZE_PREMAIN "${CHECK_TYPE_SIZE_PREMAIN}#include \"${def}\"\n")
- ENDFOREACH(def)
- IF(CMAKE_REQUIRED_LIBRARIES)
- SET(CHECK_TYPE_SIZE_ADD_LIBRARIES
- "-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}")
- ENDIF(CMAKE_REQUIRED_LIBRARIES)
- IF(CMAKE_REQUIRED_INCLUDES)
- SET(CHECK_TYPE_SIZE_ADD_INCLUDES
- "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}")
- ENDIF(CMAKE_REQUIRED_INCLUDES)
-
- CONFIGURE_FILE("${CMAKE_ROOT}/Modules/CheckTypeSizeC.c.in"
- "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckTypeSizeC.c" IMMEDIATE @ONLY)
- FILE(READ "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckTypeSizeC.c"
- CHECK_TYPE_SIZE_FILE_CONTENT)
- TRY_COMPILE(HAVE_${VARIABLE}
- ${CMAKE_BINARY_DIR}
- "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckTypeSizeC.c"
- COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
- CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_TYPE_SIZE_FLAGS}
- "${CHECK_TYPE_SIZE_ADD_LIBRARIES}"
- "${CHECK_TYPE_SIZE_ADD_INCLUDES}"
- OUTPUT_VARIABLE OUTPUT
- COPY_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckTypeSize.bin" )
-
- IF(HAVE_${VARIABLE})
- FILE(STRINGS "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckTypeSize.bin"
- CMAKE_CHECKTYPESIZE_STRINGS LIMIT_COUNT 2 REGEX "INFO:sizeof")
-
- SET(CMAKE_CHECKTYPESIZE_FIRST_RESULT "FIRST_LOOP")
- FOREACH(info ${CMAKE_CHECKTYPESIZE_STRINGS})
- IF("${info}" MATCHES ".*INFO:sizeof\\[0*([^]]*)\\].*")
- STRING(REGEX REPLACE ".*INFO:sizeof\\[0*([^]]*)\\].*" "\\1" ${VARIABLE} "${info}")
- ENDIF("${info}" MATCHES ".*INFO:sizeof\\[0*([^]]*)\\].*")
- IF("${CMAKE_CHECKTYPESIZE_FIRST_RESULT}" STREQUAL "FIRST_LOOP")
- SET(CMAKE_CHECKTYPESIZE_FIRST_RESULT "${${VARIABLE}}")
- ENDIF("${CMAKE_CHECKTYPESIZE_FIRST_RESULT}" STREQUAL "FIRST_LOOP")
- IF(NOT "${CMAKE_CHECKTYPESIZE_FIRST_RESULT}" STREQUAL "${${VARIABLE}}")
- MESSAGE(SEND_ERROR "CHECK_TYPE_SIZE found different results, consider setting CMAKE_OSX_ARCHITECTURES or CMAKE_TRY_COMPILE_OSX_ARCHITECTURES to one or no architecture !")
- ENDIF(NOT "${CMAKE_CHECKTYPESIZE_FIRST_RESULT}" STREQUAL "${${VARIABLE}}")
-
- ENDFOREACH(info ${CMAKE_CHECKTYPESIZE_STRINGS})
- MESSAGE(STATUS "Check size of ${TYPE} - done")
- FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
- "Determining size of ${TYPE} passed with the following output:\n${OUTPUT}\n\n")
- ELSE(HAVE_${VARIABLE})
- MESSAGE(STATUS "Check size of ${TYPE} - failed")
- FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
- "Determining size of ${TYPE} failed with the following output:\n${OUTPUT}\nCheckTypeSizeC.c:\n${CHECK_TYPE_SIZE_FILE_CONTENT}\n\n")
- SET(${VARIABLE})
- ENDIF(HAVE_${VARIABLE})
- SET(${VARIABLE} "${${VARIABLE}}" CACHE INTERNAL "Result of CHECK_TYPE_SIZE" FORCE)
- ENDIF("HAVE_${VARIABLE}" MATCHES "^HAVE_${VARIABLE}$")
-ENDMACRO(CHECK_TYPE_SIZE)
+ endif()
+
+ # Compute or load the size or size map.
+ set(${VARIABLE}_KEYS)
+ set(_map_file ${CMAKE_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/CheckTypeSize/${VARIABLE}.cmake)
+ if(NOT DEFINED HAVE_${VARIABLE})
+ __check_type_size_impl(${TYPE} ${VARIABLE} ${_map_file} ${_builtin})
+ endif()
+ include(${_map_file} OPTIONAL)
+ set(_map_file)
+ set(_builtin)
+
+ # Create preprocessor code.
+ if(${VARIABLE}_KEYS)
+ set(${VARIABLE}_CODE)
+ set(_if if)
+ foreach(key ${${VARIABLE}_KEYS})
+ set(${VARIABLE}_CODE "${${VARIABLE}_CODE}#${_if} defined(${key})\n# define ${VARIABLE} ${${VARIABLE}-${key}}\n")
+ set(_if elif)
+ endforeach()
+ set(${VARIABLE}_CODE "${${VARIABLE}_CODE}#else\n# error ${VARIABLE} unknown\n#endif")
+ set(_if)
+ elseif(${VARIABLE})
+ set(${VARIABLE}_CODE "#define ${VARIABLE} ${${VARIABLE}}")
+ else()
+ set(${VARIABLE}_CODE "/* #undef ${VARIABLE} */")
+ endif()
+endmacro()
+
+#-----------------------------------------------------------------------------
+cmake_policy(POP)