|
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) |