Bazel Blog

Bazel 5.0

Bazel 5.0 is a major release and Bazel’s second LTS release. It contains new features and backwards incompatible changes from 4.x, the previous LTS release.


  • --experimental_enable_bzlmod enables the new external dependency subsystem, Bzlmod.
  • The minimum required JDK to run Bazel itself is now OpenJDK 11. Note that compiling binaries using JDK 8 and lower is still supported.
  • Java rules now use toolchain resolution. (#7849)
  • Starlark now permits def statements to be nested (closures) and supports lambda expressions (anonymous functions).


  • //visibility:legacy_public has been removed.
  • The --all_incompatible_changes flag is now a no-op.
  • Specifying a target pattern underneath a directory specified by .bazelignore will now emit a warning, not an error.
  • The test and coverage commands no longer return 3 when a test action fails because of a system error. Instead, the exit code reflects the type of system error.
  • Bazel will no longer create a bazel-out symlink if --symlink_prefix is specified: the directory pointed to via the bazel-out symlink is accessible via ${symlink_prefix}-out.
  • Removed flag --experimental_no_product_name_out_symlink; it is effectively always true.
  • Removed --action_graph from the dump command.
  • Removed --incompatible_restrict_string_escapes from the build command.
  • Removed --{experimental_,}json_trace_compression; its value is determined by the profile name.
  • Removed --experimental_profile_cpu_usage; it is effectively always true.
  • --legacy_dynamic_scheduler is now a no-op.
  • Flipped --trim_test_configuration to true. (#6842)
  • When using --allow_analysis_failures (for example, via bazel-skylib's analysistest with expect_failure = True), analysis-time failures in aspect implementation functions will now be propagated and saved in AnalysisFailureInfo, just like analysis-time failures in rules.
  • Added --experimental_reuse_sandbox_directories to reuse already-created non-worker sandboxes with cleanup.
  • Renamed --experimental_run_validations to --run_validations and flipped its default to true.
  • Removed --experimental_forward_instrumented_files_info_by_default, now that this behavior is the default.
  • When using MemoryProfiler with multiple GCs via the --memory_profile_stable_heap_parameters flag, we do a more precise calculation of heap used at the end of the build. This will generally result in lower values.
  • Added support to length-delimited protos as undeclared output annotations.
  • Added experimental flag --experimental_dynamic_skip_first_build to skip local execution in dynamic execution until there has been a successful build. This allows doing a first clean build from remote only, filling the cache.


  • The minimum Android build tools version for the Android rules is now 30.0.0.
  • The Android rules' --use_singlejar_apkbuilder is now a no-op. SingleJar will always be used to build APKs.
  • --apk_signing_method now accepts the value v4.
  • Proguard configs generated from aapt2 link step now exclude path location comments for better determinism.
  • Removed obsolete --incompatible_prohibit_aapt1.

Apple / Xcode

  • --apple_sdk has been deleted. It is a no-op.
  • The --incompatible_disable_native_apple_binary_rule flag has been added which disables the native apple_binary rule. Users who need to use apple_binary directly (if they cannot use one of the more specific Apple rules) should load it from rules_apple.
  • Allowing the LIPO operations to be conditional in the linkMultiArchBinary API for Apple binaries. Single architecture slices are now returned through AppleBinaryOutput and the Starlark API.
  • If --experimental_prefer_mutual_xcode is passed, Bazel will choose the local default (instead of the newest mutually available version) if it's available both locally and remotely.

Build Event Protocol

  • In the build event stream, BuildMetrics.TargetMetrics.targets_loaded is no longer populated. Its value was always mostly meaningless. BuildMetrics.TargetMetrics.targets_configured and BuildMetrics.ActionSummary.actions_created now include configured aspect data.
  • --bep_publish_used_heap_size_post_build is removed. Use --memory_profile=/dev/null instead; the used_heap_size_post_build field in BEP is now populated when the --memory_profile flag is set.
  • Added --bes_header flag to pass extra headers to the BES server.
  • BEP now includes test suite expansions.
  • BEP now includes all files from successful actions in requested output groups. Previously, an output group's files were excluded if any file in the output group was not produced due to a failing action. Users can expect BEP output to be larger for failed builds.
  • In BEP, TargetComplete.output_group has a new field incomplete indicating that the file_sets field is missing one or more declared artifacts whose generating actions failed.
  • When --experimental_bep_target_summary is enabled, BEP contains a new event, TargetSummary. For each top-level configured target, this event aggregates the results for building the configured target, tests run for that configured target (if any), and building all top-level aspects applied to that configured target. This flag will eventually default to enabled.

C++ / Objective-C

  • The Starlark method generate_dsym in objc fragment has been deleted. Please use the equivalent apple_generate_dsym in cpp fragment instead.
  • Removed --incompatible_objc_compile_info_migration. (#10854)
  • Removed --incompatible_objc_provider_remove_compile_info. (#11359)
  • Made gcov optional in cc_toolchain tools.
  • Added a new flag, --incompatible_enable_cc_test_feature which switches from the use of build variables to the feature of the same name.


  • Added --incompatible_enforce_config_setting_visibility to make config_setting honor the visibility attribute (defaulting to //visibility:public) (#12932)
  • The flag --toolchain_resolution_debug now takes a regex argument, which is used to check which toolchain types or targets should have debug info printed. You may use .* as an argument to keep the current behavior of debugging every toolchain type / target.


  • All (instead of just C++) source files are now filtered for coverage output according to --instrumentation_filter and --instrument_test_targets.
  • genrule.srcs is now considered a source attribute for coverage.
  • Forward coverage-instrumented files from non-tool dependencies by default.
  • label_keyed_string_dict attributes are now considered when gathering instrumented files for coverage.
  • Java branch coverage now applies Jacoco’s coverage filters. (#12696)


  • Removed javac_jar from JavaToolchainInfo.
  • Flipped --incompatible_disallow_resource_jars to true, disabling resouce_jars attribute on java_library. (#13221)
  • Flipped --incompatible_java_common_parameters to true, removing host_javabase parameter from java_common.compile. (#12373)
  • Flipped --incompatible_use_toolchain_resolution_for_java_rules to true. Flags --javabase and --java_toolchain are now no-op. (#7849)
  • Only native libraries supported by C++ targets in deps and runtime_deps are collected. No longer collecting .so files (#13043) or libraries in the data attribute. (#13550)
  • JavaToolchainInfo.jvm_opt returns a depset instead of a list.
  • Added a _direct_source_jars output group to Java related targets.
  • Added an enable_annotation_processing option to java_common.compile, which can be used to disable any annotation processors passed to plugins or in exported_plugins of deps.
  • Removed java_lite_proto_library.strict_deps attribute.
  • Bazel now uses the Starlark implementations of java_library and java_plugin instead of their native counterparts.
  • java_plugins can now only be used in the plugins and exported_plugins attributes. (#14012)
  • Javac workers now support cancellation.
  • Javac workers now cache the bootclasspath classes.


  • pkg_deb is no longer part of @bazel_tools//build_defs/pkg:pkg.bzl. Use instead.
  • Dropped fragile xz support from built in pkg_tar. Users requiring xz compression should switch to [bazelbuild/rules_pkg](

Persistent Workers

  • Multiplex persistent workers can now use the JSON protocol (#7998).
  • Updated worker protocol to allow request cancellation, and added --experimental_worker_cancellation flag to turn on cancellation for workers that implement it (#614).


  • The --incompatible_load_python_rules_from_bzl flag is now a no-op.
  • Relax restriction for "-" in the package name for Python sources. Now py_binary and py_test targets can have a main source file with "-" in the path.

Remote Execution

  • Disk cache can now be used in remote execution. (#13852)
  • Merkle tree calculation can be cached with --experimental_remote_merkle_tree_cache. The cache size is unlimited by default but can be controlled by --experimental_remote_merkle_tree_cache_size. (#13879)
  • File uploads are scheduled into background if --experimental_remote_cache_async is set. (#13655)
  • --remote_max_connections applies to gRPC connections as well. (#14202)
  • Remote metadata is saved into action cache if --exprimental_action_cache_store_output_metadata is set. (#13604)
  • Data transfers between Bazel and remote server are compressed via zstd if --experimental_remote_cache_compression is set. (#14041)
  • Added support for tag no-remote-cache-upload. (#14338)
  • Bug fixes and UX improvements.


  • Query output=xml/proto/location for source files will now show the location of line 1 of the source file (as the new default) instead of its location in the BUILD file.
  • Query --order_output=auto will now sort lexicographically. However, when somepath is used as a top level function (e.g. query 'somepath(a, b)'), it will continue to output in dependency order. If you do not want the lexicographical output ordering, specify another --order_output value (no, deps or full) based on what ordering you require.
  • cquery --noimplicit_deps now correctly filters out resolved cc_toolchains.

Starlark / Build Language

  • Starlark now permits def statements to be nested (closures) and supports lambda expressions (anonymous functions). Recursion is still not permitted.
  • Args.add_all and Args.add_joined can now accept closures in map_each if explicitly enabled via the allow_closure parameter. Beware that closures may retain large data structures into the execution phase.
  • dict.setdefault(key, ...) now fails if dict is frozen, even if it already contains key. This is an incompatible API change. (#12642)
  • The deprecated relative_to_caller_repository parameter has been removed from the Label constructor.
  • The undocumented ctx.expand feature no longer exists.
  • Add runfiles.merge_all() for merging a sequence of runfiles objects.
  • runfiles.merge() and merge_all() now respect --nested_set_depth_limit. If you hit the depth limit because you were calling merge() in a loop, use merge_all() on a sequence of runfiles objects instead.
  • native.existing_rule now returns select values in a form that is accepted by rule instantiation. This is a breaking API change, though the fallout is expected to be small.
  • Added --incompatible_existing_rules_immutable_view flag to make the native.existing_rule and native.existing_rules functions more efficient by returning immutable, lightweight dict-like view objects instead of mutable dicts.
  • Flipped --incompatible_disable_depset_items (#9017). The flag is now a no-op.


This release contains contributions from many people at Google, as well as Adam Liddell, Alex Eagle, amberdixon, Andrew Katson, Anthony Pratti, Artem V. Navrotskiy, Austin Schuh, Benedek Thaler, Benjamin Lee, Benjamin Peterson, Brandon Jacklyn, Brentley Jones, bromano, Cameron Mulhern, Christopher Sauer, Cristian Hancila, Dan Bamikiya, Dan Fleming, Daniel McCarney, Daniel Wagner-Hall, Danny Wolf, Dave Nicponski, David Cummings, David Ostrovsky, Delwin9999, Denys Kurylenko, Dmitry Ivankov, dorranh, ecngtng, Ed Schouten, Eitan Adler, Elliotte Rusty Harold, Eric Cousineau, Ethan Steinberg, Fabian Meumertzheim, FaBrand, Felix Ehrenpfort, Finn Ball, frazze-jobb, Fredrik Medley, Garrett Holmstrom, Gautam Korlam, George Gensure, goodspark, Grzegorz Lukasik, hvadehra, Ikko Ashimine, Jesse Chan, Joe Lencioni, Johannes Abt, John Laxson, Jonathan Schear, Justus Tumacder, Keith Smiley, kekxv, Kevin Hogeland, Lauri Peltonen, Liu Liu, László Csomor, Marc Zych, Mark Karpov, Masoud Koleini, Mathieu Olivari, Matt Mackay, Mauricio Galindo, Max Liu, Menny Even Danan, Michael Chinen, Nathaniel Brough, Nick Korostelev, Niek Peeters, Nikolay Shelukhin, Noa Resare, odisseus, Oleh Stolyar, Olek Wojnar, Oliver Eikemeier, Olle Lundberg, Omar Zuniga, Paul Gschwendtner, Peter Kasting, Philipp Schrader, Pras Velagapudi, Qais Patankar, Rabi Shanker Guha, Rai, Ron Braunstein, Ryan Beasley, samhowes, Samuel Giddins, Sebastian Olsson, Sergey Tyurin, Steve Siano, steve-the-bayesian, Stiopa Koltsov, tatiana, Tetsuo Kiso, Thi Doãn, Thomas Carmet, ThomasCJY, Timothe Peignier, Timothy Klim, Tobi, Torgil Svensson, Trustin Lee, Ulf Adams, Ulrik Falklof, Uri Baghin, Vaidas Pilkauskas, Vertexwahn, wisechengyi, Wren Turkal, Xavier Bonaventura, Yannic Bonenberger, Yury Evtikhov, Yuval Kaplan, zqzzq.