blob: 291fe32f0bb2df3fb819c5fb512de25d8ba84306 [file] [log] [blame]
#!/usr/bin/env python3
#
# Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
"""Script to generate configuration files for analysis servers of C++ and Dart.
It generates compile_commands.json for C++ clang and intellij and
analysis_options.yaml for the Dart analyzer.
"""
import argparse
import json
import os
import re
import subprocess
import sys
import generate_buildfiles
import utils
HOST_OS = utils.GuessOS()
def GenerateIdeFiles(options):
GenerateCompileCommands(options)
def GenerateCompileCommands(options):
"""Generate compile_commands.json for the C++ analysis servers.
compile_commands.json is used by the c++ clang and intellij language analysis
servers used in IDEs such as Visual Studio Code and Emacs.
Args:
options: supported options include: verbose, force, dir
Returns:
success (0) or failure (non zero)
"""
fname = os.path.join(options.dir, "compile_commands.json")
if os.path.isfile(fname) and not options.force:
print(fname + " already exists, use --force to override")
return
gn_result = generate_buildfiles.RunGn(options)
if gn_result != 0:
return gn_result
out_folder = utils.GetBuildRoot(HOST_OS,
mode="debug",
arch=options.arch,
target_os=options.os,
sanitizer=options.sanitizer)
if not os.path.isdir(out_folder):
return 1
command_set = json.loads(
subprocess.check_output([
"buildtools/ninja/ninja", "-C", out_folder, "-t", "compdb", "-x",
"cxx", "cc", "h"
]))
commands = []
for obj in command_set:
command = obj["command"]
# Skip precompiled mode, a lot of code is commented out in precompiled mode
if "-DDART_PRECOMPILED_RUNTIME" in command:
continue
# Remove warnings
command = command.replace("-Werror", "")
match = re.search(r"(\.\.\/\.\.\/[^ ]+\/clang\/bin\/clang)", command)
if match:
command = match.group(1) + command[match.end():]
else:
print("Path ending in clang/bin/clang not found in the command.")
# Remove ninja prepend on Windows.
# This is not fully correct, as now it fails to find a sysroot for
# Windows. However, clangd completely fails with the `-t` flag.
command = re.sub(r"([^\s]*)ninja -t msvc -e environment.x64 --", "",
command)
# Add sysroot from out\DebugX64\environment.x64 on Windows.
# TODO(dacoharkes): Fetch the paths from that file.
windowsSysroots = [
'C:\\src\\depot_tools\\win_toolchain\\vs_files\\27370823e7\\Windows Kits\\10\\Include\\10.0.22621.0\\um',
'C:\\src\\depot_tools\\win_toolchain\\vs_files\\27370823e7\\Windows Kits\\10\\Include\\10.0.22621.0\\shared',
'C:\\src\\depot_tools\\win_toolchain\\vs_files\\27370823e7\\Windows Kits\\10\\Include\\10.0.22621.0\\winrt',
'C:\\src\\depot_tools\\win_toolchain\\vs_files\\27370823e7\\Windows Kits\\10\\Include\\10.0.22621.0\\ucrt',
'C:\\src\\depot_tools\\win_toolchain\\vs_files\\27370823e7\\VC\\Tools\\MSVC\\14.34.31933\\include',
'C:\\src\\depot_tools\\win_toolchain\\vs_files\\27370823e7\\VC\\Tools\\MSVC\\14.34.31933\\atlmfc\\include',
]
for windowsSysroot in windowsSysroots:
command = command.replace(
"-DDART_TARGET_OS_WINDOWS",
"-DDART_TARGET_OS_WINDOWS \"-I%s\"" % windowsSysroot)
# Prevent packing errors from causing fatal_too_many_errors on Windows.
command = command.replace("-DDART_TARGET_OS_WINDOWS",
"-DDART_TARGET_OS_WINDOWS -ferror-limit=0")
obj["command"] = command
commands += [obj]
with open(fname, "w") as f:
json.dump(commands, f, indent=4)
return 0
def main(argv):
parser = argparse.ArgumentParser(
description="Python script to generate compile_commands.json and "
"analysis_options.yaml which are used by the analysis servers for "
"c++ and Dart.")
parser.add_argument("-v",
"--verbose",
help="Verbose output.",
action="store_true")
parser.add_argument("-f",
"--force",
help="Override files.",
action="store_true")
parser.add_argument("-d",
"--dir",
help="Target directory.",
default=utils.DART_DIR)
parser.add_argument("-a",
"--arch",
help="Target architecture for runtime sources.",
default="x64")
parser.add_argument("-s",
"--os",
help="Target operating system for runtime sources.",
default=HOST_OS)
parser.add_argument('--sanitizer',
type=str,
help='Build variants (comma-separated).',
metavar='[none,asan,lsan,msan,tsan,ubsan]',
default='none')
options = parser.parse_args(argv[1:])
return GenerateIdeFiles(options)
if __name__ == "__main__":
sys.exit(main(sys.argv))