1# 2#//===----------------------------------------------------------------------===// 3#// 4#// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5#// See https://llvm.org/LICENSE.txt for license information. 6#// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7#// 8#//===----------------------------------------------------------------------===// 9# 10 11include(CheckCCompilerFlag) 12include(CheckCSourceCompiles) 13include(CheckCXXSourceCompiles) 14include(CheckCXXCompilerFlag) 15include(CheckIncludeFile) 16include(CheckLibraryExists) 17include(CheckIncludeFiles) 18include(CheckSymbolExists) 19include(LibompCheckFortranFlag) 20include(LLVMCheckCompilerLinkerFlag) 21 22# Check for versioned symbols 23function(libomp_check_version_symbols retval) 24 set(source_code 25 "#include <stdio.h> 26 void func1() { printf(\"Hello\"); } 27 void func2() { printf(\"World\"); } 28 __asm__(\".symver func1, func@VER1\"); 29 __asm__(\".symver func2, func@VER2\"); 30 int main(void) { 31 func1(); 32 func2(); 33 return 0; 34 }") 35 set(version_script_source "VER1 { }; VER2 { } VER1;") 36 file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/__version_script.txt "${version_script_source}") 37 set(CMAKE_REQUIRED_FLAGS -Wl,--version-script=${CMAKE_CURRENT_BINARY_DIR}/__version_script.txt) 38 check_c_source_compiles("${source_code}" ${retval}) 39 set(${retval} ${${retval}} PARENT_SCOPE) 40 file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/__version_script.txt) 41endfunction() 42 43# Includes the architecture flag in both compile and link phase 44function(libomp_check_architecture_flag flag retval) 45 set(CMAKE_REQUIRED_FLAGS "${flag}") 46 check_c_compiler_flag("${flag}" ${retval}) 47 set(${retval} ${${retval}} PARENT_SCOPE) 48endfunction() 49 50# Checking CXX, Linker Flags 51 52# GCC silently accepts any -Wno-<foo> option, but warns about those options 53# being unrecognized only if the compilation triggers other warnings to be 54# printed. Therefore, check for whether the compiler supports options in the 55# form -W<foo>, and if supported, add the corresponding -Wno-<foo> option. 56 57check_cxx_compiler_flag(-fno-exceptions LIBOMP_HAVE_FNO_EXCEPTIONS_FLAG) 58check_cxx_compiler_flag(-fno-rtti LIBOMP_HAVE_FNO_RTTI_FLAG) 59check_cxx_compiler_flag(-Wclass-memaccess LIBOMP_HAVE_WCLASS_MEMACCESS_FLAG) 60check_cxx_compiler_flag(-Wcovered-switch-default LIBOMP_HAVE_WCOVERED_SWITCH_DEFAULT_FLAG) 61check_cxx_compiler_flag(-Wframe-address LIBOMP_HAVE_WFRAME_ADDRESS_FLAG) 62check_cxx_compiler_flag(-Wstrict-aliasing LIBOMP_HAVE_WSTRICT_ALIASING_FLAG) 63check_cxx_compiler_flag(-Wstringop-overflow=0 LIBOMP_HAVE_WSTRINGOP_OVERFLOW_FLAG) 64check_cxx_compiler_flag(-Wstringop-truncation LIBOMP_HAVE_WSTRINGOP_TRUNCATION_FLAG) 65check_cxx_compiler_flag(-Wswitch LIBOMP_HAVE_WSWITCH_FLAG) 66check_cxx_compiler_flag(-Wuninitialized LIBOMP_HAVE_WUNINITIALIZED_FLAG) 67check_cxx_compiler_flag(-Wreturn-type-c-linkage LIBOMP_HAVE_WRETURN_TYPE_C_LINKAGE_FLAG) 68check_cxx_compiler_flag(-Wcast-qual LIBOMP_HAVE_WCAST_QUAL_FLAG) 69check_cxx_compiler_flag(-Wint-to-void-pointer-cast LIBOMP_HAVE_WINT_TO_VOID_POINTER_CAST_FLAG) 70# check_cxx_compiler_flag(-Wconversion LIBOMP_HAVE_WCONVERSION_FLAG) 71check_cxx_compiler_flag(-msse2 LIBOMP_HAVE_MSSE2_FLAG) 72check_cxx_compiler_flag(-ftls-model=initial-exec LIBOMP_HAVE_FTLS_MODEL_FLAG) 73libomp_check_architecture_flag(-mmic LIBOMP_HAVE_MMIC_FLAG) 74libomp_check_architecture_flag(-m32 LIBOMP_HAVE_M32_FLAG) 75if(WIN32) 76 if(MSVC) 77 # Check Windows MSVC style flags. 78 check_cxx_compiler_flag(/EHsc LIBOMP_HAVE_EHSC_FLAG) 79 check_cxx_compiler_flag(/GS LIBOMP_HAVE_GS_FLAG) 80 check_cxx_compiler_flag(/Oy- LIBOMP_HAVE_Oy__FLAG) 81 check_cxx_compiler_flag(/arch:SSE2 LIBOMP_HAVE_ARCH_SSE2_FLAG) 82 check_cxx_compiler_flag(/Qsafeseh LIBOMP_HAVE_QSAFESEH_FLAG) 83 endif() 84 check_cxx_compiler_flag(-mrtm LIBOMP_HAVE_MRTM_FLAG) 85 # It is difficult to create a dummy masm assembly file 86 # and then check the MASM assembler to see if these flags exist and work, 87 # so we assume they do for Windows. 88 set(LIBOMP_HAVE_SAFESEH_MASM_FLAG TRUE) 89 set(LIBOMP_HAVE_COFF_MASM_FLAG TRUE) 90 # Change Windows flags /MDx to /MTx 91 foreach(libomp_lang IN ITEMS C CXX) 92 foreach(libomp_btype IN ITEMS DEBUG RELWITHDEBINFO RELEASE MINSIZEREL) 93 string(REPLACE "/MD" "/MT" 94 CMAKE_${libomp_lang}_FLAGS_${libomp_btype} 95 "${CMAKE_${libomp_lang}_FLAGS_${libomp_btype}}" 96 ) 97 endforeach() 98 endforeach() 99endif() 100if(${LIBOMP_FORTRAN_MODULES}) 101 libomp_check_fortran_flag(-m32 LIBOMP_HAVE_M32_FORTRAN_FLAG) 102endif() 103 104# Check non-posix pthread API here before CMAKE_REQUIRED_DEFINITIONS gets messed up 105check_symbol_exists(pthread_setname_np "pthread.h" LIBOMP_HAVE_PTHREAD_SETNAME_NP) 106check_symbol_exists(pthread_set_name_np "pthread.h;pthread_np.h" LIBOMP_HAVE_PTHREAD_SET_NAME_NP) 107 108# Check for Unix shared memory 109check_symbol_exists(shm_open "sys/mman.h" LIBOMP_HAVE_SHM_OPEN_NO_LRT) 110if (NOT LIBOMP_HAVE_SHM_OPEN_NO_LRT) 111 set(CMAKE_REQUIRED_LIBRARIES -lrt) 112 check_symbol_exists(shm_open "sys/mman.h" LIBOMP_HAVE_SHM_OPEN_WITH_LRT) 113 set(CMAKE_REQUIRED_LIBRARIES) 114endif() 115 116# Check for aligned memory allocator function 117check_include_file(xmmintrin.h LIBOMP_HAVE_XMMINTRIN_H) 118set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) 119if (LIBOMP_HAVE_XMMINTRIN_H) 120 set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -DLIBOMP_HAVE_XMMINTRIN_H") 121endif() 122set(source_code "// check for _mm_malloc 123 #ifdef LIBOMP_HAVE_XMMINTRIN_H 124 #include <xmmintrin.h> 125 #endif 126 int main() { void *ptr = _mm_malloc(sizeof(int) * 1000, 64); _mm_free(ptr); return 0; }") 127check_cxx_source_compiles("${source_code}" LIBOMP_HAVE__MM_MALLOC) 128set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS}) 129check_symbol_exists(aligned_alloc "stdlib.h" LIBOMP_HAVE_ALIGNED_ALLOC) 130check_symbol_exists(posix_memalign "stdlib.h" LIBOMP_HAVE_POSIX_MEMALIGN) 131check_symbol_exists(_aligned_malloc "malloc.h" LIBOMP_HAVE__ALIGNED_MALLOC) 132 133# Check linker flags 134if(WIN32) 135 llvm_check_compiler_linker_flag(C /SAFESEH LIBOMP_HAVE_SAFESEH_FLAG) 136elseif(NOT APPLE) 137 llvm_check_compiler_linker_flag(C -Wl,-x LIBOMP_HAVE_X_FLAG) 138 llvm_check_compiler_linker_flag(C -Wl,--as-needed LIBOMP_HAVE_AS_NEEDED_FLAG) 139 llvm_check_compiler_linker_flag(C "-Wl,--version-script=${LIBOMP_SRC_DIR}/exports_test_so.txt" LIBOMP_HAVE_VERSION_SCRIPT_FLAG) 140 llvm_check_compiler_linker_flag(C -static-libgcc LIBOMP_HAVE_STATIC_LIBGCC_FLAG) 141 llvm_check_compiler_linker_flag(C -Wl,-z,noexecstack LIBOMP_HAVE_Z_NOEXECSTACK_FLAG) 142endif() 143 144# Check Intel(R) C Compiler specific flags 145if(CMAKE_C_COMPILER_ID STREQUAL "Intel" OR CMAKE_C_COMPILER_ID STREQUAL "IntelLLVM") 146 check_cxx_compiler_flag(/Qlong_double LIBOMP_HAVE_LONG_DOUBLE_FLAG) 147 check_cxx_compiler_flag(/Qdiag-disable:177 LIBOMP_HAVE_DIAG_DISABLE_177_FLAG) 148 check_cxx_compiler_flag(/Qinline-min-size=1 LIBOMP_HAVE_INLINE_MIN_SIZE_FLAG) 149 check_cxx_compiler_flag(-Qoption,cpp,--extended_float_types LIBOMP_HAVE_EXTENDED_FLOAT_TYPES_FLAG) 150 check_cxx_compiler_flag(-falign-stack=maintain-16-byte LIBOMP_HAVE_FALIGN_STACK_FLAG) 151 check_cxx_compiler_flag("-opt-streaming-stores never" LIBOMP_HAVE_OPT_STREAMING_STORES_FLAG) 152 llvm_check_compiler_linker_flag(C -static-intel LIBOMP_HAVE_STATIC_INTEL_FLAG) 153 llvm_check_compiler_linker_flag(C -no-intel-extensions LIBOMP_HAVE_NO_INTEL_EXTENSIONS_FLAG) 154 check_library_exists(irc_pic _intel_fast_memcpy "" LIBOMP_HAVE_IRC_PIC_LIBRARY) 155endif() 156 157# Checking threading requirements. Note that compiling to WebAssembly threads 158# with either the Emscripten or wasi-threads flavor ends up using the pthreads 159# interface in a WebAssembly-compiled libc; CMake does not yet know how to 160# detect this. 161if (NOT WASM) 162 find_package(Threads REQUIRED) 163 if(WIN32) 164 if(NOT CMAKE_USE_WIN32_THREADS_INIT) 165 libomp_error_say("Need Win32 thread interface on Windows.") 166 endif() 167 else() 168 if(NOT CMAKE_USE_PTHREADS_INIT) 169 libomp_error_say("Need pthread interface on Unix-like systems.") 170 endif() 171 endif() 172endif() 173 174# Checking for x86-specific waitpkg and rtm attribute and intrinsics 175if (IA32 OR INTEL64) 176 check_include_file(immintrin.h LIBOMP_HAVE_IMMINTRIN_H) 177 if (NOT LIBOMP_HAVE_IMMINTRIN_H) 178 check_include_file(intrin.h LIBOMP_HAVE_INTRIN_H) 179 endif() 180 check_cxx_source_compiles("__attribute__((target(\"rtm\"))) 181 int main() {return 0;}" LIBOMP_HAVE_ATTRIBUTE_RTM) 182 check_cxx_source_compiles("__attribute__((target(\"waitpkg\"))) 183 int main() {return 0;}" LIBOMP_HAVE_ATTRIBUTE_WAITPKG) 184 libomp_append(CMAKE_REQUIRED_DEFINITIONS -DIMMINTRIN_H LIBOMP_HAVE_IMMINTRIN_H) 185 libomp_append(CMAKE_REQUIRED_DEFINITIONS -DINTRIN_H LIBOMP_HAVE_INTRIN_H) 186 libomp_append(CMAKE_REQUIRED_DEFINITIONS -DATTRIBUTE_WAITPKG LIBOMP_HAVE_ATTRIBUTE_WAITPKG) 187 libomp_append(CMAKE_REQUIRED_DEFINITIONS -DATTRIBUTE_RTM LIBOMP_HAVE_ATTRIBUTE_RTM) 188 set(source_code "// check for attribute and wait pkg intrinsics 189 #ifdef IMMINTRIN_H 190 #include <immintrin.h> 191 #endif 192 #ifdef INTRIN_H 193 #include <intrin.h> 194 #endif 195 #ifdef ATTRIBUTE_WAITPKG 196 __attribute__((target(\"waitpkg\"))) 197 #endif 198 static inline int __kmp_umwait(unsigned hint, unsigned long long counter) { 199 return _umwait(hint, counter); 200 } 201 int main() { int a = __kmp_umwait(0, 1000); return a; }") 202 check_cxx_source_compiles("${source_code}" LIBOMP_HAVE_WAITPKG_INTRINSICS) 203 set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) 204 if (LIBOMP_HAVE_MRTM_FLAG) 205 set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -mrtm") 206 endif() 207 set(source_code "// check for attribute rtm and rtm intrinsics 208 #ifdef IMMINTRIN_H 209 #include <immintrin.h> 210 #endif 211 #ifdef INTRIN_H 212 #include <intrin.h> 213 #endif 214 #ifdef ATTRIBUTE_RTM 215 __attribute__((target(\"rtm\"))) 216 #endif 217 static inline int __kmp_xbegin() { 218 return _xbegin(); 219 } 220 int main() { int a = __kmp_xbegin(); return a; }") 221 check_cxx_source_compiles("${source_code}" LIBOMP_HAVE_RTM_INTRINSICS) 222 set(CMAKE_REQUIRED_DEFINITIONS) 223 set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS}) 224endif() 225 226# Find python3 executable 227# Python3 is used to create kmp_i18n_id.inc and 228# kmp_i18n_default.inc and for Windows the *.def files. 229find_package(Python3 REQUIRED COMPONENTS Interpreter) 230 231# Checking features 232# Check if version symbol assembler directives are supported 233if (LIBOMP_HAVE_VERSION_SCRIPT_FLAG) 234 libomp_check_version_symbols(LIBOMP_HAVE_VERSION_SYMBOLS) 235else() 236 set(LIBOMP_HAVE_VERSION_SYMBOLS FALSE) 237endif() 238 239# Check if quad precision types are available 240if(CMAKE_C_COMPILER_ID STREQUAL "GNU") 241 set(LIBOMP_HAVE_QUAD_PRECISION TRUE) 242elseif(CMAKE_C_COMPILER_ID STREQUAL "Intel" OR CMAKE_C_COMPILER_ID STREQUAL "IntelLLVM") 243 if(LIBOMP_HAVE_EXTENDED_FLOAT_TYPES_FLAG) 244 set(LIBOMP_HAVE_QUAD_PRECISION TRUE) 245 else() 246 set(LIBOMP_HAVE_QUAD_PRECISION TRUE) 247 endif() 248else() 249 set(LIBOMP_HAVE_QUAD_PRECISION FALSE) 250endif() 251 252# Check if adaptive locks are available 253if((${IA32} OR ${INTEL64}) AND NOT MSVC) 254 set(LIBOMP_HAVE_ADAPTIVE_LOCKS TRUE) 255else() 256 set(LIBOMP_HAVE_ADAPTIVE_LOCKS FALSE) 257endif() 258 259# Check if stats-gathering is available 260if(${LIBOMP_STATS}) 261 check_c_source_compiles( 262 "__thread int x; 263 int main(int argc, char** argv) 264 { x = argc; return x; }" 265 LIBOMP_HAVE___THREAD) 266 check_c_source_compiles( 267 "int main(int argc, char** argv) 268 { unsigned long long t = __builtin_readcyclecounter(); return 0; }" 269 LIBOMP_HAVE___BUILTIN_READCYCLECOUNTER) 270 if(NOT LIBOMP_HAVE___BUILTIN_READCYCLECOUNTER) 271 if(${IA32} OR ${INTEL64} OR ${MIC}) 272 check_include_file(x86intrin.h LIBOMP_HAVE_X86INTRIN_H) 273 libomp_append(CMAKE_REQUIRED_DEFINITIONS -DLIBOMP_HAVE_X86INTRIN_H LIBOMP_HAVE_X86INTRIN_H) 274 check_c_source_compiles( 275 "#ifdef LIBOMP_HAVE_X86INTRIN_H 276 # include <x86intrin.h> 277 #endif 278 int main(int argc, char** argv) { unsigned long long t = __rdtsc(); return 0; }" LIBOMP_HAVE___RDTSC) 279 set(CMAKE_REQUIRED_DEFINITIONS) 280 endif() 281 endif() 282 if(LIBOMP_HAVE___THREAD AND (LIBOMP_HAVE___RDTSC OR LIBOMP_HAVE___BUILTIN_READCYCLECOUNTER)) 283 set(LIBOMP_HAVE_STATS TRUE) 284 else() 285 set(LIBOMP_HAVE_STATS FALSE) 286 endif() 287endif() 288 289# Check if OMPT support is available 290# Currently, __builtin_frame_address() is required for OMPT 291# Weak attribute is required for Unices (except Darwin), LIBPSAPI is used for Windows 292check_c_source_compiles("int main(int argc, char** argv) { 293 void* p = __builtin_frame_address(0); 294 return 0;}" LIBOMP_HAVE___BUILTIN_FRAME_ADDRESS) 295check_c_source_compiles("__attribute__ ((weak)) int foo(int a) { return a*a; } 296 int main(int argc, char** argv) { 297 return foo(argc);}" LIBOMP_HAVE_WEAK_ATTRIBUTE) 298set(CMAKE_REQUIRED_LIBRARIES psapi) 299check_c_source_compiles("#include <windows.h> 300 #include <psapi.h> 301 int main(int artc, char** argv) { 302 return EnumProcessModules(NULL, NULL, 0, NULL); 303 }" LIBOMP_HAVE_PSAPI) 304set(CMAKE_REQUIRED_LIBRARIES) 305if(NOT LIBOMP_HAVE___BUILTIN_FRAME_ADDRESS) 306 set(LIBOMP_HAVE_OMPT_SUPPORT FALSE) 307else() 308 if( # hardware architecture supported? 309 ((LIBOMP_ARCH STREQUAL x86_64) OR 310 (LIBOMP_ARCH STREQUAL i386) OR 311# (LIBOMP_ARCH STREQUAL arm) OR 312 (LIBOMP_ARCH STREQUAL aarch64) OR 313 (LIBOMP_ARCH STREQUAL aarch64_32) OR 314 (LIBOMP_ARCH STREQUAL aarch64_a64fx) OR 315 (LIBOMP_ARCH STREQUAL ppc64le) OR 316 (LIBOMP_ARCH STREQUAL ppc64) OR 317 (LIBOMP_ARCH STREQUAL riscv64) OR 318 (LIBOMP_ARCH STREQUAL loongarch64) OR 319 (LIBOMP_ARCH STREQUAL s390x)) 320 AND # OS supported? 321 ((WIN32 AND LIBOMP_HAVE_PSAPI) OR APPLE OR 322 (NOT (WIN32 OR ${CMAKE_SYSTEM_NAME} MATCHES "AIX") AND LIBOMP_HAVE_WEAK_ATTRIBUTE))) 323 set(LIBOMP_HAVE_OMPT_SUPPORT TRUE) 324 else() 325 set(LIBOMP_HAVE_OMPT_SUPPORT FALSE) 326 endif() 327endif() 328 329set(LIBOMP_HAVE_OMPT_SUPPORT ${LIBOMP_HAVE_OMPT_SUPPORT} PARENT_SCOPE) 330 331# Check if HWLOC support is available 332if(${LIBOMP_USE_HWLOC}) 333 find_path(LIBOMP_HWLOC_INCLUDE_DIR NAMES hwloc.h HINTS ${LIBOMP_HWLOC_INSTALL_DIR} PATH_SUFFIXES include) 334 set(CMAKE_REQUIRED_INCLUDES ${LIBOMP_HWLOC_INCLUDE_DIR}) 335 check_include_file(hwloc.h LIBOMP_HAVE_HWLOC_H) 336 set(CMAKE_REQUIRED_INCLUDES) 337 find_library(LIBOMP_HWLOC_LIBRARY 338 NAMES hwloc libhwloc 339 HINTS ${LIBOMP_HWLOC_INSTALL_DIR}/lib) 340 if(LIBOMP_HWLOC_LIBRARY) 341 check_library_exists(${LIBOMP_HWLOC_LIBRARY} hwloc_topology_init 342 ${LIBOMP_HWLOC_INSTALL_DIR}/lib LIBOMP_HAVE_LIBHWLOC) 343 get_filename_component(LIBOMP_HWLOC_LIBRARY_DIR ${LIBOMP_HWLOC_LIBRARY} PATH) 344 endif() 345 if(LIBOMP_HAVE_HWLOC_H AND LIBOMP_HAVE_LIBHWLOC AND LIBOMP_HWLOC_LIBRARY) 346 set(LIBOMP_HAVE_HWLOC TRUE) 347 else() 348 set(LIBOMP_HAVE_HWLOC FALSE) 349 libomp_say("Could not find hwloc") 350 endif() 351endif() 352 353# Check if ThreadSanitizer support is available 354if("${CMAKE_SYSTEM_NAME}" MATCHES "Linux" AND ${INTEL64}) 355 set(LIBOMP_HAVE_TSAN_SUPPORT TRUE) 356else() 357 set(LIBOMP_HAVE_TSAN_SUPPORT FALSE) 358endif() 359