Skip to content

Commit

Permalink
Speed up build by avoiding build config duplication
Browse files Browse the repository at this point in the history
Compile substantially all of workerd in the bazel 'target' configuration
instead of 'exec', which allows us to avoid compiling major components
twice.
This should offer a large performance improvement, especially when
rebuilding after a V8 update or building all targets and drive down the
worst-case CI build time significantly.
Bazel supports an exec configuration for building code that needs to run
on the host machine during the build, e.g. tools used to generate source
files or type definitions. When not cross-compiling exec and target will
be the same, but bazel does not offer a flag to use just one configuration
when the configurations are identical (bazelbuild/bazel#14848),
making manual changes necessary.
Bazel appears to offer no way to detect if exec and host are the same, so
this feature is implemented through an opt-in command line flag enabled in
.bazelrc, which makes it possible to easily disable the change when
cross-compilation support is needed.
  • Loading branch information
fhanau committed Jun 13, 2023
1 parent 6535767 commit 80aef6d
Show file tree
Hide file tree
Showing 6 changed files with 501 additions and 1 deletion.
8 changes: 8 additions & 0 deletions .bazelrc
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ build:fastdbg --@rules_rust//:extra_rustc_flags=-C,panic=unwind,-C,debug-asserti
# improvement, ~35k or ~75k with LTO.
build:thin-lto --@rules_rust//:extra_rustc_flags=-C,panic=abort,-C,codegen-units=1

# Avoid compiling build targets twice by almost always compiling using the target configuration.
# Note that a cross-platform build requires compiling code that runs on the host machine to use the
# exec configuration, disable this flag when cross-compiling. See https://github.com/bazelbuild/bazel/issues/14848
# for an in-depth discussion.
build --//:use_cfg_target=True
# TODO: Not functional yet
# build --@v8//:use_cfg_target=True

#
# Linux and macOS
#
Expand Down
5 changes: 5 additions & 0 deletions BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ bool_flag(
build_setting_default = True,
)

bool_flag(
name = "use_cfg_target",
build_setting_default = False,
)

config_setting(
name = "set_dead_strip",
flag_values = {"dead_strip": "True"},
Expand Down
1 change: 1 addition & 0 deletions WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ git_repository(
"//:patches/v8/0008-Disable-bazel-whole-archive-build.patch",
"//:patches/v8/0009-Make-v8-Locker-automatically-call-isolate-Enter.patch",
"//:patches/v8/0010-Add-an-API-to-capture-and-restore-the-cage-base-poin.patch",
"//:patches/v8/0011-Use-target-cfg.patch",
],
)

Expand Down
37 changes: 37 additions & 0 deletions build/run_binary_target.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Workaround for bazel not supporting a shared exec and target configuration, even when they are
# identical. https://github.com/bazelbuild/bazel/issues/14848
# Derived from the tensorflow project (https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/tools/api/generator/api_gen.bzl)
# See https://github.com/tensorflow/tensorflow/issues/60167 for discussion

def _run_binary_target_impl(ctx):
tool = ctx.attr.tool[DefaultInfo].files_to_run.executable
flags = [ ctx.expand_location(a) if "$(location" in a else a for a in ctx.attr.args ]

cmd = " ".join([tool.path] + flags)
ctx.actions.run_shell(
inputs = ctx.files.srcs,
outputs = ctx.outputs.outs,
tools = [tool],
use_default_shell_env = True,
command = cmd,
)

run_binary_target = rule(
implementation = _run_binary_target_impl,
attrs = {
"outs": attr.output_list(mandatory = True),
"srcs": attr.label_list(allow_files = True),
"args": attr.string_list(),
# Conditionally set cfg based on use_cfg_target to support cross-platform build when needed
"tool": attr.label(
executable = True,
# TODO: The select() statement works locally yet produces an error on CI. Investigate
# what's causing this.
cfg = "target",
# cfg = select({
# "@//:use_cfg_target": "target",
# "//conditions:default": "exec",
# }),
mandatory = True),
},
)
Loading

0 comments on commit 80aef6d

Please sign in to comment.