try using mksnapshot.exe on cross compile

This commit is contained in:
John Kleinschmidt
2026-03-24 17:01:11 -04:00
parent 71f792cf35
commit 400cb880aa
4 changed files with 212 additions and 1 deletions

View File

@@ -42,9 +42,81 @@ runs:
shell: bash
if: ${{ inputs.target-platform == 'win' }}
run: |
GN_APPENDED_ARGS="$GN_EXTRA_ARGS target_cpu=\"${{ inputs.target-arch }}\" use_v8_context_snapshot=true target_os=\"win\""
GN_APPENDED_ARGS="$GN_EXTRA_ARGS target_cpu=\"${{ inputs.target-arch }}\" use_v8_context_snapshot=true v8_win_cross_compile_using_wine=true target_os=\"win\""
echo "GN_EXTRA_ARGS=$GN_APPENDED_ARGS" >> $GITHUB_ENV
echo "ELECTRON_BUILD_TOOLS_MAIN_STAR=`pwd`/src/electron/build/siso/main.star" >> $GITHUB_ENV
- name: Install wine for Windows builds on non-Windows hosts
shell: bash
if: ${{ inputs.target-platform == 'win' && runner.os != 'Windows' }}
run: |
sudo dpkg --add-architecture amd64
sudo apt-get update
# apt-get may return non-zero from post-install triggers (e.g. man-db)
# even when the package installs successfully, so tolerate that and
# verify the binary exists afterward.
sudo apt-get install -y --no-install-recommends wine64 || true
# Debug: show where wine64 binary was actually installed
echo "=== wine64 package file list (bin entries) ==="
dpkg -L wine64 2>/dev/null | grep bin || echo "(no bin entries found)"
echo "=== /usr/bin/wine* ==="
ls -la /usr/bin/wine* 2>/dev/null || echo "(no wine binaries in /usr/bin/)"
echo "=== dpkg status ==="
dpkg -s wine64 2>/dev/null | head -5 || echo "(wine64 package not found)"
# Find wine64 - check known path first, then fall back to PATH lookup,
# then search via dpkg/find in case it was installed elsewhere.
if [ -x /usr/bin/wine64 ]; then
WINE64_PATH=/usr/bin/wine64
elif command -v wine64 >/dev/null 2>&1; then
WINE64_PATH=$(command -v wine64)
else
echo "wine64 not at /usr/bin/wine64 or in PATH, searching..."
WINE64_PATH=$(dpkg -L wine64 2>/dev/null | grep -m1 'bin/wine64$' || true)
if [ ! -x "$WINE64_PATH" ]; then
WINE64_PATH=$(find /usr -name 'wine64' -executable 2>/dev/null | head -1)
fi
if [ -z "$WINE64_PATH" ] || [ ! -x "$WINE64_PATH" ]; then
echo "ERROR: wine64 binary not found anywhere after install"
exit 1
fi
fi
echo "Found wine64 at: $WINE64_PATH"
export WINEPREFIX="$HOME/.wine"
mkdir -p "$WINEPREFIX"
echo "WINEPREFIX=$WINEPREFIX" >> $GITHUB_ENV
# Initialize wine prefix to avoid first-run delays during build
"$WINE64_PATH" wineboot --init 2>/dev/null || true
# Pass wine64 path to GN so siso can find it regardless of PATH
GN_APPENDED_ARGS="$GN_EXTRA_ARGS v8_wine_path=\"$WINE64_PATH\""
echo "GN_EXTRA_ARGS=$GN_APPENDED_ARGS" >> $GITHUB_ENV
# - name: Download mksnapshot.zip
# shell: bash
# if: ${{ inputs.target-platform == 'win' }}
# run: |
# # Download mksnapshot.zip from https://electronbuildtools.blob.core.windows.net/windows-toolchains/mksnapshot.zip
# curl -L -o mksnapshot.zip https://electronbuildtools.blob.core.windows.net/windows-toolchains/mksnapshot.zip
# if [ $? -ne 0 ]; then
# echo "Failed to download mksnapshot.zip"
# exit 1
# fi
# if [ -f mksnapshot.zip ]; then
# echo "Successfully downloaded mksnapshot.zip"
# else
# echo "mksnapshot.zip not found after download"
# exit 1
# fi
# if [ -f mksnapshot.zip ]; then
# unzip mksnapshot.zip -d mksnapshot
# PREBUILT_MKSNAPSHOT="$(pwd)/mksnapshot/mksnapshot.exe"
# if [ -f "$PREBUILT_MKSNAPSHOT" ]; then
# GN_APPENDED_ARGS="$GN_EXTRA_ARGS v8_prebuilt_mksnapshot=\"$PREBUILT_MKSNAPSHOT\""
# echo "GN_EXTRA_ARGS=$GN_APPENDED_ARGS" >> $GITHUB_ENV
# echo "Using pre-built mksnapshot at $PREBUILT_MKSNAPSHOT"
# else
# echo "mksnapshot binary not found in mksnapshot.zip, will build from source"
# fi
# else
# echo "mksnapshot.zip not found, skipping unzip and PATH update"
# fi
- name: Add Clang problem matcher
shell: bash
run: echo "::add-matcher::src/electron/.github/problem-matchers/clang.json"

