cmake_modules/CheckTypeSize.cmake
changeset 11658 f87ed83568c8
equal deleted inserted replaced
11657:ae6706411b24 11658:f87ed83568c8
       
     1 #.rst:
       
     2 # CheckTypeSize
       
     3 # -------------
       
     4 #
       
     5 # Check sizeof a type
       
     6 #
       
     7 # ::
       
     8 #
       
     9 #   CHECK_TYPE_SIZE(TYPE VARIABLE [BUILTIN_TYPES_ONLY]
       
    10 #                                 [LANGUAGE <language>])
       
    11 #
       
    12 # Check if the type exists and determine its size.  On return,
       
    13 # "HAVE_${VARIABLE}" holds the existence of the type, and "${VARIABLE}"
       
    14 # holds one of the following:
       
    15 #
       
    16 # ::
       
    17 #
       
    18 #    <size> = type has non-zero size <size>
       
    19 #    "0"    = type has arch-dependent size (see below)
       
    20 #    ""     = type does not exist
       
    21 #
       
    22 # Both ``HAVE_${VARIABLE}`` and ``${VARIABLE}`` will be created as internal
       
    23 # cache variables.
       
    24 #
       
    25 # Furthermore, the variable "${VARIABLE}_CODE" holds C preprocessor code
       
    26 # to define the macro "${VARIABLE}" to the size of the type, or leave
       
    27 # the macro undefined if the type does not exist.
       
    28 #
       
    29 # The variable "${VARIABLE}" may be "0" when CMAKE_OSX_ARCHITECTURES has
       
    30 # multiple architectures for building OS X universal binaries.  This
       
    31 # indicates that the type size varies across architectures.  In this
       
    32 # case "${VARIABLE}_CODE" contains C preprocessor tests mapping from
       
    33 # each architecture macro to the corresponding type size.  The list of
       
    34 # architecture macros is stored in "${VARIABLE}_KEYS", and the value for
       
    35 # each key is stored in "${VARIABLE}-${KEY}".
       
    36 #
       
    37 # If the BUILTIN_TYPES_ONLY option is not given, the macro checks for
       
    38 # headers <sys/types.h>, <stdint.h>, and <stddef.h>, and saves results
       
    39 # in HAVE_SYS_TYPES_H, HAVE_STDINT_H, and HAVE_STDDEF_H.  The type size
       
    40 # check automatically includes the available headers, thus supporting
       
    41 # checks of types defined in the headers.
       
    42 #
       
    43 # If LANGUAGE is set, the specified compiler will be used to perform the
       
    44 # check. Acceptable values are C and CXX
       
    45 #
       
    46 # Despite the name of the macro you may use it to check the size of more
       
    47 # complex expressions, too.  To check e.g.  for the size of a struct
       
    48 # member you can do something like this:
       
    49 #
       
    50 # ::
       
    51 #
       
    52 #   check_type_size("((struct something*)0)->member" SIZEOF_MEMBER)
       
    53 #
       
    54 #
       
    55 #
       
    56 # The following variables may be set before calling this macro to modify
       
    57 # the way the check is run:
       
    58 #
       
    59 # ::
       
    60 #
       
    61 #   CMAKE_REQUIRED_FLAGS = string of compile command line flags
       
    62 #   CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
       
    63 #   CMAKE_REQUIRED_INCLUDES = list of include directories
       
    64 #   CMAKE_REQUIRED_LIBRARIES = list of libraries to link
       
    65 #   CMAKE_REQUIRED_QUIET = execute quietly without messages
       
    66 #   CMAKE_EXTRA_INCLUDE_FILES = list of extra headers to include
       
    67 
       
    68 #=============================================================================
       
    69 # Copyright 2002-2009 Kitware, Inc.
       
    70 #
       
    71 # Distributed under the OSI-approved BSD License (the "License");
       
    72 # see accompanying file Copyright.txt for details.
       
    73 #
       
    74 # This software is distributed WITHOUT ANY WARRANTY; without even the
       
    75 # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
       
    76 # See the License for more information.
       
    77 #=============================================================================
       
    78 # (To distribute this file outside of CMake, substitute the full
       
    79 #  License text for the above reference.)
       
    80 
       
    81 include(CheckIncludeFile)
       
    82 include(CheckIncludeFileCXX)
       
    83 
       
    84 cmake_policy(PUSH)
       
    85 cmake_policy(VERSION 3.0)
       
    86 
       
    87 get_filename_component(__check_type_size_dir "${CMAKE_CURRENT_LIST_FILE}" PATH)
       
    88 
       
    89 #-----------------------------------------------------------------------------
       
    90 # Helper function.  DO NOT CALL DIRECTLY.
       
    91 function(__check_type_size_impl type var map builtin language)
       
    92   if(NOT CMAKE_REQUIRED_QUIET)
       
    93     message(STATUS "Check size of ${type}")
       
    94   endif()
       
    95 
       
    96   # Include header files.
       
    97   set(headers)
       
    98   if(builtin)
       
    99     if(HAVE_SYS_TYPES_H)
       
   100       set(headers "${headers}#include <sys/types.h>\n")
       
   101     endif()
       
   102     if(HAVE_STDINT_H)
       
   103       set(headers "${headers}#include <stdint.h>\n")
       
   104     endif()
       
   105     if(HAVE_STDDEF_H)
       
   106       set(headers "${headers}#include <stddef.h>\n")
       
   107     endif()
       
   108   endif()
       
   109   foreach(h ${CMAKE_EXTRA_INCLUDE_FILES})
       
   110     set(headers "${headers}#include \"${h}\"\n")
       
   111   endforeach()
       
   112 
       
   113   # Perform the check.
       
   114 
       
   115   if("${language}" STREQUAL "C")
       
   116     set(src ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckTypeSize/${var}.c)
       
   117   elseif("${language}" STREQUAL "CXX")
       
   118     set(src ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckTypeSize/${var}.cpp)
       
   119   else()
       
   120     message(FATAL_ERROR "Unknown language:\n  ${language}\nSupported languages: C, CXX.\n")
       
   121   endif()
       
   122   set(bin ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckTypeSize/${var}.bin)
       
   123   configure_file(${__check_type_size_dir}/CheckTypeSize.c.in ${src} @ONLY)
       
   124   try_run(${var}_run_result HAVE_${var} ${CMAKE_BINARY_DIR} ${src}
       
   125     COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
       
   126     LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}
       
   127     CMAKE_FLAGS
       
   128       "-DCOMPILE_DEFINITIONS:STRING=${CMAKE_REQUIRED_FLAGS}"
       
   129       "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}"
       
   130     RUN_OUTPUT_VARIABLE ${var}_run_output
       
   131     COMPILE_OUTPUT_VARIABLE output
       
   132     )
       
   133 
       
   134   if(${HAVE_${var}} AND NOT "${${var}_run_result}" STREQUAL "FAILED_TO_RUN")
       
   135     set(${var} ${${var}_run_result})
       
   136     if(NOT CMAKE_REQUIRED_QUIET)
       
   137       message(STATUS "Check size of ${type} - done")
       
   138     endif()
       
   139     file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
       
   140       "Determining size of ${type} passed with the following output:\n${output}\n\n")
       
   141     set(${var} "${${var}}" CACHE INTERNAL "CHECK_TYPE_SIZE: sizeof(${type})")
       
   142   else()
       
   143     # The check failed to compile.
       
   144     if(NOT CMAKE_REQUIRED_QUIET)
       
   145       message(STATUS "Check size of ${type} - failed")
       
   146     endif()
       
   147     file(READ ${src} content)
       
   148     file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
       
   149       "Determining size of ${type} failed with the following output:\n${output}\n${src}:\n${content}\n\n")
       
   150     set(${var} "" CACHE INTERNAL "CHECK_TYPE_SIZE: ${type} unknown")
       
   151     file(REMOVE ${map})
       
   152   endif()
       
   153 endfunction()
       
   154 
       
   155 #-----------------------------------------------------------------------------
       
   156 macro(CHECK_TYPE_SIZE TYPE VARIABLE)
       
   157   # parse arguments
       
   158   unset(doing)
       
   159   foreach(arg ${ARGN})
       
   160     if("x${arg}" STREQUAL "xBUILTIN_TYPES_ONLY")
       
   161       set(_CHECK_TYPE_SIZE_${arg} 1)
       
   162       unset(doing)
       
   163     elseif("x${arg}" STREQUAL "xLANGUAGE") # change to MATCHES for more keys
       
   164       set(doing "${arg}")
       
   165       set(_CHECK_TYPE_SIZE_${doing} "")
       
   166     elseif("x${doing}" STREQUAL "xLANGUAGE")
       
   167       set(_CHECK_TYPE_SIZE_${doing} "${arg}")
       
   168       unset(doing)
       
   169     else()
       
   170       message(FATAL_ERROR "Unknown argument:\n  ${arg}\n")
       
   171     endif()
       
   172   endforeach()
       
   173   if("x${doing}" MATCHES "^x(LANGUAGE)$")
       
   174     message(FATAL_ERROR "Missing argument:\n  ${doing} arguments requires a value\n")
       
   175   endif()
       
   176   if(DEFINED _CHECK_TYPE_SIZE_LANGUAGE)
       
   177     if(NOT "x${_CHECK_TYPE_SIZE_LANGUAGE}" MATCHES "^x(C|CXX)$")
       
   178       message(FATAL_ERROR "Unknown language:\n  ${_CHECK_TYPE_SIZE_LANGUAGE}.\nSupported languages: C, CXX.\n")
       
   179     endif()
       
   180     set(_language ${_CHECK_TYPE_SIZE_LANGUAGE})
       
   181   else()
       
   182     set(_language C)
       
   183   endif()
       
   184 
       
   185   # Optionally check for standard headers.
       
   186   if(_CHECK_TYPE_SIZE_BUILTIN_TYPES_ONLY)
       
   187     set(_builtin 0)
       
   188   else()
       
   189     set(_builtin 1)
       
   190     if("${_language}" STREQUAL "C")
       
   191       check_include_file(sys/types.h HAVE_SYS_TYPES_H)
       
   192       check_include_file(stdint.h HAVE_STDINT_H)
       
   193       check_include_file(stddef.h HAVE_STDDEF_H)
       
   194     elseif("${_language}" STREQUAL "CXX")
       
   195       check_include_file_cxx(sys/types.h HAVE_SYS_TYPES_H)
       
   196       check_include_file_cxx(stdint.h HAVE_STDINT_H)
       
   197       check_include_file_cxx(stddef.h HAVE_STDDEF_H)
       
   198     endif()
       
   199   endif()
       
   200   unset(_CHECK_TYPE_SIZE_BUILTIN_TYPES_ONLY)
       
   201   unset(_CHECK_TYPE_SIZE_LANGUAGE)
       
   202 
       
   203   # Compute or load the size or size map.
       
   204   set(${VARIABLE}_KEYS)
       
   205   set(_map_file ${CMAKE_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/CheckTypeSize/${VARIABLE}.cmake)
       
   206   if(NOT DEFINED HAVE_${VARIABLE})
       
   207     __check_type_size_impl(${TYPE} ${VARIABLE} ${_map_file} ${_builtin} ${_language})
       
   208   endif()
       
   209   include(${_map_file} OPTIONAL)
       
   210   set(_map_file)
       
   211   set(_builtin)
       
   212 
       
   213   # Create preprocessor code.
       
   214   if(${VARIABLE}_KEYS)
       
   215     set(${VARIABLE}_CODE)
       
   216     set(_if if)
       
   217     foreach(key ${${VARIABLE}_KEYS})
       
   218       set(${VARIABLE}_CODE "${${VARIABLE}_CODE}#${_if} defined(${key})\n# define ${VARIABLE} ${${VARIABLE}-${key}}\n")
       
   219       set(_if elif)
       
   220     endforeach()
       
   221     set(${VARIABLE}_CODE "${${VARIABLE}_CODE}#else\n# error ${VARIABLE} unknown\n#endif")
       
   222     set(_if)
       
   223   elseif(${VARIABLE})
       
   224     set(${VARIABLE}_CODE "#define ${VARIABLE} ${${VARIABLE}}")
       
   225   else()
       
   226     set(${VARIABLE}_CODE "/* #undef ${VARIABLE} */")
       
   227   endif()
       
   228 endmacro()
       
   229 
       
   230 #-----------------------------------------------------------------------------
       
   231 cmake_policy(POP)