1#!/usr/bin/env python3 2# compile_commands.json generator 3# Copyright (C) 2024 Intel Corporation 4# 5# This software may be distributed under the terms of the BSD license. 6# See README for more details. 7 8import os 9import sys 10import glob 11import json 12import argparse 13 14parser = argparse.ArgumentParser(description='Read each of the build directories that are given and generate ' 15 'a compile_commands.json file. If a source file is found multiple times, ' 16 'then the compile flags from the last build directory will be used.') 17parser.add_argument('-o', '--output', default='compile_commands.json', type=str, 18 help="Output file to generate") 19parser.add_argument('builddirs', nargs='+', type=str, metavar="builddir", 20 help='Build directories to search') 21 22args = parser.parse_args() 23 24files = {} 25 26for builddir in args.builddirs: 27 for cmd_file in glob.glob('**/*.o.cmd', root_dir=builddir, recursive=True): 28 with open(os.path.join(builddir, cmd_file), encoding='ascii') as f: 29 base_dir, cmd = f.readline().split(':', 1) 30 src_file = cmd.rsplit(maxsplit=1)[1] 31 32 src_file = os.path.abspath(os.path.join(base_dir, src_file)) 33 files[src_file] = { 34 'command': cmd.strip(), 35 'directory': base_dir, 36 'file': src_file, 37 } 38 39flist = json.dumps(sorted(list(files.values()), key=lambda k: k['file']), indent=2, sort_keys=True) 40 41try: 42 # Avoid writing the file if it did not change, first read original 43 with open(args.output, 'rt', encoding='UTF-8') as f: 44 orig = [] 45 while data := f.read(): 46 orig.append(data) 47 orig = ''.join(orig) 48except OSError: 49 orig = '' 50 51# And only write if something changed 52if orig != flist: 53 with open(args.output, 'wt', encoding='UTF-8') as f: 54 f.write(flist) 55