ProcessorCount.cmake 7.8 KB

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