92 lines
3.3 KiB
Python
92 lines
3.3 KiB
Python
#!/usr/bin/env python3
|
|
from argparse import ArgumentParser
|
|
import os
|
|
import json
|
|
import re
|
|
import subprocess
|
|
import shlex
|
|
|
|
|
|
def actorFile(actor: str, build: str, src: str):
|
|
res = actor.replace(build, src, 1)
|
|
res = res.replace("actor.g.cpp", "actor.cpp")
|
|
return res.replace("actor.g.h", "actor.h")
|
|
|
|
|
|
def rreplace(s, old, new, occurrence=1):
|
|
li = s.rsplit(old, occurrence)
|
|
return new.join(li)
|
|
|
|
|
|
def actorCommand(cmd: str, build: str, src: str):
|
|
r1 = re.compile("-c (.+)(actor\.g\.cpp)")
|
|
m1 = r1.search(cmd)
|
|
if m1 is None:
|
|
return cmd
|
|
cmd1 = r1.sub("\\1actor.cpp", cmd)
|
|
return rreplace(cmd1, build, src)
|
|
|
|
|
|
parser = ArgumentParser(
|
|
description="Generates a new compile_commands.json for rtags+flow"
|
|
)
|
|
parser.add_argument("-b", help="Build directory", dest="builddir", default=os.getcwd())
|
|
parser.add_argument("-s", help="Build directory", dest="srcdir", default=os.getcwd())
|
|
parser.add_argument("-o", help="Output file", dest="out", default="processed_compile_commands.json")
|
|
parser.add_argument("-ninjatool", help="Ninja tool", dest="ninjatool", default="")
|
|
parser.add_argument("input", help="compile_commands.json", default="compile_commands.json", nargs="?")
|
|
args = parser.parse_args()
|
|
|
|
print("transform {} with build directory {}".format(args.input, args.builddir))
|
|
|
|
with open(args.input) as f:
|
|
cmds = json.load(f)
|
|
|
|
swiftCompilationCommands = {}
|
|
|
|
if len(args.ninjatool) > 0:
|
|
print("aquiring Swift compile commands using {}".format(args.ninjatool))
|
|
try:
|
|
ninjaInvocation = subprocess.run([args.ninjatool, "-t", "compdb"], cwd=args.builddir, capture_output=True)
|
|
ninjaCMDs = json.loads(ninjaInvocation.stdout.decode('utf-8'))
|
|
for fileCmd in ninjaCMDs:
|
|
file = fileCmd['file']
|
|
if not file.endswith('.swift'):
|
|
continue
|
|
cmd = fileCmd['command']
|
|
# Skip invocations that are used to emit the header file for C++.
|
|
if cmd.find('-emit-clang-header') != -1:
|
|
continue
|
|
|
|
# Cleanup '&&' and ':' tokens from command generated by Ninja.
|
|
transformedSubCmd = [x for x in shlex.split(cmd) if x != '&&' and x != ':']
|
|
cmd = shlex.join(transformedSubCmd)
|
|
|
|
# Figure out which files are actually using this command.
|
|
filesInCmd = [x for x in transformedSubCmd if x.endswith('.swift')]
|
|
for cmdFile in filesInCmd:
|
|
swiftCompilationCommands[cmdFile] = {'file': cmdFile, 'command': cmd, 'directory': fileCmd['directory']}
|
|
except:
|
|
print("error: failed to aquire Swift compilation commands")
|
|
|
|
result = []
|
|
|
|
for cmd in cmds:
|
|
additional_flags = ["-Wno-unknown-attributes"]
|
|
cmd["command"] = cmd["command"].replace(
|
|
" -DNO_INTELLISENSE ", " {} ".format(" ".join(additional_flags))
|
|
)
|
|
if cmd["file"].endswith("actor.g.cpp"):
|
|
# here we need to rewrite the rule
|
|
cmd["command"] = actorCommand(cmd["command"], args.builddir, args.srcdir)
|
|
cmd["file"] = actorFile(cmd["file"], args.builddir, args.srcdir)
|
|
result.append(cmd)
|
|
elif cmd['file'].endswith('.swift'):
|
|
if cmd['file'] in swiftCompilationCommands:
|
|
result.append(swiftCompilationCommands[cmd['file']])
|
|
else:
|
|
result.append(cmd)
|
|
|
|
with open(args.out, "w") as f:
|
|
json.dump(result, f, indent=4)
|