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