1#!/usr/bin/env python3 2# 3# check-units.py: check the number of compilation units and identify 4# those that are rebuilt multiple times 5# 6# Copyright (C) 2025 Linaro Ltd. 7# 8# SPDX-License-Identifier: GPL-2.0-or-later 9 10from os import access, R_OK, path 11from sys import exit 12import json 13import argparse 14from pathlib import Path 15from collections import Counter 16 17 18def extract_build_units(cc_path): 19 """ 20 Extract the build units and their counds from compile_commands.json file. 21 22 Returns: 23 Hash table of ["unit"] = count 24 """ 25 26 j = json.load(open(cc_path, 'r')) 27 files = [f['file'] for f in j] 28 build_units = Counter(files) 29 30 return build_units 31 32 33def analyse_units(build_units, top_n): 34 """ 35 Analyse the build units and report stats and the top 10 rebuilds 36 """ 37 38 print(f"Total source files: {len(build_units.keys())}") 39 print(f"Total build units: {sum(units.values())}") 40 41 # Create a sorted list by number of rebuilds 42 sorted_build_units = sorted(build_units.items(), 43 key=lambda item: item[1], 44 reverse=True) 45 46 print("Most rebuilt units:") 47 for unit, count in sorted_build_units[:top_n]: 48 print(f" {unit} built {count} times") 49 50 print("Least rebuilt units:") 51 for unit, count in sorted_build_units[-10:]: 52 print(f" {unit} built {count} times") 53 54 55if __name__ == "__main__": 56 parser = argparse.ArgumentParser( 57 description="analyse number of build units in compile_commands.json") 58 parser.add_argument("cc_path", type=Path, default=None, 59 help="Path to compile_commands.json") 60 parser.add_argument("-n", type=int, default=20, 61 help="Dump the top <n> entries") 62 63 args = parser.parse_args() 64 65 if path.isfile(args.cc_path) and access(args.cc_path, R_OK): 66 units = extract_build_units(args.cc_path) 67 analyse_units(units, args.n) 68 exit(0) 69 else: 70 print(f"{args.cc_path} doesn't exist or isn't readable") 71 exit(1) 72