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 81include(CheckIncludeFile) 82include(CheckIncludeFileCXX) 83 84cmake_policy(PUSH) 85cmake_policy(VERSION 3.0) 86 87get_filename_component(__check_type_size_dir "${CMAKE_CURRENT_LIST_FILE}" PATH) 88 89#----------------------------------------------------------------------------- 90# Helper function. DO NOT CALL DIRECTLY. 91function(__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() 153endfunction() 154 155#----------------------------------------------------------------------------- 156macro(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() 228endmacro() 229 230#----------------------------------------------------------------------------- 231cmake_policy(POP) 232