Skip to content

tools, build: make v8 build pythonic #58304

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/label-pr-config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ subSystemLabels:
/^tools\/(?:certdata|mkssldef|mk-ca-bundle)/: tools, openssl, tls
/^tools\/msvs\//: tools, windows, install, needs-ci
/^tools\/[^/]+\.bat$/: tools, windows, needs-ci
/^tools\/make-v8/: tools, v8 engine, needs-ci
/^tools\/build_v8/: tools, v8 engine, needs-ci
/^tools\/v8_gypfiles/: tools, v8 engine, needs-ci
/^tools\/snapshot/: needs-ci
/^tools\/build-addons.mjs/: needs-ci
Expand Down
3 changes: 1 addition & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -307,8 +307,7 @@ endif
# Rebuilds deps/v8 as a git tree, pulls its third-party dependencies, and
# builds it.
v8: ## Build deps/v8.
export PATH="$(NO_BIN_OVERRIDE_PATH)" && \
tools/make-v8.sh $(V8_ARCH).$(BUILDTYPE_LOWER) $(V8_BUILD_OPTIONS)
$(PYTHON) tools/build_v8.py $(V8_ARCH).$(BUILDTYPE_LOWER) --v8-build-options "$(V8_BUILD_OPTIONS)"

.PHONY: jstest
jstest: build-addons build-js-native-api-tests build-node-api-tests build-sqlite-tests ## Run addon tests and JS tests.
Expand Down
2 changes: 1 addition & 1 deletion doc/contributing/maintaining/maintaining-V8.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ See [`git-node-v8-backport`][] for more documentation and additional options.
_vY.x-staging_ branch and notify the `@nodejs/v8` team.
* Run the Node.js [V8 CI][] in addition to the [Node.js CI][].
The CI uses the `test-v8` target in the `Makefile`, which uses
`tools/make-v8.sh` to reconstruct a git tree in the `deps/v8` directory to
`tools/build_v8.py` to reconstruct a git tree in the `deps/v8` directory to
run V8 tests.[^1]

Here are the steps for the bug mentioned above:
Expand Down
138 changes: 138 additions & 0 deletions tools/build_v8.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
#!/usr/bin/env python3

import os
import sys
import subprocess
import platform
import shlex
import shutil
from pathlib import Path
from argparse import ArgumentParser

from v8.fetch_deps import FetchDeps
from v8.node_common import UninitGit
from utils import IsWindows

v8_arch_map = {
"amd64": "x64",
"x86_64": "x64",
"i386": "x86",
"i686": "x86",
"arm64": "arm64",
"aarch64": "arm64",
}

class V8Builder:
"""Handles the building of V8 for different architectures."""

def __init__(self, build_arch_type, jobs=None, v8_build_options=None):
self.build_arch_type = build_arch_type
self.jobs = jobs
self.v8_build_options = v8_build_options
self.arch = platform.machine()
self.v8_dir = Path('deps/v8').resolve()

def fetch_dependencies(self):
"""Initialize repository and fetch dependencies."""
UninitGit(str(self.v8_dir))
self.depot_tools = FetchDeps(str(self.v8_dir))

def get_ninja_jobs_arg(self):
"""Return jobs argument for ninja if specified."""
return ['-j', str(self.jobs)] if self.jobs else []

def create_symlink(self, env_var, default_bin, build_tools):
"""Create compiler symlink if a custom compiler is specified."""
custom_compiler = os.environ.get(env_var)

if not custom_compiler or custom_compiler == default_bin:
return

bin_path = shutil.which(custom_compiler)
if not bin_path or 'ccache' in bin_path:
return

link_path = Path(build_tools) / default_bin
try:
if link_path.exists() or link_path.is_symlink():
link_path.unlink()
link_path.symlink_to(bin_path)
except OSError as e:
print(f"Failed to create symlink: {e}")

def build_special_arch(self):
"""Build for s390x or ppc64le architectures."""
target_arch = 'ppc64' if self.arch == 'ppc64le' else self.arch
build_tools = '/home/iojs/build-tools'

env = os.environ.copy()
env['BUILD_TOOLS'] = build_tools
env['LD_LIBRARY_PATH'] = f"{build_tools}:{env.get('LD_LIBRARY_PATH', '')}"
env['PATH'] = f"{build_tools}:{env['PATH']}"
env['PKG_CONFIG_PATH'] = f"{build_tools}/pkg-config"

self.create_symlink('CC', 'gcc', build_tools)
self.create_symlink('CXX', 'g++', build_tools)

cc_wrapper = 'cc_wrapper="ccache"' if 'CXX' in env and 'ccache' in env['CXX'] else ""

gn_args = (
f"is_component_build=false is_debug=false use_goma=false "
f"goma_dir=\"None\" use_custom_libcxx=false v8_target_cpu=\"{target_arch}\" "
f"target_cpu=\"{target_arch}\" v8_enable_backtrace=true {cc_wrapper}"
)

