2013-10-15 19:17:36 +04:00
#.rst:
# CheckTypeSize
# -------------
#
# Check sizeof a type
#
# ::
#
2013-10-18 13:55:18 +04:00
# CHECK_TYPE_SIZE(TYPE VARIABLE [BUILTIN_TYPES_ONLY]
# [LANGUAGE <language>])
2013-10-15 19:17:36 +04:00
#
# 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}".
2009-12-17 23:14:47 +03:00
#
# 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
2013-10-15 19:17:36 +04:00
# 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.
2009-12-17 23:14:47 +03:00
#
2013-10-18 13:55:18 +04:00
# If LANGUAGE is set, the specified compiler will be used to perform the
# check. Acceptable values are C and CXX
#
2013-10-15 19:17:36 +04:00
# Despite the name of the macro you may use it to check the size of more
# complex expressions, too. To check e.g. for the size of a struct
2012-08-13 20:58:30 +04:00
# member you can do something like this:
#
2013-10-15 19:17:36 +04:00
# ::
#
# check_type_size("((struct something*)0)->member" SIZEOF_MEMBER)
#
#
#
# The following variables may be set before calling this macro to modify
# the way the check is run:
#
# ::
2006-02-14 23:29:13 +03:00
#
2013-10-15 19:17:36 +04:00
# CMAKE_REQUIRED_FLAGS = string of compile command line flags
# 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
2014-03-30 06:12:27 +04:00
# CMAKE_REQUIRED_QUIET = execute quietly without messages
2013-10-15 19:17:36 +04:00
# CMAKE_EXTRA_INCLUDE_FILES = list of extra headers to include
2008-04-25 17:09:06 +04:00
2009-09-28 19:46:51 +04:00
#=============================================================================
# Copyright 2002-2009 Kitware, Inc.
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
2010-08-07 04:48:47 +04:00
# (To distribute this file outside of CMake, substitute the full
2009-09-28 19:46:51 +04:00
# License text for the above reference.)
2008-04-25 17:09:06 +04:00
include ( CheckIncludeFile )
2014-03-16 01:56:47 +04:00
include ( CheckIncludeFileCXX )
2008-04-25 17:09:06 +04:00
2009-12-17 23:14:47 +03:00
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.
2013-10-18 13:55:18 +04:00
function ( __check_type_size_impl type var map builtin language )
2014-03-30 06:12:27 +04:00
if ( NOT CMAKE_REQUIRED_QUIET )
message ( STATUS "Check size of ${type}" )
endif ( )
2009-12-17 23:14:47 +03:00
# 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.
2012-02-17 02:35:43 +04:00
2013-10-18 13:55:18 +04:00
if ( "${language}" STREQUAL "C" )
set ( src ${ CMAKE_BINARY_DIR } ${ CMAKE_FILES_DIRECTORY } /CheckTypeSize/ ${ var } .c )
elseif ( "${language}" STREQUAL "CXX" )
set ( src ${ CMAKE_BINARY_DIR } ${ CMAKE_FILES_DIRECTORY } /CheckTypeSize/ ${ var } .cpp )
else ( )
message ( FATAL_ERROR "Unknown language:\n ${language}\nSupported languages: C, CXX.\n" )
endif ( )
2009-12-17 23:14:47 +03:00
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 }
C O M P I L E _ D E F I N I T I O N S $ { C M A K E _ R E Q U I R E D _ D E F I N I T I O N S }
2013-02-09 13:34:37 +04:00
L I N K _ L I B R A R I E S $ { C M A K E _ R E Q U I R E D _ L I B R A R I E S }
2009-12-17 23:14:47 +03:00
C M A K E _ F L A G S
" - D C O M P I L E _ D E F I N I T I O N S : S T R I N G = $ { C M A K E _ R E Q U I R E D _ F L A G S } "
" - D I N C L U D E _ D I R E C T O R I E S : S T R I N G = $ { C M A K E _ R E Q U I R E D _ I N C L U D E S } "
O U T P U T _ V A R I A B L E o u t p u t
C O P Y _ F I L E $ { b i n }
)
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 ( )
2014-03-30 06:12:27 +04:00
if ( NOT CMAKE_REQUIRED_QUIET )
message ( STATUS "Check size of ${type} - done" )
endif ( )
2009-12-17 23:14:47 +03:00
file ( APPEND ${ CMAKE_BINARY_DIR } ${ CMAKE_FILES_DIRECTORY } /CMakeOutput.log
" D e t e r m i n i n g s i z e o f $ { t y p e } p a s s e d w i t h t h e f o l l o w i n g o u t p u t : \ n $ { o u t p u t } \ n \ n " )
set ( ${ var } "${${var}}" CACHE INTERNAL "CHECK_TYPE_SIZE: sizeof(${type})" )
2012-08-13 21:50:14 +04:00
else ( )
2009-12-17 23:14:47 +03:00
# The check failed to compile.
2014-03-30 06:12:27 +04:00
if ( NOT CMAKE_REQUIRED_QUIET )
message ( STATUS "Check size of ${type} - failed" )
endif ( )
2009-12-17 23:14:47 +03:00
file ( READ ${ src } content )
file ( APPEND ${ CMAKE_BINARY_DIR } ${ CMAKE_FILES_DIRECTORY } /CMakeError.log
" D e t e r m i n i n g s i z e o f $ { t y p e } f a i l e d w i t h t h e f o l l o w i n g o u t p u t : \ n $ { o u t p u t } \ n $ { s r c } : \ n $ { c o n t e n t } \ n \ n " )
set ( ${ var } "" CACHE INTERNAL "CHECK_TYPE_SIZE: ${type} unknown" )
file ( REMOVE ${ map } )
2012-08-13 21:50:14 +04:00
endif ( )
2009-12-17 23:14:47 +03:00
endfunction ( )
#-----------------------------------------------------------------------------
macro ( CHECK_TYPE_SIZE TYPE VARIABLE )
2013-10-18 13:55:18 +04:00
# parse arguments
unset ( doing )
foreach ( arg ${ ARGN } )
if ( "x${arg}" STREQUAL "xBUILTIN_TYPES_ONLY" )
set ( _CHECK_TYPE_SIZE_ ${ arg } 1 )
unset ( doing )
elseif ( "x${arg}" STREQUAL "xLANGUAGE" ) # change to MATCHES for more keys
set ( doing "${arg}" )
set ( _CHECK_TYPE_SIZE_ ${ doing } "" )
elseif ( "x${doing}" STREQUAL "xLANGUAGE" )
set ( _CHECK_TYPE_SIZE_ ${ doing } "${arg}" )
unset ( doing )
else ( )
message ( FATAL_ERROR "Unknown argument:\n ${arg}\n" )
endif ( )
endforeach ( )
if ( "x${doing}" MATCHES "^x(LANGUAGE)$" )
message ( FATAL_ERROR "Missing argument:\n ${doing} arguments requires a value\n" )
endif ( )
if ( DEFINED _CHECK_TYPE_SIZE_LANGUAGE )
if ( NOT "x${_CHECK_TYPE_SIZE_LANGUAGE}" MATCHES "^x(C|CXX)$" )
message ( FATAL_ERROR "Unknown language:\n ${_CHECK_TYPE_SIZE_LANGUAGE}.\nSupported languages: C, CXX.\n" )
endif ( )
set ( _language ${ _CHECK_TYPE_SIZE_LANGUAGE } )
else ( )
set ( _language C )
endif ( )
2009-12-17 23:14:47 +03:00
# Optionally check for standard headers.
2013-10-18 13:55:18 +04:00
if ( _CHECK_TYPE_SIZE_BUILTIN_TYPES_ONLY )
2009-12-17 23:14:47 +03:00
set ( _builtin 0 )
else ( )
set ( _builtin 1 )
2014-03-16 01:56:47 +04:00
if ( "${_language}" STREQUAL "C" )
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 )
elseif ( "${_language}" STREQUAL "CXX" )
check_include_file_cxx ( sys/types.h HAVE_SYS_TYPES_H )
check_include_file_cxx ( stdint.h HAVE_STDINT_H )
check_include_file_cxx ( stddef.h HAVE_STDDEF_H )
endif ( )
2009-12-17 23:14:47 +03:00
endif ( )
2014-01-09 18:57:07 +04:00
unset ( _CHECK_TYPE_SIZE_BUILTIN_TYPES_ONLY )
unset ( _CHECK_TYPE_SIZE_LANGUAGE )
2009-12-17 23:14:47 +03:00
# 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 } )
2013-10-18 13:55:18 +04:00
__check_type_size_impl ( ${ TYPE } ${ VARIABLE } ${ _map_file } ${ _builtin } ${ _language } )
2009-12-17 23:14:47 +03:00
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 )