Commit ca277a62947 for nodejs
commit ca277a62947bd9313acbfd3acd7b0a2f5f1e0a31
Author: Chengzhong Wu <legendecas@gmail.com>
Date: Fri Oct 23 18:01:33 2026 -0400
build,test: setup perfetto tests on windows build
Signed-off-by: Chengzhong Wu <cwu631@bloomberg.net>
PR-URL: https://github.com/nodejs/node/pull/66731
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
diff --git a/.gitignore b/.gitignore
index 9ba14770743..84c35fbdd94 100644
--- a/.gitignore
+++ b/.gitignore
@@ -123,6 +123,7 @@ tools/*/*.i.tmp
# === Rules for tools/perfetto ===
/tools/perfetto/trace_processor_shell
+/tools/perfetto/trace_processor_shell.exe
# === Rules for test artifacts ===
/*.tap
diff --git a/Makefile b/Makefile
index a4de0b2d683..361fed3df4c 100644
--- a/Makefile
+++ b/Makefile
@@ -349,7 +349,7 @@ TRACE_PROCESSOR_SHELL_DEPS = deps/perfetto/VERSION
endif
$(TRACE_PROCESSOR_SHELL_PATH): $(TRACE_PROCESSOR_SHELL_DEPS)
- @tools/perfetto/get_trace_processor $@
+ @$(PYTHON) tools/perfetto/get_trace_processor.py $@
.PHONY: test
# This does not run tests of third-party libraries inside deps.
diff --git a/test/common/trace_events.js b/test/common/trace_events.js
index 67fc0919350..cbb5dbdcc60 100644
--- a/test/common/trace_events.js
+++ b/test/common/trace_events.js
@@ -4,7 +4,8 @@
// binary format.
// This depends on perfetto's `trace_processor_shell` converts to pftrace format
// to JSON format. Run `make tools/perfetto/trace_processor_shell` to download
-// it, or point `TRACE_PROCESSOR_SHELL_PATH` at an existing build of it.
+// it (`vcbuild test` does so on Windows), or point `TRACE_PROCESSOR_SHELL_PATH`
+// at an existing build of it.
const assert = require('assert');
const { spawnSync } = require('child_process');
@@ -14,7 +15,8 @@ const common = require('./');
const traceProcessor = path.resolve(
__dirname, '..', '..',
- process.env.TRACE_PROCESSOR_SHELL_PATH || 'tools/perfetto/trace_processor_shell');
+ process.env.TRACE_PROCESSOR_SHELL_PATH ||
+ `tools/perfetto/trace_processor_shell${common.isWindows ? '.exe' : ''}`);
// The JSON form of a trace runs about three times the size of the trace it was
// converted from, and the traces these tests produce are a few hundred KiB at
@@ -29,7 +31,7 @@ const defaultTraceFileName = `node_trace.1.${traceFileExt}`;
function checkTraceProcessor() {
if (common.hasPerfetto && !fs.existsSync(traceProcessor)) {
assert.fail('trace_processor_shell is missing, ' +
- 'run `make tools/perfetto/trace_processor_shell` to download it');
+ 'run `python3 tools/perfetto/get_trace_processor.py` to download it');
}
}
diff --git a/test/trace_events/README.md b/test/trace_events/README.md
index 756dd9aeba6..6b78efd220b 100644
--- a/test/trace_events/README.md
+++ b/test/trace_events/README.md
@@ -2,10 +2,12 @@
When the `node` binary is built with configure flag `--with-perfetto`,
the tests in this folder depends on `tools/perfetto/trace_processor_shell`,
-which is downloaded with `tools/perfetto/get_trace_processor` via
+which is downloaded with `tools/perfetto/get_trace_processor.py` via
`make tools/perfetto/trace_processor_shell`, to convert Perfetto binary trace
-files to JSON format. Set `TRACE_PROCESSOR_SHELL_PATH` to use an existing build
-of the tool instead of downloading a release.
+files to JSON format. On Windows, `vcbuild.bat` downloads
+`tools/perfetto/trace_processor_shell.exe` with the same script before running
+the tests. Set `TRACE_PROCESSOR_SHELL_PATH` to use an existing build of the
+tool instead of downloading a release.
Refer to <https://perfetto.dev/docs/reference/trace-processor-cli>
for help of the `trace_processor_shell` CLI.
diff --git a/tools/perfetto/get_trace_processor b/tools/perfetto/get_trace_processor
deleted file mode 100755
index f00fee8b21e..00000000000
--- a/tools/perfetto/get_trace_processor
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/bin/sh
-# Downloads perfetto's trace_processor_shell, matching the SDK version vendored
-# in deps/perfetto. The trace events tests read back the binary traces that
-# perfetto builds write through this tool.
-set -e
-
-script_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
-version=$(cat "$script_dir/../../deps/perfetto/VERSION")
-trace_processor="${1:-$script_dir/trace_processor_shell}"
-
-# Perfetto names its release archives <os>-<arch>, which does not match uname.
-case "$(uname -s)" in
- Darwin) os=mac ;;
- Linux) os=linux ;;
- *) echo "No perfetto release for $(uname -s)" >&2; exit 1 ;;
-esac
-
-case "$(uname -m)" in
- x86_64 | amd64) arch=amd64 ;;
- arm64 | aarch64) arch=arm64 ;;
- *) echo "No perfetto release for $(uname -m)" >&2; exit 1 ;;
-esac
-
-url="https://github.com/google/perfetto/releases/download/v$version/$os-$arch.zip"
-archive=$(mktemp)
-
-rm -f "$trace_processor"
-echo "Downloading $url"
-curl -sSfL -o "$archive" "$url"
-unzip -q -j -o "$archive" '*/trace_processor_shell' -d "$script_dir"
-rm -f "$archive"
-chmod +x "$trace_processor"
-# The archive carries the release's own mtime. Make decides whether the tool is
-# current by comparing it against deps/perfetto/VERSION, so it has to come out
-# newer than the version file it was downloaded for.
-touch "$trace_processor"
diff --git a/tools/perfetto/get_trace_processor.py b/tools/perfetto/get_trace_processor.py
new file mode 100755
index 00000000000..ed519922b19
--- /dev/null
+++ b/tools/perfetto/get_trace_processor.py
@@ -0,0 +1,61 @@
+#!/usr/bin/env python3
+# Downloads perfetto's trace_processor_shell, matching the SDK version vendored
+# in deps/perfetto. The trace events tests read back the binary traces that
+# perfetto builds write through this tool.
+
+import io
+import os
+import platform
+import sys
+import urllib.request
+import zipfile
+
+script_dir = os.path.dirname(os.path.abspath(__file__))
+version_file = os.path.join(script_dir, '..', '..', 'deps', 'perfetto', 'VERSION')
+is_windows = platform.system() == 'Windows'
+
+# Perfetto names its release archives <os>-<arch>, which does not match what
+# platform reports.
+OS_NAMES = {'Darwin': 'mac', 'Linux': 'linux'}
+ARCH_NAMES = {'x86_64': 'amd64', 'arm64': 'arm64', 'aarch64': 'arm64'}
+
+
+def release_name():
+ # Perfetto releases only an x64 build for Windows. Windows on arm64 runs it
+ # under emulation.
+ if is_windows:
+ return 'windows-amd64'
+
+ os_name = OS_NAMES.get(platform.system())
+ arch = ARCH_NAMES.get(platform.machine())
+ if os_name is None or arch is None:
+ sys.exit(f'No perfetto release for {platform.system()} {platform.machine()}')
+ return f'{os_name}-{arch}'
+
+
+def main():
+ exe = 'trace_processor_shell.exe' if is_windows else 'trace_processor_shell'
+ trace_processor = sys.argv[1] if len(sys.argv) > 1 else os.path.join(script_dir, exe)
+
+ # The tool is current when it is newer than the version file it was
+ # downloaded for, so a version bump re-downloads it.
+ if (os.path.exists(trace_processor) and
+ os.path.getmtime(trace_processor) > os.path.getmtime(version_file)):
+ return
+
+ with open(version_file) as f:
+ version = f.read().strip()
+ name = release_name()
+ url = f'https://github.com/google/perfetto/releases/download/v{version}/{name}.zip'
+
+ print(f'Downloading {url}')
+ with urllib.request.urlopen(url) as response:
+ archive = zipfile.ZipFile(io.BytesIO(response.read()))
+ print(f'Extracting {name}/{exe} to {trace_processor}')
+ with open(trace_processor, 'wb') as dst:
+ dst.write(archive.read(f'{name}/{exe}'))
+ os.chmod(trace_processor, 0o755)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/vcbuild.bat b/vcbuild.bat
index 8b8c393133c..2e7a569ef73 100644
--- a/vcbuild.bat
+++ b/vcbuild.bat
@@ -85,6 +85,7 @@ set compile_commands=
set cfg=
set v8temporal=
set v8windbg=
+set with_perfetto=
set exit_code=0
:next-arg
@@ -116,6 +117,7 @@ if /i "%1"=="pgo-generate" set pgo_generate=1&goto arg-ok
if /i "%1"=="pgo-use" set pgo_use=1&goto arg-ok
if /i "%1"=="v8temporal" set v8temporal=1&goto arg-ok
if /i "%1"=="v8windbg" set v8windbg=1&goto arg-ok
+if /i "%1"=="with-perfetto" set with_perfetto=1&goto arg-ok
if /i "%1"=="licensertf" set licensertf=1&goto arg-ok
if /i "%1"=="test" set test_args=%test_args% %common_test_suites%&set lint_cpp=1&set lint_js=1&set lint_md=1&goto arg-ok
if /i "%1"=="test-ci-native" set test_args=%test_args% %test_ci_args% -p tap --logfile test.tap %CI_NATIVE_SUITES% %CI_DOC%&set build_addons=1&set build_js_native_api_tests=1&set build_node_api_tests=1&set build_ffi_tests=1&set cctest_args=%cctest_args% --gtest_output=xml:cctest.junit.xml&goto arg-ok
@@ -272,6 +274,7 @@ if defined compile_commands set configure_flags=%configure_flags% -C
if defined cfg set configure_flags=%configure_flags% --control-flow-guard
if defined v8temporal set configure_flags=%configure_flags% --v8-enable-temporal-support
if defined v8windbg set configure_flags=%configure_flags% --enable-v8windbg
+if defined with_perfetto set configure_flags=%configure_flags% --with-perfetto
if "%target_arch%"=="x86" (
echo "32-bit Windows builds are not supported anymore."
@@ -826,6 +829,13 @@ echo running 'cctest %cctest_args%'
"%config%\cctest" %cctest_args%
if %errorlevel% neq 0 set exit_code=%errorlevel%
:run-test-py
+@rem Download trace_processor_shell for perfetto builds.
+if defined TRACE_PROCESSOR_SHELL_PATH goto run-test-py-start
+findstr /r /c:"v8_use_perfetto.: 1," config.gypi >nul 2>&1
+if errorlevel 1 goto run-test-py-start
+python tools\perfetto\get_trace_processor.py
+if errorlevel 1 exit /b 1
+:run-test-py-start
echo running 'python tools\test.py %test_args%'
python tools\test.py %test_args%
if %errorlevel% neq 0 set exit_code=%errorlevel%