tree: 78ff0a2f526a4264a04364b9b5743bb1a5ae6c41 [path history] [tgz]
  1. docs/
  2. BUILD.bazel
  3. BUILD.gn
  4. compare_bazel_sdks.py
  5. idk_to_bazel_sdk.py
  6. README.md
  7. rules.bzl
build/bazel/bazel_sdk/README.md

How the platform build manages IDKs and SDKs

This document describes how the Fuchsia IDKs and Bazel SDKs are generated by the platform build, the role of each instance and their relationships. This information is crucial for the rest of the migration to Bazel, and will be updated accordingly.

The GN-generated IDKs and Bazel SDKs

The Fuchsia IDK

The GN //sdk:final_fuchsia_idk target is used to build [^1] and validate the Fuchsia IDK (formerly known as the “core” or “partner” IDK), which is the official archive distributed to third-party SDK developers. It contains all atoms in the “partner” category, as well as prebuilt binaries for all combinations of supported CPU architectures and API levels.

Currently, this is built directly from Ninja (no Bazel required) as the shape of the Fuchsia IDK (i.e. which atoms it includes) it entirely defined in the GN build graph (in //sdk/BUILD.gn).

Note that building the Fuchsia IDK takes a long time [^2][^3] due to the high number of (cpu, api_level) combinations that must be built. Thus, this target is only built by a few dedicated builder configurations (e.g. sdk-core-linux).

[^1]: //sdk:final_fuchsia_idk.exported is the GN target for the IDK. //sdk:final_fuchsia_idk wraps it along with its validation and archive targets.

[^2]: Because these sub-builds are rarely built, the remote cache is rarely helpful. As a result, each sub-build takes approximately 5 to 8 minutes. Due to sub-build mechanics, the sub-builds cannot start until the contents of the IDK have already been built once and thus start late in the build. Also, sub-build parallelism is limited for performance reasons, so there will be effectively multiple rounds of sub-builds.

[^3]: For local builds, the build time can be significantly reduced by setting the idk_buildable_cpus and idk_buildable_api_levels GN args.

The Fuchsia Bazel SDK

The GN //sdk:final_fuchsia_sdk target is used to build (but not validate or generate the archive) the official Fuchsia Bazel SDK distributed to third-party developers. It augments the Fuchsia IDK with our set of Bazel-specific build rules and target declarations.

Its content is directly usable by third-party Bazel projects, which can include it with a simple local_repository() directive in their WORKSPACE.bazel file, such as:

local_repository(
    name = "fuchsia_sdk",
    path = "/path/to/fuchsia_sdk",
)

Just like the Fuchsia IDK, the Fuchsia Bazel SDK is built directly from GN, without using any Bazel workspace, and building it takes so long that this is only done on a few dedicated builder configurations (e.g. sdk-bazel-linux).

The In-Tree IDK

The GN //sdk:bazel_in_tree_idk target is used to build an IDK (actually an IDK collection) that has the same set of atoms as the Fuchsia IDK, but which only provides prebuilt binaries for the current target_cpu architecture, and the HEAD API level (using artifacts from the main PLATFORM build). It is only intended to be used to populate the @fuchsia_sdk and @fuchsia_in_tree_idk repositories (described below).

The In-Tree Internal IDK

The GN //sdk:bazel_internal_only_idk target groups atoms with an unstable API and that are not ready to be moved to the “partner” category. This should only be used to populate the @internal_sdk repository of the in-tree Bazel workspace. These atoms should never be used outside of the platform build.

It only contains prebuilt binaries for the current target_cpu architecture, and the HEAD API level (also from the PLATFORM build)).

Nothing in the GN graph should depend on this.

IDK and SDK subsets

As previously mentioned, building the Fuchsia IDK and Fuchsia Bazel SDK can take a long time. As a mitigation for platform developers working with these targets or needing to locally build an SDK to test with a specific target, there are a small number of GN targets that generate the IDK or SDK with support for targeting a subset of API levels and/or CPU architectures. These can be used like the publishable IDK and SDK, respectively.

The following subsets are currently supported:

  • API level HEAD and default target CPU architecture:
    • //sdk:final_fuchsia_idk_head_only
    • //sdk:final_fuchsia_sdk_head_only

The Bazel external repositories

The platform build's internal Bazel workspace also uses a number of external repositories that are related to the IDK and the Bazel SDK:

The @fuchsia_in_tree_idk repository:

This repository currently wraps the Ninja-generated in-tree IDK as a Bazel repository. A key difference though is that its metadata files contain Bazel target labels, instead of file paths, for any buildable artifacts (i.e. not source files), for example, pkg/fdio/meta.json looks like:

