diff --git a/README.md b/README.md index 5c08d1ae..792e2368 100644 --- a/README.md +++ b/README.md @@ -2,20 +2,35 @@ This repository contains helper/wrapper scripts to make building Electron easier. +## Table of Contents + +- [Installation](#installation) +- [Quickstart](#quickstart) +- [Concepts](#concepts) +- [Core workflow](#core-workflow): [`init`](#e-init) · [`sync`](#e-sync) · [`build`](#e-build) +- [Running Electron](#running-electron): [`start`](#e-start) · [`node`](#e-node) · [`debug`](#e-debug) · [`test`](#e-test) · [`npm`](#e-npm) +- [Inspecting state](#inspecting-state): [`show`](#e-show) · [`shell`](#e-shell) +- [Working with code](#working-with-code): [`patches`](#e-patches) · [`open`](#e-open) · [`pr`](#e-pr) · [`backport`](#e-backport) · [`cherry-pick`](#e-cherry-pick) · [`rcv`](#e-rcv) +- [Managing configs](#managing-configs): [`use`](#e-use) · [`remove`](#e-remove) · [`sanitize-config`](#e-sanitize-config) · [`worktree`](#e-worktree) · [`load-macos-sdk`](#e-load-macos-sdk) +- [Infrastructure](#infrastructure): [`depot-tools`](#e-depot-tools) · [`gh-auth`](#e-gh-auth) · [`auto-update`](#e-auto-update) +- [Configuration file reference](#configuration-file-reference) +- [Environment variables](#environment-variables) +- [Shell completion](#shell-completion) +- [Advanced](#advanced) + ## Installation -A handful of prerequisites, such as git, python, and npm, are -required for building Electron itself; these can be found in -[Platform Prerequisites][platform-prerequisites]. `npm` can be used -with `build-tools` itself as well, but we've configured it to run -with `yarn`, so we also recommend you [install it to your system](https://yarnpkg.com/lang/en/docs/install/). +A handful of prerequisites, such as git, python, and npm, are required for building Electron itself; +these can be found in [Platform Prerequisites][platform-prerequisites]. `npm` can be used with +`build-tools` itself as well, but we've configured it to run with `yarn`, so we also recommend you +[install it to your system](https://yarnpkg.com/lang/en/docs/install/). -From here, you'll need a command-line prompt. On Mac and Linux, this will -be a terminal with a shell, e.g. bash or zsh. You can also use these on -Windows if you install them, or use built-in tools like Windows' -[Command Prompt](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/windows-commands#command-shell-overview). +From here, you'll need a command-line prompt. On Mac and Linux, this will be a terminal with a +shell, e.g. bash or zsh. You can also use these on Windows if you install them, or use built-in +tools like Windows' [Command Prompt](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/windows-commands#command-shell-overview). -Please note that `build-tools` (due to nested dependencies) might not work properly in powershell, please use `cmd` on Windows for optimum results. +Please note that `build-tools` (due to nested dependencies) might not work properly in PowerShell; +please use `cmd` on Windows for optimum results. ```sh # Install build-tools package globally: @@ -23,11 +38,10 @@ npm i -g @electron/build-tools ``` > [!NOTE] -> The `@electron/build-tools` npm package is a thin wrapper for the actual `build-tools` scripts. Its code lives in the [electron/build-tools-installer](https://github.com/electron/build-tools-installer) repository. - -## Getting the Code and Building Electron +> The `@electron/build-tools` npm package is a thin wrapper for the actual `build-tools` scripts. +> Its code lives in the [electron/build-tools-installer](https://github.com/electron/build-tools-installer) repository. -You can run a new Electron build with this command: +## Quickstart ```sh # The 'Hello, World!' of build-tools: get and build `main` @@ -38,28 +52,23 @@ You can run a new Electron build with this command: e init --root=~/electron --bootstrap testing ``` -That command's going to run for awhile. While you're waiting, grab a -cup of hot caffeine and read about what your computer is doing: +That command's going to run for awhile. While you're waiting, grab a cup of hot caffeine and read +about what your computer is doing. -### Concepts +## Concepts -Electron's build-tools command is named `e`. Like [nvm][nvm] and git, -you'll invoke `e` with commands and subcommands. See `e --help` or `e help ` -for many more details. +Electron's build-tools command is named `e`. Like [nvm][nvm] and git, you'll invoke `e` with +commands and subcommands. See `e --help` or `e help ` for more details on any command. -`e` also borrows another inspiration from nvm: having multiple configurations -that you can switch between so that one is the current, active configuration. -Many choices go into an Electron build: +`e` also borrows another inspiration from nvm: having multiple configurations that you can switch +between so that one is the current, active configuration. Many choices go into an Electron build: -* Which [Electron branch](https://github.com/electron/electron/branches) - is used (e.g. `main`, `13-x-y`) -* Which [.gn config file][gn-configs] is imported (e.g. - [testing](https://github.com/electron/electron/blob/main/build/args/testing.gn) or - [release](https://github.com/electron/electron/blob/main/build/args/release.gn)) -* Any compile-time options (e.g. Clang's [asan or tsan][sanitizers]) +- Which [Electron branch](https://github.com/electron/electron/branches) is used (e.g. `main`, `36-x-y`) +- Which [.gn config file][gn-configs] is imported (e.g. [testing](https://github.com/electron/electron/blob/main/build/args/testing.gn) or [release](https://github.com/electron/electron/blob/main/build/args/release.gn)) +- Any compile-time options (e.g. Clang's [asan or tsan][sanitizers]) -`e` holds all these variables together in a build configuration. You can -have multiple build configurations and manage them in a way similar to nvm: +`e` holds all these variables together in a build configuration. You can have multiple build +configurations and manage them in a way similar to nvm: | nvm | e | Description | |:---------------------|:-------------------|:-----------------------------------------------| @@ -67,20 +76,18 @@ have multiple build configurations and manage them in a way similar to nvm: | nvm current | e show current | Show which configuration is currently in use | | nvm use <name> | e use <name> | Change which configuration is currently in use | -To run a single command against a config other than the current one without -switching, pass `--config=` as the first argument: +To run a single command against a config other than the current one without switching, pass +`--config=` as the first argument: ```sh $ e --config=my-release build $ e --config=main-debug show root ``` -Getting the source code is a lot more than cloning `electron/electron`. -Electron is built on top of Chromium (with Electron patches) and Node -(with more Electron patches). A source tree needs to have all of the -above **and** for their versions to be in sync with each other. Electron -uses Chromium's [Depot Tools][depot-tools] and [GN][gn] for wrangling -and building the code. `e` wraps these tools: +Getting the source code is a lot more than cloning `electron/electron`. Electron is built on top of +Chromium (with Electron patches) and Node (with more Electron patches). A source tree needs to have +all of the above **and** for their versions to be in sync with each other. Electron uses Chromium's +[Depot Tools][depot-tools] and [GN][gn] for wrangling and building the code. `e` wraps these tools: | Command | Description | |:--------|:---------------------------------------------------------------| @@ -88,35 +95,45 @@ and building the code. `e` wraps these tools: | e sync | Get / update / synchronize source code branches | | e build | Build it! | -### `e init` +## Core workflow -`e init` initializes a new local development environment for Electron. +### `e init` -To see all potential options for this command, run: +Create a new local development environment for Electron. ```sh -$ e init --help +$ e init [options] ``` -New build configs are created with `e init`. It has several command-line -options to specify the build configuration, e.g. the path to the source -code, compile-time options, and so on. See `e init --help` for in-depth -details. +Each build config has a name, chosen by you to use as a mnemonic when switching between build +configs with `e use `. This is the name's only purpose, so choose whatever you find easiest to +work with — whether it's `electron`, `36-x-y--testing`, or `chocolate-onion-popsicle`. + +Each build also needs a root directory. All the source code and built files will be stored +somewhere beneath it. `e init` uses `$PWD/electron` by default, but you can choose your own with +`--root=/some/path`. If you want to make multiple build types of the same branch, you can reuse an +existing root to share it between build configs. + +**Options** -Each build config has a name, chosen by you to use as a mnemonic when -switching between build configs with `e use `. This is the name's -only purpose, so choose whatever you find easiest to work with — -whether it's `electron`, `6-1-x--testing`, or `chocolate-onion-popsicle`. +| Option | Description | +|:-----------------------------|:---------------------------------------------------------------------------------| +| `-r, --root ` | Root for source and build files (default: `$PWD/electron`) | +| `-i, --import ` | GN args file to import from `build/args/.gn` (default: `testing`) | +| `-o, --out ` | Output directory name under `$root/src/out/` (default: capitalized `--import`) | +| `-f, --force` | Overwrite an existing build config with the same name | +| `--asan`, `--tsan`, `--msan`, `--lsan` | Enable Clang's address / thread / memory / leak sanitizer | +| `--mas` | Build for the macOS App Store (macOS only) | +| `--target-cpu ` | Target architecture: `x86`, `x64`, `arm`, `arm64` | +| `--bootstrap` | Run `e sync` and `e build` immediately after creating the config | +| `--remote-build ` | Remote-execution backend: `siso` (default) or `none` | +| `--use-https` | Set git remotes with `https://` URLs instead of `git@github.com:` | +| `--fork ` | Add a remote named `fork` pointing at the given GitHub fork | -Each build also needs a root directory. All the source code and built -files will be stored somewhere beneath it. `e init` uses `$PWD/electron` -by default, but you can choose your own with `--root=/some/path`. If you -want to make multiple build types of the same branch, you can reuse -an existing root to share it between build configs. +**Example** -As an example, let's say you're starting from scratch and want both -testing and release builds of the main branch in `electron/electron`. -You might do this: +As an example, let's say you're starting from scratch and want both testing and release builds of +the main branch in `electron/electron`. You might do this: ```sh # making 'release' and 'testing' builds from main @@ -138,415 +155,626 @@ $ e show configs * main-release main-testing -$ e show current -main-release -$ e show root -~/src/electron - $ e use main-testing Now using config 'main-testing' -$ e show current -main-testing -$ e show root -~/src/electron ``` -As a convenience, `e init --bootstrap` will run `e sync` and `e build` -after creating the build config. Let's see what those do: +As a convenience, `e init --bootstrap` will run `e sync` and `e build` after creating the build +config. On macOS, `e init` also loads the required macOS SDKs. ### `e sync` -To see all potential options for this command, run: +Fetch or update the source tree. ```sh -$ e sync --help +$ e sync [--3] [gclientArgs...] ``` -`e sync` is a wrapper around `gclient sync` from [Depot Tools][depot-tools]. -If you're starting from scratch, this will (slowly) fetch all the source -code. It's also useful after switching Electron branches to synchronize -the rest of the sources to the versions needed by the new Electron branch. +`e sync` is a wrapper around `gclient sync` from [Depot Tools][depot-tools]. If you're starting +from scratch, this will (slowly) fetch all the source code. It's also useful after switching +Electron branches to synchronize the rest of the sources to the versions needed by the new Electron +branch. -`e sync` is usually all you need. Any extra args are passed along to gclient itself. +Any extra args are passed along to gclient. To make your output more verbose, you can add an +increasing number of `-v`s (e.g. `e sync -v`, `e sync -vvvv`). -```sh -$ e show current -main-testing - -$ e show root -~/src/electron - -$ e sync -Running "gclient sync --with_branch_heads --with_tags" in '~/src/electron/src' -[sync output omitted] -``` - -To make your output more verbose, you can add an increasing number of `-v`s. For example, +**Options** -```sh -# basic verbosity -$ e sync -v -Running "gclient sync --with_branch_heads --with_tags -v" in '~/src/electron/src' -[sync output omitted] - -# significant verbosity -$ e sync -vvvv -Running "gclient sync --with_branch_heads --with_tags -vvvv" in '~/src/electron/src' -[sync output omitted] -``` +| Option | Description | +|:-------------------|:--------------------------------------------------------------------------------| +| `--3, --three-way` | Apply Electron patches using a three-way merge. Useful when upgrading Chromium. | ### `e build` -`e build` builds an Electron executable. - -To see all potential options for this command, run: +Build an Electron executable. ```sh -$ e build --help +$ e build [options] [ninjaArgs...] ``` -Once you have the source, the next step is to build it with `e build --target [target]`. -Some of the build targets you may want to build include: - -| Target | Description | -|:--------------|:---------------------------------------------------------| -| third_party/breakpad:dump_syms | Builds the breakpad `dump_syms` binary | -| electron:electron_chromedriver_zip | Builds the `chromedriver` binary | -| electron | Builds the Electron binary **(Default)** | -| electron:electron_dist_zip | Builds the Electron binary and generates a dist zip file | -| electron:electron_mksnapshot_zip | Builds the `mksnapshot` binary | -| electron:node_headers | Builds the node headers `.tar.gz` file | -| electron:electron_symbols | Generate the breakpad symbols in release builds | - -To build a specific ninja target, run `e build --target [target]`: +Once you have the source, the next step is to build it. Running `e build` with no target will build +`electron` by default. -```sh -$ e build --target electron:node_headers -``` +To see an exhaustive list of all possible build targets, run `e d gn ls out/`, where `` +is e.g. `Testing` or `Release` depending on your build type. This will log a long list of targets +to the console and also allow you to build some of Chromium's targets. -Running `e build` with no target will build `electron` by default. +Any extra args are passed along to [ninja][ninja], so for example `e build -v` runs a verbose +build. -Any extra args are passed along to [ninja][ninja], so for example -`e build -v` runs a verbose build of `electron`. +**Options** -To see an exhaustive list of all possible build targets, you can run `e d gn ls out/[TYPE]`, -where `[TYPE]` is e.g. `Testing` or `Release` depending on your build type. This will log a long -list of targets to the console and also allow you to build some of Chromium's targets. +| Option | Description | +|:-----------------------|:----------------------------------------------------------------------------------------------------| +| `-t, --target `| Build a specific ninja target (default: `electron`, or `defaultTarget` from the config) | +| `--gen ` | Control `gn gen`: `on` (default, re-runs if args changed), `off` (skip), or `only` (run and exit) | +| `--no-remote` | Build entirely locally, disabling RBE / remote execution | -For example, running `e d gn ls out/Testing | grep "//ui/views/"` produces something like: +**Commonly used targets** -```console -//ui/views/controls/webview:test_support -//ui/views/controls/webview:webview -//ui/views/debug:views_debug -//ui/views/examples:copy_content_resources -//ui/views/examples:views_examples -//ui/views/examples:views_examples_lib -//ui/views/examples:views_examples_proc -//ui/views/examples:views_examples_resources_grd -//ui/views/examples:views_examples_resources_grd_grit -//ui/views/examples:views_examples_resources_pak -//ui/views/examples:views_examples_unittests -//ui/views/examples:views_examples_unittests__runner -//ui/views/examples:views_examples_with_content -//ui/views/examples:views_examples_with_content_lib -//ui/views/resources:resources -//ui/views/resources:resources_grd -//ui/views/resources:resources_grd_grit -//ui/views/window/vector_icons:vector_icons -//ui/views/window/vector_icons:window_control_vector_icons -``` +| Target | Description | +|:-------------------------------------|:---------------------------------------------------------| +| `electron` | Build the Electron binary **(default)** | +| `electron:electron_dist_zip` | Build the Electron binary and generate a dist zip | +| `electron:electron_chromedriver_zip` | Build the `chromedriver` binary | +| `electron:electron_mksnapshot_zip` | Build the `mksnapshot` binary | +| `electron:node_headers` | Build the node headers `.tar.gz` | +| `electron:electron_symbols` | Generate breakpad symbols (release builds) | +| `third_party/breakpad:dump_syms` | Build the breakpad `dump_syms` binary | -You could then run `e build --target ui/views/examples:views_examples_with_content` to produce Chrome's `//ui/views` example executable and run it with `./out/Testing/views_examples_with_content`. +For example, running `e d gn ls out/Testing | grep "//ui/views/"` will list Chromium's `//ui/views` +targets, and you can then `e build --target ui/views/examples:views_examples_with_content`. When first run, `e build` will try to set up reclient to speed up your builds. The permission prompt can look scary because GitHub's UI is less than optimal ([related discussion](https://github.com/orgs/community/discussions/37117)). However, Electron only -obtains user profile access and `read:org` permission. No permission is granted to any of your +obtains user-profile access and `read:org` permission. No permission is granted to any of your repositories or content. -## Using Electron +## Running Electron + +| Command | Description | +|:----------|:-------------------------------------| +| `e start` | Run the Electron build | +| `e node` | Run the Electron build as Node | +| `e debug` | Run the Electron build in a debugger | +| `e test` | Run Electron's spec runner | +| `e npm` | Run an npm command with the local Electron substituted for the published one | + +### `e start` + +Run the local Electron executable. Alias: `e run`. Extra args are forwarded to Electron. + +```sh +$ e start . +$ e start /path/to/app +$ e start /path/to/app --js-flags +``` -After you've built Electron, it's time to use it! +### `e node` -| Command | Description | -|:--------|:-------------------------------------| -| e start | Run the Electron build | -| e node | Run the Electron build as Node | -| e debug | Run the Electron build in a debugger | -| e test | Run Electron's spec runner | +Run the local Electron build as if it were Node (sets `ELECTRON_RUN_AS_NODE=1`). -As usual, any extra args are passed along to the executable. For example, -`e node --version` will print out Electron's node version. +```sh +$ e node --version # prints Electron's Node version +$ e node /path/to/script.js +``` ### `e debug` -`e debug` runs your local Electron build inside of [lldb][lldb] or [gdb][gdb]. +Run your local Electron build inside of [lldb][lldb] (macOS) or [gdb][gdb] (Linux). ```sh -$ uname -Linux $ e debug +# Linux: Reading symbols from /home/yourname/electron/gn/main/src/out/Testing/electron... (gdb) -``` -```sh -$ uname -Darwin - -$ e debug +# macOS: target create "/Users/yourname/electron-gn/src/out/Testing/Electron.app/Contents/MacOS/Electron" (lldb) ``` -### `e d` +### `e test` -`e d` runs [Depot Tools][depot-tools] commands. Some useful commands: +Start the local Electron build's test runner. Any extra args are passed along to the runner. ```sh -# run gclient sync directly -e d gclient sync - -# login to reclient -e d rbe login +# run all tests +$ e test -# check reclient status -e d rbe status +# run only main-process tests +$ e test --runners=main -# get the list of all build args -e d gn args --list -C out/Testing +# run Node.js' own test suite under Electron's `RUN_AS_NODE` mode +$ e test --node ``` -### `e test` +**Options** + +| Option | Description | +|:-------------------------------|:-------------------------------------------------------------------------------| +| `--electronVersion ` | Run against a published Electron release instead of your local build | +| `--node` | Run the Node.js spec runner (mutually exclusive with `--nan`) | +| `--nan` | Run the NaN spec runner (mutually exclusive with `--node`) | +| `--runners ` | Run a subset of the main Electron tests | +| `--disable-logging` | Don't pass `--enable-logging` to the spec runner | +| `--no-remote` | Build test-runner components (e.g. `node_headers`) without remote execution | -`e test` starts the local Electron build's test runner. Any extra args are passed -along to the runner. +### `e npm` -To see all potential options for this command, run: +Run an npm command with `ELECTRON_OVERRIDE_DIST_PATH` set so that any spawned `electron` binary is +your local from-source build instead of the one installed from npm. ```sh -$ e test --help +$ e npm test +$ e npm run start ``` -Example: +Useful for testing your local Electron against an app's existing `electron` dependency. + +## Inspecting state + +### `e show` + +Show information about the current build config. + +| Subcommand | Description | +|:--------------------|:----------------------------------------------------------------------------------------| +| `e show current` | Print the active config name. `-g/--git` appends git status; `-f/--filepath` the path. | +| `e show configs` | List all build configs (active is marked with `*`). Alias: `e show ls`. | +| `e show env` | Environment variables injected by the active config (diffed against your current env). Add `--json` for JSON. | +| `e show exe` | Path of the built Electron executable. Alias: `e show exec`. | +| `e show root` | Path of the root directory — home of `.gclient`. | +| `e show src [name]` | Path of a named source dir (default: `electron`). E.g. `e show src base`. | +| `e show out` | The outdir name (e.g. `Testing`). Pass `--path` for the absolute path. | +| `e show depotdir` | Path of the depot-tools directory that build-tools manages. | + +**Example** ```sh -# run all tests -e test +$ e show exe +/Users/username/electron-gn-root/src/out/Testing/Electron.app/Contents/MacOS/Electron + +$ e show out +Testing + +$ cd `e show src base` && pwd +/home/username/electron-gn-root/src/base -# run main process tests -e test --runners=main +$ ripgrep --t h TakeHeapSnapshot `e show src` ``` -Possible extra arguments to pass: +### `e shell` -* `--node` - Run Node.js' own tests with Electron in `RUN_AS_NODE` mode. -* `--runners=` - The set of tests to run, can be either `main` or `native`. +Launch a shell environment populated with build-tools' environment variables and context. Useful +for invoking `gn` and `ninja` directly (instead of through `e d`), for bash completion, and for +copy-pasting commands from Chromium docs unchanged. -### `e show` +```sh +$ e shell +# Launching build-tools shell with "/bin/zsh" +``` + +Not supported on Windows. -`e show` shows information about the current build config. +## Working with code -To see all potential options for this command, run: +### `e patches` + +Refresh patches in `$root/src/electron/patches/`. ```sh -$ e show --help +$ e patches ``` -| Command | Description | -|:-------------------|:---------------------------------------------------------------| -| e show current | The name of the active build config | -| e show configs | Lists all build configs | -| e show env | Show environment variables injected by the active build config | -| e show exe | The path of the built Electron executable | -| e show root | The path of the root directory from `e init --root`. | -| e show src \[name] | The path of the named (default: electron) source dir | -| e show stats | Build statistics | +**Options** + +| Option | Description | +|:---------------------|:--------------------------------------------------------------------------------------------------| +| `-c, --config `| Override the patches config (default: `$root/src/electron/patches/config.json`) | +| `--list-targets` | Print all supported patch targets | +| `--commit-updates` | Auto-commit non-content patch changes (rebuilt offsets, etc.). Skips files with content diffs. | -Example usage: +Supported targets are defined in Electron's `patches/config.json` and typically include: + +| Target | Source Directory | Patch Directory | +|:------------|:-----------------------------------|:----------------------------------| +| `node` | `src/third_party/electron_node` | `src/electron/patches/node` | +| `chromium` | `src` | `src/electron/patches/chromium` | +| `boringssl` | `src/third_party/boringssl/src` | `src/electron/patches/boringssl` | +| `v8` | `src/v8` | `src/electron/patches/v8` | +| `perfetto` | `src/third_party/perfetto` | `src/electron/patches/perfetto` | +| `icu` | `src/third_party/icu` | `src/electron/patches/icu` | + +Use `e patches all` to refresh every target, or `e patches --list-targets` to see the full list for +your checkout. + +### `e open` + +Open the GitHub page for a commit, pull request, or issue. ```sh -$ uname -Darwin +$ e open +``` -$ e show exe -/Users/username/electron-gn-root/src/out/Testing/Electron.app/Contents/MacOS/Electron +`e open 0920d01` finds the commit with abbreviated sha1 `0920d01`, looks up its associated PR, and +opens `https://github.com/electron/electron/pull/` in your browser. Since you can also pass +a number directly, `e open 23450` opens that PR or issue. Pass `--print` to print the URL instead. -$ uname -Linux +### `e pr` -$ e show exe -/home/username/electron-gn-root/src/out/Testing/electron +Work with pull requests to `electron/electron`. -$ e show out -Testing +| Subcommand | Description | +|:------------------------|:-----------------------------------------------------------------------------------------------------------------| +| `e pr open` | Open a GitHub compare URL for creating a PR (default subcommand; `e pr` is the same). | +| `e pr download-dist ` | Download built artifacts from the latest Build workflow run of a PR. | -$ e show src -/home/username/electron-gn-root/src/electron +**`e pr open` options** -$ cd `e show src base` && pwd -/home/username/electron-gn-root/src/base +| Option | Description | +|:---------------------------|:------------------------------------------------------------------------------------| +| `-s, --source ` | Source branch (default: current HEAD) | +| `-t, --target ` | Target branch (default: guessed from the Electron version in your checkout) | +| `-b, --backport ` | Pre-fill the PR body with notes and title from the original PR being backported | -$ ripgrep --t h TakeHeapSnapshot `e show src` +**`e pr download-dist` options** + +| Option | Description | +|:---------------------------|:------------------------------------------------------------------------------------------------------------| +| `--platform ` | Platform to download (default: current) | +| `--arch ` | Architecture (default: current) | +| `-o, --output ` | Artifact output directory (default: `~/.electron_build_tools/artifacts/pr_{number}_{hash}_{platform}_{arch}`) | +| `-s, --skip-confirmation` | Skip the confirmation prompt (enabled automatically in CI) | + +`e pr download-dist` requires a GitHub token — see [`e gh-auth`](#e-gh-auth). + +### `e backport` + +Assist with a manual backport for a given PR. + +```sh +$ e backport ``` -### `e remove ` +It reads `needs-manual-bp/*` labels on the PR to find target branches, prompts you to choose one, +checks it out, updates it, and cherry-picks the merge commit. If conflicts arise, resolve them and +continue the cherry-pick yourself; then use `e pr open --backport ` to raise the backport PR. -`e remove|rm ` removes a build config from the list. +```sh +$ e backport 1234 +# select branch you want to backport PR to +30-x-y +# resolve any merge conflicts +$ git cherry-pick --continue +$ git push +$ e pr open --backport 1234 +``` -### `e open ` +Requires a GitHub token — see [`e gh-auth`](#e-gh-auth). -`e open` opens the GitHub page for the specified commit, pull request, or issue. +### `e cherry-pick` -To see all potential options for this command, run: +Open a PR to `electron/electron` that cherry-picks an upstream CL into our patches folder. Alias: +`e auto-cherry-pick`. ```sh -$ e open --help +$ e cherry-pick [additionalBranchesOrUrls...] ``` -For example, `e open 0920d01` will find the commit with an abbreviated -sha1 of `0920d01`, see that it's associated with pull request #23450, -and open https://github.com/electron/electron/pull/23450 in your browser. -Since you can pass in a pull request or issue number as well, -`e open 23450` would have the same effect. +Supported patch URLs are Gerrit CLs (Chromium / V8 / DevTools) and Node.js GitHub commit URLs. +You may pass multiple target branches and/or multiple patch URLs in one invocation; the tool will +bundle them into one PR per target branch. + +**Options** + +| Option | Description | +|:-------------------|:-------------------------------------------------------------------------------------------| +| `--security` | Mark as a security backport (adjusts labels, PR template, and CVE handling) | +| `--no-cve-lookup` | Skip the `issues.chromium.org` CVE lookup (and the interactive cookie borrow it requires) | -### `e patches [patch-dir]` +Requires a GitHub token — see [`e gh-auth`](#e-gh-auth). -`e patches` exports patches to the specified patch directory in Electron source tree. +### `e rcv` -To see all potential options for this command, run: +Reconstruct an intermediate Chromium version from a roll PR (useful for bisecting a Chromium roll). +Alias: `e reconstruct-chromium-version`. ```sh -$ e patches --help +$ e rcv [chromium-version-or-sha] ``` -Valid patch directories can include: +Fetches the Chromium versions between the roll's base and head, optionally prompts you to pick an +intermediate version, checks out the parent of the roll's merge commit, creates a branch +`rcv/pr//version/`, and cherry-picks the CLs that fall within the chosen version +range. Also regenerates generated files (`gen-hunspell-filenames.js`, `gen-libc++-filenames.js`). -* `node` -* `v8` -* `boringssl` -* `chromium` -* `perfetto` -* `icu` +**Options** -| Command | Source Directory | Patch Directory | -|:---------------------|:-----------------------------------|:----------------------------------| -| e patches node | `src/third_party/electron_node` | `src/electron/patches/node` | -| e patches chromium | `src` | `src/electron/patches/chromium` | -| e patches boringssl | `src/third_party/boringssl/src` | `src/electron/patches/boringssl` | -| e patches v8 | `src/v8` | `src/electron/patches/v8` | -| e patches perfetto | `src/third_party/perfetto` | `src/electron/patches/perfetto` | -| e patches icu | `src/third_party/icu` | `src/electron/patches/icu` | +| Option | Description | +|:-----------------------------|:----------------------------------------------------------------------------------| +| `--sort` | Sort cherry-picked commits by CL merge time | +| `--merge-strategy-option` | Git merge strategy option when cherry-picking (default: `theirs`) | -[depot-tools]: https://commondatastorage.googleapis.com/chrome-infra-docs/flat/depot_tools/docs/html/depot_tools_tutorial.html#_setting_up -[gdb]: https://web.eecs.umich.edu/~sugih/pointers/summary.html -[gn-configs]: https://github.com/electron/electron/tree/main/build/args -[gn]: https://chromium.googlesource.com/chromium/src/tools/gn/+/48062805e19b4697c5fbd926dc649c78b6aaa138/README.md -[lldb]: https://lldb.llvm.org/use/tutorial.html -[ninja]: https://ninja-build.org -[nvm]: https://github.com/nvm-sh/nvm -[platform-prerequisites]: https://electronjs.org/docs/development/build-instructions-gn#platform-prerequisites -[sanitizers]: https://github.com/google/sanitizers +Requires a GitHub token — see [`e gh-auth`](#e-gh-auth). -### `e sanitize-config ` +## Managing configs -`e sanitize-config` updates and/or overwrites an existing config to conform to latest `build-tools` updates. - -To see all potential options for this command, run: +### `e use` ```sh -$ e sanitize-config --help +$ e use ``` -Sometimes `build-tools` will make updates to its config requirements. In these events warnings will be output to console to inform you that `build-tools` has temporarily handled the issues. You can make these warnings go away either by manually updating your config files or by running this command to automatically overwrite the existing configs to update formatting. +Switch the active build config. -### `e shell` +### `e remove` -`e shell` launches a shell environment populated with build-tools' environment variables and context. +```sh +$ e remove # alias: e rm +``` + +Delete a build config from the list. Does not touch the source tree or build output. -Developers may for example find themselves wishing to access `gn` and `ninja` directly - instead of using `e d gn` to access that this command can be used. This also enables bash completion and the ability to copy-paste commands from Chromium docs without modification. +### `e sanitize-config` ```sh -$ e shell -# Launching build-tools shell with "/bin/zsh" -# Running "/bin/zsh" +$ e sanitize-config [name] ``` -### `e backport ` +Update an existing config to conform to the latest build-tools schema. Sometimes `build-tools` will +make changes to its config requirements; in those cases, warnings are printed and the issue is +handled temporarily at load time. Running `e sanitize-config` rewrites the file to the new format, +so the warnings go away for good. Defaults to the current config if no name is given. -`e backport ` assists with manual backport processes on the specified pull request. +### `e worktree` -To see all potential options for this command, run: +Manage additional gclient working directories that share git objects with an existing checkout. +Useful when you want to iterate on multiple branches or configs simultaneously without re-syncing +full Chromium trees. Unix only (requires symlinks). + +| Subcommand | Description | +|:--------------------------------------|:------------------------------------------------------------------| +| `e worktree add ` | Create a new worktree + matching build config from an existing one | +| `e worktree clean ` | Delete a worktree directory and its build config | + +**`e worktree add` options** + +| Option | Description | +|:--------------------|:---------------------------------------------------------------------------------------------| +| `--source ` | Build config to clone from (default: current) | +| `-o, --out ` | Output directory under `$root/src/out/` (default: same as source) | +| `--no-sync` | Skip running `e sync` after creating the worktree | +| `-f, --force` | Overwrite an existing build config of the same name | + +**`e worktree clean` options** + +| Option | Description | +|:---------|:------------------------------------------------------------------------------------------------------| +| `--yes` | Confirm deletion (required — this removes the entire worktree directory) | + +`clean` will refuse to delete a worktree that isn't symlinked from an `e worktree add`, and will +refuse to delete the currently-active config — `e use` somewhere else first. + +**Example** ```sh -$ e backport --help +$ e worktree add testing2 ~/src/electron2 +$ e worktree add asan ~/src/electron-asan --source testing -o Asan --no-sync +$ e worktree clean testing2 --yes ``` -Example: +### `e load-macos-sdk` ```sh -# select the PR to backport -e backport 1234 +$ e load-macos-sdk [version] +``` -# select branch you want to backport PR to -30-x-y +Downloads and symlinks the macOS SDK(s) required by the current config into the Chromium checkout +(may require `sudo`). Called automatically by `e init`, `e sync`, and `e build` on macOS; you'll +rarely need to run it directly. The config's `preserveSDK` field controls how many recent SDKs are +kept on disk (default: 5). -# resolve any merge conflicts -git cherry-pick --continue +## Infrastructure -# push changes -git push +### `e depot-tools` -# create pull request -e pr open --backport 1234 +```sh +$ e depot-tools # alias: e d ``` -## Common Usage +Run a command against the depot-tools checkout that `build-tools` manages, with the environment +set up correctly for the current config. Some useful examples: + +```sh +# run gclient sync directly +$ e d gclient sync + +# login to reclient +$ e d rbe login + +# check reclient status +$ e d rbe status + +# list all GN build args +$ e d gn args --list -C out/Testing +``` -### Building a Specific Electron Version +`e d auto-update enable|disable` toggles auto-updates for depot-tools itself (separate from +build-tools' own auto-update). -`e init` checks out the HEAD of the main branch. To build against a specific version of Electron, checkout that version with these commands: +### `e gh-auth` ```sh -# Change working directory to the Electron source directory -cd `e show src` +$ e gh-auth [--shell] +``` -# Checkout the desired Electron version (in this case, 11.0.0) -git checkout tags/v11.0.0 -b v11.0.0 +Generate a device-flow OAuth token for the Electron GitHub org. The token is used by `e pr`, +`e backport`, `e cherry-pick`, and `e rcv`. -# Sync dependencies with the current branch -e sync +Pass `--shell` to print an `export` statement suitable for sourcing: -# Build Electron -e build +```sh +$ eval $(e gh-auth --shell) ``` -## Advanced Usage +The token is read from the `ELECTRON_BUILD_TOOLS_GH_AUTH` environment variable. + +### `e auto-update` + +Manage build-tools' own updates. Alias: `e check-for-updates`. + +| Subcommand | Description | +|:------------------------|:----------------------------------------------------------------------------| +| `e auto-update` | Check for updates and apply them immediately | +| `e auto-update check` | Same as above | +| `e auto-update enable` | Enable the 4-hour background update check | +| `e auto-update disable` | Disable the background update check | + +With the default configuration, build-tools automatically checks for updates every 4 hours. +Auto-update is skipped entirely if `BUILD_TOOLS_SHA` is set (i.e. you've checked out a specific +commit for debugging). + +## Configuration file reference + +Build configs live in `configs/` as JSON or YAML files named `evm..`. The +currently-active config is tracked in `configs/evm-current.txt` (or `EVM_CURRENT_FILE` — see +[Advanced](#per-session-active-configs)). The full schema is declared in +[`evm-config.schema.json`](./evm-config.schema.json) and validated on every load. + +See [`example-configs/`](./example-configs/) for annotated templates (`evm.base.yml`, +`evm.testing.yml`, `evm.release.yml`, `evm.chromium.yml`). + +**Top-level fields** + +| Field | Type | Description | +|:------------------------|:--------------------------------------|:-------------------------------------------------------------------------------------| +| `root` | string | Top directory — home of `.gclient` | +| `remotes.electron.origin` | string | Origin git URL for `electron/electron` (ssh or https) | +| `remotes.electron.fork` | string (optional) | Optional fork remote URL | +| `gen.args` | string[] | GN arguments written to `out//args.gn` | +| `gen.out` | string | Output directory name (e.g. `Testing`) | +| `env.CHROMIUM_BUILDTOOLS_PATH` | string | Path to Chromium buildtools inside the checkout | +| `env.GIT_CACHE_PATH` | string (optional) | Git cache path for gclient (shared across configs) | +| `env.*` | string | Any additional env vars to inject into build-tools' subprocesses | +| `defaultTarget` | string (default: `electron`) | Default ninja target for `e build` | +| `execName` | string (default: `Electron`) | Name of the built executable for `e start` | +| `remoteBuild` | `siso` \| `reclient` \| `none` | Which remote-execution backend to use | +| `rbeHelperPath` | string (optional) | Path to a custom RBE credential helper | +| `rbeServiceAddress` | string (optional) | Alternative RBE cluster address | +| `preserveSDK` | integer (default: 5) | Number of recent macOS SDKs to keep on disk | +| `configValidationLevel` | `strict` \| `warn` \| `none` | How strictly to validate the config file (default: `strict`) | +| `extends` | string (optional) | Name of a base config to inherit from; arrays concatenate and objects deep-merge | +| `$schema` | URI | Reference to `evm-config.schema.json` for editor validation | + +A config must supply **one** of: + +1. `extends` (inherit everything from another config), **or** +2. `root` + `remotes` + `gen` + `env` (a full Electron build), **or** +3. `defaultTarget: chrome` + `root` + `env` (a Chromium-only build). + +**Config inheritance (`extends`)** — useful for keeping shared fields (git cache path, buildtools +path, git remotes) in a base config and deriving per-variant configs from it: + +```yaml +# evm.base.yml +root: /Users/me/src/electron +remotes: + electron: + origin: git@github.com:electron/electron.git +env: + CHROMIUM_BUILDTOOLS_PATH: /Users/me/src/electron/src/buildtools + GIT_CACHE_PATH: /Users/me/.git_cache + +# evm.testing.yml +extends: base +gen: + args: + - import("//electron/build/args/testing.gn") + out: Testing +``` + +**Preferred format on save** — by default `e init` and `e sanitize-config` write JSON. Set +`EVM_FORMAT=yml` to prefer YAML. + +## Environment variables -### Per-Session Active Configs +| Variable | Purpose | +|:-------------------------------------|:----------------------------------------------------------------------------------------------------| +| `EVM_CONFIG` | Override the configs directory (default: `/configs`) | +| `EVM_CURRENT` | Override the active config for the current process (set internally by `--config=`) | +| `EVM_CURRENT_FILE` | Alternative location for the active-config pointer file. Enables per-session active configs. | +| `EVM_FORMAT` | Preferred on-disk format for configs when saving: `json` (default), `yml`, or `yaml` | +| `BUILD_TOOLS_SHA` | If set, skip the auto-update check (useful when you've checked out a specific build-tools commit) | +| `DEPOT_TOOLS_DIR` | Override the depot-tools directory (default: `/.depot_tools`) | +| `GIT_CACHE_PATH` | Consumed by `e init` as the default for new configs' `env.GIT_CACHE_PATH` | +| `GN_EXTRA_ARGS` | When `CI=1`, appended to the GN args for `e build` (space-separated `key=value` tokens) | -If you want your shell sessions to each have different active configs, try this in your `~/.profile` or `~/.zshrc` or `~/.bashrc`: +## Shell completion + +A zsh completion script lives at [`tools/zsh/_e`](./tools/zsh/_e). Source it from your `.zshrc` +(or symlink it into an `fpath` directory) to get completion for subcommands, options, config +names, and build targets. + +## Advanced + +### Building a specific Electron version + +`e init` checks out the HEAD of the main branch. To build against a specific version: ```sh -export EVM_CURRENT_FILE="$(mktemp --tmpdir evm-current.XXXXXXXX.txt)" +# change to the Electron source directory +$ cd `e show src` + +# check out the desired Electron version (in this case, 11.0.0) +$ git checkout tags/v11.0.0 -b v11.0.0 + +# sync dependencies with the current branch +$ e sync + +# build +$ e build ``` -This will create per-shell temporary files in which the active config file can be changed with `e use`. +### Per-session active configs + +If you want your shell sessions to each have different active configs, try this in your +`~/.profile` / `~/.zshrc` / `~/.bashrc`: -### Disabling Automatic Updates +```sh +export EVM_CURRENT_FILE="$(mktemp --tmpdir evm-current.XXXXXXXX.txt)" +``` -With the default configuration, build-tools will automatically check for updates every 4 hours. +This creates per-shell temporary files in which the active config can be changed with `e use`, +without affecting other shells. -You can enable and disable these automatic updates with the following commands: +### Disabling automatic updates + +Build-tools automatically checks for updates every 4 hours. You can toggle this: ```sh $ e auto-update enable $ e auto-update disable ``` -Regardless of whether automatic updates are enabled, you can manually call the following command to immediately trigger an update. +Regardless, you can trigger an update immediately with `e auto-update check`. + +### Appending GN args in CI + +In CI (`CI=1`), `GN_EXTRA_ARGS` is appended to the GN args read from your config. This is a handy +way to override args without editing the config file: ```sh -$ e auto-update check +$ CI=1 GN_EXTRA_ARGS="is_official_build=true" e build ``` + +[depot-tools]: https://commondatastorage.googleapis.com/chrome-infra-docs/flat/depot_tools/docs/html/depot_tools_tutorial.html#_setting_up +[gdb]: https://web.eecs.umich.edu/~sugih/pointers/summary.html +[gn-configs]: https://github.com/electron/electron/tree/main/build/args +[gn]: https://gn.googlesource.com/gn/+/main/docs/reference.md +[lldb]: https://lldb.llvm.org/use/tutorial.html +[ninja]: https://ninja-build.org +[nvm]: https://github.com/nvm-sh/nvm +[platform-prerequisites]: https://electronjs.org/docs/development/build-instructions-gn#platform-prerequisites +[sanitizers]: https://github.com/google/sanitizers