From 79bb1df04faf96f03f2b5a6b2dcb95fcff1a3b0d Mon Sep 17 00:00:00 2001 From: Joel Klinghed Date: Wed, 14 Mar 2018 21:54:33 +0100 Subject: Use standalone coverage script for legacy targets ninja coverage -> generate all possible reports (text, xml, html) depending on gcovr and/or lcov/genhtml availability. ninja coverage-html -> generate only html report ninja coverage-xml -> generate only xml report ninja coverage-text -> generate only text report Make all targets phony, the old legacy rules where just annoying as you would have to remove the old report before being able to generate a new one. ninja coverage succeeds if it can generate at least one report. ninja coverage-* only succeeds if it can generate the requested report --- mesonbuild/scripts/coverage.py | 182 ++++++++++++++++++++++++----------------- 1 file changed, 109 insertions(+), 73 deletions(-) (limited to 'mesonbuild/scripts/coverage.py') diff --git a/mesonbuild/scripts/coverage.py b/mesonbuild/scripts/coverage.py index 2d1f8c3..dcc9465 100644 --- a/mesonbuild/scripts/coverage.py +++ b/mesonbuild/scripts/coverage.py @@ -14,87 +14,123 @@ from mesonbuild import environment -import sys, os, subprocess, pathlib +import argparse, sys, os, subprocess, pathlib + +def coverage(outputs, source_root, build_root, log_dir): + outfiles = [] + exitcode = 0 -def coverage(source_root, build_root, log_dir): (gcovr_exe, gcovr_new_rootdir, lcov_exe, genhtml_exe) = environment.find_coverage_tools() - if gcovr_exe: - # gcovr >= 3.1 interprets rootdir differently - if gcovr_new_rootdir: - rootdir = build_root - else: - rootdir = source_root - subprocess.check_call([gcovr_exe, - '-x', - '-r', rootdir, - '-o', os.path.join(log_dir, 'coverage.xml'), - ]) - subprocess.check_call([gcovr_exe, - '-r', rootdir, - '-o', os.path.join(log_dir, 'coverage.txt'), - ]) - if lcov_exe and genhtml_exe: - htmloutdir = os.path.join(log_dir, 'coveragereport') - covinfo = os.path.join(log_dir, 'coverage.info') - initial_tracefile = covinfo + '.initial' - run_tracefile = covinfo + '.run' - raw_tracefile = covinfo + '.raw' - subprocess.check_call([lcov_exe, - '--directory', build_root, - '--capture', - '--initial', - '--output-file', - initial_tracefile]) - subprocess.check_call([lcov_exe, - '--directory', build_root, - '--capture', - '--output-file', run_tracefile, - '--no-checksum', - '--rc', 'lcov_branch_coverage=1', - ]) - # Join initial and test results. - subprocess.check_call([lcov_exe, - '-a', initial_tracefile, - '-a', run_tracefile, - '-o', raw_tracefile]) - # Remove all directories outside the source_root from the covinfo - subprocess.check_call([lcov_exe, - '--extract', raw_tracefile, - os.path.join(source_root, '*'), - '--output-file', covinfo]) - subprocess.check_call([genhtml_exe, - '--prefix', build_root, - '--output-directory', htmloutdir, - '--title', 'Code coverage', - '--legend', - '--show-details', - '--branch-coverage', - covinfo]) - elif gcovr_exe and gcovr_new_rootdir: - htmloutdir = os.path.join(log_dir, 'coveragereport') - subprocess.check_call([gcovr_exe, - '--html', - '--html-details', - '-r', build_root, - '-o', os.path.join(htmloutdir, 'index.html'), - ]) - if gcovr_exe: + + # gcovr >= 3.1 interprets rootdir differently + if gcovr_new_rootdir: + gcovr_rootdir = build_root + else: + gcovr_rootdir = source_root + + if not outputs or 'xml' in outputs: + if gcovr_exe: + subprocess.check_call([gcovr_exe, + '-x', + '-r', gcovr_rootdir, + '-o', os.path.join(log_dir, 'coverage.xml'), + ]) + outfiles.append(('Xml', pathlib.Path(log_dir, 'coverage.xml'))) + elif outputs: + print('gcovr needed to generate Xml coverage report') + exitcode = 1 + + if not outputs or 'text' in outputs: + if gcovr_exe: + subprocess.check_call([gcovr_exe, + '-r', gcovr_rootdir, + '-o', os.path.join(log_dir, 'coverage.txt'), + ]) + outfiles.append(('Text', pathlib.Path(log_dir, 'coverage.txt'))) + elif outputs: + print('gcovr needed to generate text coverage report') + exitcode = 1 + + if not outputs or 'html' in outputs: + if lcov_exe and genhtml_exe: + htmloutdir = os.path.join(log_dir, 'coveragereport') + covinfo = os.path.join(log_dir, 'coverage.info') + initial_tracefile = covinfo + '.initial' + run_tracefile = covinfo + '.run' + raw_tracefile = covinfo + '.raw' + subprocess.check_call([lcov_exe, + '--directory', build_root, + '--capture', + '--initial', + '--output-file', + initial_tracefile]) + subprocess.check_call([lcov_exe, + '--directory', build_root, + '--capture', + '--output-file', run_tracefile, + '--no-checksum', + '--rc', 'lcov_branch_coverage=1', + ]) + # Join initial and test results. + subprocess.check_call([lcov_exe, + '-a', initial_tracefile, + '-a', run_tracefile, + '-o', raw_tracefile]) + # Remove all directories outside the source_root from the covinfo + subprocess.check_call([lcov_exe, + '--extract', raw_tracefile, + os.path.join(source_root, '*'), + '--output-file', covinfo]) + subprocess.check_call([genhtml_exe, + '--prefix', build_root, + '--output-directory', htmloutdir, + '--title', 'Code coverage', + '--legend', + '--show-details', + '--branch-coverage', + covinfo]) + outfiles.append(('Html', pathlib.Path(htmloutdir, 'index.html'))) + elif gcovr_exe and gcovr_new_rootdir: + htmloutdir = os.path.join(log_dir, 'coveragereport') + subprocess.check_call([gcovr_exe, + '--html', + '--html-details', + '-r', build_root, + '-o', os.path.join(htmloutdir, 'index.html'), + ]) + outfiles.append(('Html', pathlib.Path(htmloutdir, 'index.html'))) + elif outputs: + print('lcov/genhtml or gcovr >= 3.1 needed to generate Html coverage report') + exitcode = 1 + + if not outputs and not outfiles: + print('Need gcovr or lcov/genhtml to generate any coverage reports') + exitcode = 1 + + if outfiles: print('') - print('XML coverage report can be found at', - pathlib.Path(log_dir, 'coverage.xml').as_uri()) - print('Text coverage report can be found at', - pathlib.Path(log_dir, 'coverage.txt').as_uri()) - if (lcov_exe and genhtml_exe) or (gcovr_exe and gcovr_new_rootdir): - print('Html coverage report can be found at', - pathlib.Path(htmloutdir, 'index.html').as_uri()) - return 0 + for (filetype, path) in outfiles: + print(filetype + ' coverage report can be found at', path.as_uri()) + + return exitcode def run(args): if not os.path.isfile('build.ninja'): print('Coverage currently only works with the Ninja backend.') return 1 - source_root, build_root, log_dir = args[:] - return coverage(source_root, build_root, log_dir) + parser = argparse.ArgumentParser(description='Generate coverage reports') + parser.add_argument('--text', dest='outputs', action='append_const', + const='text', help='generate Text report') + parser.add_argument('--xml', dest='outputs', action='append_const', + const='xml', help='generate Xml report') + parser.add_argument('--html', dest='outputs', action='append_const', + const='html', help='generate Html report') + parser.add_argument('source_root') + parser.add_argument('build_root') + parser.add_argument('log_dir') + options = parser.parse_args(args) + return coverage(options.outputs, options.source_root, + options.build_root, options.log_dir) if __name__ == '__main__': sys.exit(run(sys.argv[1:])) -- cgit v1.1 From 8bad2d98277854ff58ef84c27b89604b544c279f Mon Sep 17 00:00:00 2001 From: Joel Klinghed Date: Thu, 15 Mar 2018 21:59:39 +0100 Subject: Exclude subprojects when doing coverage Restore subproject exclusion for the html coverage report that existed in the ninja backend legacy target. Also exclude subprojects for the gcovr generated reports. --- mesonbuild/scripts/coverage.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'mesonbuild/scripts/coverage.py') diff --git a/mesonbuild/scripts/coverage.py b/mesonbuild/scripts/coverage.py index dcc9465..eaa86fe 100644 --- a/mesonbuild/scripts/coverage.py +++ b/mesonbuild/scripts/coverage.py @@ -16,7 +16,7 @@ from mesonbuild import environment import argparse, sys, os, subprocess, pathlib -def coverage(outputs, source_root, build_root, log_dir): +def coverage(outputs, source_root, subproject_root, build_root, log_dir): outfiles = [] exitcode = 0 @@ -33,6 +33,7 @@ def coverage(outputs, source_root, build_root, log_dir): subprocess.check_call([gcovr_exe, '-x', '-r', gcovr_rootdir, + '-e', subproject_root, '-o', os.path.join(log_dir, 'coverage.xml'), ]) outfiles.append(('Xml', pathlib.Path(log_dir, 'coverage.xml'))) @@ -44,6 +45,7 @@ def coverage(outputs, source_root, build_root, log_dir): if gcovr_exe: subprocess.check_call([gcovr_exe, '-r', gcovr_rootdir, + '-e', subproject_root, '-o', os.path.join(log_dir, 'coverage.txt'), ]) outfiles.append(('Text', pathlib.Path(log_dir, 'coverage.txt'))) @@ -81,6 +83,11 @@ def coverage(outputs, source_root, build_root, log_dir): '--extract', raw_tracefile, os.path.join(source_root, '*'), '--output-file', covinfo]) + # Remove all directories inside subproject dir + subprocess.check_call([lcov_exe, + '--remove', covinfo, + os.path.join(subproject_root, '*'), + '--output-file', covinfo]) subprocess.check_call([genhtml_exe, '--prefix', build_root, '--output-directory', htmloutdir, @@ -96,6 +103,7 @@ def coverage(outputs, source_root, build_root, log_dir): '--html', '--html-details', '-r', build_root, + '-e', subproject_root, '-o', os.path.join(htmloutdir, 'index.html'), ]) outfiles.append(('Html', pathlib.Path(htmloutdir, 'index.html'))) @@ -126,11 +134,13 @@ def run(args): parser.add_argument('--html', dest='outputs', action='append_const', const='html', help='generate Html report') parser.add_argument('source_root') + parser.add_argument('subproject_root') parser.add_argument('build_root') parser.add_argument('log_dir') options = parser.parse_args(args) return coverage(options.outputs, options.source_root, - options.build_root, options.log_dir) + options.subproject_root, options.build_root, + options.log_dir) if __name__ == '__main__': sys.exit(run(sys.argv[1:])) -- cgit v1.1 From b2ffb6b56560d212e58192b85b0a8e9232a66dd4 Mon Sep 17 00:00:00 2001 From: Joel Klinghed Date: Fri, 16 Mar 2018 00:20:22 +0100 Subject: Generate coveragereport directory for gcovr html target --- mesonbuild/scripts/coverage.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'mesonbuild/scripts/coverage.py') diff --git a/mesonbuild/scripts/coverage.py b/mesonbuild/scripts/coverage.py index eaa86fe..916c84f 100644 --- a/mesonbuild/scripts/coverage.py +++ b/mesonbuild/scripts/coverage.py @@ -99,6 +99,8 @@ def coverage(outputs, source_root, subproject_root, build_root, log_dir): outfiles.append(('Html', pathlib.Path(htmloutdir, 'index.html'))) elif gcovr_exe and gcovr_new_rootdir: htmloutdir = os.path.join(log_dir, 'coveragereport') + if not os.path.isdir(htmloutdir): + os.mkdir(htmloutdir) subprocess.check_call([gcovr_exe, '--html', '--html-details', -- cgit v1.1