259 lines
12 KiB
Markdown
259 lines
12 KiB
Markdown
# 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:
|
|
|
|
```python
|
|
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 https://github.com/brave/brave-browser/issues/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:
|
|
|
|
```python
|
|
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:
|
|
|
|
```bash
|
|
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 │
|
|
└─────────────────────────────────────────────────────────────────┘
|
|
```
|