1## --------------------------------------------------------------------- 2## 3## Copyright (C) 2012 - 2020 by the deal.II authors 4## 5## This file is part of the deal.II library. 6## 7## The deal.II library is free software; you can use it, redistribute 8## it, and/or modify it under the terms of the GNU Lesser General 9## Public License as published by the Free Software Foundation; either 10## version 2.1 of the License, or (at your option) any later version. 11## The full text of the license can be found in the file LICENSE.md at 12## the top level directory of deal.II. 13## 14## --------------------------------------------------------------------- 15 16######################################################################## 17# # 18# Check for various compiler features: # 19# # 20######################################################################## 21 22# 23# This file sets up: 24# 25# DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS 26# DEAL_II_VECTOR_ITERATOR_IS_POINTER 27# DEAL_II_HAVE_BUILTIN_EXPECT 28# DEAL_II_HAVE_GLIBC_STACKTRACE 29# DEAL_II_HAVE_LIBSTDCXX_DEMANGLER 30# DEAL_II_COMPILER_HAS_ATTRIBUTE_PRETTY_FUNCTION 31# DEAL_II_COMPILER_HAS_ATTRIBUTE_ALWAYS_INLINE 32# DEAL_II_ALWAYS_INLINE 33# DEAL_II_RESTRICT 34# DEAL_II_COMPILER_HAS_DIAGNOSTIC_PRAGMA 35# DEAL_II_COMPILER_HAS_FUSE_LD_GOLD 36# 37 38# 39# A couple of test results depend on compiler flags and the C++ mode. 40# Nota Bene: If your test depends on the value of compile flags set in 41# ${DEAL_II_CXX_FLAGS} it is probably a language feature and should go into 42# check_01_cxx_features.cmake 43# 44 45 46# 47# Check whether the compiler allows to use arithmetic operations 48# +-*/ on vectorized data types or whether we need to use 49# _mm_add_pd for addition and so on. +-*/ is preferred because 50# it allows the compiler to choose other optimizations like 51# fused multiply add, whereas _mm_add_pd explicitly enforces the 52# assembler command. 53# 54# - Matthias Maier, rewritten 2012 55# 56CHECK_CXX_SOURCE_COMPILES( 57 " 58 #include <x86intrin.h> 59 int main() 60 { 61 __m128d a, b; 62 a = _mm_set_sd (1.0); 63 b = _mm_set1_pd (2.1); 64 __m128d c = a + b; 65 __m128d d = b - c; 66 __m128d e = c * a + d; 67 __m128d f = e/a; 68#ifdef __AVX512F__ 69 __m512d g, h; 70 g = _mm512_set1_pd (1.0); 71 h = _mm512_set1_pd (2.1); 72 __m512d i = g + h; 73 g = i - g; 74 h *= i; 75 i = h/i; 76 (void)i; 77#endif 78 (void)f; 79 } 80 " 81 DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS) 82 83 84# 85# Check whether the std::vector::iterator is just a plain pointer 86# 87# (Yes. It is not a bug. But the logic is the same.) 88# 89# - Matthias Maier, rewritten 2012 90# 91CHECK_CXX_COMPILER_BUG( 92 " 93 #include <vector> 94 template <typename T> void f(T) {} 95 template void f(int *); 96 template void f(std::vector<int>::iterator); 97 int main(){return 0;} 98 " 99 DEAL_II_VECTOR_ITERATOR_IS_POINTER) 100 101 102# 103# Check for existence of the __builtin_expect facility of newer 104# GCC compilers. This can be used to hint the compiler's branch 105# prediction unit in some cases. We use it in the AssertThrow 106# macros. 107# 108# Intel compilers don't handle __builtin_expect in C++14 constexpr contexts 109# properly so we disable this feature in case we are going to use 110# DEAL_II_CONSTEXPR with an Intel compiler. 111# 112# - Matthias Maier, rewritten 2012 113# 114IF(NOT CMAKE_CXX_COMPILER_ID MATCHES "Intel") 115 CHECK_CXX_SOURCE_COMPILES( 116 " 117 bool f() { return true; } 118 int main(){ if (__builtin_expect(f(),false)) {} } 119 " 120 DEAL_II_HAVE_BUILTIN_EXPECT) 121ENDIF() 122 123 124# 125# Check whether glibc-like stacktrace information is available 126# for the Exception class. If it is, then try to also determine 127# whether the compiler accepts the -rdynamic flag, since that is 128# recommended for linking if one wants to have meaningful 129# backtraces. 130# 131# - Matthias Maier, rewritten 2012 132# 133CHECK_CXX_SOURCE_COMPILES( 134 " 135 #include <execinfo.h> 136 #include <stdlib.h> 137 void * array[25]; 138 int nSize = backtrace(array, 25); 139 char ** symbols = backtrace_symbols(array, nSize); 140 int main(){ free(symbols); return 0; } 141 " 142 DEAL_II_HAVE_GLIBC_STACKTRACE) 143 144IF(DEAL_II_HAVE_GLIBC_STACKTRACE AND NOT DEAL_II_STATIC_EXECUTABLE) 145 ENABLE_IF_LINKS(DEAL_II_LINKER_FLAGS "-rdynamic") 146ENDIF() 147 148 149# 150# Check whether the compiler offers a way to demangle symbols 151# from within the program. Used inside the exception stacktrace 152# mechanism. 153# 154# The example code is taken from 155# http://gcc.gnu.org/onlinedocs/libstdc++/18_support/howto.html#6 156# 157# - Matthias Maier, rewritten 2012 158# 159CHECK_CXX_SOURCE_COMPILES( 160 " 161 #include <exception> 162 #include <iostream> 163 #include <cxxabi.h> 164 #include <cstdlib> 165 166 struct empty { }; 167 168 template <typename T, int N> 169 struct bar { }; 170 171 int status; 172 char *realname; 173 174 int main() 175 { 176 // exception classes not in <stdexcept>, thrown by the implementation 177 // instead of the user 178 std::bad_exception e; 179 realname = abi::__cxa_demangle(e.what(), 0, 0, &status); 180 free(realname); 181 182 183 // typeid 184 bar<empty,17> u; 185 const std::type_info &ti = typeid(u); 186 187 realname = abi::__cxa_demangle(ti.name(), 0, 0, &status); 188 free(realname); 189 190 return 0; 191 } 192 " 193 DEAL_II_HAVE_LIBSTDCXX_DEMANGLER) 194 195 196# 197# GCC and some other compilers have __PRETTY_FUNCTION__, showing 198# an unmangled version of the function we are presently in, 199# while __FUNCTION__ (or __func__ in ISO C99) simply give the 200# function name which would not include the arguments of that 201# function, leading to problems in C++ with overloaded function 202# names. 203# 204# If __PRETTY_FUNCTION__ is not available, try to find out whether 205# __func__ is available and use the preprocessor to set the first 206# thing to the second. If this is also not the case, then set it 207# to something indicating non-availability. 208# 209# - Matthias Maier, rewritten 2012 210# 211 212CHECK_CXX_SOURCE_COMPILES( 213 " 214 #include <iostream> 215 int main() 216 { 217 std::cout << __PRETTY_FUNCTION__ << std::endl; 218 return 0; 219 } 220 " 221 DEAL_II_COMPILER_HAS_ATTRIBUTE_PRETTY_FUNCTION) 222 223IF(NOT DEAL_II_COMPILER_HAS_ATTRIBUTE_PRETTY_FUNCTION) 224 CHECK_CXX_SOURCE_COMPILES( 225 " 226 #include <iostream> 227 int main() 228 { 229 std::cout << __func__ << std::endl; 230 return 0; 231 } 232 " 233 DEAL_II_COMPILER_HAS_ATTRIBUTE_FUNC) 234 235 IF(DEAL_II_COMPILER_HAS_ATTRIBUTE_FUNC) 236 SET(__PRETTY_FUNCTION__ "__func__") 237 ELSE() 238 SET(__PRETTY_FUNCTION__ "\"(not available)\"") 239 ENDIF() 240ENDIF() 241 242 243# 244# Newer versions of GCC can pass a flag to the assembler to 245# compress debug sections. At the time of writing this test, 246# this can save around 230 MB of disk space on the object 247# files we produce (810MB down to 570MB for the debug versions 248# of object files). Unfortunately, the sections have to be 249# unpacked again when they are put into the shared libs, so 250# no savings there. 251# 252# The flag also doesn't appear to be working on Cygwin, as 253# per email by John Fowkes on the mailing list in Feb 2012, 254# so don't run the test on cygwin. 255# 256# Finally, Intel's icpc compiler complains about the flag 257# but apparently only if the file to be compiled contains 258# particular content. See bug #46 in the Google Code bug 259# data base (http://code.google.com/p/dealii/issues/detail?id=46). 260# It proved impossible to track down under which circumstances 261# this happens, and so it was disabled for icpc. 262# 263# - Matthias Maier, rewritten 2012, 2013 264# 265IF( (NOT CMAKE_SYSTEM_NAME MATCHES "CYGWIN") AND 266 (NOT CMAKE_SYSTEM_NAME MATCHES "Windows") AND 267 (NOT CMAKE_CXX_COMPILER_ID MATCHES "Intel") ) 268 ADD_FLAGS(CMAKE_REQUIRED_FLAGS "${DEAL_II_CXX_FLAGS_DEBUG}") 269 ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS_DEBUG "-Wa,--compress-debug-sections") 270 RESET_CMAKE_REQUIRED() 271ENDIF() 272 273 274# 275# Do a similar check with the always_inline attribute on functions. 276# 277CHECK_CXX_SOURCE_COMPILES( 278 " 279 __attribute__((always_inline)) int fn () { return 0; } 280 int main () { return fn(); } 281 " 282 DEAL_II_COMPILER_HAS_ATTRIBUTE_ALWAYS_INLINE 283 ) 284 285IF(DEAL_II_COMPILER_HAS_ATTRIBUTE_ALWAYS_INLINE) 286 SET(DEAL_II_ALWAYS_INLINE "__attribute__((always_inline))") 287ELSE() 288 SET(DEAL_II_ALWAYS_INLINE " ") 289ENDIF() 290 291 292# 293# Check whether the compiler understands the __restrict keyword. 294# 295CHECK_CXX_SOURCE_COMPILES( 296 " 297 void fn (double *__restrict a, double *__restrict b) { a[0] = b[0]; a[1] = b[0]; } 298 int main() { } 299 " 300 DEAL_II_COMPILER_HAS_RESTRICT_KEYWORD 301 ) 302 303IF(DEAL_II_COMPILER_HAS_RESTRICT_KEYWORD) 304 SET(DEAL_II_RESTRICT "__restrict") 305ELSE() 306 SET(DEAL_II_RESTRICT " ") 307ENDIF() 308 309 310# 311# GCC and Clang allow fine grained control of diagnostics via the "GCC 312# diagnostic" pragma. Check whether the compiler supports the "push" and 313# "pop" mechanism and the "ignored" toggle. Further, test for the 314# alternative "_Pragma(...)" variant (and that it does not emit a warning). 315# 316# - Matthias Maier, 2015 317# 318ADD_FLAGS(CMAKE_REQUIRED_FLAGS "${_werror_flag}") 319CHECK_CXX_SOURCE_COMPILES( 320 " 321 _Pragma(\"GCC diagnostic push\") 322 _Pragma(\"GCC diagnostic ignored \\\\\\\"-Wextra\\\\\\\"\") 323 _Pragma(\"GCC diagnostic ignored \\\\\\\"-Wunknown-pragmas\\\\\\\"\") 324 _Pragma(\"GCC diagnostic ignored \\\\\\\"-Wpragmas\\\\\\\"\") 325 int main() { return 0; } 326 _Pragma(\"GCC diagnostic pop\") 327 " 328 DEAL_II_COMPILER_HAS_DIAGNOSTIC_PRAGMA) 329RESET_CMAKE_REQUIRED() 330 331 332# 333# Use 'lld' or the 'gold' linker if possible, given that either of them is 334# substantially faster. 335# 336# We have to try to link a full executable with -fuse-ld=lld or -fuse-ld=gold 337# to check whether "ld.lld" or "ld.gold" is actually available. 338# 339# Clang always reports "argument unused during compilation", but fails at link 340# time for an unsupported linker. 341# 342# ICC also emits a warning but passes for unsupported linkers 343# unless we turn diagnostic warnings into errors. 344# 345# We also test linker support with "-shared -fPIC". This catches an 346# incompatibility where LLD refuses to produce a shared object from an 347# object file compiled by the Intel Compiler: 348# 349# ld.lld: error: can't create dynamic relocation R_X86_64_64 against symbol: 350# __gxx_personality_v0 in readonly segment; recompile object files with -fPIC 351# or pass '-Wl,-z,notext' to allow text relocations in the output 352# 353# even if we actually had -fPIC option present. If we add -Wl,-z,notext, it 354# will link, but the produced libdeal_II.so is faulty and will crash randomly. 355# 356# Wolfgang Bangerth, Matthias Maier, Daniel Arndt, Binrui Dong, 2015, 2018-2020 357# 358 359IF(NOT CMAKE_CXX_COMPILER_ID MATCHES "MSVC") 360 361 IF(CMAKE_CXX_COMPILER_ID MATCHES "Clang") 362 ADD_FLAGS(CMAKE_REQUIRED_FLAGS "-Wno-unused-command-line-argument") 363 ELSEIF(CMAKE_CXX_COMPILER_ID MATCHES "Intel") 364 ADD_FLAGS(CMAKE_REQUIRED_FLAGS "-diag-error warn") 365 ENDIF() 366 ADD_FLAGS(CMAKE_REQUIRED_FLAGS "-Werror") 367 ADD_FLAGS(CMAKE_REQUIRED_FLAGS "-shared") 368 ADD_FLAGS(CMAKE_REQUIRED_FLAGS "-fPIC") 369 370 # 371 # Check for ld.lld and ld.gold support: 372 # 373 ADD_FLAGS(CMAKE_REQUIRED_FLAGS "-fuse-ld=lld") 374 CHECK_CXX_SOURCE_COMPILES( 375 " 376 #include <iostream> 377 void foo() { std::cout << \"Hello, world!\" << std::endl; } 378 " 379 DEAL_II_COMPILER_HAS_FUSE_LD_LLD) 380 381 STRIP_FLAG(CMAKE_REQUIRED_FLAGS "-fuse-ld=lld") 382 ADD_FLAGS(CMAKE_REQUIRED_FLAGS "-fuse-ld=gold") 383 CHECK_CXX_SOURCE_COMPILES( 384 " 385 #include <iostream> 386 void foo() { std::cout << \"Hello, world!\" << std::endl; } 387 " 388 DEAL_II_COMPILER_HAS_FUSE_LD_GOLD) 389 390 IF(DEAL_II_COMPILER_HAS_FUSE_LD_LLD) 391 ADD_FLAGS(DEAL_II_LINKER_FLAGS "-fuse-ld=lld") 392 ELSEIF(DEAL_II_COMPILER_HAS_FUSE_LD_GOLD) 393 ADD_FLAGS(DEAL_II_LINKER_FLAGS "-fuse-ld=gold") 394 ENDIF() 395 396 RESET_CMAKE_REQUIRED() 397ENDIF() 398