build_gn.py 4.64 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
#!/usr/bin/env python
# Copyright 2017 the V8 project authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""
Use this script to build libv8_monolith.a as dependency for Node.js
Required dependencies can be fetched with fetch_deps.py.

Usage: build_gn.py <Debug/Release> <v8-path> <build-path> [<build-flags>]...

Build flags are passed either as "strings" or numeric value. True/false
are represented as 1/0. E.g.

  v8_promise_internal_field_count=2
  target_cpu="x64"
  v8_enable_disassembler=0
"""

20
import argparse
21 22 23 24 25 26 27
import os
import subprocess
import sys

import node_common

GN_ARGS = [
28 29 30 31
  "v8_monolithic=true",
  "is_component_build=false",
  "v8_use_external_startup_data=false",
  "use_custom_libcxx=false",
32 33
]

34 35
BUILD_TARGET = "v8_monolith"

36 37 38 39 40 41
def FindTargetOs(flags):
  for flag in flags:
    if flag.startswith("target_os="):
      return flag[len("target_os="):].strip('"')
  raise Exception('No target_os was set.')

42 43 44 45 46 47 48 49 50 51
def FindGn(options):
  if options.host_os == "linux":
    os_path = "linux64"
  elif options.host_os == "mac":
    os_path = "mac"
  elif options.host_os == "win":
    os_path = "win"
  else:
    raise "Operating system not supported by GN"
  return os.path.join(options.v8_path, "buildtools", os_path, "gn")
52

53 54
def GenerateBuildFiles(options):
  gn = FindGn(options)
55 56 57 58 59
  gn_args = list(GN_ARGS)
  target_os = FindTargetOs(options.flag)
  if target_os != "win":
    gn_args.append("use_sysroot=false")

60
  for flag in options.flag:
61 62 63
    flag = flag.replace("=1", "=true")
    flag = flag.replace("=0", "=false")
    flag = flag.replace("target_cpu=ia32", "target_cpu=\"x86\"")
64
    gn_args.append(flag)
65
  if options.mode == "Debug":
66
    gn_args.append("is_debug=true")
67
  else:
68 69 70 71 72
    gn_args.append("is_debug=false")

  flattened_args = ' '.join(gn_args)
  if options.extra_gn_args:
    flattened_args += ' ' + options.extra_gn_args
73

74 75
  args = [gn, "gen", options.build_path, "-q", "--args=" + flattened_args]
  subprocess.check_call(args)
76 77 78 79

def Build(options):
  depot_tools = node_common.EnsureDepotTools(options.v8_path, False)
  ninja = os.path.join(depot_tools, "ninja")
80 81 82 83 84 85 86 87 88 89 90 91 92
  if sys.platform == 'win32':
    # Required because there is an extension-less file called "ninja".
    ninja += ".exe"
  args = [ninja, "-C", options.build_path, BUILD_TARGET]
  if options.max_load:
    args += ["-l" + options.max_load]
  if options.max_jobs:
    args += ["-j" + options.max_jobs]
  else:
    with open(os.path.join(options.build_path, "args.gn")) as f:
      if "use_goma = true" in f.read():
        args += ["-j500"]
  subprocess.check_call(args)
93 94 95 96 97

def ParseOptions(args):
  parser = argparse.ArgumentParser(
      description="Build %s with GN" % BUILD_TARGET)
  parser.add_argument("--mode", help="Build mode (Release/Debug)")
98 99 100
  parser.add_argument("--v8_path", help="Path to V8", required=True)
  parser.add_argument("--build_path", help="Path to build result",
                      required=True)
101 102 103
  parser.add_argument("--flag", help="Translate GYP flag to GN",
                      action="append")
  parser.add_argument("--host_os", help="Current operating system")
104 105
  parser.add_argument("--bundled-win-toolchain",
                      help="Value for DEPOT_TOOLS_WIN_TOOLCHAIN")
106 107
  parser.add_argument("--bundled-win-toolchain-root",
                      help="Value for DEPOT_TOOLS_WIN_TOOLCHAIN_ROOT")
108 109 110 111 112 113
  parser.add_argument("--depot-tools", help="Absolute path to depot_tools")
  parser.add_argument("--extra-gn-args", help="Additional GN args")
  parser.add_argument("--build", help="Run ninja as opposed to gn gen.",
                      action="store_true")
  parser.add_argument("--max-jobs", help="ninja's -j parameter")
  parser.add_argument("--max-load", help="ninja's -l parameter")
114
  options = parser.parse_args(args)
115

116
  options.build_path = os.path.abspath(options.build_path)
117

118 119 120 121 122 123
  if not options.build:
    assert options.host_os
    assert options.mode == "Debug" or options.mode == "Release"

    options.v8_path = os.path.abspath(options.v8_path)
    assert os.path.isdir(options.v8_path)
124

125
  return options
126

127

128
if __name__ == "__main__":
129
  options = ParseOptions(sys.argv[1:])
130 131
  # Build can result in running gn gen, so need to set environment variables
  # for build as well as generate.
132 133 134 135 136 137 138 139
  if options.bundled_win_toolchain:
    os.environ['DEPOT_TOOLS_WIN_TOOLCHAIN'] = options.bundled_win_toolchain
  if options.bundled_win_toolchain_root:
    os.environ['DEPOT_TOOLS_WIN_TOOLCHAIN_ROOT'] = (
        options.bundled_win_toolchain_root)
  if options.depot_tools:
    os.environ['PATH'] = (
        options.depot_tools + os.path.pathsep + os.environ['PATH'])
140 141 142 143
  if not options.build:
    GenerateBuildFiles(options)
  else:
    Build(options)