ProcessorCount.cmake 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. # Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. # file Copyright.txt or https://cmake.org/licensing for details.
  3. #.rst:
  4. # ProcessorCount
  5. # --------------
  6. #
  7. # ProcessorCount(var)
  8. #
  9. # Determine the number of processors/cores and save value in ${var}
  10. #
  11. # Sets the variable named ${var} to the number of physical cores
  12. # available on the machine if the information can be determined.
  13. # Otherwise it is set to 0. Currently this functionality is implemented
  14. # for AIX, cygwin, FreeBSD, HPUX, IRIX, Linux, Mac OS X, QNX, Sun and
  15. # Windows.
  16. #
  17. # This function is guaranteed to return a positive integer (>=1) if it
  18. # succeeds. It returns 0 if there's a problem determining the processor
  19. # count.
  20. #
  21. # Example use, in a ctest -S dashboard script:
  22. #
  23. # ::
  24. #
  25. # include(ProcessorCount)
  26. # ProcessorCount(N)
  27. # if(NOT N EQUAL 0)
  28. # set(CTEST_BUILD_FLAGS -j${N})
  29. # set(ctest_test_args ${ctest_test_args} PARALLEL_LEVEL ${N})
  30. # endif()
  31. #
  32. #
  33. #
  34. # This function is intended to offer an approximation of the value of
  35. # the number of compute cores available on the current machine, such
  36. # that you may use that value for parallel building and parallel
  37. # testing. It is meant to help utilize as much of the machine as seems
  38. # reasonable. Of course, knowledge of what else might be running on the
  39. # machine simultaneously should be used when deciding whether to request
  40. # a machine's full capacity all for yourself.
  41. # A more reliable way might be to compile a small C program that uses the CPUID
  42. # instruction, but that again requires compiler support or compiling assembler
  43. # code.
  44. function(ProcessorCount var)
  45. # Unknown:
  46. set(count 0)
  47. if(WIN32)
  48. # Windows:
  49. set(count "$ENV{NUMBER_OF_PROCESSORS}")
  50. #message("ProcessorCount: WIN32, trying environment variable")
  51. endif()
  52. if(NOT count)
  53. # Mac, FreeBSD, OpenBSD (systems with sysctl):
  54. find_program(ProcessorCount_cmd_sysctl sysctl
  55. PATHS /usr/sbin /sbin)
  56. mark_as_advanced(ProcessorCount_cmd_sysctl)
  57. if(ProcessorCount_cmd_sysctl)
  58. execute_process(COMMAND ${ProcessorCount_cmd_sysctl} -n hw.ncpu
  59. ERROR_QUIET
  60. OUTPUT_STRIP_TRAILING_WHITESPACE
  61. OUTPUT_VARIABLE count)
  62. #message("ProcessorCount: trying sysctl '${ProcessorCount_cmd_sysctl}'")
  63. endif()
  64. endif()
  65. if(NOT count)
  66. # Linux (systems with getconf):
  67. find_program(ProcessorCount_cmd_getconf getconf)
  68. mark_as_advanced(ProcessorCount_cmd_getconf)
  69. if(ProcessorCount_cmd_getconf)
  70. execute_process(COMMAND ${ProcessorCount_cmd_getconf} _NPROCESSORS_ONLN
  71. ERROR_QUIET
  72. OUTPUT_STRIP_TRAILING_WHITESPACE
  73. OUTPUT_VARIABLE count)
  74. #message("ProcessorCount: trying getconf '${ProcessorCount_cmd_getconf}'")
  75. endif()
  76. endif()
  77. if(NOT count)
  78. # HPUX (systems with machinfo):
  79. find_program(ProcessorCount_cmd_machinfo machinfo
  80. PATHS /usr/contrib/bin)
  81. mark_as_advanced(ProcessorCount_cmd_machinfo)
  82. if(ProcessorCount_cmd_machinfo)
  83. execute_process(COMMAND ${ProcessorCount_cmd_machinfo}
  84. ERROR_QUIET
  85. OUTPUT_STRIP_TRAILING_WHITESPACE
  86. OUTPUT_VARIABLE machinfo_output)
  87. string(REGEX MATCHALL "Number of CPUs = ([0-9]+)" procs "${machinfo_output}")
  88. set(count "${CMAKE_MATCH_1}")
  89. if(NOT count)
  90. string(REGEX MATCHALL "([0-9]+) logical processors" procs "${machinfo_output}")
  91. set(count "${CMAKE_MATCH_1}")
  92. endif()
  93. #message("ProcessorCount: trying machinfo '${ProcessorCount_cmd_machinfo}'")
  94. else()
  95. find_program(ProcessorCount_cmd_mpsched mpsched)
  96. mark_as_advanced(ProcessorCount_cmd_mpsched)
  97. if(ProcessorCount_cmd_mpsched)
  98. execute_process(COMMAND ${ProcessorCount_cmd_mpsched} -s
  99. OUTPUT_QUIET
  100. ERROR_STRIP_TRAILING_WHITESPACE
  101. ERROR_VARIABLE mpsched_output)
  102. string(REGEX MATCHALL "Processor Count *: *([0-9]+)" procs "${mpsched_output}")
  103. set(count "${CMAKE_MATCH_1}")
  104. #message("ProcessorCount: trying mpsched -s '${ProcessorCount_cmd_mpsched}'")
  105. endif()
  106. endif()
  107. endif()
  108. if(NOT count)
  109. # IRIX (systems with hinv):
  110. find_program(ProcessorCount_cmd_hinv hinv
  111. PATHS /sbin)
  112. mark_as_advanced(ProcessorCount_cmd_hinv)
  113. if(ProcessorCount_cmd_hinv)
  114. execute_process(COMMAND ${ProcessorCount_cmd_hinv}
  115. ERROR_QUIET
  116. OUTPUT_STRIP_TRAILING_WHITESPACE
  117. OUTPUT_VARIABLE hinv_output)
  118. string(REGEX MATCHALL "([0-9]+) .* Processors" procs "${hinv_output}")
  119. set(count "${CMAKE_MATCH_1}")
  120. #message("ProcessorCount: trying hinv '${ProcessorCount_cmd_hinv}'")
  121. endif()
  122. endif()
  123. if(NOT count)
  124. # AIX (systems with lsconf):
  125. find_program(ProcessorCount_cmd_lsconf lsconf
  126. PATHS /usr/sbin)
  127. mark_as_advanced(ProcessorCount_cmd_lsconf)
  128. if(ProcessorCount_cmd_lsconf)
  129. execute_process(COMMAND ${ProcessorCount_cmd_lsconf}
  130. ERROR_QUIET
  131. OUTPUT_STRIP_TRAILING_WHITESPACE
  132. OUTPUT_VARIABLE lsconf_output)
  133. string(REGEX MATCHALL "Number Of Processors: ([0-9]+)" procs "${lsconf_output}")
  134. set(count "${CMAKE_MATCH_1}")
  135. #message("ProcessorCount: trying lsconf '${ProcessorCount_cmd_lsconf}'")
  136. endif()
  137. endif()
  138. if(NOT count)
  139. # QNX (systems with pidin):
  140. find_program(ProcessorCount_cmd_pidin pidin)
  141. mark_as_advanced(ProcessorCount_cmd_pidin)
  142. if(ProcessorCount_cmd_pidin)
  143. execute_process(COMMAND ${ProcessorCount_cmd_pidin} info
  144. ERROR_QUIET
  145. OUTPUT_STRIP_TRAILING_WHITESPACE
  146. OUTPUT_VARIABLE pidin_output)
  147. string(REGEX MATCHALL "Processor[0-9]+: " procs "${pidin_output}")
  148. list(LENGTH procs count)
  149. #message("ProcessorCount: trying pidin '${ProcessorCount_cmd_pidin}'")
  150. endif()
  151. endif()
  152. if(NOT count)
  153. # Sun (systems where psrinfo tool is available)
  154. find_program(ProcessorCount_cmd_psrinfo psrinfo PATHS /usr/sbin /sbin)
  155. mark_as_advanced(ProcessorCount_cmd_psrinfo)
  156. if (ProcessorCount_cmd_psrinfo)
  157. execute_process(COMMAND ${ProcessorCount_cmd_psrinfo} -p -v
  158. ERROR_QUIET
  159. OUTPUT_STRIP_TRAILING_WHITESPACE
  160. OUTPUT_VARIABLE psrinfo_output)
  161. string(REGEX MATCH "([0-9]+) virtual processor" procs "${psrinfo_output}")
  162. set(count "${CMAKE_MATCH_1}")
  163. #message("ProcessorCount: trying psrinfo -p -v '${ProcessorCount_cmd_prvinfo}'")
  164. else()
  165. # Sun (systems where uname -X emits "NumCPU" in its output):
  166. find_program(ProcessorCount_cmd_uname uname)
  167. mark_as_advanced(ProcessorCount_cmd_uname)
  168. if(ProcessorCount_cmd_uname)
  169. execute_process(COMMAND ${ProcessorCount_cmd_uname} -X
  170. ERROR_QUIET
  171. OUTPUT_STRIP_TRAILING_WHITESPACE
  172. OUTPUT_VARIABLE uname_X_output)
  173. string(REGEX MATCHALL "NumCPU = ([0-9]+)" procs "${uname_X_output}")
  174. set(count "${CMAKE_MATCH_1}")
  175. #message("ProcessorCount: trying uname -X '${ProcessorCount_cmd_uname}'")
  176. endif()
  177. endif()
  178. endif()
  179. # Execute this code when all previously attempted methods return empty
  180. # output:
  181. #
  182. if(NOT count)
  183. # Systems with /proc/cpuinfo:
  184. set(cpuinfo_file /proc/cpuinfo)
  185. if(EXISTS "${cpuinfo_file}")
  186. file(STRINGS "${cpuinfo_file}" procs REGEX "^processor.: [0-9]+$")
  187. list(LENGTH procs count)
  188. #message("ProcessorCount: trying cpuinfo '${cpuinfo_file}'")
  189. endif()
  190. endif()
  191. if(NOT count)
  192. # Haiku
  193. find_program(ProcessorCount_cmd_sysinfo sysinfo)
  194. if(ProcessorCount_cmd_sysinfo)
  195. execute_process(COMMAND ${ProcessorCount_cmd_sysinfo}
  196. ERROR_QUIET
  197. OUTPUT_STRIP_TRAILING_WHITESPACE
  198. OUTPUT_VARIABLE sysinfo_X_output)
  199. string(REGEX MATCHALL "\nCPU #[0-9]+:" procs "\n${sysinfo_X_output}")
  200. list(LENGTH procs count)
  201. #message("ProcessorCount: trying sysinfo '${ProcessorCount_cmd_sysinfo}'")
  202. endif()
  203. endif()
  204. # Since cygwin builds of CMake do not define WIN32 anymore, but they still
  205. # run on Windows, and will still have this env var defined:
  206. #
  207. if(NOT count)
  208. set(count "$ENV{NUMBER_OF_PROCESSORS}")
  209. #message("ProcessorCount: last fallback, trying environment variable")
  210. endif()
  211. # Ensure an integer return (avoid inadvertently returning an empty string
  212. # or an error string)... If it's not a decimal integer, return 0:
  213. #
  214. if(NOT count MATCHES "^[0-9]+$")
  215. set(count 0)
  216. endif()
  217. set(${var} ${count} PARENT_SCOPE)
  218. endfunction()