From 111e3df45dddd5b4ae98ad957f8183980c90a503 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Wed, 10 May 2017 19:31:12 +0300 Subject: [PATCH] Moved coverage commands to a standalone script. --- mesonbuild/backend/ninjabackend.py | 12 ++++++ mesonbuild/coredata.py | 1 + mesonbuild/mesonmain.py | 3 ++ mesonbuild/scripts/coverage.py | 61 ++++++++++++++++++++++++++++++ 4 files changed, 77 insertions(+) create mode 100644 mesonbuild/scripts/coverage.py diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 4885f4bbe..572724805 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -567,6 +567,18 @@ int dummy; self.processed_targets[target.name + target.type_suffix()] = True def generate_coverage_rules(self, outfile): + e = NinjaBuildElement(self.all_outputs, 'coverage', 'CUSTOM_COMMAND', 'PHONY') + e.add_item('COMMAND', [sys.executable, + self.environment.get_build_command(), + '--internal', 'coverage', + self.environment.get_source_dir(), + self.environment.get_build_dir(), + self.environment.get_log_dir()]) + e.add_item('description', 'Generates coverage reports.') + e.write(outfile) + self.generate_coverage_legacy_rules(outfile) + + def generate_coverage_legacy_rules(self, outfile): (gcovr_exe, lcov_exe, genhtml_exe) = environment.find_coverage_tools() added_rule = False if gcovr_exe: diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index a336278b2..7bc20f8b6 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -334,6 +334,7 @@ forbidden_target_names = {'clean': None, 'clean-ctlist': None, 'clean-gcno': None, 'clean-gcda': None, + 'coverage': None, 'coverage-text': None, 'coverage-xml': None, 'coverage-html': None, diff --git a/mesonbuild/mesonmain.py b/mesonbuild/mesonmain.py index 282df363d..4fecc5847 100644 --- a/mesonbuild/mesonmain.py +++ b/mesonbuild/mesonmain.py @@ -249,6 +249,9 @@ def run_script_command(args): elif cmdname == 'dist': import mesonbuild.scripts.dist as abc cmdfunc = abc.run + elif cmdname == 'coverage': + import mesonbuild.scripts.coverage as abc + cmdfunc = abc.run else: raise MesonException('Unknown internal command {}.'.format(cmdname)) return cmdfunc(cmdargs) diff --git a/mesonbuild/scripts/coverage.py b/mesonbuild/scripts/coverage.py new file mode 100644 index 000000000..59e475a84 --- /dev/null +++ b/mesonbuild/scripts/coverage.py @@ -0,0 +1,61 @@ +# Copyright 2017 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from mesonbuild import environment + +import sys, os, subprocess, re + +def coverage(source_root, build_root, log_dir): + (gcovr_exe, lcov_exe, genhtml_exe) = environment.find_coverage_tools() + if gcovr_exe: + subprocess.check_call([gcovr_exe, + '-x', + '-r', source_root, + '-o', os.path.join(log_dir, 'coverage.xml'), + ]) + subprocess.check_call([gcovr_exe, + '-r', source_root, + '-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') + lcov_command = [lcov_exe, + '--directory', build_root, + '--capture', + '--output-file', covinfo, + '--no-checksum', + '--rc', 'lcov_branch_coverage=1', + ] + genhtml_command = [genhtml_exe, + '--prefix', build_root, + '--output-directory', htmloutdir, + '--title', 'Code coverage', + '--legend', + '--show-details', + '--branch-coverage', + covinfo] + subprocess.check_call(lcov_command) + subprocess.check_call(genhtml_command) + return 0 + +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) + +if __name__ == '__main__': + sys.exit(run(sys.argv[1:])) \ No newline at end of file