File: generate_config_gypi.py

package info (click to toggle)
nodejs 22.18.0%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 252,988 kB
  • sloc: cpp: 1,594,216; javascript: 592,155; ansic: 125,008; python: 60,768; sh: 4,124; makefile: 2,875; asm: 1,732; pascal: 1,565; perl: 248; lisp: 222; xml: 42
file content (113 lines) | stat: -rwxr-xr-x 4,184 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#!/usr/bin/env python3
# Copyright (c) 2013-2019 GitHub Inc.
# Copyright 2019 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.

# This script reads the configurations of GN and outputs a config.gypi file that
# will be used to populate process.config.variables.

import argparse
import json
import re
import os
import subprocess
import sys

sys.path.append(os.path.dirname(__file__))
import getnapibuildversion

# Regex used for parsing results of "gn args".
GN_RE = re.compile(r'(\w+)\s+=\s+(.*?)$', re.MULTILINE)
GN = 'gn.bat' if sys.platform == 'win32' else 'gn'

def bool_to_number(v):
  return 1 if v else 0

def bool_string_to_number(v):
  return bool_to_number(v == 'true')

def get_gn_config(out_dir):
  # Read args from GN configurations.
  gn_args = subprocess.check_output(
      [GN, 'args', '--list', '--short', '-C', out_dir])
  config = dict(re.findall(GN_RE, gn_args.decode()))
  # Get napi_build_version from Node, which is not part of GN args.
  config['napi_build_version'] = getnapibuildversion.get_napi_version()
  return config

def get_v8_config(out_dir, node_gn_path):
  with open(os.path.join(out_dir, 'v8_features.json')) as f:
    v8_config = json.load(f)
  for key, value in v8_config.items():
    if isinstance(value, bool):
      v8_config[key] = bool_to_number(value)
  return v8_config

def translate_config(out_dir, config, v8_config):
  config_gypi = {
    'target_defaults': {
      'default_configuration':
          'Debug' if config['is_debug'] == 'true' else 'Release',
    },
    'variables': {
      'asan': bool_string_to_number(config['is_asan']),
      'clang': bool_to_number(config['is_clang']),
      'enable_lto': config['use_thin_lto'],
      'is_debug': bool_string_to_number(config['is_debug']),
      'llvm_version': 13,
      'napi_build_version': config['napi_build_version'],
      'node_builtin_shareable_builtins':
          eval(config['node_builtin_shareable_builtins']),
      'node_module_version': int(config['node_module_version']),
      'node_use_openssl': config['node_use_openssl'],
      'node_use_amaro': config['node_use_amaro'],
      'node_use_node_code_cache': config['node_use_node_code_cache'],
      'node_use_node_snapshot': config['node_use_node_snapshot'],
      'v8_enable_inspector':  # this is actually a node misnomer
          bool_string_to_number(config['node_enable_inspector']),
      'shlib_suffix': 'dylib' if sys.platform == 'darwin' else 'so',
      'tsan': bool_string_to_number(config['is_tsan']),
      # TODO(zcbenz): Shared components are not supported in GN config yet.
      'node_shared': 'false',
      'node_shared_brotli': 'false',
      'node_shared_cares': 'false',
      'node_shared_http_parser': 'false',
      'node_shared_libuv': 'false',
      'node_shared_nghttp2': 'false',
      'node_shared_nghttp3': 'false',
      'node_shared_ngtcp2': 'false',
      'node_shared_openssl': 'false',
      'node_shared_sqlite': 'false',
      'node_shared_zlib': 'false',
    }
  }
  config_gypi['variables'].update(v8_config)
  return config_gypi

def main():
  parser = argparse.ArgumentParser(
      description='Generate config.gypi file from GN configurations')
  parser.add_argument('target', help='path to generated config.gypi file')
  parser.add_argument('--out-dir', help='path to the output directory',
                      default='out/Release')
  parser.add_argument('--node-gn-path', help='path of the node target in GN',
                      default='//node')
  parser.add_argument('--dep-file', help='path to an optional dep file',
                      default=None)
  args, unknown_args = parser.parse_known_args()

  config = get_gn_config(args.out_dir)
  v8_config = get_v8_config(args.out_dir, args.node_gn_path)

  # Write output.
  with open(args.target, 'w') as f:
    f.write(repr(translate_config(args.out_dir, config, v8_config)))

  # Write depfile. Force regenerating config.gypi when GN configs change.
  if args.dep_file:
    with open(args.dep_file, 'w') as f:
      f.write('%s: %s '%(args.target, 'build.ninja'))

if __name__ == '__main__':
  main()