Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .bazelrc.common
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,7 @@ common:bazel-7.x --show_progress
common:bazel-8.x --incompatible_disable_autoloads_in_main_repo
# Remind people to set good test timeouts / sizes
common --test_verbose_timeout_warnings

# Resource size tuning (default: fits 8-core machine)
common --@rules_foreign_cc//foreign_cc/settings:size_enormous_cpu=4
common --@rules_foreign_cc//foreign_cc/settings:size_large_cpu=3
1 change: 1 addition & 0 deletions examples/third_party/curl/BUILD.curl.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ cmake(
"@platforms//os:windows": ["libcurl.lib"],
"//conditions:default": ["libcurl.a"],
}),
resource_size = "large",
toolchains = ["@rules_perl//:current_toolchain"],
visibility = ["//visibility:public"],
deps = [
Expand Down
1 change: 1 addition & 0 deletions examples/third_party/gn/BUILD.gn.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ ninja(
"cp -a out/gn $$INSTALLDIR/bin",
]),
}),
resource_size = "large",
targets = select({
"@platforms//os:windows": ["gn.exe"],
"//conditions:default": [""],
Expand Down
1 change: 1 addition & 0 deletions examples/third_party/log4cxx/BUILD.log4cxx.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ configure_make(
}),
lib_source = ":all_srcs",
out_static_libs = ["liblog4cxx.a"],
resource_size = "large",
target_compatible_with = select({
"@platforms//os:windows": ["@platforms//:incompatible"],
"//conditions:default": [],
Expand Down
2 changes: 2 additions & 0 deletions examples/third_party/openssl/BUILD.openssl.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ configure_make_variant(
"libssl-1_1-x64.dll",
"libcrypto-1_1-x64.dll",
],
resource_size = "enormous",
target_compatible_with = select({
"@platforms//os:windows": [],
"//conditions:default": ["@platforms//:incompatible"],
Expand Down Expand Up @@ -126,6 +127,7 @@ configure_make(
]),
"//conditions:default": "",
}),
resource_size = "enormous",
target_compatible_with = select({
"@platforms//os:windows": ["@platforms//:incompatible"],
"//conditions:default": [],
Expand Down
1 change: 1 addition & 0 deletions examples/third_party/python/BUILD.python3.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ configure_make(
"python3.10",
],
out_data_dirs = ["lib"],
resource_size = "enormous",
target_compatible_with = select({
"@platforms//os:windows": ["@platforms//:incompatible"],
"//conditions:default": [],
Expand Down
1 change: 1 addition & 0 deletions examples/third_party/subversion/BUILD.subversion.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ configure_make(
"svn",
"svnversion",
],
resource_size = "enormous",
target_compatible_with = select({
"@platforms//os:windows": ["@platforms//:incompatible"],
"//conditions:default": [],
Expand Down
95 changes: 65 additions & 30 deletions foreign_cc/private/resource_sets.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ load("@bazel_lib//lib:resource_sets.bzl", "resource_set_for")
load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo", "int_flag", "string_flag")
load("@rules_shell//shell:sh_binary.bzl", "sh_binary")

_PARALLELISM_OVERCOMMIT_DEFAULT = 2
_PARALLELISM_OVERCOMMIT_SETTING = "parallelism_overcommit"

_DEFAULT_SIZE = "default"
_SIZES = {
"enormous": {
Expand Down Expand Up @@ -56,11 +59,20 @@ def _setting(size, resource, mode):
def create_settings():
"""create the settings that configure these functions."""
settings = {
"size_default": {
_PARALLELISM_OVERCOMMIT_SETTING: {
"sort_key": (0, 0, 0, ""),
"value": _PARALLELISM_OVERCOMMIT_DEFAULT,
},
"size_default": {
"sort_key": (0, 0, 1, ""),
"value": _DEFAULT_SIZE,
},
}
int_flag(
name = _PARALLELISM_OVERCOMMIT_SETTING,
build_setting_default = _PARALLELISM_OVERCOMMIT_DEFAULT,
visibility = ["//visibility:public"],
)
string_flag(
name = "size_default",
build_setting_default = _DEFAULT_SIZE,
Expand Down Expand Up @@ -123,23 +135,32 @@ SIZE_ATTRIBUTES = {
default = _DEFAULT_SIZE,
mandatory = False,
doc = """\
Set the approximate size of this build. This does two things:
1. Sets the environment variables to tell the underlying build system the
requested parallelization; examples are CMAKE_BUILD_PARALLEL_LEVEL for cmake
or MAKEFLAGS for autotools.
2. Sets the resource_set attribute on the action to tell bazel how many cores
are being used, so it schedules appropriately.

The sizes map to labels, which can be used to override the meaning of the
sizes. See @rules_foreign_cc//foreign_cc/settings:size_{size}_{cpu|mem}.
Running `bazel run @rules_foreign_cc//foreign_cc/settings` will print out all
the settings in bazelrc format for easy customization.

The `serial` size is special: it sets cpu=1, and provides no override for cpu
(just mem), so `serial` can be used for packages that are known-broken for
parallelization.
Set the approximate size of this build, which controls two things:

1. The Bazel scheduler reservation, so large builds don't all run at once.
2. The parallelism passed to the underlying build system via environment
variables (CMAKE_BUILD_PARALLEL_LEVEL, GNUMAKEFLAGS, NINJA_JOBS, etc.).

Build tool parallelism is set to the scheduler reservation plus a small
overcommit (default +2, matching ninja's ncpus+2 convention). This hides
I/O latency and lets configure_make targets — whose configure phase is
always serial — make better use of their allocation during the parallel
make phase. The overcommit can be tuned with
@rules_foreign_cc//foreign_cc/settings:parallelism_overcommit.

Each size maps to a cpu and mem value that can be overridden per-size.
See @rules_foreign_cc//foreign_cc/settings:size_{size}_{cpu|mem}, or run
`bazel run @rules_foreign_cc//foreign_cc/settings` to print all settings
in bazelrc format.

The `serial` size is special: it fixes cpu=1 with no overcommit, for
packages that are known-broken under parallel builds.
""",
),
"_parallelism_overcommit": attr.label(
default = "//foreign_cc/settings:" + _PARALLELISM_OVERCOMMIT_SETTING,
providers = [BuildSettingInfo],
),
} | {
_setting(size = size, resource = resource, mode = "key"): attr.label(
default = _setting(size, resource, mode = "label"),
Expand Down Expand Up @@ -170,10 +191,13 @@ def get_resource_set(attr):
Args:
attr: the ctx.attr associated with the target
Returns:
A tuple of:
- the resource_set, or None if it's the bazel default
- cpu_cores, or 0 if it's the bazel default
- mem in MB, or 0 if it's the bazel default
A struct with:
- resource_set: the resource_set callback, or None if bazel default
- cpu: cpu_cores, or 0 if bazel default
- mem: mem in MB, or 0 if bazel default
- allow_cpu_overcommit: True if the build tool may use more
parallelism than the scheduler reservation (False for sizes
like "serial" that must enforce an exact -j value)
"""
size = _DEFAULT_SIZE
if attr.resource_size != _DEFAULT_SIZE:
Expand All @@ -182,7 +206,12 @@ def get_resource_set(attr):
size = _get_size_config(attr, _DEFAULT_SIZE, None)

if size == _DEFAULT_SIZE:
return None, 0, 0
return struct(
resource_set = None,
cpu = 0,
mem = 0,
allow_cpu_overcommit = False,
)

cfg = _SIZES[size]
cpu_value = cfg["cpu"] if _is_fixed(cfg, "cpu") else _get_size_config(attr, size, "cpu")
Expand All @@ -207,7 +236,12 @@ def get_resource_set(attr):
actual_cpu = 0
actual_mem = 0

return resource_set, actual_cpu, actual_mem
return struct(
resource_set = resource_set,
cpu = actual_cpu,
mem = actual_mem,
allow_cpu_overcommit = not _is_fixed(cfg, "cpu"),
)

def get_resource_env_vars(attr):
""" get the values of env vars controlling parallelism
Expand All @@ -225,28 +259,29 @@ def get_resource_env_vars(attr):
dict[str, str] to pass to run/run_shell
"""

resource_set, cpu, _mem = get_resource_set(attr)
resources = get_resource_set(attr)

env = None
if cpu > 0:
sc = str(cpu)
if resources.cpu > 0:
overcommit = attr._parallelism_overcommit[BuildSettingInfo].value if resources.allow_cpu_overcommit else 0
parallelism = str(resources.cpu + overcommit)
env = {
"CMAKE_BUILD_PARALLEL_LEVEL": sc,
"CMAKE_BUILD_PARALLEL_LEVEL": parallelism,

# we set GNUMAKEFLAGS instead of MAKEFLAGS because nmake sees
# MAKEFLAGS but doesn't accept a -j argument, and we don't have a
# good way of being sure that nmake isn't going to be used as part
# of a build.
"GNUMAKEFLAGS": "-j" + sc,
"GNUMAKEFLAGS": "-j" + parallelism,

# Meson starts to honor this as of 1.7.0; before that, it only uses
# ninja's parallelization controls.
"MESON_NUM_PROCESSES": sc,
"MESON_NUM_PROCESSES": parallelism,

# Note that ninja does not honor this by default; it's our wrapper
# script that handles this.
# https://github.com/ninja-build/ninja/issues/1482
"NINJA_JOBS": sc,
"NINJA_JOBS": parallelism,
}

return resource_set, env
return resources.resource_set, env
18 changes: 9 additions & 9 deletions test/env_test/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ env_test_make(
# Note that we set GNUMAKEFLAGS, but make itself will convert it into
# MAKEFLAGS, so we'll just see MAKEFLAGS set here
"GNUMAKEFLAGS": "",
"MAKEFLAGS": " -j1 -- PREFIX={{INSTALLDIR}}",
"MAKEFLAGS": " -j3 --jobserver-auth={{JOBSERVER}} -- PREFIX={{INSTALLDIR}}",
},
make_attrs = {
"resource_size": "tiny",
Expand Down Expand Up @@ -62,7 +62,7 @@ env_test_ninja(
env_test_ninja(
name = "ninja_tiny",
check_shellvars = STANDARD_VARS | {
"NINJA_JOBS": "1",
"NINJA_JOBS": "3",
},
ninja_attrs = {
"resource_size": "tiny",
Expand All @@ -80,8 +80,8 @@ env_test_meson(
env_test_meson(
name = "meson_tiny",
check_shellvars = STANDARD_VARS | {
"MESON_NUM_PROCESSES": "1",
"NINJA_JOBS": "1",
"MESON_NUM_PROCESSES": "3",
"NINJA_JOBS": "3",
},
meson_attrs = {
"resource_size": "tiny",
Expand Down Expand Up @@ -121,12 +121,12 @@ env_test_cmake(
# since we replace the binary dir, this overrides the STANDARD_VARS
"BUILD_TMPDIR": "{{CMAKE_BINARY_DIR}}",
"CMAKEVARS_FILE": "{{INSTALLDIR}}/cmakevars.out",
"CMAKE_BUILD_PARALLEL_LEVEL": "1",
"CMAKE_BUILD_PARALLEL_LEVEL": "3",
# Note that we set GNUMAKEFLAGS, but make itself will convert it into
# MAKEFLAGS, so for the cmake test we won't see it converted yet.
"GNUMAKEFLAGS": "-j1",
"GNUMAKEFLAGS": "-j3",
"MAKEFLAGS": "",
"NINJA_JOBS": "1",
"NINJA_JOBS": "3",
},
cmake_attrs = {
"resource_size": "tiny",
Expand Down Expand Up @@ -161,15 +161,15 @@ env_test_configure_make(
# since we replace the builddir, this overrides the STANDARD_VARS
"BUILD_TMPDIR": "{{abs_builddir}}",
"INSTALLDIR": "{{INSTALLDIR}}",
"MAKEFLAGS": " -j1",
"MAKEFLAGS": " -j3 --jobserver-auth={{JOBSERVER}}",
"abs_builddir": "{{abs_builddir}}",
"abs_srcdir": "{{abs_srcdir}}",
},
check_shellvars = STANDARD_VARS | {
# since we replace the builddir, this overrides the STANDARD_VARS
"BUILD_TMPDIR": "{{abs_builddir}}",
"INSTALLDIR": "{{INSTALLDIR}}",
"MAKEFLAGS": " -j1",
"MAKEFLAGS": " -j3 --jobserver-auth={{JOBSERVER}}",
},
configure_make_attrs = {
"resource_size": "tiny",
Expand Down
1 change: 1 addition & 0 deletions test/env_test/Makefile.in.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,7 @@ all:
# Note that this is order-sensitive, since INSTALLDIR is a subdir of \
# EXT_BUILD_ROOT and we want the replacement to be most specific first. \
$(SED) -i.bak \
-e 's|--jobserver-auth=[^ ]*|--jobserver-auth={{JOBSERVER}}|g' \
-e 's|$(abs_srcdir)|{{abs_srcdir}}|g' \
-e 's|$(abs_builddir)|{{abs_builddir}}|g' \
-e 's|$(BUILD_TMPDIR)|{{BUILD_TMPDIR}}|g' \
Expand Down
1 change: 1 addition & 0 deletions test/env_test/Makefile.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ all:
# Note that this is order-sensitive, since INSTALLDIR is a subdir of \
# EXT_BUILD_ROOT and we want the replacement to be most specific first. \
sed -i.bak \
-e 's|--jobserver-auth=[^ ]*|--jobserver-auth={{JOBSERVER}}|g' \
-e 's|$(BUILD_TMPDIR)|{{BUILD_TMPDIR}}|g' \
-e 's|$(EXT_BUILD_DEPS)|{{EXT_BUILD_DEPS}}|g' \
-e 's|$(INSTALLDIR)|{{INSTALLDIR}}|g' \
Expand Down
2 changes: 1 addition & 1 deletion toolchains/private/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ native_tool_toolchain(
cmake_tool(
name = "cmake_tool",
srcs = "@cmake_src//:all_srcs",
resource_size = "medium",
resource_size = "enormous",
tags = ["manual"],
)

Expand Down
Loading