Skip to content

Commit

Permalink
[feat] Print statistics after analysis through Makefile
Browse files Browse the repository at this point in the history
"CodeChecker analyze --makefile ..." is generating a Makefile that
contains analyzer commands. With "make" command one can execute analysis
using this generated Makefile.

This commit is about printing some statistics about the analysis based
on the Makefile. The statistics contain the number of successful and
failed analysis.
  • Loading branch information
bruntib committed Jul 22, 2024
1 parent b049040 commit 5f39043
Showing 1 changed file with 49 additions and 3 deletions.
52 changes: 49 additions & 3 deletions analyzer/codechecker_analyzer/makefile.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import hashlib
import os
import shlex
import stat
import uuid

from codechecker_common.logger import get_logger
Expand Down Expand Up @@ -56,6 +57,8 @@ def __init__(self, analyzers, output_path, config_map,
self.__stats_dir = statistics_data['stats_out_dir']

self.__makefile = os.path.join(output_path, 'Makefile')
self.__stat_sh = os.path.join(output_path, 'print_stat.sh')
self.__exit_codes_dir = os.path.join(output_path, 'exit_codes')

self.__config = None
self.__func_map_cmd = None
Expand Down Expand Up @@ -110,13 +113,48 @@ def __write_default_targets(self, mfile):
analyzer.
"""
mfile.write("# Default target to run all analysis.\n"
"default: all\n\n")
"default: create_exit_code_folder all\n"
f"\t@bash {self.__stat_sh}\n"
f"\t@rm -rf {self.__exit_codes_dir}\n\n"
"# Folder for creating exit codes of analyses.\n"
"create_exit_code_folder:\n"
f"\t@rm -rf {self.__exit_codes_dir}\n"
f"\t@mkdir {self.__exit_codes_dir}\n\n")

for analyzer in self.__analyzers:
analyzer_name = self.__format_analyzer_type(analyzer)
mfile.write(f"# Target to run only '{analyzer_name}' analysis.\n"
f"all: all_{analyzer_name}\n\n")

def __write_print_stats(self, sfile):
""" Write target to print analyzer statistics.
At the end of the analysis the Makefile should print statistics about
how many actions were analyzed by the specific analyzers.
"""
sfile.write(
'declare -A success\n'
'declare -A all\n'
'sum=0\n'
f'for filename in $(ls {self.__exit_codes_dir}); do\n'
' success[$filename]='
f'$(grep ^0$ {self.__exit_codes_dir}/$filename | wc -l)\n'
f' all[$filename]=$(wc -l < {self.__exit_codes_dir}/$filename)\n'
' sum=$(($sum + ${all[$filename]}))\n'
'done\n'
'echo "----==== Summary ====----"\n'
'echo "Successfully analyzed"\n'
'for analyzer in "${!success[@]}"; do\n'
' echo $analyzer: ${success[$analyzer]}\n'
'done\n'
'echo "Failed to analyze"\n'
'for analyzer in "${!success[@]}"; do\n'
' echo $analyzer: $((${all[$analyzer]} - '
'${success[$analyzer]}))\n'
'done\n'
'echo "Total analyzed compilation commands: $sum"\n'
'echo "----=================----"\n')

def __get_ctu_pre_analysis_cmds(self, action):
""" Get CTU pre-analysis commands. """
cmds = []
Expand Down Expand Up @@ -238,6 +276,9 @@ def __write_analysis_targets(self, mfile, action, post_pre_all_target):
target = self.__get_target_name(action)
analyzer_name = self.__format_analyzer_type(action.analyzer_type)

save_exit_code = \
f"; echo $$? >> {self.__exit_codes_dir}/{action.analyzer_type}"

if action.analyzer_type == ClangTidy.ANALYZER_NAME:
analyzer_output_file = rh.analyzer_result_file + ".output"
file_name = "{source_file}_{analyzer}_" + target
Expand All @@ -247,11 +288,12 @@ def __write_analysis_targets(self, mfile, action, post_pre_all_target):
"--filename", file_name,
analyzer_output_file]

command = f"@{' '.join(analyzer_cmd)} > {analyzer_output_file}\n" \
command = f"@{' '.join(analyzer_cmd)} > " \
f"{analyzer_output_file}{save_exit_code}\n" \
f"\t@{' '.join(report_converter_cmd)} 1>/dev/null\n" \
f"\t@rm -rf {analyzer_output_file}\n"
else:
command = f"@{' '.join(analyzer_cmd)} 1>/dev/null"
command = f"@{' '.join(analyzer_cmd)} 1>/dev/null{save_exit_code}"

mfile.write(
f'{target}: {post_pre_all_target}\n'
Expand All @@ -265,6 +307,10 @@ def create(self, actions):
LOG.info("Creating Makefile from the analyzer commands: '%s'...",
self.__makefile)

with open(self.__stat_sh, 'w+',
encoding='utf-8', errors='ignore') as sfile:
self.__write_print_stats(sfile)

with open(self.__makefile, 'w+',
encoding='utf-8', errors='ignore') as mfile:
self.__write_header(mfile)
Expand Down

0 comments on commit 5f39043

Please sign in to comment.