skia2/.bazelrc
Kevin Lubick c4872ce644 [bazel] Add support for Macs to make Linux RBE builds
The big change here is having the C++ toolchain use
Bazel platforms instead of the C++ specific flags/setup.
In Bazel, platforms are a general purpose way to define
things like os, cpu architecture, etc. We were not using
platforms previously, because the best documentation at
the time focused on the old ways.

However, the old ways were clumsy/difficult when trying
to manage cross-compilation, specifically when trying
to have a Mac host trigger a build on our Linux RBE
system targeting a Linux x64 system. Thus, rather than
keep investing in the legacy system, this CL migrates
us to using platforms where possible.

Suggested background reading to better understand this CL:
 - https://bazel.build/concepts/platforms-intro
 - https://bazel.build/docs/platforms
 - https://bazel.build/docs/toolchains#registering-building-toolchains

The hermetic toolchain itself is not changing in this CL
(and likely does not need to), only how we tell Bazel
about it (i.e. registering it) and how Bazel decides
to use it (i.e. resolving toolchains).

Here is my understanding of how platforms and toolchains
interact (supported by some evidence from [1][2])
 - Bazel needs to resolve platforms for the Host, Execution,
   and Target.
   - If not specified via flags, these are the machine from
     which Bazel is invoked, aka "@local_config_platform//:host".
   - With this CL, the Host could be a Mac laptop, the Execution
     platform is our Linux RBE pool, and the Target is "a Linux
     system with a x64 CPU"
 - To specify the Host, that is, describe to Bazel the
   capabilities of the system it is running on, one can
   set --host_platform [3] with a label pointing to a platform()
   containing the appropriate settings. Tip: have this
   platform inherit from @local_config_platform//:host
   so it can add to any of the constraint_settings and
   constraint_values that Bazel deduces automatically.
 - To specify the Target platform(s), that is, the system
   on which a final output resides and can execute, one
   can set the --platforms flag with a label referencing
   a platform().
 - Bazel will then choose an execution platform to fulfill
   that request. Bazel will look through a list of available
   platforms, which can be augmented* with the
   --extra_execution_platforms. Platforms specified by this
   flag will be considered higher than the default platforms!
 - Having selected the appropriate platforms, Bazel now
   needs to select a toolchain to actually run the actions
   of the appropriate type.
 - Bazel looks through the list of available toolchains
   and finds one that "matches" the Execution and the Target
   platform. This means, the toolchain's exec_compatible_with
   is a strict subset of the Execution platform and
   the toolchain's target_compatible_with is a strict subset
   of the Target platform. To register toolchains* (i.e. add
   them to the resolution list), we use --extra_toolchains.
   Once Bazel finds a match, it stops looking.
   Using --toolchain_resolution_debug=".*" makes Bazel log
   how it is resolving these toolchains and what execution
   platform it picked.

* We can also register execution platforms and toolchains in
  WORKSPACE.bazel [4], but the flags come with higher priority
  and that made resolution a bit tricky. Also, when we want
  to conditionally add them (e.g. --config=linux_rbe), we
  cannot remove them conditionally in the WORKSPACE.bazel file.

The above resolution flow directly necessitated the changes
in this CL.

Example usage of the new configs and platforms:

    # Can be run on a x64 Linux host and uses the hermetic toolchain.
    bazel build //:skia_public

    # Can be run on Mac or Linux and uses the Linux RBE system along
    # with the hermetic toolchain to compile a binary for Linux x64.
    bazel build //:skia_public --config=linux_rbe --config=for_linux_x64

    # Shorthand for above
    bazel build //:skia_public --config=for_linux_x64_with_rbe

Notice we don't have to type out --config=clang_linux anymore!
That was due to me reading the Bazel docs more carefully and
realizing we can set options for *all* Bazel build commands.