out_dir = f"out.gn/{self.build_arch_type}"
subprocess.run(['gn', 'gen', '-v', out_dir, f"--args={gn_args}"], env=env, check=True)

ninja_cmd = ['ninja', '-v', '-C', out_dir]
ninja_cmd.extend(self.get_ninja_jobs_arg())
ninja_cmd.extend(['d8', 'cctest', 'inspector-test'])
subprocess.run(ninja_cmd, env=env, check=True)

def build_standard_arch(self):
"""Build for standard architectures using depot_tools."""
env = os.environ.copy()
env['PATH'] = f"{self.depot_tools}:{env.get('PATH', '')}"

v8gen_cmd = [sys.executable, 'tools/dev/v8gen.py', '-vv', self.build_arch_type]
if self.v8_build_options:
v8gen_cmd.extend(shlex.split(self.v8_build_options))
if IsWindows():
env["DEPOT_TOOLS_WIN_TOOLCHAIN"] = "0"

subprocess.run(v8gen_cmd, env=env, check=True)

out_dir = f"out.gn/{self.build_arch_type}"
ninja_cmd = ['ninja', '-C', out_dir]
ninja_cmd.extend(self.get_ninja_jobs_arg())
ninja_cmd.extend(['d8', 'cctest', 'inspector-test'])
subprocess.run(ninja_cmd, env=env, check=True)

def build(self):
"""Main build function that orchestrates the build process."""
os.chdir(self.v8_dir)
self.fetch_dependencies()

if self.arch in ['s390x', 'ppc64le']:
self.build_special_arch()
else:
self.build_standard_arch()

def main():
"""Parse arguments and initiate the V8 build."""
parser = ArgumentParser(description='Build V8 with specified configuration')
parser.add_argument('build_arch_type', nargs='?', default=f"{v8_arch_map.get(platform.machine(), 'x64')}.release",
help='Build architecture type (e.g., x64.release)')
parser.add_argument('-j', '--jobs', type=int,
help='Number of jobs to run simultaneously')
parser.add_argument('--v8-build-options', type=str, default=None,
help='Additional V8 build options as a quoted string')

args = parser.parse_args()

builder = V8Builder(args.build_arch_type, args.jobs, args.v8_build_options)
builder.build()

if __name__ == '__main__':
main()
60 changes: 0 additions & 60 deletions tools/make-v8.sh

This file was deleted.

4 changes: 2 additions & 2 deletions tools/test-v8.bat
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ set path=%DEPOT_TOOLS_PATH%;%path%
pushd .

set ERROR_STATUS=0
echo calling: tools\make-v8.sh
sh tools\make-v8.sh
echo calling: tools\build_v8.py
python3 tools\build_v8.py
if errorlevel 1 set ERROR_STATUS=1&goto test-v8-exit
cd %~dp0
cd deps\v8
Expand Down
12 changes: 9 additions & 3 deletions tools/v8/fetch_deps.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import subprocess
import sys

import node_common
from . import node_common

GCLIENT_SOLUTION = [
{ "name" : "v8",
Expand Down Expand Up @@ -77,9 +77,15 @@ def FetchDeps(v8_path):
env = os.environ.copy()
# gclient needs to have depot_tools in the PATH.
env["PATH"] = depot_tools + os.pathsep + env["PATH"]
gclient = os.path.join(depot_tools, "gclient.py")

if os.name == 'nt':
gclient = [os.path.join(depot_tools, "gclient.bat")]
env["DEPOT_TOOLS_WIN_TOOLCHAIN"] = "0"
else:
gclient = [sys.executable, os.path.join(depot_tools, "gclient.py")]

spec = "solutions = %s" % GCLIENT_SOLUTION
subprocess.check_call([sys.executable, gclient, "sync", "--spec", spec],
subprocess.check_call([*gclient, "sync", "--spec", spec],
cwd=os.path.join(v8_path, os.path.pardir),
env=env)
except:
Expand Down
10 changes: 2 additions & 8 deletions tools/v8/node_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# for py2/py3 compatibility
from __future__ import print_function

import os
import pipes
import shutil
import stat
import subprocess
Expand All @@ -27,10 +23,8 @@ def _Get(v8_path):
pass
if fetch_if_not_exist:
print("Checking out depot_tools.")
# shell=True needed on Windows to resolve git.bat.
subprocess.check_call("git clone {} {}".format(
pipes.quote(DEPOT_TOOLS_URL),
pipes.quote(depot_tools)), shell=True)

subprocess.check_call(['git', 'clone', DEPOT_TOOLS_URL, depot_tools])
# Using check_output to hide warning messages.
subprocess.check_output(
[sys.executable, gclient_path, "metrics", "--opt-out"],
Expand Down
Loading