1# Distributed under the OSI-approved BSD 3-Clause License. See accompanying 2# file Copyright.txt or https://cmake.org/licensing for details. 3 4#[=======================================================================[.rst: 5FindThreads 6----------- 7 8This module determines the thread library of the system. 9 10Imported Targets 11^^^^^^^^^^^^^^^^ 12 13.. versionadded:: 3.1 14 15This module defines the following :prop_tgt:`IMPORTED` target: 16 17``Threads::Threads`` 18 The thread library, if found. 19 20Result Variables 21^^^^^^^^^^^^^^^^ 22 23The following variables are set: 24 25``Threads_FOUND`` 26 If a supported thread library was found. 27``CMAKE_THREAD_LIBS_INIT`` 28 The thread library to use. This may be empty if the thread functions 29 are provided by the system libraries and no special flags are needed 30 to use them. 31``CMAKE_USE_WIN32_THREADS_INIT`` 32 If the found thread library is the win32 one. 33``CMAKE_USE_PTHREADS_INIT`` 34 If the found thread library is pthread compatible. 35``CMAKE_HP_PTHREADS_INIT`` 36 If the found thread library is the HP thread library. 37 38Variables Affecting Behavior 39^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 40 41.. variable:: THREADS_PREFER_PTHREAD_FLAG 42 43 .. versionadded:: 3.1 44 45 If the use of the -pthread compiler and linker flag is preferred then 46 the caller can set this variable to TRUE. The compiler flag can only be 47 used with the imported target. Use of both the imported target as well 48 as this switch is highly recommended for new code. 49 50 This variable has no effect if the system libraries provide the 51 thread functions, i.e. when ``CMAKE_THREAD_LIBS_INIT`` will be empty. 52#]=======================================================================] 53 54include (CheckLibraryExists) 55set(Threads_FOUND FALSE) 56set(CMAKE_REQUIRED_QUIET_SAVE ${CMAKE_REQUIRED_QUIET}) 57set(CMAKE_REQUIRED_QUIET ${Threads_FIND_QUIETLY}) 58 59if(CMAKE_C_COMPILER_LOADED) 60 include (CheckIncludeFile) 61 include (CheckCSourceCompiles) 62elseif(CMAKE_CXX_COMPILER_LOADED) 63 include (CheckIncludeFileCXX) 64 include (CheckCXXSourceCompiles) 65else() 66 message(FATAL_ERROR "FindThreads only works if either C or CXX language is enabled") 67endif() 68 69# simple pthread test code 70set(PTHREAD_C_CXX_TEST_SOURCE [====[ 71#include <pthread.h> 72 73static void* test_func(void* data) 74{ 75 return data; 76} 77 78int main(void) 79{ 80 pthread_t thread; 81 pthread_create(&thread, NULL, test_func, NULL); 82 pthread_detach(thread); 83 pthread_cancel(thread); 84 pthread_join(thread, NULL); 85 pthread_atfork(NULL, NULL, NULL); 86 pthread_exit(NULL); 87 88 return 0; 89} 90]====]) 91 92# Internal helper macro. 93# Do NOT even think about using it outside of this file! 94macro(_check_threads_lib LIBNAME FUNCNAME VARNAME) 95 if(NOT Threads_FOUND) 96 CHECK_LIBRARY_EXISTS(${LIBNAME} ${FUNCNAME} "" ${VARNAME}) 97 if(${VARNAME}) 98 set(CMAKE_THREAD_LIBS_INIT "-l${LIBNAME}") 99 set(CMAKE_HAVE_THREADS_LIBRARY 1) 100 set(Threads_FOUND TRUE) 101 endif() 102 endif () 103endmacro() 104 105# Internal helper macro. 106# Do NOT even think about using it outside of this file! 107macro(_check_pthreads_flag) 108 if(NOT Threads_FOUND) 109 # If we did not find -lpthreads, -lpthread, or -lthread, look for -pthread 110 if(NOT DEFINED THREADS_HAVE_PTHREAD_ARG) 111 message(CHECK_START "Check if compiler accepts -pthread") 112 if(CMAKE_C_COMPILER_LOADED) 113 set(_threads_src ${CMAKE_CURRENT_LIST_DIR}/CheckForPthreads.c) 114 elseif(CMAKE_CXX_COMPILER_LOADED) 115 set(_threads_src ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindThreads/CheckForPthreads.cxx) 116 configure_file(${CMAKE_CURRENT_LIST_DIR}/CheckForPthreads.c "${_threads_src}" COPYONLY) 117 endif() 118 try_compile(THREADS_HAVE_PTHREAD_ARG 119 ${CMAKE_BINARY_DIR} 120 ${_threads_src} 121 CMAKE_FLAGS -DLINK_LIBRARIES:STRING=-pthread 122 OUTPUT_VARIABLE _cmake_check_pthreads_output) 123 124 string(APPEND _cmake_find_threads_output "${_cmake_check_pthreads_output}") 125 unset(_cmake_check_pthreads_output) 126 unset(_threads_src) 127 128 if(THREADS_HAVE_PTHREAD_ARG) 129 set(Threads_FOUND TRUE) 130 message(CHECK_PASS "yes") 131 else() 132 message(CHECK_FAIL "no") 133 endif() 134 135 endif() 136 137 if(THREADS_HAVE_PTHREAD_ARG) 138 set(Threads_FOUND TRUE) 139 set(CMAKE_THREAD_LIBS_INIT "-pthread") 140 endif() 141 endif() 142endmacro() 143 144# Do we have pthreads? 145if(CMAKE_C_COMPILER_LOADED) 146 CHECK_INCLUDE_FILE("pthread.h" CMAKE_HAVE_PTHREAD_H) 147else() 148 CHECK_INCLUDE_FILE_CXX("pthread.h" CMAKE_HAVE_PTHREAD_H) 149endif() 150 151if(CMAKE_HAVE_PTHREAD_H) 152 # 153 # We have pthread.h 154 # Let's check for the library now. 155 # 156 set(CMAKE_HAVE_THREADS_LIBRARY) 157 if(NOT THREADS_HAVE_PTHREAD_ARG) 158 # Check if pthread functions are in normal C library. 159 # We list some pthread functions in PTHREAD_C_CXX_TEST_SOURCE test code. 160 # If the pthread functions already exist in C library, we could just use 161 # them instead of linking to the additional pthread library. 162 if(CMAKE_C_COMPILER_LOADED) 163 CHECK_C_SOURCE_COMPILES("${PTHREAD_C_CXX_TEST_SOURCE}" CMAKE_HAVE_LIBC_PTHREAD) 164 elseif(CMAKE_CXX_COMPILER_LOADED) 165 CHECK_CXX_SOURCE_COMPILES("${PTHREAD_C_CXX_TEST_SOURCE}" CMAKE_HAVE_LIBC_PTHREAD) 166 endif() 167 if(CMAKE_HAVE_LIBC_PTHREAD) 168 set(CMAKE_THREAD_LIBS_INIT "") 169 set(CMAKE_HAVE_THREADS_LIBRARY 1) 170 set(Threads_FOUND TRUE) 171 else() 172 # Check for -pthread first if enabled. This is the recommended 173 # way, but not backwards compatible as one must also pass -pthread 174 # as compiler flag then. 175 if (THREADS_PREFER_PTHREAD_FLAG) 176 _check_pthreads_flag() 177 endif () 178 179 if(CMAKE_SYSTEM MATCHES "GHS-MULTI") 180 _check_threads_lib(posix pthread_create CMAKE_HAVE_PTHREADS_CREATE) 181 endif() 182 _check_threads_lib(pthreads pthread_create CMAKE_HAVE_PTHREADS_CREATE) 183 _check_threads_lib(pthread pthread_create CMAKE_HAVE_PTHREAD_CREATE) 184 if(CMAKE_SYSTEM_NAME MATCHES "SunOS") 185 # On sun also check for -lthread 186 _check_threads_lib(thread thr_create CMAKE_HAVE_THR_CREATE) 187 endif() 188 endif() 189 endif() 190 191 _check_pthreads_flag() 192endif() 193 194if(CMAKE_THREAD_LIBS_INIT OR CMAKE_HAVE_LIBC_PTHREAD) 195 set(CMAKE_USE_PTHREADS_INIT 1) 196 set(Threads_FOUND TRUE) 197endif() 198 199if(CMAKE_SYSTEM_NAME MATCHES "Windows") 200 set(CMAKE_USE_WIN32_THREADS_INIT 1) 201 set(Threads_FOUND TRUE) 202endif() 203 204if(CMAKE_USE_PTHREADS_INIT) 205 if(CMAKE_SYSTEM_NAME MATCHES "HP-UX") 206 # Use libcma if it exists and can be used. It provides more 207 # symbols than the plain pthread library. CMA threads 208 # have actually been deprecated: 209 # http://docs.hp.com/en/B3920-90091/ch12s03.html#d0e11395 210 # http://docs.hp.com/en/947/d8.html 211 # but we need to maintain compatibility here. 212 # The CMAKE_HP_PTHREADS setting actually indicates whether CMA threads 213 # are available. 214 CHECK_LIBRARY_EXISTS(cma pthread_attr_create "" CMAKE_HAVE_HP_CMA) 215 if(CMAKE_HAVE_HP_CMA) 216 set(CMAKE_THREAD_LIBS_INIT "-lcma") 217 set(CMAKE_HP_PTHREADS_INIT 1) 218 set(Threads_FOUND TRUE) 219 endif() 220 set(CMAKE_USE_PTHREADS_INIT 1) 221 endif() 222 223 if(CMAKE_SYSTEM MATCHES "OSF1-V") 224 set(CMAKE_USE_PTHREADS_INIT 0) 225 set(CMAKE_THREAD_LIBS_INIT ) 226 endif() 227 228 if(CMAKE_SYSTEM MATCHES "CYGWIN_NT" OR CMAKE_SYSTEM MATCHES "MSYS_NT") 229 set(CMAKE_USE_PTHREADS_INIT 1) 230 set(Threads_FOUND TRUE) 231 set(CMAKE_THREAD_LIBS_INIT ) 232 set(CMAKE_USE_WIN32_THREADS_INIT 0) 233 endif() 234endif() 235 236set(CMAKE_REQUIRED_QUIET ${CMAKE_REQUIRED_QUIET_SAVE}) 237include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) 238FIND_PACKAGE_HANDLE_STANDARD_ARGS(Threads DEFAULT_MSG Threads_FOUND) 239 240if(THREADS_FOUND AND NOT TARGET Threads::Threads) 241 add_library(Threads::Threads INTERFACE IMPORTED) 242 243 if(THREADS_HAVE_PTHREAD_ARG) 244 set_property(TARGET Threads::Threads 245 PROPERTY INTERFACE_COMPILE_OPTIONS "$<$<COMPILE_LANG_AND_ID:CUDA,NVIDIA>:SHELL:-Xcompiler -pthread>" 246 "$<$<NOT:$<COMPILE_LANG_AND_ID:CUDA,NVIDIA>>:-pthread>") 247 endif() 248 249 if(CMAKE_THREAD_LIBS_INIT) 250 set_property(TARGET Threads::Threads PROPERTY INTERFACE_LINK_LIBRARIES "${CMAKE_THREAD_LIBS_INIT}") 251 endif() 252elseif(NOT THREADS_FOUND AND _cmake_find_threads_output) 253 file(APPEND 254 ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log 255 "Determining if compiler accepts -pthread failed with the following output:\n${_cmake_find_threads_output}\n\n") 256endif() 257 258unset(_cmake_find_threads_output) 259