Current Limitations:
 - Targets which require a py_binary (e.g. Dawn's genrules)
   will not work on RBE when cross compiling because the
   python runtime we download is for the host machine, not
   the executor. This means //example:hello_world_dawn does
   not work on Mac when cross-compiling via linux_rbe.
 - Mac M1 linking not quite working with SkOpts settings.
   Probably need to set -target [5]

Suggested Review order:
 - toolchain/BUILD.bazel Notice how we do away with
   cc_toolchain_suite for toolchain. These have the same
   role: giving Bazel the information about where a toolchain
   can run. The platforms one is more expressive (IMO), allowing
   us to say both where to run the toolchain and what it can
   make. In order to more easily force the use of our hermetic
   toolchain, but also allow the hermetic toolchain to be used
   on RBE, we specify "use_hermetic_toolchain" only on the target,
   because the RBE image does not have the hermetic toolchain
   on it by default (but can certainly run it).
 - bazel/platform/BUILD.bazel to see the custom constraint_setting
   and corresponding constraint_value. The names for both of these
   are completely arbitrary - they do not need to have any deeper
   meaning or relation to any file or Docker image or system or
   any other constraints. Think of the constraint_setting as
   an Enum and the constraint_value being the one and only member.
   We need to pass around a constant value, not a type, so we
   need to provide the constraint_value (e.g. in toolchain/BUILD.bazel)
   but not a constraint_setting. However we need a
   constraint_setting declared so we can make a constraint_value
   of that "type".
   Notice the platform declared here - it allows us to force
   Bazel to use the hermetic toolchain because of the extra
   constraint_value.
 - .bazelrc I set a few flags that will be on for all
   bazel build commands. Importantly, this causes the C++
   build logic to use platforms and not the old, bespoke way.
   I also found a way to avoid using the local toolchain on
   the host, which will hopefully lead to clearer errors
   if platforms are mis-specified instead of odd compile
   errors because the host toolchain is too old or something.
   There are also a few RBE settings tweaked to be a bit
   more modern, as well the new shorthands for specifying
   target platforms (e.g. for_linux_x64).
 - bazel/buildrc where we have to turn off the platforms
   logic for emscripten https://github.com/emscripten-core/emsdk/issues/984
 - bazel/rbe/BUILD.bazel for a fix in the platform description
   that makes it work on Mac.
 - Notice that _m1 has been removed from the mac-related toolchain
   files because the same toolchain should work on both
   architectures.
 - All other changes in any order.

[1] https://bazel.build/docs/toolchains#debugging-toolchains
[2] https://bazel.build/docs/toolchains#toolchain-resolution
[3] https://bazel.build/reference/command-line-reference
[4] https://bazel.build/docs/toolchains#registering-building-toolchains
[5] 17dc3f16fc/gn/skia/BUILD.gn (L258-L271)
Change-Id: I515c114099d659639a808f74e47d489a68b7af62
Bug: skia:12541
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/549737
Reviewed-by: Erik Rose <erikrose@google.com>
Reviewed-by: Jorge Betancourt <jmbetancourt@google.com>
2022-06-23 12:00:43 +00:00

134 lines
7.2 KiB
Plaintext

# https://bazel.build/concepts/platforms-intro#cxx
# This forces Bazel's C++ rules use platforms to select toolchains instead of the default
# --crosstool_top, --compiler, etc.
build --incompatible_enable_cc_toolchain_resolution
# We do not want Bazel to detect any C++ toolchains on the local machine
# https://github.com/bazelbuild/bazel/blob/4ccc21f2f089971e5f4032397764a4be3549c40a/tools/cpp/cc_configure.bzl#L47
build --action_env=BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1
# We would like developers to not upload to the remote build cache, only the RBE workers themselves.
build --remote_upload_local_results=false
# This tells Bazel that the host platform can use the hermetic toolchain. This is a small lie until
# Windows support is added.
build --host_platform=//bazel/platform:host_with_hermetic_toolchain
# Register our toolchains. We do this here, and not in WORKSPACE.bazel because
# --extra_toolchains has priority over register_toolchains and we conditionally add some toolchains
# for RBE.
build --extra_toolchains=//toolchain:clang_linux_x64_toolchain
build --extra_toolchains=//toolchain:clang_mac_x64_toolchain
build --extra_toolchains=//toolchain:clang_mac_arm64_toolchain
# --platforms refers to the target for which we are compiling. By setting the target to be a
# platform which has our own custom constraint_setting and constraint_value
# (skia_hermetic_toolchain=use_hermetic_toolchain), this causes Bazel to resolve the toolchain
# to be our hermetic one because our hermetic toolchains have that same constraint set in their
# target_compatible_with list.
build:for_linux_x64 --platforms=//bazel/platform:linux_x64_hermetic
build:for_linux_x64_with_rbe --config=linux_rbe --platforms=//bazel/platform:linux_x64_hermetic
build:for_mac_arm64 --platforms=//bazel/platform:mac_arm64_hermetic
build:for_mac_x64 --platforms=//bazel/platform:mac_x64_hermetic
# some aliases using more common lingo
build:for_mac_m1 --config=for_mac_arm64
build:for_mac_intel --config=for_mac_x64
# =============================================================================
# Alias to build configurations below. This makes configuring things from
# the command line easier.
build --flag_alias=fontmgr_factory=//bazel/common_config_settings:fontmgr_factory
build --flag_alias=gpu_backend=//bazel/common_config_settings:gpu_backend
build --flag_alias=include_decoder=//bazel/common_config_settings:include_decoder
build --flag_alias=include_encoder=//bazel/common_config_settings:include_encoder
build --flag_alias=include_fontmgr=//bazel/common_config_settings:include_fontmgr
build --flag_alias=shaper_backend=//bazel/common_config_settings:shaper_backend
build --flag_alias=with_gl_standard=//bazel/common_config_settings:with_gl_standard
build --flag_alias=disable_effect_serialization=no//bazel/common_config_settings:enable_effect_serialization
build --flag_alias=enable_effect_serialization=//bazel/common_config_settings:enable_effect_serialization
build --flag_alias=disable_sksl=no//bazel/common_config_settings:enable_sksl
build --flag_alias=enable_sksl=//bazel/common_config_settings:enable_sksl
build --flag_alias=disable_skslc=no//bazel/common_config_settings:enable_skslc
build --flag_alias=enable_skslc=//bazel/common_config_settings:enable_skslc
build --flag_alias=disable_sksl_tracing=no//bazel/common_config_settings:enable_sksl_tracing
build --flag_alias=enable_sksl_tracing=//bazel/common_config_settings:enable_sksl_tracing
build --flag_alias=disable_tracing=no//bazel/common_config_settings:enable_tracing
build --flag_alias=enable_tracing=//bazel/common_config_settings:enable_tracing
build --flag_alias=disable_vma=no//bazel/common_config_settings:use_vulkan_memory_allocator
build --flag_alias=enable_vma=//bazel/common_config_settings:use_vulkan_memory_allocator
build --flag_alias=with_icu=//bazel/common_config_settings:use_icu
build --flag_alias=with_no_icu=no//bazel/common_config_settings:use_icu
# CanvasKit flags
build --flag_alias=ck_enable_fonts=//modules/canvaskit:enable_fonts
build --flag_alias=ck_disable_fonts=no//modules/canvaskit:enable_fonts
# =============================================================================
# REMOTE BUILD EXECUTION
# =============================================================================
# =====
# The following was copied from https://github.com/bazelbuild/bazel-toolchains/blob/ea243d43269df23de03a797cff2347e1fc3d02bb/bazelrc/bazel-4.1.0.bazelrc
# We should be free to modify this as we see fit.
#
# Depending on how many machines are in the remote execution instance, setting
# this higher can make builds faster by allowing more jobs to run in parallel.
# Setting it too high can result in jobs that timeout, however, while waiting
# for a remote machine to execute them.
build:remote --jobs=50
# Set several flags related to specifying the platform, toolchain and java
# properties.
build:remote --java_runtime_version=rbe_jdk
build:remote --tool_java_runtime_version=rbe_jdk
# When a remote configuration is chosen, add "remote" to the list of spawn_strategies.
build:remote --spawn_strategy=remote,sandboxed
# Enable remote execution so actions are performed on the remote systems.
build:remote --remote_executor=grpcs://remotebuildexecution.googleapis.com
# Enforce stricter environment rules, which eliminates some non-hermetic
# behavior and therefore improves both the remote cache hit rate and the
# correctness and repeatability of the build.
build:remote --incompatible_strict_action_env=true
# No compile task should take more than 180 seconds. Really long running tasks
# are probably a result of spinning up new workers.
build:remote --remote_timeout=180
# Enable authentication. This will pick up application default credentials by
# default. You can use --google_credentials=some_file.json to use a service
# account credential instead.
# See https://developers.google.com/remote-build-execution/docs/authentication
# To authenticate, you should run gcloud auth application-default login
build:remote --google_default_credentials=true
# End of the copied RBE settings
#=====
# Use the RBE instance on the skia-rbe GCP project.
build:remote --remote_instance_name projects/skia-rbe/instances/default_instance
# The linxu_rbe config will build on RBE and default to compiling for linux_x64 using
# the hermetic toolchain.
build:linux_rbe --config=remote
# On the RBE instances, we also have the Java and C++ toolchain from the Docker image available.
# These need to come after the --extra_toolchains flags (above) that register our hermetic
# toolchains, because we only want these backup toolchains to be used by Bazel internals,
# if at all.
build:linux_rbe --extra_toolchains=//bazel/rbe/gce_linux/java:all
build:linux_rbe --extra_toolchains=//bazel/rbe/gce_linux/config:cc-toolchain
# Make the RBE platform available for selection as an Execution platform.
build:linux_rbe --extra_execution_platforms=//bazel/rbe:gce_linux_platform
# Import our specified build configurations
# https://docs.bazel.build/versions/main/best-practices.html#using-the-bazelrc-file
# We chose to split our build configurations into their own file to have better organization
# because we anticipate that file growing large.
import %workspace%/bazel/buildrc
# Import User's custom builds if they have defined any
try-import %workspace%/bazel/user/buildrc