1#!/usr/bin/env python3 2# Copyright 2020 the V8 project authors. All rights reserved. 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6"""\ 7Creates a "compile_commands.json" file for V8, for the needs of clangd and 8similar code indexers. Also updates generated C++ sources, and compiles the 9Torque Language Server, for a complete code indexing experience. 10""" 11 12import json 13import os 14import subprocess 15import sys 16 17PYLIB_PATH = 'tools/clang/pylib' 18GM_PATH = 'tools/dev' 19PYLIB_CHECK = os.path.join(PYLIB_PATH, 'clang', 'compile_db.py') 20GM_CHECK = os.path.join(GM_PATH, 'gm.py') 21def CheckRelativeImport(path): 22 if not os.path.exists(path): 23 print("Error: Please run this script from the root of a V8 checkout. %s " 24 "must be a valid relative path." % path) 25 sys.exit(1) 26CheckRelativeImport(PYLIB_CHECK) 27CheckRelativeImport(GM_CHECK) 28 29sys.path.insert(0, PYLIB_PATH) 30from clang import compile_db 31 32sys.path.insert(0, GM_PATH) 33import gm 34 35def _Call(cmd, silent=False): 36 if not silent: print("# %s" % cmd) 37 return subprocess.call(cmd, shell=True) 38 39def _Write(filename, content): 40 with open(filename, "w") as f: 41 f.write(content) 42 43def PrepareBuildDir(arch, mode): 44 build_dir = os.path.join("out", "%s.%s" % (arch, mode)) 45 if not os.path.exists(build_dir): 46 print("# mkdir -p %s" % build_dir) 47 os.makedirs(build_dir) 48 args_gn = os.path.join(build_dir, "args.gn") 49 if not os.path.exists(args_gn): 50 conf = gm.Config(arch, mode, []) 51 _Write(args_gn, conf.GetGnArgs()) 52 build_ninja = os.path.join(build_dir, "build.ninja") 53 if not os.path.exists(build_ninja): 54 code = _Call("gn gen %s" % build_dir) 55 if code != 0: raise Error("gn gen failed") 56 else: 57 _Call("ninja -C %s build.ninja" % build_dir) 58 return build_dir 59 60def AddTargetsForArch(arch, combined): 61 build_dir = PrepareBuildDir(arch, "debug") 62 commands = compile_db.ProcessCompileDatabase( 63 compile_db.GenerateWithNinja(build_dir, ["all"]), []) 64 added = 0 65 for c in commands: 66 key = c["file"] 67 if key not in combined: 68 combined[key] = c 69 added += 1 70 print("%s: added %d compile commands" % (arch, added)) 71 72def UpdateCompileCommands(): 73 print(">>> Updating compile_commands.json...") 74 combined = {} 75 AddTargetsForArch("x64", combined) 76 AddTargetsForArch("ia32", combined) 77 AddTargetsForArch("arm", combined) 78 AddTargetsForArch("arm64", combined) 79 commands = [] 80 for key in combined: 81 commands.append(combined[key]) 82 _Write("compile_commands.json", json.dumps(commands, indent=2)) 83 84def CompileLanguageServer(): 85 print(">>> Compiling Torque Language Server...") 86 PrepareBuildDir("x64", "release") 87 _Call("autoninja -C out/x64.release torque-language-server") 88 89def GenerateCCFiles(): 90 print(">>> Generating generated C++ source files...") 91 # This must be called after UpdateCompileCommands(). 92 assert os.path.exists("out/x64.debug/build.ninja") 93 _Call("autoninja -C out/x64.debug v8_generated_cc_files") 94 95def StartGoma(): 96 gomadir = gm.DetectGoma() 97 if (gomadir is not None and 98 _Call("ps -e | grep compiler_proxy > /dev/null", silent=True) != 0): 99 _Call("%s/goma_ctl.py ensure_start" % gomadir) 100 101if __name__ == "__main__": 102 StartGoma() 103 CompileLanguageServer() 104 UpdateCompileCommands() 105 GenerateCCFiles() 106