xref: /llvm-project/openmp/runtime/cmake/config-ix.cmake (revision 37e109c6f86e7562a7f0b54a229f57e36b778f05)
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