Backward Compatibility

Bazel is still in Beta and new releases may include backward incompatible
changes. As we make changes and polish the extension mechanism, old features
may be removed and new features that are not backward compatible may be added.

Backward incompatible changes are introduced gradually:

The backward incompatible change is introduced behind a flag with its
default value set to false.

In a later release, the flag’s default value will be set to true. You
can still use the flag to disable the change.

Then in a later release, the flag will be removed and you will no longer be
able to disable the change.

To check if your code will be compatible with future releases you can:

Build your code with the flag --all_incompatible_changes. This flag
enables all backward incompatible changes, and so you can ensure your code
is compatible with upcoming changes.

Dictionary concatenation

We are removing the + operator on dictionaries. This includes the += form
where the left-hand side is a dictionary. This is done to improve compatibility
with Python. A possible workaround is to use the .update method instead.

Load must appear at top of file

Previously, the load statement could appear anywhere in a .bzl file so long
as it was at the top level. With this change, for .bzl files, load must
appear at the beginning of the file, i.e. before any other non-load statement.

Depset is no longer iterable

When the flag is set to true, depset objects are not treated as iterable. This
prohibits directly iterating over depsets in for loops, taking its size via
len(), and passing it to many functions such as list, tuple, min, max,
sorted, all, and any. It does not prohibit checking for emptiness by
converting the depset to a boolean.

The goal of this change is to avoid accidental iteration on depset, which can
be expensive. If you really need
to iterate over a depset, you can call the .to_list() method to obtain a
flattened list of its contents.

String is no longer iterable

When the flag is set to true, string objects are not treated as iterable. This
affects for loops and many functions, e.g. list, tuple, min, max,
sorted, all, and any. String iteration has been a source of errors and
confusion, such as this error:

Package name is a function

The current package name should be retrieved by calling package_name() in
BUILD files or native.package_name() in .bzl files. The old way of referring
to the magic PACKAGE_NAME variable bends the language since it is neither a
parameter, local variable, nor global variable.

Likewise, the magic REPOSITORY_NAME variable is replaced by
repository_name() and native.repository_name(). Both deprecations use the
same flag.

FileType is deprecated

The FileType function is going away. The main use-case was
as an argument to the rule function. It’s no longer
needed, you can simply pass a list of strings to restrict the file types the
rule accepts.

New args API

The Args object returned by ctx.actions.args() has dedicated
methods for appending the contents of a list or depset to the command line.
Previously these use cases were lumped into its add()
method, resulting in a more cluttered API.

With this flag, add() only works for scalar values, and its deprecated
parameters are disabled. To add many arguments at once you must use add_all()
or add_joined() instead.

The previous default parameter of these attribute types was severely
bug-prone, as two targets of the same rule would be unable to exist in the same
package under default behavior. (Two targets both generating foo.txt in the
same package would conflict.)

Remove native git repository

