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