11cb0ef41Sopenharmony_ci#!/usr/bin/env python3
21cb0ef41Sopenharmony_ci# Copyright 2020 the V8 project authors. All rights reserved.
31cb0ef41Sopenharmony_ci# Use of this source code is governed by a BSD-style license that can be
41cb0ef41Sopenharmony_ci# found in the LICENSE file.
51cb0ef41Sopenharmony_ci
61cb0ef41Sopenharmony_ci"""\
71cb0ef41Sopenharmony_ciCreates a "compile_commands.json" file for V8, for the needs of clangd and
81cb0ef41Sopenharmony_cisimilar code indexers. Also updates generated C++ sources, and compiles the
91cb0ef41Sopenharmony_ciTorque Language Server, for a complete code indexing experience.
101cb0ef41Sopenharmony_ci"""
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_ciimport json
131cb0ef41Sopenharmony_ciimport os
141cb0ef41Sopenharmony_ciimport subprocess
151cb0ef41Sopenharmony_ciimport sys
161cb0ef41Sopenharmony_ci
171cb0ef41Sopenharmony_ciPYLIB_PATH = 'tools/clang/pylib'
181cb0ef41Sopenharmony_ciGM_PATH = 'tools/dev'
191cb0ef41Sopenharmony_ciPYLIB_CHECK = os.path.join(PYLIB_PATH, 'clang', 'compile_db.py')
201cb0ef41Sopenharmony_ciGM_CHECK = os.path.join(GM_PATH, 'gm.py')
211cb0ef41Sopenharmony_cidef CheckRelativeImport(path):
221cb0ef41Sopenharmony_ci  if not os.path.exists(path):
231cb0ef41Sopenharmony_ci    print("Error: Please run this script from the root of a V8 checkout. %s "
241cb0ef41Sopenharmony_ci          "must be a valid relative path." % path)
251cb0ef41Sopenharmony_ci    sys.exit(1)
261cb0ef41Sopenharmony_ciCheckRelativeImport(PYLIB_CHECK)
271cb0ef41Sopenharmony_ciCheckRelativeImport(GM_CHECK)
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_cisys.path.insert(0, PYLIB_PATH)
301cb0ef41Sopenharmony_cifrom clang import compile_db
311cb0ef41Sopenharmony_ci
321cb0ef41Sopenharmony_cisys.path.insert(0, GM_PATH)
331cb0ef41Sopenharmony_ciimport gm
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_cidef _Call(cmd, silent=False):
361cb0ef41Sopenharmony_ci  if not silent: print("# %s" % cmd)
371cb0ef41Sopenharmony_ci  return subprocess.call(cmd, shell=True)
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_cidef _Write(filename, content):
401cb0ef41Sopenharmony_ci  with open(filename, "w") as f:
411cb0ef41Sopenharmony_ci    f.write(content)
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_cidef PrepareBuildDir(arch, mode):
441cb0ef41Sopenharmony_ci  build_dir = os.path.join("out", "%s.%s" % (arch, mode))
451cb0ef41Sopenharmony_ci  if not os.path.exists(build_dir):
461cb0ef41Sopenharmony_ci    print("# mkdir -p %s" % build_dir)
471cb0ef41Sopenharmony_ci    os.makedirs(build_dir)
481cb0ef41Sopenharmony_ci  args_gn = os.path.join(build_dir, "args.gn")
491cb0ef41Sopenharmony_ci  if not os.path.exists(args_gn):
501cb0ef41Sopenharmony_ci    conf = gm.Config(arch, mode, [])
511cb0ef41Sopenharmony_ci    _Write(args_gn, conf.GetGnArgs())
521cb0ef41Sopenharmony_ci  build_ninja = os.path.join(build_dir, "build.ninja")
531cb0ef41Sopenharmony_ci  if not os.path.exists(build_ninja):
541cb0ef41Sopenharmony_ci    code = _Call("gn gen %s" % build_dir)
551cb0ef41Sopenharmony_ci    if code != 0: raise Error("gn gen failed")
561cb0ef41Sopenharmony_ci  else:
571cb0ef41Sopenharmony_ci    _Call("ninja -C %s build.ninja" % build_dir)
581cb0ef41Sopenharmony_ci  return build_dir
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_cidef AddTargetsForArch(arch, combined):
611cb0ef41Sopenharmony_ci  build_dir = PrepareBuildDir(arch, "debug")
621cb0ef41Sopenharmony_ci  commands = compile_db.ProcessCompileDatabase(
631cb0ef41Sopenharmony_ci                compile_db.GenerateWithNinja(build_dir, ["all"]), [])
641cb0ef41Sopenharmony_ci  added = 0
651cb0ef41Sopenharmony_ci  for c in commands:
661cb0ef41Sopenharmony_ci    key = c["file"]
671cb0ef41Sopenharmony_ci    if key not in combined:
681cb0ef41Sopenharmony_ci      combined[key] = c
691cb0ef41Sopenharmony_ci      added += 1
701cb0ef41Sopenharmony_ci  print("%s: added %d compile commands" % (arch, added))
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_cidef UpdateCompileCommands():
731cb0ef41Sopenharmony_ci  print(">>> Updating compile_commands.json...")
741cb0ef41Sopenharmony_ci  combined = {}
751cb0ef41Sopenharmony_ci  AddTargetsForArch("x64", combined)
761cb0ef41Sopenharmony_ci  AddTargetsForArch("ia32", combined)
771cb0ef41Sopenharmony_ci  AddTargetsForArch("arm", combined)
781cb0ef41Sopenharmony_ci  AddTargetsForArch("arm64", combined)
791cb0ef41Sopenharmony_ci  commands = []
801cb0ef41Sopenharmony_ci  for key in combined:
811cb0ef41Sopenharmony_ci    commands.append(combined[key])
821cb0ef41Sopenharmony_ci  _Write("compile_commands.json", json.dumps(commands, indent=2))
831cb0ef41Sopenharmony_ci
841cb0ef41Sopenharmony_cidef CompileLanguageServer():
851cb0ef41Sopenharmony_ci  print(">>> Compiling Torque Language Server...")
861cb0ef41Sopenharmony_ci  PrepareBuildDir("x64", "release")
871cb0ef41Sopenharmony_ci  _Call("autoninja -C out/x64.release torque-language-server")
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_cidef GenerateCCFiles():
901cb0ef41Sopenharmony_ci  print(">>> Generating generated C++ source files...")
911cb0ef41Sopenharmony_ci  # This must be called after UpdateCompileCommands().
921cb0ef41Sopenharmony_ci  assert os.path.exists("out/x64.debug/build.ninja")
931cb0ef41Sopenharmony_ci  _Call("autoninja -C out/x64.debug v8_generated_cc_files")
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_cidef StartGoma():
961cb0ef41Sopenharmony_ci  gomadir = gm.DetectGoma()
971cb0ef41Sopenharmony_ci  if (gomadir is not None and
981cb0ef41Sopenharmony_ci      _Call("ps -e | grep compiler_proxy > /dev/null", silent=True) != 0):
991cb0ef41Sopenharmony_ci    _Call("%s/goma_ctl.py ensure_start" % gomadir)
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_ciif __name__ == "__main__":
1021cb0ef41Sopenharmony_ci  StartGoma()
1031cb0ef41Sopenharmony_ci  CompileLanguageServer()
1041cb0ef41Sopenharmony_ci  UpdateCompileCommands()
1051cb0ef41Sopenharmony_ci  GenerateCCFiles()
106