From 9da070a192e24186bd6852e17b8fcec7d55ffe67 Mon Sep 17 00:00:00 2001 From: Jack Luo Date: Mon, 29 Jun 2026 17:51:09 -0700 Subject: [PATCH 1/7] fix(cmake): Only pass --parallel when JOBS is set, matching boost. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `cmake:build` always emitted `--parallel "{{.JOBS}}"`, so an empty/unset `JOBS` rendered `cmake --build --parallel ""`, which cmake turns into bare `gmake -f Makefile -j` — GNU make's bare `-j` means *unlimited* parallelism (no cap on concurrent jobs). For a large dependency this can spawn hundreds of compiler processes and risk OOM. This made the documented behavior ("If omitted, the native build tool's default number is used") untrue. `boost.yaml` already guards its `-j` with `{{- if .JOBS}}`; apply the same conditional to `cmake:build` so an empty `JOBS` omits `--parallel` entirely and the native build tool's default applies. `install-remote-tar` delegates to `build`, so it is covered too. Consumers that pass a `JOBS` value are unaffected. --- exports/taskfiles/utils/cmake.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/exports/taskfiles/utils/cmake.yaml b/exports/taskfiles/utils/cmake.yaml index f14699c..77f8c87 100644 --- a/exports/taskfiles/utils/cmake.yaml +++ b/exports/taskfiles/utils/cmake.yaml @@ -33,7 +33,9 @@ tasks: - >- cmake --build "{{.BUILD_DIR}}" + {{- if .JOBS}} --parallel "{{.JOBS}}" + {{- end}} {{- range .TARGETS}} --target="{{.}}" {{- end}} From 88d0d968004850681b8d2d22bbf70a84a422d1bd Mon Sep 17 00:00:00 2001 From: Jack Luo Date: Mon, 29 Jun 2026 18:11:49 -0700 Subject: [PATCH 2/7] fix(cmake): Bound build parallelism to the CPU count when JOBS is unset. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `cmake:build` always emitted `--parallel "{{.JOBS}}"` with `JOBS` defaulting to the empty string, so an unset `JOBS` rendered `cmake --build --parallel ""`. cmake turns that into bare `gmake -f Makefile -j`, i.e. unbounded parallelism — a single build could spawn far more compiler processes than there are cores, oversubscribing the machine and risking OOM on large dependencies. Bound the default to the number of logical CPUs (`nproc`/`sysctl`, falling back to `1`), so `--parallel` always receives a finite, right-sized value and a single build no longer oversubscribes. Callers can still override via `JOBS` (or `CMAKE_JOBS`, which flows through `install-remote-tar` -> `build`). This matches `boost:build-and-install` (b2 defaults to the core count for boost >= 1.76.0). Cross-build scheduling — running several `cmake:build` invocations concurrently — remains the caller's responsibility; set `JOBS` lower to avoid oversubscribing across builds. Cross-platform: `nproc` (Linux) -> `sysctl -n hw.logicalcpu` (macOS) -> `echo 1`. --- exports/taskfiles/utils/cmake.yaml | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/exports/taskfiles/utils/cmake.yaml b/exports/taskfiles/utils/cmake.yaml index 77f8c87..17157d5 100644 --- a/exports/taskfiles/utils/cmake.yaml +++ b/exports/taskfiles/utils/cmake.yaml @@ -15,7 +15,8 @@ tasks: # @param {string} BUILD_DIR Directory containing the generated build system to use. # @param {string[]} [EXTRA_ARGS] Any additional arguments to pass to the build command. # @param {int} [JOBS] The maximum number of concurrent processes to use when building. If - # omitted, the native build tool's default number is used. See `man cmake`. + # omitted, defaults to the number of logical CPUs (via `nproc`/`sysctl`), matching the + # `boost:build-and-install` default. # @param {string[]} [TARGETS] A list of specific targets to build instead of the default target. build: internal: true @@ -23,8 +24,13 @@ tasks: vars: EXTRA_ARGS: ref: "default (list) .EXTRA_ARGS" + # Number of logical CPUs, used as the default for `JOBS` when the caller doesn't set it. + # Portable across Linux (`nproc`) and macOS (`sysctl`). + _CPU_COUNT: + sh: |- + nproc 2>/dev/null || sysctl -n hw.logicalcpu 2>/dev/null || echo 1 JOBS: >- - {{default "" .JOBS}} + {{default ._CPU_COUNT .JOBS}} TARGETS: ref: "default (list) .TARGETS" requires: @@ -33,9 +39,7 @@ tasks: - >- cmake --build "{{.BUILD_DIR}}" - {{- if .JOBS}} --parallel "{{.JOBS}}" - {{- end}} {{- range .TARGETS}} --target="{{.}}" {{- end}} @@ -156,7 +160,7 @@ tasks: # @param {string[]} [CMAKE_INSTALL_ARGS] Any additional arguments to pass to the CMake install # command. # @param {int} [CMAKE_JOBS] The maximum number of concurrent processes to use when building. If - # omitted, the native build tool's default number is used. See `man cmake`. + # omitted, defaults to the number of logical CPUs (see `build`'s `JOBS`). # @param {string} [CMAKE_SETTINGS_DIR] The directory where the project's CMake settings file # should be stored. # @param {string} [CMAKE_SOURCE_DIR=.] The path, within the extraction directory, containing the From 411fd330a848e454ce2b4e447649b7ccebc9f603 Mon Sep 17 00:00:00 2001 From: Jack Luo Date: Mon, 29 Jun 2026 19:03:27 -0700 Subject: [PATCH 3/7] docs(cmake): Drop fragile boost cross-ref from JOBS param doc. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `JOBS` doc said the nproc default "matches the `boost:build-and-install` default", but that coupling is only conditionally true (b2 defaults to the core count for boost >= 1.76.0, via a different mechanism — omitting `-j` vs passing `--parallel`), and it makes `cmake.yaml`'s param doc depend on another module's behaviour. Drop the cross-reference so the comment is self-contained. --- exports/taskfiles/utils/cmake.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/exports/taskfiles/utils/cmake.yaml b/exports/taskfiles/utils/cmake.yaml index 17157d5..0a2bb00 100644 --- a/exports/taskfiles/utils/cmake.yaml +++ b/exports/taskfiles/utils/cmake.yaml @@ -15,8 +15,7 @@ tasks: # @param {string} BUILD_DIR Directory containing the generated build system to use. # @param {string[]} [EXTRA_ARGS] Any additional arguments to pass to the build command. # @param {int} [JOBS] The maximum number of concurrent processes to use when building. If - # omitted, defaults to the number of logical CPUs (via `nproc`/`sysctl`), matching the - # `boost:build-and-install` default. + # omitted, defaults to the number of logical CPUs (via `nproc`/`sysctl`). # @param {string[]} [TARGETS] A list of specific targets to build instead of the default target. build: internal: true From 32f8c2231223ce98400a326c449ebba5d6c08923 Mon Sep 17 00:00:00 2001 From: Jack Luo Date: Mon, 29 Jun 2026 22:13:39 -0700 Subject: [PATCH 4/7] Update exports/taskfiles/utils/cmake.yaml Co-authored-by: Bingran Hu --- exports/taskfiles/utils/cmake.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/exports/taskfiles/utils/cmake.yaml b/exports/taskfiles/utils/cmake.yaml index 0a2bb00..f6c1f47 100644 --- a/exports/taskfiles/utils/cmake.yaml +++ b/exports/taskfiles/utils/cmake.yaml @@ -159,7 +159,8 @@ tasks: # @param {string[]} [CMAKE_INSTALL_ARGS] Any additional arguments to pass to the CMake install # command. # @param {int} [CMAKE_JOBS] The maximum number of concurrent processes to use when building. If - # omitted, defaults to the number of logical CPUs (see `build`'s `JOBS`). + # omitted, defaults to the number of logical CPUs reported by the system. Falls back to 1 for a + # serial build if the CPU count cannot be determined. # @param {string} [CMAKE_SETTINGS_DIR] The directory where the project's CMake settings file # should be stored. # @param {string} [CMAKE_SOURCE_DIR=.] The path, within the extraction directory, containing the From b262b05dcf366dd005a184922c809813f0812857 Mon Sep 17 00:00:00 2001 From: Jack Luo Date: Mon, 29 Jun 2026 22:13:44 -0700 Subject: [PATCH 5/7] Update exports/taskfiles/utils/cmake.yaml Co-authored-by: Bingran Hu --- exports/taskfiles/utils/cmake.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/exports/taskfiles/utils/cmake.yaml b/exports/taskfiles/utils/cmake.yaml index f6c1f47..15c370d 100644 --- a/exports/taskfiles/utils/cmake.yaml +++ b/exports/taskfiles/utils/cmake.yaml @@ -27,7 +27,10 @@ tasks: # Portable across Linux (`nproc`) and macOS (`sysctl`). _CPU_COUNT: sh: |- - nproc 2>/dev/null || sysctl -n hw.logicalcpu 2>/dev/null || echo 1 + nproc 2>/dev/null \ + || getconf _NPROCESSORS_ONLN 2>/dev/null \ + || sysctl -n hw.logicalcpu 2>/dev/null \ + || echo 1 JOBS: >- {{default ._CPU_COUNT .JOBS}} TARGETS: From 8f1ac92f5e337b5b1b44c37334d3c648ffc1f461 Mon Sep 17 00:00:00 2001 From: Jack Luo Date: Mon, 29 Jun 2026 22:13:56 -0700 Subject: [PATCH 6/7] Update exports/taskfiles/utils/cmake.yaml Co-authored-by: Bingran Hu --- exports/taskfiles/utils/cmake.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/exports/taskfiles/utils/cmake.yaml b/exports/taskfiles/utils/cmake.yaml index 15c370d..1a84829 100644 --- a/exports/taskfiles/utils/cmake.yaml +++ b/exports/taskfiles/utils/cmake.yaml @@ -15,7 +15,8 @@ tasks: # @param {string} BUILD_DIR Directory containing the generated build system to use. # @param {string[]} [EXTRA_ARGS] Any additional arguments to pass to the build command. # @param {int} [JOBS] The maximum number of concurrent processes to use when building. If - # omitted, defaults to the number of logical CPUs (via `nproc`/`sysctl`). + # omitted, defaults to the number of logical CPUs reported by the system. Falls back to 1 for a + # serial build if the CPU count cannot be determined. # @param {string[]} [TARGETS] A list of specific targets to build instead of the default target. build: internal: true From 103e7a954357961e7dda5adbb609c89433e97b11 Mon Sep 17 00:00:00 2001 From: Bingran Hu Date: Tue, 30 Jun 2026 01:17:28 -0400 Subject: [PATCH 7/7] Update exports/taskfiles/utils/cmake.yaml --- exports/taskfiles/utils/cmake.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exports/taskfiles/utils/cmake.yaml b/exports/taskfiles/utils/cmake.yaml index 1a84829..0b59009 100644 --- a/exports/taskfiles/utils/cmake.yaml +++ b/exports/taskfiles/utils/cmake.yaml @@ -25,7 +25,7 @@ tasks: EXTRA_ARGS: ref: "default (list) .EXTRA_ARGS" # Number of logical CPUs, used as the default for `JOBS` when the caller doesn't set it. - # Portable across Linux (`nproc`) and macOS (`sysctl`). + # Portable across Linux (`nproc`), POSIX (`getconf`), and macOS (`sysctl`). _CPU_COUNT: sh: |- nproc 2>/dev/null \