{
  "binaries": {
    "x64": {
      "debug": "@fuchsia_in_tree_idk//.build-id:15/646fc64e58e6bc964d5781afec10233689ab08.debug",
      "dist": "@fuchsia_in_tree_idk//arch/x64:dist/libfdio.so",
      "dist_path": "lib/libfdio.so",                            # <-- configuration string
      "link": "@fuchsia_in_tree_idk//arch/x64:lib/libfdio.so"   # <-- ninja artifact
    }
  },
  "deps": [],
  "format": "shared",
  "headers": [
    "pkg/fdio/include/lib/fdio/directory.h",   # <-- symlink to source file
    "pkg/fdio/include/lib/fdio/fd.h",          # <-- symlink to source file
    ...
  ],
  "ifs": "fdio.ifs",
  "include_dir": "pkg/fdio/include",
  "name": "fdio",
  "root": "pkg/fdio",
  "type": "cc_prebuilt_library"
}

In the current implementation, the labels point to simple symlinks that go into the Ninja build directory. But this extra level of indirection will allow, in the future, building said artifacts directly with Bazel.

Note that this does not comply with the official IDK layout, so its content cannot be used or distributed outside of the platform build's Bazel workspace.

The @fuchsia_sdk repository:

This repository exposes the same set of atoms and binaries as the in-tree IDK, augmented with Bazel SDK rule definitions and Bazel targets for each atom.

It is used by the BUILD.bazel files inside of fuchsia.git, to use SDK atom targets and our set of Bazel rules to develop Fuchsia packages with them.

It is populated by parsing the content of the @fuchsia_in_tree_idk repository.

Note that its content cannot be used directly in external Bazel workspaces.

The @fuchsia_internal_only_idk repository:

This is similar to @fuchsia_in_tree_idk, but wraps the content of the //sdk:bazel_internal_only_idk instead.

The @internal_sdk repository:

This repository exposes SDK atoms and binaries from the in-tree internal IDK to the platform build's Bazel workspace. This means that only prebuilts for the current target_cpu architecture and HEAD API levels are available there.

It is populated by parsing the content of the @fuchsia_internal_only_idk repository.

Existing dependencies

The following diagram illustrates the dependencies between the items described above. The notation [foo()] denotes a repository rule invocation, which occurs when Bazel sets up external repositories, while [[bar()]] denotes a regular build rule invoked through an explcitit bazel build command.

GN Build Graph                                       |  Bazel Workspace
                                                     |
                                                     |
  Fuchsia IDK                                        |
     |   //sdk:final_fuchsia_idk                     |
     |                                               |
  [fuchsia_sdk_repository() in Python]               |
     |                                               |
     v                                               |
  Fuchsia Bazel SDK                                  |
        //sdk:final_fuchsia_sdk                      |
                                                     |
                                                     |
  Bazel In-Tree IDK                                  |
    //sdk:bazel_in_tree_idk                          |
                                                     |
                                                     |          @fuchsia_in_tree_idk ---[fuchsia_sdk_repository()]---> @fuchsia_sdk
                                                     |
                                                     |
  Bazel In-Tree Internal IDK                         |
    //sdk:bazel_internal_only_idk                    |
                    |                                |
                    `----------[fuchsia_idk_repository()]--> @fuchsia_internal_only_idk
                                                     |                   |
                                                     |                   |
                                                     |       [fuchsia_sdk_repository()]
                                                     |                   |
                                                     |                   v
                                                     |             @internal_sdk
                                                     |

The IDK and SDK subsets are entirely within GN:

GN Build Graph                                       |  Bazel Workspace
                                                     |
                                                     |
  Fuchsia HEAD-only IDK                              |
     |   //sdk:final_fuchsia_idk_head_only           |
     |                                               |
  [fuchsia_sdk_repository() in Python]               |
     |                                               |
     v                                               |
  Fuchsia HEAD-only Bazel SDK                        |
        //sdk:final_fuchsia_sdk_head_only            |
                                                     |

The fuchsia_idk_repository() function

This function takes an IDK as input, and populates a Bazel repository, with it, changing the content of its metadata files to include Bazel targets for buildable artifacts, plus adding the necessary BUILD.bazel files that they reference.

Note that the output repository‘s content does not follow the official IDK layout anymore, and should never be used outside of the platform build’s Bazel workspace.

The fuchsia_sdk_repository() function

This function takes an IDK as input, and generates a Bazel SDK directory or repository as output.

Its logic is written in a special way to allow it to run either in a Starlark environment (i.e. as a Bazel repository rule), or in a Python one (i.e. as a build action, either from Ninja or Bazel).

Currently, it is used as Python at build time to generate the Fuchsia Bazel SDK from the Fuchsia IDK, as a Ninja action, and the final Fuchsia in-tree SDK, as a Bazel action.

It is also used as Starlark in the Bazel repository rules that generate the @fuchsia_sdk and @internal_sdk repositories.