From d212bc71708441b47489119f64d6748a4e2861c2 Mon Sep 17 00:00:00 2001 From: David Sanders Date: Fri, 1 May 2026 14:26:36 -0700 Subject: [PATCH] build: create a symlink to src/buildtools during sync Assisted-by: Claude Opus 4.6 --- .devcontainer/on-create-command.sh | 1 - .github/workflows/pipeline-electron-lint.yml | 12 ++--- .../pipeline-segment-electron-build.yml | 2 - .../pipeline-segment-electron-clang-tidy.yml | 2 - .../pipeline-segment-electron-gn-check.yml | 7 ++- .../pipeline-segment-electron-publish.yml | 2 - DEPS | 9 ++++ docs/development/build-instructions-gn.md | 21 -------- script/create-buildtools-symlink.py | 50 +++++++++++++++++++ script/gn-check.js | 4 -- script/lib/util.py | 5 -- script/lib/utils.js | 4 -- script/lint.js | 15 ++---- 13 files changed, 72 insertions(+), 62 deletions(-) create mode 100644 script/create-buildtools-symlink.py diff --git a/.devcontainer/on-create-command.sh b/.devcontainer/on-create-command.sh index 6a441b3a0f..2181b1e92d 100755 --- a/.devcontainer/on-create-command.sh +++ b/.devcontainer/on-create-command.sh @@ -54,7 +54,6 @@ if [ ! -f $buildtools/configs/evm.testing.json ]; then \"out\": \"Testing\" }, \"env\": { - \"CHROMIUM_BUILDTOOLS_PATH\": \"/workspaces/gclient/src/buildtools\", \"GIT_CACHE_PATH\": \"/workspaces/gclient/.git-cache\" }, \"\$schema\": \"file:///home/builduser/.electron_build_tools/evm-config.schema.json\", diff --git a/.github/workflows/pipeline-electron-lint.yml b/.github/workflows/pipeline-electron-lint.yml index bcc12e72d0..e580711b59 100644 --- a/.github/workflows/pipeline-electron-lint.yml +++ b/.github/workflows/pipeline-electron-lint.yml @@ -57,9 +57,6 @@ jobs: @Subdir src/buildtools/linux64 gn/gn/linux-amd64 $gn_version CIPD - - buildtools_path="$(pwd)/src/buildtools" - echo "CHROMIUM_BUILDTOOLS_PATH=$buildtools_path" >> $GITHUB_ENV - name: Download clang-format Binary shell: bash run: | @@ -80,11 +77,10 @@ jobs: - name: Run Lint shell: bash run: | - # gn.py tries to find a gclient root folder starting from the current dir. - # When it fails and returns "None" path, the whole script fails. Let's "fix" it. - touch .gclient - # Another option would be to checkout "buildtools" inside the Electron checkout, - # but then we would lint its contents (at least gn format), and it doesn't pass it. + # Clean things up so `depot_tools/gclient_paths.py` finds src/buildtools properly + echo '' > .gclient + rm -f .gclient_entries + ln -s src/buildtools buildtools cd src/electron node script/yarn.js install --immutable diff --git a/.github/workflows/pipeline-segment-electron-build.yml b/.github/workflows/pipeline-segment-electron-build.yml index b8aa494efa..a6b045392f 100644 --- a/.github/workflows/pipeline-segment-electron-build.yml +++ b/.github/workflows/pipeline-segment-electron-build.yml @@ -189,8 +189,6 @@ jobs: run: | (cd src/electron && git checkout .) && node src/electron/script/generate-deps-hash.js echo "DEPSHASH=$(cat src/electron/.depshash)" >> $GITHUB_ENV - - name: Add CHROMIUM_BUILDTOOLS_PATH to env - run: echo "CHROMIUM_BUILDTOOLS_PATH=$(pwd)/src/buildtools" >> $GITHUB_ENV - name: Free up space (macOS) if: ${{ inputs.target-platform == 'macos' }} uses: ./src/electron/.github/actions/free-space-macos diff --git a/.github/workflows/pipeline-segment-electron-clang-tidy.yml b/.github/workflows/pipeline-segment-electron-clang-tidy.yml index 0f34bebc0c..1694d24669 100644 --- a/.github/workflows/pipeline-segment-electron-clang-tidy.yml +++ b/.github/workflows/pipeline-segment-electron-clang-tidy.yml @@ -111,8 +111,6 @@ jobs: run: | (cd src/electron && git checkout .) && node src/electron/script/generate-deps-hash.js echo "DEPSHASH=$(cat src/electron/.depshash)" >> $GITHUB_ENV - - name: Add CHROMIUM_BUILDTOOLS_PATH to env - run: echo "CHROMIUM_BUILDTOOLS_PATH=$(pwd)/src/buildtools" >> $GITHUB_ENV - name: Checkout Electron uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd with: diff --git a/.github/workflows/pipeline-segment-electron-gn-check.yml b/.github/workflows/pipeline-segment-electron-gn-check.yml index ef5b69210c..4ad68c6d1d 100644 --- a/.github/workflows/pipeline-segment-electron-gn-check.yml +++ b/.github/workflows/pipeline-segment-electron-gn-check.yml @@ -112,8 +112,6 @@ jobs: run: | (cd src/electron && git checkout .) && node src/electron/script/generate-deps-hash.js echo "DEPSHASH=$(cat src/electron/.depshash)" >> $GITHUB_ENV - - name: Add CHROMIUM_BUILDTOOLS_PATH to env - run: echo "CHROMIUM_BUILDTOOLS_PATH=$(pwd)/src/buildtools" >> $GITHUB_ENV - name: Checkout Electron uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd with: @@ -128,6 +126,11 @@ jobs: git pack-refs - name: Run GN Check for ${{ inputs.target-archs }} run: | + # `depot_tools/gclient_paths.py` tries to find a gclient root folder starting from the current dir. + # We also need to set up a symlink to src/buildtools so that `build-tools` can find it properly. + touch .gclient + ln -s src/buildtools buildtools + for target_cpu in ${{ inputs.target-archs }} do e init -f --root=$(pwd) --out=Default ${{ inputs.gn-build-type }} --import ${{ inputs.gn-build-type }} --target-cpu $target_cpu --remote-build none diff --git a/.github/workflows/pipeline-segment-electron-publish.yml b/.github/workflows/pipeline-segment-electron-publish.yml index 4e2e9e0ff4..215556a8c8 100644 --- a/.github/workflows/pipeline-segment-electron-publish.yml +++ b/.github/workflows/pipeline-segment-electron-publish.yml @@ -202,8 +202,6 @@ jobs: src/electron/script/generate-deps-hash.js echo "DEPSHASH=$(cat src/electron/.depshash)" >> $GITHUB_ENV - - name: Add CHROMIUM_BUILDTOOLS_PATH to env - run: echo "CHROMIUM_BUILDTOOLS_PATH=$(pwd)/src/buildtools" >> $GITHUB_ENV - name: Free up space (macOS) if: ${{ inputs.target-platform == 'macos' }} uses: ./src/electron/.github/actions/free-space-macos diff --git a/DEPS b/DEPS index 73c23a1f6e..47308796b0 100644 --- a/DEPS +++ b/DEPS @@ -155,6 +155,15 @@ hooks = [ 'import os, subprocess; os.chdir(os.path.join("src", "electron")); subprocess.check_call(["node", ".yarn/releases/yarn-4.12.0.cjs", "install", "--immutable"]);', ], }, + { + 'name': 'buildtools_symlink', + 'condition': 'checkout_chromium and process_deps', + 'pattern': 'src/electron', + 'action': [ + 'python3', + 'src/electron/script/create-buildtools-symlink.py', + ], + }, { 'name': 'sysroot_arm', 'pattern': '.', diff --git a/docs/development/build-instructions-gn.md b/docs/development/build-instructions-gn.md index 4d1037f26b..ffd8e58e66 100644 --- a/docs/development/build-instructions-gn.md +++ b/docs/development/build-instructions-gn.md @@ -173,27 +173,6 @@ $ gclient sync -f ### Building -**Set the environment variable for chromium build tools** - -On Linux & MacOS - -```sh -$ cd src -$ export CHROMIUM_BUILDTOOLS_PATH=`pwd`/buildtools -``` - -On Windows: - -```sh -# cmd -$ cd src -$ set CHROMIUM_BUILDTOOLS_PATH=%cd%\buildtools - -# PowerShell -$ cd src -$ $env:CHROMIUM_BUILDTOOLS_PATH = "$(Get-Location)\buildtools" -``` - **To generate Testing build config of Electron:** On Linux & MacOS diff --git a/script/create-buildtools-symlink.py b/script/create-buildtools-symlink.py new file mode 100644 index 0000000000..73cec08f81 --- /dev/null +++ b/script/create-buildtools-symlink.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +"""Create a buildtools symlink in the gclient root directory. + +This enables gclient_paths.py to locate buildtools without needing the +CHROMIUM_BUILDTOOLS_PATH environment variable. +""" + +import os +import sys + + +def main(): + electron_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + src_dir = os.path.dirname(electron_dir) + gclient_root = os.path.dirname(src_dir) + + source = os.path.join(src_dir, 'buildtools') + link_name = os.path.join(gclient_root, 'buildtools') + + if not os.path.isdir(source): + print(f'buildtools not found at {source}', file=sys.stderr) + return 1 + + # Already a symlink - verify it points to the right place. + if os.path.islink(link_name): + if os.path.realpath(link_name) == os.path.realpath(source): + return 0 + os.remove(link_name) + elif os.path.exists(link_name): + # A real file or directory we shouldn't clobber. + print(f'{link_name} already exists and is not a symlink', + file=sys.stderr) + return 1 + + rel = os.path.relpath(source, gclient_root) + try: + os.symlink(rel, link_name, target_is_directory=True) + except OSError as e: + print(f'Failed to create symlink {link_name} -> {rel}: {e}', + file=sys.stderr) + if sys.platform == 'win32': + print('On Windows, creating symlinks requires Developer Mode ' + 'or administrator privileges.', file=sys.stderr) + return 1 + + return 0 + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/script/gn-check.js b/script/gn-check.js index c984f6b4dc..5b420c2f8a 100644 --- a/script/gn-check.js +++ b/script/gn-check.js @@ -7,14 +7,11 @@ $ node ./script/gn-check.js [--outDir=dirName] const minimist = require('minimist'); const cp = require('node:child_process'); -const path = require('node:path'); const args = minimist(process.argv.slice(2), { string: ['outDir'] }); const { getDepotToolsEnv, getOutDir } = require('./lib/utils'); -const SOURCE_ROOT = path.normalize(path.dirname(__dirname)); - const OUT_DIR = getOutDir({ outDir: args.outDir }); if (!OUT_DIR) { throw new Error('No viable out dir: one of Debug, Testing, or Release must exist.'); @@ -22,7 +19,6 @@ if (!OUT_DIR) { const env = { ...getDepotToolsEnv(), - CHROMIUM_BUILDTOOLS_PATH: path.resolve(SOURCE_ROOT, '..', 'buildtools'), DEPOT_TOOLS_WIN_TOOLCHAIN: '0' }; diff --git a/script/lib/util.py b/script/lib/util.py index d073bdbedd..fcfaeb2652 100644 --- a/script/lib/util.py +++ b/script/lib/util.py @@ -233,9 +233,4 @@ def get_depot_tools_env(): if depot_tools_env is None: raise RuntimeError("Couldn't find depot_tools, ensure it's on your PATH") - if 'CHROMIUM_BUILDTOOLS_PATH' not in depot_tools_env: - raise RuntimeError( - 'CHROMIUM_BUILDTOOLS_PATH environment variable must be set' - ) - return depot_tools_env diff --git a/script/lib/utils.js b/script/lib/utils.js index 1211d5b881..8179190614 100644 --- a/script/lib/utils.js +++ b/script/lib/utils.js @@ -194,10 +194,6 @@ function getDepotToolsEnv() { throw new Error("Couldn't find depot_tools, ensure it's on your PATH"); } - if (!('CHROMIUM_BUILDTOOLS_PATH' in depotToolsEnv)) { - throw new Error('CHROMIUM_BUILDTOOLS_PATH environment variable must be set'); - } - return depotToolsEnv; } diff --git a/script/lint.js b/script/lint.js index 3c82f07de8..9c02e20c52 100755 --- a/script/lint.js +++ b/script/lint.js @@ -116,13 +116,11 @@ const LINTERS = [ roots: ['shell'], test: (filename) => filename.endsWith('.cc') || (filename.endsWith('.h') && !isObjCHeader(filename)), run: (opts, filenames) => { - const env = { - ...getDepotToolsEnv(), - CHROMIUM_BUILDTOOLS_PATH: path.resolve(ELECTRON_ROOT, '..', 'buildtools') - }; const clangFormatFlags = opts.fix ? ['--fix'] : []; for (const chunk of chunkFilenames(filenames)) { - spawnAndCheckExitCode('python3', ['script/run-clang-format.py', ...clangFormatFlags, ...chunk], { env }); + spawnAndCheckExitCode('python3', ['script/run-clang-format.py', ...clangFormatFlags, ...chunk], { + env: getDepotToolsEnv() + }); cpplint([`--filter=${CPPLINT_FILTERS.join(',')}`, ...chunk]); } } @@ -132,13 +130,9 @@ const LINTERS = [ roots: ['shell'], test: (filename) => filename.endsWith('.mm') || (filename.endsWith('.h') && isObjCHeader(filename)), run: (opts, filenames) => { - const env = { - ...getDepotToolsEnv(), - CHROMIUM_BUILDTOOLS_PATH: path.resolve(ELECTRON_ROOT, '..', 'buildtools') - }; const clangFormatFlags = opts.fix ? ['--fix'] : []; spawnAndCheckExitCode('python3', ['script/run-clang-format.py', '-r', ...clangFormatFlags, ...filenames], { - env + env: getDepotToolsEnv() }); const filter = [...CPPLINT_FILTERS, '-readability/braces']; cpplint(['--extensions=mm,h', `--filter=${filter.join(',')}`, ...filenames]); @@ -175,7 +169,6 @@ const LINTERS = [ .map((filename) => { const env = { ...getDepotToolsEnv(), - CHROMIUM_BUILDTOOLS_PATH: path.resolve(ELECTRON_ROOT, '..', 'buildtools'), DEPOT_TOOLS_WIN_TOOLCHAIN: '0' }; const args = ['format', filename];