Skip to content

Latest commit

 

History

History
258 lines (199 loc) · 11.9 KB

File metadata and controls

258 lines (199 loc) · 11.9 KB

Brave's Siso Build System Customization

This document explains how we customize the upstream Chromium Siso build system to support our build requirements, particularly the chromium_src override mechanism.

Overview

Siso is Chromium's distributed build execution system that enables remote compilation and caching. We extend Siso to handle our build architecture where files in brave/chromium_src/ can override corresponding upstream Chromium files without modifying the upstream source tree.

1. Integration Point in //build/config/siso/main.star

The entry point for our customization is:

brave_siso_config.configure(ctx, step_config, filegroups, handlers)

This call happens after all upstream Chromium configurations have been applied:

  • Platform-specific configurations (Linux, macOS, Windows)
  • Mojo code generation rules
  • Rust compilation rules
  • Blink/web platform rules

By hooking in at this stage, we can modify the final configuration that Siso will use, ensuring our customizations take precedence over upstream defaults.

2. Configuration Customizations

2.1 Step Configuration (step_config)

The step configuration defines rules for build steps to run remotely by Siso. Rules can adjust remote execution behavior, inputs, outputs, timeouts, and more. We make several adjustments to make the build system work for us:

Rule Removal

  • TypeScript rules are disabled because our chromium_src mechanism requires special handling of TypeScript inputs/outputs that needs to be implemented. See brave/brave-browser#48135
  • Rust rules are disabled on non-Linux hosts for remote execution. Unlike Clang (where we can use Linux toolchains for cross-compilation), Rust's Linux toolchain doesn't include cross-compilation support for macOS and Windows targets. Running these remotely requires Windows and macOS workers, which we don't have.

Timeout Adjustments

Build nodes are typically single-core, so we give some build steps extra time to complete.

  • Clang rules get 10-minute timeouts
  • Mojo and Blink Python rules get 15-minute timeouts

Platform Label Cleanup

The current remote execution backend we use doesn't support certain Chromium platform labels like action_default and action_large. Removing these prevents remote execution failures due to unrecognized labels.

2.2 Filegroup Customizations

Siso includes all macOS and iOS frameworks by default. We exclude some frameworks that are not actually used by the build, but lead to remote execution failures:

  • vecLib.framework from macOS frameworks. This is a non-canonical symlink in the macOS SDK that prevents remote system from correctly setting up remote workspace. Since it's not used by the build, we can safely exclude it.

Linux Clang Toolchain Dependencies (Non-Linux Hosts)

On Windows and macOS development machines, we configure Siso to automatically include Linux clang build dependencies for cross-compilation via RBE:

  1. The Linux clang binary itself is included automatically by the redirect_cc handler
  2. Additional filegroups (headers and other build-specific files) are configured by mirroring the host platform's toolchain input dependencies and creating corresponding _linux versions
  3. These Linux toolchain filegroups are then added to input_deps for each clang binary variant

This ensures that when compilation actions are sent to remote Linux workers, all necessary toolchain dependencies are included in the RBE request, not just the compiler binary itself.

2.3 Handler Customizations

Handlers are the custom logic that processes individual build actions. We add two handlers:

The redirect_cc Handler

This handler intercepts C/C++/Objective-C compilation commands and checks if a corresponding override file exists in brave/chromium_src/.

For example, when compiling chrome/browser/ui/browser.cc:

  1. Siso receives a compilation command with input ../../chrome/browser/ui/browser.cc
  2. The redirect_cc handler checks if ../../brave/chromium_src/chrome/browser/ui/browser.cc exists
  3. If it exists, the handler:
    • Replaces the source file argument with the override path
    • Adds the override file to the action's input list (so it gets uploaded for remote execution)
    • Updates the command accordingly

On macOS and Windows development machines, the handler also:

  • Sets up a remote wrapper script that ensures Linux clang toolchain is used instead of the macOS/Windows toolchain
  • Adds the Linux clang binary as an executable input

This enables remote compilation on Linux workers even when building from non-Linux hosts.

The chromium_src_inputs Handler (for Python actions)

Python-based build actions can have chromium_src overrides. Overrides can exist for python files and also for input files. This handler ensures that the build system knows about all the potential file overrides and uploads them for remote execution:

  1. Scans all Python action inputs for files with supported extensions (.mojom, .pdl, .json, .html, etc.)
  2. For each input file, checks if a brave/chromium_src/ override exists
  3. Adds all found overrides to the action's input list
  4. Ensures Brave utility scripts (brave_chromium_utils.py, override_utils.py) are uploaded for remote execution

