#!/usr/bin/env python3
# compile_commands.json generator
# Copyright (C) 2024 Intel Corporation
#
# This software may be distributed under the terms of the BSD license.
# See README for more details.

import os
import sys
import glob
import json
import argparse

parser = argparse.ArgumentParser(description='Read each of the build directories that are given and generate '
                                 'a compile_commands.json file. If a source file is found multiple times, '
                                 'then the compile flags from the last build directory will be used.')
parser.add_argument('-o', '--output', default='compile_commands.json', type=str,
                    help="Output file to generate")
parser.add_argument('builddirs', nargs='+', type=str, metavar="builddir",
                    help='Build directories to search')

args = parser.parse_args()

files = {}

for builddir in args.builddirs:
    for cmd_file in glob.glob('**/*.o.cmd', root_dir=builddir, recursive=True):
        with open(os.path.join(builddir, cmd_file), encoding='ascii') as f:
            base_dir, cmd = f.readline().split(':', 1)
            src_file = cmd.rsplit(maxsplit=1)[1]

        src_file = os.path.abspath(os.path.join(base_dir, src_file))
        files[src_file] = {
            'command': cmd.strip(),
            'directory': base_dir,
            'file': src_file,
        }

flist = json.dumps(sorted(list(files.values()), key=lambda k: k['file']), indent=2, sort_keys=True)

try:
   # Avoid writing the file if it did not change, first read original
   with open(args.output, 'rt', encoding='UTF-8') as f:
       orig = []
       while data := f.read():
           orig.append(data)
       orig = ''.join(orig)
except OSError:
    orig = ''

# And only write if something changed
if orig != flist:
    with open(args.output, 'wt', encoding='UTF-8') as f:
        f.write(flist)