View File

@@ -1,4 +1,5 @@
load("@builtin//encoding.star", "json")
load("@builtin//lib/gn.star", "gn")
load("@builtin//path.star", "path")
load("@builtin//runtime.star", "runtime")
load("@builtin//struct.star", "module")
@@ -58,6 +59,33 @@ def init(ctx):
"lld-link": step_config["platforms"]["default"],
})
# When cross-compiling for Windows using wine, mksnapshot.exe is run via
# wine64 on the local machine. The remote execution service cannot handle
# this, so force mksnapshot to run locally. The wine64 prefix also changes
# the command so the upstream v8/mksnapshot rule's command_prefix won't
# match — add an explicit rule for the wine-prefixed command.
if "args.gn" in ctx.metadata:
gn_args = gn.args(ctx)
if gn_args.get("v8_win_cross_compile_using_wine", "").strip('"') == "true":
# Force the existing v8/mksnapshot rule to run locally
for rule in step_config["rules"]:
if rule.get("name") == "v8/mksnapshot":
rule["remote"] = False
# Add a rule that matches the wine64-prefixed mksnapshot command.
# With wine, GN emits: python3 ../../v8/tools/run.py <wine_path> ./mksnapshot.exe
# The upstream command_prefix ("python3 ...run.py ./mksnapshot") won't
# match because wine_path appears before ./mksnapshot.exe.
wine_path = gn_args.get("v8_wine_path", "").strip('"')
if wine_path:
step_config["rules"].insert(0, {
"name": "v8/mksnapshot_wine",
"command_prefix": "python3 ../../v8/tools/run.py " + wine_path,
"remote": False,
"timeout": "2m",
"output_local": True,
})
return module(
"config",
step_config = json.encode(step_config),

View File

@@ -1,2 +1,3 @@
chore_allow_customizing_microtask_policy_per_context.patch
build_warn_instead_of_abort_on_builtin_pgo_profile_mismatch.patch
feat_support_running_mksnapshot_exe_via_wine_for_windows.patch

View File

@@ -0,0 +1,110 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: John Kleinschmidt <kleinschmidtorama@gmail.com>
Date: Tue, 24 Mar 2026 16:29:55 -0400
Subject: feat: support running mksnapshot.exe via Wine for Windows
cross-compile
When v8_win_cross_compile_using_wine=true is set, mksnapshot is built as a
Windows .exe using the target toolchain and executed via Wine on the Linux
host. This avoids needing source-level cross-compile patches for the
unwinding info code paths.
diff --git a/BUILD.gn b/BUILD.gn
index 985f946d5f87b4e6eb32a011ac47a0073248e5f2..fc24800d3334b74debe84f9ac8b348b4fdba63af 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -2681,7 +2681,11 @@ template("run_mksnapshot") {
suffix = "_$name"
}
action("run_mksnapshot_" + name) {
- deps = [ ":mksnapshot($v8_snapshot_toolchain)" ]
+ if (v8_prebuilt_mksnapshot != "") {
+ deps = []
+ } else {
+ deps = [ ":mksnapshot($v8_snapshot_toolchain)" ]
+ }
if (v8_verify_deterministic_mksnapshot) {
# We archive the snapshot executable when verifying snapshot
# determinism to ease debugging.
@@ -2735,10 +2739,23 @@ template("run_mksnapshot") {
data += [ "$root_out_dir/mksnapshot_output${suffix}.log" ]
}
+ _mksnapshot_dir = get_label_info(":mksnapshot($v8_snapshot_toolchain)",
+ "root_out_dir")
+ if (v8_prebuilt_mksnapshot != "") {
+ _mksnapshot_bin = v8_prebuilt_mksnapshot
+ } else if (v8_win_cross_compile_using_wine) {
+ _mksnapshot_bin = _mksnapshot_dir + "/mksnapshot.exe"
+ } else {
+ _mksnapshot_bin = _mksnapshot_dir + "/mksnapshot"
+ }
+
+ if (v8_win_cross_compile_using_wine) {
+ assert(v8_wine_path != "",
+ "v8_wine_path must be set when v8_win_cross_compile_using_wine is true")
+ args += [ v8_wine_path ]
+ }
args += [
- "./" + rebase_path(get_label_info(":mksnapshot($v8_snapshot_toolchain)",
- "root_out_dir") + "/mksnapshot",
- root_build_dir),
+ "./" + rebase_path(_mksnapshot_bin, root_build_dir),
"--turbo_instruction_scheduling",
"--turbo-always-optimize-spills",
diff --git a/gni/snapshot_toolchain.gni b/gni/snapshot_toolchain.gni
index 37ed262640d048a6fa5923279ae0388c1c0ae766..d9830914f0abd919143f0cf8b3069c5a3f70516e 100644
--- a/gni/snapshot_toolchain.gni
+++ b/gni/snapshot_toolchain.gni
@@ -32,6 +32,21 @@ declare_args() {
# toolchain that matches the bit-width of the target CPU, but runs on
# the host.
v8_snapshot_toolchain = ""
+
+ # When cross-compiling for Windows on a non-Windows host, build mksnapshot
+ # as a Windows .exe and run it via Wine instead of building a host-native
+ # mksnapshot with cross-compile patches.
+ v8_win_cross_compile_using_wine = false
+
+ # Absolute path to the wine64 binary. Required when
+ # v8_win_cross_compile_using_wine is true.
+ v8_wine_path = ""
+
+ # Path to a pre-built mksnapshot binary to use instead of building one from
+ # source. When set, run_mksnapshot will use this binary directly and skip
+ # building the mksnapshot target. The path should be absolute or relative
+ # to the source root.
+ v8_prebuilt_mksnapshot = ""
}
# Try to infer the appropriate snapshot toolchain for the v8_current_cpu
@@ -69,7 +84,12 @@ if (v8_snapshot_toolchain == "") {
# Cross-build from same ISA on one OS to another. For example:
# * targeting win/x64 on a linux/x64 host
# * targeting win/arm64 on a mac/arm64 host
- v8_snapshot_toolchain = host_toolchain
+ if (v8_win_cross_compile_using_wine && is_win && host_os != "win") {
+ # Build mksnapshot as a Windows .exe and run it via Wine.
+ v8_snapshot_toolchain = current_toolchain
+ } else {
+ v8_snapshot_toolchain = host_toolchain
+ }
} else if (host_cpu == "arm64" && current_cpu == "x64") {
# Cross-build from arm64 to intel (likely on an Apple Silicon mac).
v8_snapshot_toolchain =
@@ -119,7 +139,13 @@ assert(v8_snapshot_toolchain != "",
# We reuse the snapshot toolchain for building torque and other generators to
# avoid building v8_libbase on the host more than once. On mips with big endian,
# the snapshot toolchain is the target toolchain and, hence, can't be used.
-v8_generator_toolchain = v8_snapshot_toolchain
+# When using Wine for cross-compilation, mksnapshot is built as a Windows .exe
+# but other generators (torque, etc.) must still be host-native binaries.
+if (v8_win_cross_compile_using_wine && is_win && host_os != "win") {
+ v8_generator_toolchain = host_toolchain
+} else {
+ v8_generator_toolchain = v8_snapshot_toolchain
+}
if (host_cpu == "x64" && v8_current_cpu == "mips64") {
v8_generator_toolchain = "//build/toolchain/linux:clang_x64"
}