The handler also attaches a remote wrapper script that:

  • Sets PYTHONPATH to include Brave's script directories
  • Fixes path separators when commands originate from Windows hosts

3. Siso Configuration Files: .sisoenv and .sisorc

.sisoenv - Remote Execution Service Configuration

This file is generated by upstream Chromium's configure_siso.py script during gclient runhooks. The configuration comes from custom_vars in the .gclient file:

solutions = [
  {
    "custom_vars": {
      "reapi_address": "remotebuild.example.com:443",
      "reapi_backend_config_path": "/path/to/backend.star",
      "reapi_instance": "default",
    },
  }
]

The reapi_backend_config_path is required and specifies which backend configuration to use. This Starlark file defines platform properties like the Docker image to use for remote workers. We currently use google.star which comes with upstream Chromium. This allows us to:

  • Use the same remote execution Docker image as Chromium
  • Automatically get updates when Chromium updates their toolchain requirements
  • Avoid maintaining our own backend configuration

During npm run sync, we generate the .gclient file and set these custom_vars based on the rbe_service variable in brave/.env. This results in a .sisoenv file like:

SISO_REAPI_INSTANCE=default
SISO_REAPI_ADDRESS=remotebuild.example.com:443

This file tells Siso:

  • Where to connect for remote execution (the cluster address)
  • Which instance to use on that cluster

Without this configuration, Siso would try to use Chromium's default remote execution service (Google's RBE).

.sisorc - Ninja/Siso Runtime Flags

This file is generated by brave_custom.py in the configure_sisorc() function during gclient runhooks (via npm run sync). It configures Siso's runtime flags:

  • -reapi_keep_exec_stream: Keeps the connection to the remote execution service alive continuously. Our backend requires this; without it, Siso would disconnect every minute, aborting long-running remote compilations.

  • -fs_min_flush_timeout 300s: Sets a 5-minute timeout for blob downloads from remote execution. This gives Siso more time to download build outputs on slower network connections before timing out and falling back to local compilation.

  • -cache_dir and -local_cache_enable: Enables a local disk cache for remote execution results if the SISO_CACHE_DIR environment variable is set. The cache directory is created automatically if it doesn't exist.

The reason to pass these flags via .sisorc instead of npm run build is to allow autoninja to apply these flags automatically.

Architecture Diagram

┌─────────────────────────────────────────────────────────────────┐
│  Developer runs: npm run sync                                   │
│    └─> generates .gclient with custom_vars                      │
│          ├─> reapi_address (from rbe_service .env var)          │
│          └─> reapi_backend_config_path ('google.star')          │
│          ├─> reapi_instance ('default')                         │
└──────────────────────┬──────────────────────────────────────────┘
                       │
                       ▼
┌─────────────────────────────────────────────────────────────────┐
│  gclient runhooks                                               │
│    ├─> configure_siso.py (upstream Chromium)                    │
│    │     ├─> write .sisoenv (from .gclient custom_vars)         │
│    │     └─> copy /path/to/backend.star → backend.star          │
│    └─> reclient configurator                                    │
│          └─> brave_custom.py callbacks                          │
│                ├─> generate python_remote_wrapper               │
│                └─> write .sisorc (ninja flags from env vars)    │
└──────────────────────┬──────────────────────────────────────────┘
                       │
                       ▼
┌─────────────────────────────────────────────────────────────────┐
│  Developer runs: ninja -C out/Component                         │
│    └─> siso                                                     │
│          ├─> reads .sisoenv (RBE cluster and instance config)   │
│          ├─> reads .sisorc (runtime flags)                      │
│          └─> loads main.star                                    │
│                └─> calls brave_siso_config.configure()          │
│                      ├─> adjusts step_config (rules/timeouts)   │
│                      ├─> adjusts filegroups (exclusions)        │
│                      └─> installs handlers                      │
│                            ├─> redirect_cc (C++ overrides)      │
│                            └─> chromium_src_inputs (Py actions) │
└──────────────────────┬──────────────────────────────────────────┘
                       │
                       ▼
┌─────────────────────────────────────────────────────────────────┐
│  For each build action:                                         │
│    ├─> Handler checks for brave/chromium_src/ overrides         │
│    ├─> Adds overrides to inputs                                 │
│    ├─> Uploads inputs to remote worker                          │
│    ├─> Executes remotely (or locally if disabled)               │
│    └─> Caches results locally and remotely                      │
└─────────────────────────────────────────────────────────────────┘