introspection.cmake raw
1 # Copyright (c) 2023-present The Limenka developers
2 # Distributed under the MIT software license, see the accompanying
3 # file COPYING or https://opensource.org/license/mit/.
4
5 include(CheckCXXSourceCompiles)
6 include(CheckCXXSymbolExists)
7 include(CheckIncludeFileCXX)
8
9 # The following HAVE_{HEADER}_H variables go to the limenka-build-config.h header.
10 check_include_file_cxx(sys/prctl.h HAVE_SYS_PRCTL_H)
11 check_include_file_cxx(sys/resources.h HAVE_SYS_RESOURCES_H)
12 check_include_file_cxx(sys/vmmeter.h HAVE_SYS_VMMETER_H)
13 check_include_file_cxx(vm/vm_param.h HAVE_VM_VM_PARAM_H)
14
15 check_cxx_symbol_exists(O_CLOEXEC "fcntl.h" HAVE_O_CLOEXEC)
16 check_cxx_symbol_exists(fdatasync "unistd.h" HAVE_FDATASYNC)
17 check_cxx_symbol_exists(fork "unistd.h" HAVE_DECL_FORK)
18 check_cxx_symbol_exists(pipe2 "unistd.h" HAVE_DECL_PIPE2)
19 check_cxx_symbol_exists(setsid "unistd.h" HAVE_DECL_SETSID)
20
21 check_include_file_cxx(sys/types.h HAVE_SYS_TYPES_H)
22 check_include_file_cxx(ifaddrs.h HAVE_IFADDRS_H)
23 if(HAVE_SYS_TYPES_H AND HAVE_IFADDRS_H)
24 include(TestAppendRequiredLibraries)
25 test_append_socket_library(core_interface)
26 endif()
27
28 include(TestAppendRequiredLibraries)
29 test_append_atomic_library(core_interface)
30
31 check_cxx_symbol_exists(std::system "cstdlib" HAVE_STD_SYSTEM)
32 check_cxx_symbol_exists(::_wsystem "stdlib.h" HAVE__WSYSTEM)
33 if(HAVE_STD_SYSTEM OR HAVE__WSYSTEM)
34 set(HAVE_SYSTEM 1)
35 endif()
36
37 check_cxx_source_compiles("
38 #include <string.h>
39
40 int main()
41 {
42 char buf[100];
43 char* p{strerror_r(0, buf, sizeof buf)};
44 (void)p;
45 }
46 " STRERROR_R_CHAR_P
47 )
48
49 # Check for malloc_info (for memory statistics information in getmemoryinfo).
50 check_cxx_symbol_exists(malloc_info "malloc.h" HAVE_MALLOC_INFO)
51
52 # Check for mallopt(M_ARENA_MAX) (to set glibc arenas).
53 check_cxx_source_compiles("
54 #include <malloc.h>
55
56 int main()
57 {
58 mallopt(M_ARENA_MAX, 1);
59 }
60 " HAVE_MALLOPT_ARENA_MAX
61 )
62
63 # Check for posix_fallocate().
64 check_cxx_source_compiles("
65 // same as in src/util/fs_helpers.cpp
66 #ifdef __linux__
67 #ifdef _POSIX_C_SOURCE
68 #undef _POSIX_C_SOURCE
69 #endif
70 #define _POSIX_C_SOURCE 200112L
71 #endif // __linux__
72 #include <fcntl.h>
73
74 int main()
75 {
76 return posix_fallocate(0, 0, 0);
77 }
78 " HAVE_POSIX_FALLOCATE
79 )
80
81 # Check for strong getauxval() support in the system headers.
82 check_cxx_source_compiles("
83 #include <sys/auxv.h>
84
85 int main()
86 {
87 getauxval(AT_HWCAP);
88 }
89 " HAVE_STRONG_GETAUXVAL
90 )
91
92 # Check for UNIX sockets.
93 check_cxx_source_compiles("
94 #include <sys/socket.h>
95 #include <sys/un.h>
96
97 int main()
98 {
99 struct sockaddr_un addr;
100 addr.sun_family = AF_UNIX;
101 }
102 " HAVE_SOCKADDR_UN
103 )
104
105 # Check for close_range().
106 # NOTE: At least FreeBSD supports the generic variant.
107 check_cxx_source_compiles("
108 // same as in src/util/subprocess.cpp
109 #include <limits.h>
110 #include <unistd.h>
111
112 int main()
113 {
114 return close_range(3, UINT_MAX, 0);
115 }
116 " HAVE_CLOSE_RANGE_GENERIC
117 )
118 if(NOT HAVE_CLOSE_RANGE_GENERIC)
119 check_cxx_source_compiles("
120 // same as in src/util/subprocess.cpp
121 #define _GNU_SOURCE
122 #include <linux/close_range.h>
123 #include <limits.h>
124 #include <unistd.h>
125
126 int main()
127 {
128 return close_range(3, UINT_MAX, 0);
129 }
130 " HAVE_CLOSE_RANGE_LINUX
131 )
132 endif()
133
134 # Check for different ways of gathering OS randomness:
135 # - Linux getrandom()
136 check_cxx_source_compiles("
137 #include <sys/random.h>
138
139 int main()
140 {
141 getrandom(nullptr, 32, 0);
142 }
143 " HAVE_GETRANDOM
144 )
145
146 # - BSD getentropy()
147 check_cxx_source_compiles("
148 #include <sys/random.h>
149
150 int main()
151 {
152 getentropy(nullptr, 32);
153 }
154 " HAVE_GETENTROPY_RAND
155 )
156
157
158 # - BSD sysctl()
159 check_cxx_source_compiles("
160 #include <sys/types.h>
161 #include <sys/sysctl.h>
162
163 #ifdef __linux__
164 #error Don't use sysctl on Linux, it's deprecated even when it works
165 #endif
166
167 int main()
168 {
169 sysctl(nullptr, 2, nullptr, nullptr, nullptr, 0);
170 }
171 " HAVE_SYSCTL
172 )
173
174 # - BSD sysctl(KERN_ARND)
175 check_cxx_source_compiles("
176 #include <sys/types.h>
177 #include <sys/sysctl.h>
178
179 #ifdef __linux__
180 #error Don't use sysctl on Linux, it's deprecated even when it works
181 #endif
182
183 int main()
184 {
185 static int name[2] = {CTL_KERN, KERN_ARND};
186 sysctl(name, 2, nullptr, nullptr, nullptr, 0);
187 }
188 " HAVE_SYSCTL_ARND
189 )
190
191 if(NOT MSVC)
192 include(CheckSourceCompilesWithFlags)
193
194 # Check for SSE4.1 intrinsics.
195 set(SSE41_CXXFLAGS -msse4.1)
196 check_cxx_source_compiles_with_flags([[
197 #include <immintrin.h>
198
199 #if defined(__clang__)
200 #pragma clang attribute push(__attribute__((__target__("sse4.1"))), apply_to = function)
201 __attribute__((__target__("arch=skylake-avx512")))
202 #elif defined(__GNUC__)
203 #pragma GCC target ("sse4.1")
204 #endif
205
206 int main()
207 {
208 __m128i a = _mm_set1_epi32(0);
209 __m128i b = _mm_set1_epi32(1);
210 __m128i r = _mm_blend_epi16(a, b, 0xFF);
211 return _mm_extract_epi32(r, 3);
212 }
213
214 #if defined(__clang__)
215 #pragma clang attribute pop
216 #endif
217 ]] HAVE_SSE41
218 CXXFLAGS ${SSE41_CXXFLAGS}
219 )
220 set(ENABLE_SSE41 ${HAVE_SSE41})
221
222 # Check for AVX2 intrinsics.
223 set(AVX2_CXXFLAGS -mavx -mavx2)
224 check_cxx_source_compiles_with_flags([[
225 #include <immintrin.h>
226
227 #if defined(__clang__)
228 #pragma clang attribute push(__attribute__((__target__("avx,avx2"))), apply_to = function)
229 #elif defined(__GNUC__)
230 #pragma GCC target ("avx,avx2")
231 #endif
232
233 int main()
234 {
235 __m256i l = _mm256_set1_epi32(0);
236 return _mm256_extract_epi32(l, 7);
237 }
238
239 #if defined(__clang__)
240 #pragma clang attribute pop
241 #endif
242 ]] HAVE_AVX2
243 CXXFLAGS ${AVX2_CXXFLAGS}
244 )
245 set(ENABLE_AVX2 ${HAVE_AVX2})
246
247 # Check for x86 SHA-NI intrinsics.
248 set(X86_SHANI_CXXFLAGS -msse4 -msha)
249 check_cxx_source_compiles_with_flags([[
250 #include <immintrin.h>
251
252 #if defined(__clang__)
253 #pragma clang attribute push(__attribute__((__target__("sse4,sse4.1,sha"))), apply_to = function)
254 #elif defined(__GNUC__)
255 #pragma GCC target ("sse4,sse4.1,sha")
256 #endif
257
258 int main()
259 {
260 __m128i i = _mm_set1_epi32(0);
261 __m128i j = _mm_set1_epi32(1);
262 __m128i k = _mm_set1_epi32(2);
263 return _mm_extract_epi32(_mm_sha256rnds2_epu32(i, j, k), 0);
264 }
265
266 #if defined(__clang__)
267 #pragma clang attribute pop
268 #endif
269 ]] HAVE_X86_SHANI
270 CXXFLAGS ${X86_SHANI_CXXFLAGS}
271 )
272 set(ENABLE_X86_SHANI ${HAVE_X86_SHANI})
273
274 # Check for ARMv8 SHA-NI intrinsics.
275 set(ARM_SHANI_CXXFLAGS -march=armv8-a+crypto)
276 check_cxx_source_compiles_with_flags([[
277 #include <arm_neon.h>
278
279 #if defined(__clang__)
280 #pragma clang attribute push(__attribute__((__target__("armv8-a+crypto"))), apply_to = function)
281 #elif defined(__GNUC__)
282 #pragma GCC target ("armv8-a+crypto")
283 #endif
284
285 int main()
286 {
287 uint32x4_t a, b, c;
288 vsha256h2q_u32(a, b, c);
289 vsha256hq_u32(a, b, c);
290 vsha256su0q_u32(a, b);
291 vsha256su1q_u32(a, b, c);
292 }
293
294 #if defined(__clang__)
295 #pragma clang attribute pop
296 #endif
297 ]] HAVE_ARM_SHANI
298 CXXFLAGS ${ARM_SHANI_CXXFLAGS}
299 )
300 set(ENABLE_ARM_SHANI ${HAVE_ARM_SHANI})
301
302 # Check for POWER8 vector intrinsics.
303 function(check_power8_vector VAR)
304 check_cxx_source_compiles_with_flags([[
305 #include <altivec.h>
306 #include <stdint.h>
307
308 int main()
309 {
310 unsigned char src[16];
311 __builtin_crypto_vshasigmaw((__vector uint32_t)vec_vsx_ld(0, src), 1, 0xf);
312 return 0;
313 }
314 ]] ${VAR}
315 CXXFLAGS ${POWER8_CXXFLAGS}
316 )
317 endfunction()
318 set(POWER8_CXXFLAGS -mpower8-vector)
319 check_power8_vector(HAVE_POWER8_VECTOR)
320 set(ENABLE_POWER8 ${HAVE_POWER8_VECTOR})
321 if(NOT HAVE_POWER8_VECTOR)
322 set(POWER8_CXXFLAGS -mcpu=power8)
323 check_power8_vector(HAVE_MCPU_POWER8_FOR_VECTOR)
324 set(ENABLE_POWER8 ${HAVE_MCPU_POWER8_FOR_VECTOR})
325 endif()
326 endif()
327