1#!/usr/bin/env python3
2# coding: utf-8
3#
4# © 2021 Qualcomm Innovation Center, Inc. All rights reserved.
5#
6# SPDX-License-Identifier: BSD-3-Clause
7
8"""
9Simple script to parse the compile_commands to extract generated source and
10header files, to pass to cscope or other source indexing tools.
11"""
12
13import json
14import sys
15import os
16import re
17
18build_dir = 'build'
19commands_file = 'compile_commands.json'
20compile_commands = []
21
22conf_default_weight = 60
23build_preferences = {}
24
25files = set()
26incdirs = set()
27
28include_regex = re.compile('(-iquote|-I) (\\w+[-\\{:s}\\w]+)'.format(os.sep))
29imacros_regex = re.compile('(-imacros) (\\w+[-\\{:s}\\w.]+)'.format(os.sep))
30
31for dir, dir_dirs, dir_files in os.walk('config/featureset'):
32    regex = re.compile('^# indexer-weight: (\\d+)')
33    for file in dir_files:
34        file_base = os.path.splitext(file)[0]
35        if file.endswith('.conf'):
36            build_preferences[file_base] = conf_default_weight
37            infile = os.path.join(dir, file)
38            with open(infile, 'r') as f:
39                for i, line in enumerate(f):
40                    weights = regex.findall(line)
41                    if weights:
42                        build_preferences[file_base] = int(weights[0])
43
44for dir, dir_dirs, dir_files in os.walk(build_dir):
45    if commands_file in dir_files:
46        x = os.stat(dir)
47        time = max(x.st_atime, x.st_mtime, x.st_ctime)
48        compile_commands.append((time, os.path.join(dir, commands_file)))
49
50if not compile_commands:
51    print('no build found!', file=sys.stderr)
52    exit(1)
53
54newest = 0.0
55
56for time, f in compile_commands:
57    x = os.stat(f)
58    time = max(x.st_atime, x.st_mtime, x.st_ctime, time)
59    for p in build_preferences.keys():
60        if p in f:
61            # Boost these to preference them
62            time += build_preferences[p]
63
64    if time > newest:
65        newest = time
66        infile = f
67
68if len(compile_commands) > 1:
69    print('warning: multiple builds found, using: {:s}'.format(
70        infile), file=sys.stderr)
71
72try:
73    with open(infile, 'r') as f:
74        compile = json.loads(f.read())
75
76        for s in compile:
77            if s['file'].startswith(build_dir):
78                files.add(s['file'])
79            cmd = s['command']
80            for t, dir in include_regex.findall(cmd):
81                if dir.startswith(build_dir):
82                    incdirs.add(dir)
83            for t, f in imacros_regex.findall(cmd):
84                files.add(f)
85except FileNotFoundError:
86    exit(1)
87
88for dir in incdirs:
89    try:
90        for f in os.listdir(dir):
91            filename = os.path.join(dir, f)
92            if filename.endswith('.h'):
93                files.add(filename)
94    except OSError:
95        pass
96
97for f in files:
98    print(f)
99