@@ -5,6 +5,9 @@ load("@bazel_lib//lib:resource_sets.bzl", "resource_set_for")
55load ("@bazel_skylib//rules:common_settings.bzl" , "BuildSettingInfo" , "int_flag" , "string_flag" )
66load ("@rules_shell//shell:sh_binary.bzl" , "sh_binary" )
77
8+ _PARALLELISM_OVERCOMMIT_DEFAULT = 2
9+ _PARALLELISM_OVERCOMMIT_SETTING = "parallelism_overcommit"
10+
811_DEFAULT_SIZE = "default"
912_SIZES = {
1013 "enormous" : {
@@ -56,11 +59,20 @@ def _setting(size, resource, mode):
5659def create_settings ():
5760 """create the settings that configure these functions."""
5861 settings = {
59- "size_default" : {
62+ _PARALLELISM_OVERCOMMIT_SETTING : {
6063 "sort_key" : (0 , 0 , 0 , "" ),
64+ "value" : _PARALLELISM_OVERCOMMIT_DEFAULT ,
65+ },
66+ "size_default" : {
67+ "sort_key" : (0 , 0 , 1 , "" ),
6168 "value" : _DEFAULT_SIZE ,
6269 },
6370 }
71+ int_flag (
72+ name = _PARALLELISM_OVERCOMMIT_SETTING ,
73+ build_setting_default = _PARALLELISM_OVERCOMMIT_DEFAULT ,
74+ visibility = ["//visibility:public" ],
75+ )
6476 string_flag (
6577 name = "size_default" ,
6678 build_setting_default = _DEFAULT_SIZE ,
@@ -123,23 +135,32 @@ SIZE_ATTRIBUTES = {
123135 default = _DEFAULT_SIZE ,
124136 mandatory = False ,
125137 doc = """\
126- Set the approximate size of this build. This does two things:
127- 1. Sets the environment variables to tell the underlying build system the
128- requested parallelization; examples are CMAKE_BUILD_PARALLEL_LEVEL for cmake
129- or MAKEFLAGS for autotools.
130- 2. Sets the resource_set attribute on the action to tell bazel how many cores
131- are being used, so it schedules appropriately.
132-
133- The sizes map to labels, which can be used to override the meaning of the
134- sizes. See @rules_foreign_cc//foreign_cc/settings:size_{size}_{cpu|mem}.
135- Running `bazel run @rules_foreign_cc//foreign_cc/settings` will print out all
136- the settings in bazelrc format for easy customization.
137-
138- The `serial` size is special: it sets cpu=1, and provides no override for cpu
139- (just mem), so `serial` can be used for packages that are known-broken for
140- parallelization.
138+ Set the approximate size of this build, which controls two things:
139+
140+ 1. The Bazel scheduler reservation, so large builds don't all run at once.
141+ 2. The parallelism passed to the underlying build system via environment
142+ variables (CMAKE_BUILD_PARALLEL_LEVEL, GNUMAKEFLAGS, NINJA_JOBS, etc.).
143+
144+ Build tool parallelism is set to the scheduler reservation plus a small
145+ overcommit (default +2, matching ninja's ncpus+2 convention). This hides
146+ I/O latency and lets configure_make targets — whose configure phase is
147+ always serial — make better use of their allocation during the parallel
148+ make phase. The overcommit can be tuned with
149+ @rules_foreign_cc//foreign_cc/settings:parallelism_overcommit.
150+
151+ Each size maps to a cpu and mem value that can be overridden per-size.
152+ See @rules_foreign_cc//foreign_cc/settings:size_{size}_{cpu|mem}, or run
153+ `bazel run @rules_foreign_cc//foreign_cc/settings` to print all settings
154+ in bazelrc format.
155+
156+ The `serial` size is special: it fixes cpu=1 with no overcommit, for
157+ packages that are known-broken under parallel builds.
141158""" ,
142159 ),
160+ "_parallelism_overcommit" : attr .label (
161+ default = "//foreign_cc/settings:" + _PARALLELISM_OVERCOMMIT_SETTING ,
162+ providers = [BuildSettingInfo ],
163+ ),
143164} | {
144165 _setting (size = size , resource = resource , mode = "key" ): attr .label (
145166 default = _setting (size , resource , mode = "label" ),
@@ -170,10 +191,13 @@ def get_resource_set(attr):
170191 Args:
171192 attr: the ctx.attr associated with the target
172193 Returns:
173- A tuple of:
174- - the resource_set, or None if it's the bazel default
175- - cpu_cores, or 0 if it's the bazel default
176- - mem in MB, or 0 if it's the bazel default
194+ A struct with:
195+ - resource_set: the resource_set callback, or None if bazel default
196+ - cpu: cpu_cores, or 0 if bazel default
197+ - mem: mem in MB, or 0 if bazel default
198+ - allow_cpu_overcommit: True if the build tool may use more
199+ parallelism than the scheduler reservation (False for sizes
200+ like "serial" that must enforce an exact -j value)
177201 """
178202 size = _DEFAULT_SIZE
179203 if attr .resource_size != _DEFAULT_SIZE :
@@ -182,7 +206,12 @@ def get_resource_set(attr):
182206 size = _get_size_config (attr , _DEFAULT_SIZE , None )
183207
184208 if size == _DEFAULT_SIZE :
185- return None , 0 , 0
209+ return struct (
210+ resource_set = None ,
211+ cpu = 0 ,
212+ mem = 0 ,
213+ allow_cpu_overcommit = False ,
214+ )
186215
187216 cfg = _SIZES [size ]
188217 cpu_value = cfg ["cpu" ] if _is_fixed (cfg , "cpu" ) else _get_size_config (attr , size , "cpu" )
@@ -207,7 +236,12 @@ def get_resource_set(attr):
207236 actual_cpu = 0
208237 actual_mem = 0
209238
210- return resource_set , actual_cpu , actual_mem
239+ return struct (
240+ resource_set = resource_set ,
241+ cpu = actual_cpu ,
242+ mem = actual_mem ,
243+ allow_cpu_overcommit = not _is_fixed (cfg , "cpu" ),
244+ )
211245
212246def get_resource_env_vars (attr ):
213247 """ get the values of env vars controlling parallelism
@@ -225,28 +259,29 @@ def get_resource_env_vars(attr):
225259 dict[str, str] to pass to run/run_shell
226260 """
227261
228- resource_set , cpu , _mem = get_resource_set (attr )
262+ resources = get_resource_set (attr )
229263
230264 env = None
231- if cpu > 0 :
232- sc = str (cpu )
265+ if resources .cpu > 0 :
266+ overcommit = attr ._parallelism_overcommit [BuildSettingInfo ].value if resources .allow_cpu_overcommit else 0
267+ parallelism = str (resources .cpu + overcommit )
233268 env = {
234- "CMAKE_BUILD_PARALLEL_LEVEL" : sc ,
269+ "CMAKE_BUILD_PARALLEL_LEVEL" : parallelism ,
235270
236271 # we set GNUMAKEFLAGS instead of MAKEFLAGS because nmake sees
237272 # MAKEFLAGS but doesn't accept a -j argument, and we don't have a
238273 # good way of being sure that nmake isn't going to be used as part
239274 # of a build.
240- "GNUMAKEFLAGS" : "-j" + sc ,
275+ "GNUMAKEFLAGS" : "-j" + parallelism ,
241276
242277 # Meson starts to honor this as of 1.7.0; before that, it only uses
243278 # ninja's parallelization controls.
244- "MESON_NUM_PROCESSES" : sc ,
279+ "MESON_NUM_PROCESSES" : parallelism ,
245280
246281 # Note that ninja does not honor this by default; it's our wrapper
247282 # script that handles this.
248283 # https://github.com/ninja-build/ninja/issues/1482
249- "NINJA_JOBS" : sc ,
284+ "NINJA_JOBS" : parallelism ,
250285 }
251286
252- return resource_set , env
287+ return resources . resource_set , env
0 commit comments