49 lines
2.1 KiB
Python
Executable file
49 lines
2.1 KiB
Python
Executable file
"""Convert CMake's compile_commands.json to the upstream Clank compile schema.
|
|
Run after configuring with the container's MSVC/Wine toolchain.
|
|
"""
|
|
import argparse
|
|
import json
|
|
import pathlib
|
|
import shlex
|
|
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('commands')
|
|
parser.add_argument('output')
|
|
parser.add_argument('--source', required=True)
|
|
parser.add_argument('--toolchain', default='/opt/toolchain')
|
|
parser.add_argument('--compiler', required=True)
|
|
parser.add_argument('--include', required=True, help='Semicolon-separated MSVC/SDK include paths')
|
|
args = parser.parse_args()
|
|
source = pathlib.Path(args.source).resolve()
|
|
|
|
def replace(value):
|
|
return value.replace('Z:' + str(source).replace('/', '\\'), '${SRC}').replace(str(source), '${SRC}').replace('Z:' + args.toolchain.replace('/', '\\'), '${TC}').replace(args.toolchain, '${TC}')
|
|
|
|
shapes, units = [], {}
|
|
for row in json.loads(pathlib.Path(args.commands).read_text()):
|
|
file = pathlib.Path(row['file']).resolve().relative_to(source).as_posix()
|
|
command = row.get('arguments') or shlex.split(row['command'])
|
|
# CMake's compiler launcher may precede cl.exe.
|
|
compiler_index = next(i for i, arg in enumerate(command) if arg.lower().endswith(('cl.exe', 'cl-wine.sh')))
|
|
flags = []
|
|
skip = False
|
|
for arg in command[compiler_index + 1:]:
|
|
if skip:
|
|
skip = False
|
|
continue
|
|
if arg in ('-o', '-MF', '-MT'):
|
|
skip = True
|
|
continue
|
|
if arg.lower().startswith(('/fo', '/fd', '/fa')) or arg in ('/showIncludes',):
|
|
continue
|
|
if arg.replace('\\', '/').removeprefix('Z:') == str(pathlib.Path(row['file']).resolve()):
|
|
continue
|
|
flags.append(replace(arg))
|
|
if '/c' not in flags and '-c' not in flags:
|
|
flags.append('/c')
|
|
if flags not in shapes:
|
|
shapes.append(flags)
|
|
units[file] = shapes.index(flags)
|
|
result = {'compiler': replace(args.compiler), 'env': {'INCLUDE': replace(args.include)}, 'shapes': shapes, 'units': dict(sorted(units.items()))}
|
|
pathlib.Path(args.output).write_text(json.dumps(result, indent=2) + '\n')
|
|
print(f'Exported {len(units)} units in {len(shapes)} compile shapes')
|