Skip to content

Commit 7ec85b1

Browse files
committed
[feat] Print statistics after analysis through Makefile
"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.
1 parent b049040 commit 7ec85b1

File tree

1 file changed

+48
-3
lines changed

1 file changed

+48
-3
lines changed

analyzer/codechecker_analyzer/makefile.py

+48-3
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ def __init__(self, analyzers, output_path, config_map,
5656
self.__stats_dir = statistics_data['stats_out_dir']
5757

5858
self.__makefile = os.path.join(output_path, 'Makefile')
59+
self.__stat_sh = os.path.join(output_path, 'print_stat.sh')
60+
self.__exit_codes_dir = os.path.join(output_path, 'exit_codes')
5961

6062
self.__config = None
6163
self.__func_map_cmd = None
@@ -110,13 +112,48 @@ def __write_default_targets(self, mfile):
110112
analyzer.
111113
"""
112114
mfile.write("# Default target to run all analysis.\n"
113-
"default: all\n\n")
115+
"default: create_exit_code_folder all\n"
116+
f"\t@bash {self.__stat_sh}\n"
117+
f"\t@rm -rf {self.__exit_codes_dir}\n\n"
118+
"# Folder for creating exit codes of analyses.\n"
119+
"create_exit_code_folder:\n"
120+
f"\t@rm -rf {self.__exit_codes_dir}\n"
121+
f"\t@mkdir {self.__exit_codes_dir}\n\n")
114122

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

128+
def __write_print_stats(self, sfile):
129+
""" Write target to print analyzer statistics.
130+
131+
At the end of the analysis the Makefile should print statistics about
132+
how many actions were analyzed by the specific analyzers.
133+
"""
134+
sfile.write(
135+
'declare -A success\n'
136+
'declare -A all\n'
137+
'sum=0\n'
138+
f'for filename in $(ls {self.__exit_codes_dir}); do\n'
139+
' success[$filename]='
140+
f'$(grep ^0$ {self.__exit_codes_dir}/$filename | wc -l)\n'
141+
f' all[$filename]=$(wc -l < {self.__exit_codes_dir}/$filename)\n'
142+
' sum=$(($sum + ${all[$filename]}))\n'
143+
'done\n'
144+
'echo "----==== Summary ====----"\n'
145+
'echo "Successfully analyzed"\n'
146+
'for analyzer in "${!success[@]}"; do\n'
147+
' echo $analyzer: ${success[$analyzer]}\n'
148+
'done\n'
149+
'echo "Failed to analyze"\n'
150+
'for analyzer in "${!success[@]}"; do\n'
151+
' echo $analyzer: $((${all[$analyzer]} - '
152+
'${success[$analyzer]}))\n'
153+
'done\n'
154+
'echo "Total analyzed compilation commands: $sum"\n'
155+
'echo "----=================----"\n')
156+
120157
def __get_ctu_pre_analysis_cmds(self, action):
121158
""" Get CTU pre-analysis commands. """
122159
cmds = []
@@ -238,6 +275,9 @@ def __write_analysis_targets(self, mfile, action, post_pre_all_target):
238275
target = self.__get_target_name(action)
239276
analyzer_name = self.__format_analyzer_type(action.analyzer_type)
240277

278+
save_exit_code = \
279+
f"; echo $$? >> {self.__exit_codes_dir}/{action.analyzer_type}"
280+
241281
if action.analyzer_type == ClangTidy.ANALYZER_NAME:
242282
analyzer_output_file = rh.analyzer_result_file + ".output"
243283
file_name = "{source_file}_{analyzer}_" + target
@@ -247,11 +287,12 @@ def __write_analysis_targets(self, mfile, action, post_pre_all_target):
247287
"--filename", file_name,
248288
analyzer_output_file]
249289

250-
command = f"@{' '.join(analyzer_cmd)} > {analyzer_output_file}\n" \
290+
command = f"@{' '.join(analyzer_cmd)} > " \
291+
f"{analyzer_output_file}{save_exit_code}\n" \
251292
f"\t@{' '.join(report_converter_cmd)} 1>/dev/null\n" \
252293
f"\t@rm -rf {analyzer_output_file}\n"
253294
else:
254-
command = f"@{' '.join(analyzer_cmd)} 1>/dev/null"
295+
command = f"@{' '.join(analyzer_cmd)} 1>/dev/null{save_exit_code}"
255296

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

309+
with open(self.__stat_sh, 'w+',
310+
encoding='utf-8', errors='ignore') as sfile:
311+
self.__write_print_stats(sfile)
312+
268313
with open(self.__makefile, 'w+',
269314
encoding='utf-8', errors='ignore') as mfile:
270315
self.__write_header(mfile)

0 commit comments

Comments
 (0)