should be used instead. These are drop-in replacements of the corresponding
native rules, however with the additional requirement that all label arguments
be provided as a fully qualified label (usually starting with @//),
for example: build_file = "@//third_party:repo.BUILD".

Flag: --incompatible_remove_native_git_repository

Default: true

Remove native http archive

When set, the native http_archive and all related rules are disabled.
The Starlark version

load("@bazel_tools//tools/build_defs/repo:http.bzl","http_archive")

should be used instead. This is a drop-in replacement, however with the
additional requirement that all label arguments be provided as
fully qualified labels (usually starting with @//). The Starlark http_archive
is also a drop-in replacement for the native new_http_archive (with
the same proviso). http.bzl also
provides http_jar and http_file (the latter only supports the urls
parameter, not url).

should be used instead. These rules are more reliable and offer additional
functionality over the native maven_jar rule. In addition to downloading
the jars, they allow defining the jar’s dependencies. They also enable
downloading src-jars.

the server_urls attribute is mandatory. If your maven_jar rule
did not specify a url then you should use the default server
(“http://central.maven.org/maven2”). If your rule did specify a url then
keep using that one.

Disallow tools in action inputs

A tool is an input coming from an attribute of type label
where the attribute has been marked executable = True. In order for an action
to run a tool, it needs access to its runfiles.

Under the old API, tools are passed to ctx.actions.run() and
ctx.actions.run_shell() via their inputs parameter. Bazel scans this
argument (which may be a large depset) to find all the inputs that are tools,
and adds their runfiles automatically.

In the new API, tools are instead passed to a dedicated tools parameter. The
inputs are not scanned. If a tool is accidentally put in inputs instead of
tools, the action will fail during the execution phase with an error due to
missing runfiles. This may be somewhat cryptic.

To support a gradual transition, all actions with a tools argument are opted
into the new API, while all actions without a tools argument still follow the
old one. In the future (when this flag is removed), all actions will use the new
API unconditionally.

This flag turns on a safety check that is useful for migrating existing code.
The safety check applies to all actions that do not have a tools argument. It
scans the inputs looking for tools, and if it finds any, it raises an error
during the analysis phase that clearly identifies the offending tools.

In the rare case that your action requires a tool as input, but does not
actually run the tool and therefore does not need its runfiles, the safety check
will fail even though the action would have succeeded. In this case, you can
bypass the check by adding a (possibly empty) tools argument to your action.
Note that once an action has been modified to take a tools argument, you will
no longer get helpful analysis-time errors for any remaining tools that should
have been migrated from inputs.

Expand directories in Args

With this flag enabled, directories are instead replaced by the full file
contents of that directory when passed to args.add_all() or
args.add_joined(). (Directories may not be passed to args.add().)

If you want the old behavior on a case-by-case basis (perhaps your tool can
handle directories on the command line), you can pass expand_directories=False
to the args.add_all() or args.add_joined() call.

Disable InMemory Tools Defaults Package

If false, Bazel constructs an in-memory //tools/defaults package based on the
command line options. If true, //tools/defaults:* is resolved from file system
as a regular package.

Flag: --incompatible_disable_tools_defaults_package

Default: false

Motivation:

//tools/default was initially created as virtual in-memory package. It
generates content dynamically based on current configuration. There is no need
of having //tools/defaults any more as LateBoundAlias can do dynamic
configuration-based label resolving. Also, having //tools/default makes
negative impact on performance, and introduces unnecessary code complexity.

All references to //tools/defaults:* targets should be removed or replaced
to corresponding target in @bazel_tools//tools/jdk: and
@bazel_tools//tools/cpp: packages.

Scope of changes and impact:

Targets in //tools/default will not exist any more. If you have any references
inside your BUILD or *.bzl files to any of its, then bazel will fail to resolve.

Migration plan:

Please replace all occurrences:

//tools/defaults:jdk

by @bazel_tools//tools/jdk:current_java_runtime

or/and @bazel_tools//tools/jdk:current_host_java_runtime

//tools/defaults:java_toolchain

by @bazel_tools//tools/jdk:current_java_toolchain

//tools/defaults:crosstool

by @bazel_tools//tools/cpp:current_cc_toolchain

or/and @bazel_tools//tools/cpp:current_cc_host_toolchain

if you need reference to libc_top, then @bazel_tools//tools/cpp:current_libc_top

These targets will not be supported any more:

//tools/defaults:coverage_report_generator

//tools/defaults:coverage_support

Disable late bound option defaults

If true, Bazel will stop retrieving the value of compiler from the cpp configuration when
--compiler is not specified. This will cause a config_setting that have
values = {"compiler": "x"} to not work properly when --compiler is not specified at command
line.

The former behavior can be achieved by changing the config_setting to use
flag_values = {"@bazel_tools//tools/cpp:compiler": "x"} instead:

Disallow using CROSSTOOL to select the cc_toolchain label

Currently Bazel selects the cc_toolchain to use from the toolchains
dictionary attribute of cc_toolchain_suite. The key it uses is constructed
the following way:

If --compiler option is specified, the key is --cpu|--compiler. Bazel
errors out if the entry doesn’t exist.

If --compiler option was not specified on command line, Bazel checks if
an entry with the key --cpu exists, and uses it if it does. If such an
entry doesn’t exist, it loops through the default_toolchain list in the
CROSSTOOL file, selects the first one that matches the --cpu option,
finds the CToolchain whose identifier matches the
default_toolchain.toolchain_identifier field, and then uses the key
CToolchain.targetCpu|Ctoolchain.compiler. It errors out if the entry
doesn’t exist.

We’re making selection of the cc_toolchain label independent of the
CROSSTOOL file: when the flag is set to True, Bazel will no longer loop
through the default_toolchain list in order to construct a key for selecting
a cc_toolchain label from cc_toolchain_suite.toolchains, but throw an error
instead.

In order to not be affected by this change, one should add entries in the
cc_toolchain_suite.toolchains for the potential values of --cpu:

Before, it could happen that the same cc_toolchain is used with multiple
CToolchains from the CROSSTOOL through default_toolchains. This is no longer
allowed, each cc_toolchain must point to at most one CToolchain by:

(deprecated, but still supported, doesn’t work without specifying compiler)
specifying cc_toolchain.cpu and cc_toolchain.compiler fields that match
CToolchain.target_cpu and CToolchain.compiler respectively.

(deprecated, but still supported, doesn’t work with
platforms) Relying on
--cpu and --compiler options.

Using cc_toolchain.toolchain_identifier will save you one migration in the
future.

Disallow using C++ Specific Make Variables from the configuration

Currently Bazel allows rule authors to access certain Make variables that are
implicitly provided to every rule by the CppConfiguration. This causes every
target to implicitly depend on CppConfiguration, which creates an undesirable
number of extra, unused, dependencies.

We are removing the implicit provision of these Make variables, and requiring
rules and targets that use these Make variables to explicitly depend on a
C++ toolchain in order to access them.

The list of Make variables is:

CC

AR

NM

LD

OBJCOPY

STRIP

GCOVTOOL

GLIBC_VERSION

C_COMPILER

CROSSTOOLTOP

ABI_GLIBC_VERSION

ABI

In order to not be affected by this change, add a C++ toolchain to the
toolchains attribute for targets, or to the_toolchains attribute for
Starlark rules. The best choice for this value is
the alias target @bazel_tools//tools/cpp:current_cc_toolchain, which will
always resolve to the currently selected C++ toolchain.

Genrules will still have access to these Make variables for the time
being because that information is plumbed not through CppConfiguration, but
through an implicit dependency on the C++ toolchain. That will also be
removed at some point in the future, so it’s considered good practice to add an
explicit dependency on the toolchain as demonstrated below.

Disable legacy C++ configuration API

You might want to migrate for this flag together with
--incompatible_disable_legacy_flags_cc_toolchain_api in a single go.
Migration instructions for
--incompatible_disable_legacy_cpp_toolchain_skylark_api use an API that is
already deprecated by --incompatible_disable_legacy_flags_cc_toolchain_api

This turns off legacy Starlark access to cc toolchain information via the
ctx.fragments.cpp fragment. Instead of declaring dependency on the ctx.fragments.cpp using the
fragments attribute declare a dependency on the @bazel_tools//tools/cpp:current_cc_toolchain
via implicit attribute named _cc_toolchain (see example below). Use find_cpp_toolchain from
@bazel_tools//tools/cpp:toolchain_utils.bzl to get the current C++ toolchain in the rule
implementation.

List of all legacy fields and their corresponding cc_toolchain alternative:

ctx.fragments.cpp

cc_toolchain

ar_executable

ar_executable()

built_in_include_directories

built_in_include_directories

c_options

c_options()

compiler

compiler

compiler_executable

compiler_executable()

compiler_options(unused_arg)

compiler_options()

cpu

cpu

cxx_options(unused_arg)

cxx_options()

dynamic_link_options(unused_arg, bool)

dynamic_link_options(bool)

fully_static_link_options(unused_arg, True)

fully_static_link_options(True)

ld_executable

ld_executable()

link_options

link_options_do_not_use

mostly_static_link_options(unused_arg, bool)

mostly_static_link_options(bool)

nm_executable

nm_executable()

objcopy_executable

objcopy_executable()

objdump_executable

objdump_executable()

preprocessor_executable

preprocessor_executable()

strip_executable

strip_executable()

sysroot

sysroot

target_gnu_system_name

target_gnu_system_name

unfiltered_compiler_options(unused_arg)

unfiltered_compiler_options(unused_arg)

If you use legacy Starlark API on ctx.host_fragment.cpp, let us know on
the tracking bug for C++ migration to platforms
about your use case. The current plan is that host fragments will be removed.
To migrate, add an implicit rule attribute in the host configuration:

Load label cannot cross package boundaries

Previously, the label argument to the load statement (the first argument) was
checked to ensure that it referenced an existing package but it was not checked
to ensure that it didn’t cross a package boundary.

For example, in

load("//a:b/c.bzl","doesntmatter")

if this flag is set to true, the above statement will be in error if //a/b
is a package; in such a case, the correct way to reference c.bzl via a label
would be //a/b:c.bzl.