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(LibompCheckLinkerFlag) 20include(LibompCheckFortranFlag) 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() { 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 51check_cxx_compiler_flag(-fno-exceptions LIBOMP_HAVE_FNO_EXCEPTIONS_FLAG) 52check_cxx_compiler_flag(-fno-rtti LIBOMP_HAVE_FNO_RTTI_FLAG) 53check_cxx_compiler_flag(-Wno-class-memaccess LIBOMP_HAVE_WNO_CLASS_MEMACCESS_FLAG) 54check_cxx_compiler_flag(-Wno-covered-switch-default LIBOMP_HAVE_WNO_COVERED_SWITCH_DEFAULT_FLAG) 55check_cxx_compiler_flag(-Wno-frame-address LIBOMP_HAVE_WNO_FRAME_ADDRESS_FLAG) 56check_cxx_compiler_flag(-Wno-strict-aliasing LIBOMP_HAVE_WNO_STRICT_ALIASING_FLAG) 57check_cxx_compiler_flag(-Wstringop-overflow=0 LIBOMP_HAVE_WSTRINGOP_OVERFLOW_FLAG) 58check_cxx_compiler_flag(-Wno-stringop-truncation LIBOMP_HAVE_WNO_STRINGOP_TRUNCATION_FLAG) 59check_cxx_compiler_flag(-Wno-switch LIBOMP_HAVE_WNO_SWITCH_FLAG) 60check_cxx_compiler_flag(-Wno-uninitialized LIBOMP_HAVE_WNO_UNINITIALIZED_FLAG) 61check_cxx_compiler_flag(-Wno-unused-but-set-variable LIBOMP_HAVE_WNO_UNUSED_BUT_SET_VARIABLE_FLAG) 62check_cxx_compiler_flag(-msse2 LIBOMP_HAVE_MSSE2_FLAG) 63check_cxx_compiler_flag(-ftls-model=initial-exec LIBOMP_HAVE_FTLS_MODEL_FLAG) 64libomp_check_architecture_flag(-mmic LIBOMP_HAVE_MMIC_FLAG) 65libomp_check_architecture_flag(-m32 LIBOMP_HAVE_M32_FLAG) 66if(WIN32) 67 if(MSVC) 68 # Check Windows MSVC style flags. 69 check_cxx_compiler_flag(/EHsc LIBOMP_HAVE_EHSC_FLAG) 70 check_cxx_compiler_flag(/GS LIBOMP_HAVE_GS_FLAG) 71 check_cxx_compiler_flag(/Oy- LIBOMP_HAVE_Oy__FLAG) 72 check_cxx_compiler_flag(/arch:SSE2 LIBOMP_HAVE_ARCH_SSE2_FLAG) 73 check_cxx_compiler_flag(/Qsafeseh LIBOMP_HAVE_QSAFESEH_FLAG) 74 endif() 75 check_cxx_compiler_flag(-mrtm LIBOMP_HAVE_MRTM_FLAG) 76 # It is difficult to create a dummy masm assembly file 77 # and then check the MASM assembler to see if these flags exist and work, 78 # so we assume they do for Windows. 79 set(LIBOMP_HAVE_SAFESEH_MASM_FLAG TRUE) 80 set(LIBOMP_HAVE_COFF_MASM_FLAG TRUE) 81 # Change Windows flags /MDx to /MTx 82 foreach(libomp_lang IN ITEMS C CXX) 83 foreach(libomp_btype IN ITEMS DEBUG RELWITHDEBINFO RELEASE MINSIZEREL) 84 string(REPLACE "/MD" "/MT" 85 CMAKE_${libomp_lang}_FLAGS_${libomp_btype} 86 "${CMAKE_${libomp_lang}_FLAGS_${libomp_btype}}" 87 ) 88 endforeach() 89 endforeach() 90else() 91 # It is difficult to create a dummy assembly file that compiles into an 92 # executable for every architecture and then check the C compiler to 93 # see if -x assembler-with-cpp exists and works, so we assume it does for non-Windows. 94 set(LIBOMP_HAVE_X_ASSEMBLER_WITH_CPP_FLAG TRUE) 95endif() 96if(${LIBOMP_FORTRAN_MODULES}) 97 libomp_check_fortran_flag(-m32 LIBOMP_HAVE_M32_FORTRAN_FLAG) 98endif() 99 100# Check for Unix shared memory 101check_symbol_exists(shm_open "sys/mman.h" LIBOMP_HAVE_SHM_OPEN_NO_LRT) 102if (NOT LIBOMP_HAVE_SHM_OPEN_NO_LRT) 103 set(CMAKE_REQUIRED_LIBRARIES -lrt) 104 check_symbol_exists(shm_open "sys/mman.h" LIBOMP_HAVE_SHM_OPEN_WITH_LRT) 105 set(CMAKE_REQUIRED_LIBRARIES) 106endif() 107 108# Check linker flags 109if(WIN32) 110 libomp_check_linker_flag(/SAFESEH LIBOMP_HAVE_SAFESEH_FLAG) 111elseif(NOT APPLE) 112 libomp_check_linker_flag(-Wl,-x LIBOMP_HAVE_X_FLAG) 113 libomp_check_linker_flag(-Wl,--warn-shared-textrel LIBOMP_HAVE_WARN_SHARED_TEXTREL_FLAG) 114 libomp_check_linker_flag(-Wl,--as-needed LIBOMP_HAVE_AS_NEEDED_FLAG) 115 libomp_check_linker_flag("-Wl,--version-script=${LIBOMP_SRC_DIR}/exports_so.txt" LIBOMP_HAVE_VERSION_SCRIPT_FLAG) 116 libomp_check_linker_flag(-static-libgcc LIBOMP_HAVE_STATIC_LIBGCC_FLAG) 117 libomp_check_linker_flag(-Wl,-z,noexecstack LIBOMP_HAVE_Z_NOEXECSTACK_FLAG) 118endif() 119 120# Check Intel(R) C Compiler specific flags 121if(CMAKE_C_COMPILER_ID STREQUAL "Intel") 122 check_cxx_compiler_flag(/Qlong_double LIBOMP_HAVE_LONG_DOUBLE_FLAG) 123 check_cxx_compiler_flag(/Qdiag-disable:177 LIBOMP_HAVE_DIAG_DISABLE_177_FLAG) 124 check_cxx_compiler_flag(/Qinline-min-size=1 LIBOMP_HAVE_INLINE_MIN_SIZE_FLAG) 125 check_cxx_compiler_flag(-Qoption,cpp,--extended_float_types LIBOMP_HAVE_EXTENDED_FLOAT_TYPES_FLAG) 126 check_cxx_compiler_flag(-falign-stack=maintain-16-byte LIBOMP_HAVE_FALIGN_STACK_FLAG) 127 check_cxx_compiler_flag("-opt-streaming-stores never" LIBOMP_HAVE_OPT_STREAMING_STORES_FLAG) 128 libomp_check_linker_flag(-static-intel LIBOMP_HAVE_STATIC_INTEL_FLAG) 129 libomp_check_linker_flag(-no-intel-extensions LIBOMP_HAVE_NO_INTEL_EXTENSIONS_FLAG) 130 check_library_exists(irc_pic _intel_fast_memcpy "" LIBOMP_HAVE_IRC_PIC_LIBRARY) 131endif() 132 133# Checking Threading requirements 134find_package(Threads REQUIRED) 135if(WIN32) 136 if(NOT CMAKE_USE_WIN32_THREADS_INIT) 137 libomp_error_say("Need Win32 thread interface on Windows.") 138 endif() 139else() 140 if(NOT CMAKE_USE_PTHREADS_INIT) 141 libomp_error_say("Need pthread interface on Unix-like systems.") 142 endif() 143endif() 144 145# Checking for x86-specific waitpkg and rtm attribute and intrinsics 146if (IA32 OR INTEL64) 147 check_include_file(immintrin.h LIBOMP_HAVE_IMMINTRIN_H) 148 if (NOT LIBOMP_HAVE_IMMINTRIN_H) 149 check_include_file(intrin.h LIBOMP_HAVE_INTRIN_H) 150 endif() 151 check_cxx_source_compiles("__attribute__((target(\"rtm\"))) 152 int main() {return 0;}" LIBOMP_HAVE_ATTRIBUTE_RTM) 153 check_cxx_source_compiles("__attribute__((target(\"waitpkg\"))) 154 int main() {return 0;}" LIBOMP_HAVE_ATTRIBUTE_WAITPKG) 155 libomp_append(CMAKE_REQUIRED_DEFINITIONS -DIMMINTRIN_H LIBOMP_HAVE_IMMINTRIN_H) 156 libomp_append(CMAKE_REQUIRED_DEFINITIONS -DINTRIN_H LIBOMP_HAVE_INTRIN_H) 157 libomp_append(CMAKE_REQUIRED_DEFINITIONS -DATTRIBUTE_WAITPKG LIBOMP_HAVE_ATTRIBUTE_WAITPKG) 158 libomp_append(CMAKE_REQUIRED_DEFINITIONS -DATTRIBUTE_RTM LIBOMP_HAVE_ATTRIBUTE_RTM) 159 set(source_code "// check for attribute and wait pkg intrinsics 160 #ifdef IMMINTRIN_H 161 #include <immintrin.h> 162 #endif 163 #ifdef INTRIN_H 164 #include <intrin.h> 165 #endif 166 #ifdef ATTRIBUTE_WAITPKG 167 __attribute__((target(\"waitpkg\"))) 168 #endif 169 static inline int __kmp_umwait(unsigned hint, unsigned long long counter) { 170 return _umwait(hint, counter); 171 } 172 int main() { int a = __kmp_umwait(0, 1000); return a; }") 173 check_cxx_source_compiles("${source_code}" LIBOMP_HAVE_WAITPKG_INTRINSICS) 174 set(source_code "// check for attribute rtm and rtm intrinsics 175 #ifdef IMMINTRIN_H 176 #include <immintrin.h> 177 #endif 178 #ifdef INTRIN_H 179 #include <intrin.h> 180 #endif 181 #ifdef ATTRIBUTE_RTM 182 __attribute__((target(\"rtm\"))) 183 #endif 184 static inline int __kmp_xbegin() { 185 return _xbegin(); 186 } 187 int main() { int a = __kmp_xbegin(); return a; }") 188 check_cxx_source_compiles("${source_code}" LIBOMP_HAVE_RTM_INTRINSICS) 189 set(CMAKE_REQUIRED_DEFINITIONS) 190endif() 191 192# Find perl executable 193# Perl is used to create omp.h (and other headers) along with kmp_i18n_id.inc and kmp_i18n_default.inc 194find_package(Perl REQUIRED) 195# The perl scripts take the --os=/--arch= flags which expect a certain format for operating systems and arch's. 196# Until the perl scripts are removed, the most portable way to handle this is to have all operating systems that 197# are neither Windows nor Mac (Most Unix flavors) be considered lin to the perl scripts. This is rooted 198# in that all the Perl scripts check the operating system and will fail if it isn't "valid". This 199# temporary solution lets us avoid trying to enumerate all the possible OS values inside the Perl modules. 200if(WIN32) 201 set(LIBOMP_PERL_SCRIPT_OS win) 202elseif(APPLE) 203 set(LIBOMP_PERL_SCRIPT_OS mac) 204else() 205 set(LIBOMP_PERL_SCRIPT_OS lin) 206endif() 207if(IA32) 208 set(LIBOMP_PERL_SCRIPT_ARCH 32) 209elseif(MIC) 210 set(LIBOMP_PERL_SCRIPT_ARCH mic) 211elseif(INTEL64) 212 set(LIBOMP_PERL_SCRIPT_ARCH 32e) 213else() 214 set(LIBOMP_PERL_SCRIPT_ARCH ${LIBOMP_ARCH}) 215endif() 216 217# Checking features 218# Check if version symbol assembler directives are supported 219libomp_check_version_symbols(LIBOMP_HAVE_VERSION_SYMBOLS) 220 221# Check if quad precision types are available 222if(CMAKE_C_COMPILER_ID STREQUAL "GNU") 223 set(LIBOMP_HAVE_QUAD_PRECISION TRUE) 224elseif(CMAKE_C_COMPILER_ID STREQUAL "Intel") 225 if(LIBOMP_HAVE_EXTENDED_FLOAT_TYPES_FLAG) 226 set(LIBOMP_HAVE_QUAD_PRECISION TRUE) 227 else() 228 set(LIBOMP_HAVE_QUAD_PRECISION TRUE) 229 endif() 230else() 231 set(LIBOMP_HAVE_QUAD_PRECISION FALSE) 232endif() 233 234# Check if adaptive locks are available 235if((${IA32} OR ${INTEL64}) AND NOT MSVC) 236 set(LIBOMP_HAVE_ADAPTIVE_LOCKS TRUE) 237else() 238 set(LIBOMP_HAVE_ADAPTIVE_LOCKS FALSE) 239endif() 240 241# Check if stats-gathering is available 242if(${LIBOMP_STATS}) 243 check_c_source_compiles( 244 "__thread int x; 245 int main(int argc, char** argv) 246 { x = argc; return x; }" 247 LIBOMP_HAVE___THREAD) 248 check_c_source_compiles( 249 "int main(int argc, char** argv) 250 { unsigned long long t = __builtin_readcyclecounter(); return 0; }" 251 LIBOMP_HAVE___BUILTIN_READCYCLECOUNTER) 252 if(NOT LIBOMP_HAVE___BUILTIN_READCYCLECOUNTER) 253 if(${IA32} OR ${INTEL64} OR ${MIC}) 254 check_include_file(x86intrin.h LIBOMP_HAVE_X86INTRIN_H) 255 libomp_append(CMAKE_REQUIRED_DEFINITIONS -DLIBOMP_HAVE_X86INTRIN_H LIBOMP_HAVE_X86INTRIN_H) 256 check_c_source_compiles( 257 "#ifdef LIBOMP_HAVE_X86INTRIN_H 258 # include <x86intrin.h> 259 #endif 260 int main(int argc, char** argv) { unsigned long long t = __rdtsc(); return 0; }" LIBOMP_HAVE___RDTSC) 261 set(CMAKE_REQUIRED_DEFINITIONS) 262 endif() 263 endif() 264 if(LIBOMP_HAVE___THREAD AND (LIBOMP_HAVE___RDTSC OR LIBOMP_HAVE___BUILTIN_READCYCLECOUNTER)) 265 set(LIBOMP_HAVE_STATS TRUE) 266 else() 267 set(LIBOMP_HAVE_STATS FALSE) 268 endif() 269endif() 270 271# Check if OMPT support is available 272# Currently, __builtin_frame_address() is required for OMPT 273# Weak attribute is required for Unices (except Darwin), LIBPSAPI is used for Windows 274check_c_source_compiles("int main(int argc, char** argv) { 275 void* p = __builtin_frame_address(0); 276 return 0;}" LIBOMP_HAVE___BUILTIN_FRAME_ADDRESS) 277check_c_source_compiles("__attribute__ ((weak)) int foo(int a) { return a*a; } 278 int main(int argc, char** argv) { 279 return foo(argc);}" LIBOMP_HAVE_WEAK_ATTRIBUTE) 280check_include_files("windows.h;psapi.h" LIBOMP_HAVE_PSAPI_H) 281check_library_exists(psapi EnumProcessModules "" LIBOMP_HAVE_LIBPSAPI) 282if(LIBOMP_HAVE_PSAPI_H AND LIBOMP_HAVE_LIBPSAPI) 283 set(LIBOMP_HAVE_PSAPI TRUE) 284endif() 285if(NOT LIBOMP_HAVE___BUILTIN_FRAME_ADDRESS) 286 set(LIBOMP_HAVE_OMPT_SUPPORT FALSE) 287else() 288 if( # hardware architecture supported? 289 ((LIBOMP_ARCH STREQUAL x86_64) OR 290 (LIBOMP_ARCH STREQUAL i386) OR 291# (LIBOMP_ARCH STREQUAL arm) OR 292 (LIBOMP_ARCH STREQUAL aarch64) OR 293 (LIBOMP_ARCH STREQUAL ppc64le) OR 294 (LIBOMP_ARCH STREQUAL ppc64) OR 295 (LIBOMP_ARCH STREQUAL riscv64)) 296 AND # OS supported? 297 ((WIN32 AND LIBOMP_HAVE_PSAPI) OR APPLE OR (NOT WIN32 AND LIBOMP_HAVE_WEAK_ATTRIBUTE))) 298 set(LIBOMP_HAVE_OMPT_SUPPORT TRUE) 299 else() 300 set(LIBOMP_HAVE_OMPT_SUPPORT FALSE) 301 endif() 302endif() 303 304# Check if HWLOC support is available 305if(${LIBOMP_USE_HWLOC}) 306 set(CMAKE_REQUIRED_INCLUDES ${LIBOMP_HWLOC_INSTALL_DIR}/include) 307 check_include_file(hwloc.h LIBOMP_HAVE_HWLOC_H) 308 set(CMAKE_REQUIRED_INCLUDES) 309 find_library(LIBOMP_HWLOC_LIBRARY 310 NAMES hwloc libhwloc 311 HINTS ${LIBOMP_HWLOC_INSTALL_DIR}/lib) 312 if(LIBOMP_HWLOC_LIBRARY) 313 check_library_exists(${LIBOMP_HWLOC_LIBRARY} hwloc_topology_init 314 ${LIBOMP_HWLOC_INSTALL_DIR}/lib LIBOMP_HAVE_LIBHWLOC) 315 get_filename_component(LIBOMP_HWLOC_LIBRARY_DIR ${LIBOMP_HWLOC_LIBRARY} PATH) 316 endif() 317 if(LIBOMP_HAVE_HWLOC_H AND LIBOMP_HAVE_LIBHWLOC AND LIBOMP_HWLOC_LIBRARY) 318 set(LIBOMP_HAVE_HWLOC TRUE) 319 else() 320 set(LIBOMP_HAVE_HWLOC FALSE) 321 libomp_say("Could not find hwloc") 322 endif() 323endif() 324 325# Check if ThreadSanitizer support is available 326if("${CMAKE_SYSTEM_NAME}" MATCHES "Linux" AND ${INTEL64}) 327 set(LIBOMP_HAVE_TSAN_SUPPORT TRUE) 328else() 329 set(LIBOMP_HAVE_TSAN_SUPPORT FALSE) 330endif() 331