@@ -249,6 +249,51 @@ export_clang_cross_env() {
249249 fi
250250}
251251
252+ set_windows_make_jobs () {
253+ local detected_jobs=" "
254+
255+ # Respect an explicit caller choice. This lets developers and CI lower the
256+ # job count for constrained systems or raise it after validating a specific
257+ # Windows toolchain. A bare "-j" remains the caller's responsibility because
258+ # GNU Make interprets it as an unlimited job count, not as "one job per CPU".
259+ if [ -n " ${MAKE_JOBS:- } " ]; then
260+ log_info " Respecting pre-set Windows build parallelism: MAKE_JOBS=$MAKE_JOBS "
261+ export MAKE_JOBS
262+ return 0
263+ fi
264+
265+ # Native Windows exposes the logical processor count through this variable,
266+ # and both Git Bash/MSYS and Cygwin normally inherit it. Prefer it because it
267+ # does not depend on an additional Unix utility being installed.
268+ if [ -n " ${NUMBER_OF_PROCESSORS:- } " ]; then
269+ detected_jobs=" $NUMBER_OF_PROCESSORS "
270+ log_info " Detected Windows logical processor count from NUMBER_OF_PROCESSORS: $detected_jobs "
271+ elif command -v nproc > /dev/null 2>&1 ; then
272+ # nproc is the usual fallback in Unix-like Windows environments.
273+ detected_jobs=$( nproc 2> /dev/null || true)
274+ log_info " Detected Windows logical processor count from nproc: ${detected_jobs:- unavailable} "
275+ elif command -v getconf > /dev/null 2>&1 ; then
276+ # getconf is more widely standardized, but it is not present in every
277+ # minimal Git Bash installation.
278+ detected_jobs=$( getconf _NPROCESSORS_ONLN 2> /dev/null || true)
279+ log_info " Detected Windows logical processor count from getconf: ${detected_jobs:- unavailable} "
280+ fi
281+
282+ # Accept only a positive decimal integer. If detection is unavailable or
283+ # malformed, use two jobs: this preserves some parallelism without restoring
284+ # the unbounded process burst that caused ARM GCC to crash on Windows.
285+ case " $detected_jobs " in
286+ " " | * [!0-9]* | 0)
287+ detected_jobs=2
288+ log_warn " Could not determine a valid Windows processor count; defaulting to $detected_jobs make jobs."
289+ ;;
290+ esac
291+
292+ MAKE_JOBS=" -j$detected_jobs "
293+ export MAKE_JOBS
294+ log_info " Using bounded Windows build parallelism: MAKE_JOBS=$MAKE_JOBS "
295+ }
296+
252297# ##############################################################################
253298# OS-specific configuration
254299#
@@ -303,25 +348,24 @@ elif [[ "$OSTYPE" == "darwin"* ]]; then
303348elif [[ " $OSTYPE " == " cygwin" ]]; then
304349 log_info " Detected platform: Cygwin on Windows (OSTYPE=$OSTYPE )"
305350
306- # Under Cygwin, aggressive parallel builds (-j) are known to cause blocking
307- # or instability on some setups. We therefore disable it by default .
308- export MAKE_JOBS= " -j "
351+ # Limit make to the detected logical processor count. GNU Make's bare "-j"
352+ # would otherwise permit an unlimited number of concurrent compiler jobs .
353+ set_windows_make_jobs
309354 export_clang_cross_env 0
310355
311356elif [[ " $OSTYPE " == " msys" * ]]; then
312357 log_info " Detected platform: MSYS / MinGW on Windows (OSTYPE=$OSTYPE )"
313358
314- # Same reasoning as for Cygwin: parallel make can be problematic; keep it off
315- # by default to avoid hard-to-debug hangs .
316- export MAKE_JOBS= " -j "
359+ # Git Bash normally reaches this branch. Use all detected logical processors
360+ # while keeping the number of concurrent compiler processes bounded .
361+ set_windows_make_jobs
317362 export_clang_cross_env 0
318363
319364elif [[ " $OSTYPE " == " win32" ]]; then
320365 # This branch is rarely seen with modern bash installations. It is kept
321366 # only as a diagnostic in case OSTYPE is literally "win32".
322367 log_info " Detected platform: Windows (OSTYPE=$OSTYPE )"
323- log_info " No default configuration implemented for plain win32."
324- export MAKE_JOBS=" -j"
368+ set_windows_make_jobs
325369 export_clang_cross_env 0
326370
327371elif [[ " $OSTYPE " == " freebsd" * ]]; then
0 commit comments