diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 8577bc77a..92d7dfb81 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -628,19 +628,24 @@ int dummy; self.generate_coverage_legacy_rules(outfile) def generate_coverage_legacy_rules(self, outfile): - (gcovr_exe, lcov_exe, genhtml_exe) = environment.find_coverage_tools() + (gcovr_exe, gcovr_3_1, lcov_exe, genhtml_exe) = environment.find_coverage_tools() added_rule = False if gcovr_exe: + # gcovr >= 3.1 interprets rootdir differently + if gcovr_3_1: + rootdir = self.environment.get_build_dir() + else: + rootdir = self.environment.get_source_dir(), added_rule = True elem = NinjaBuildElement(self.all_outputs, 'meson-coverage-xml', 'CUSTOM_COMMAND', '') - elem.add_item('COMMAND', [gcovr_exe, '-x', '-r', self.environment.get_source_dir(), + elem.add_item('COMMAND', [gcovr_exe, '-x', '-r', rootdir, '-o', os.path.join(self.environment.get_log_dir(), 'coverage.xml')]) elem.add_item('DESC', 'Generating XML coverage report.') elem.write(outfile) # Alias that runs the target defined above self.create_target_alias('meson-coverage-xml', outfile) elem = NinjaBuildElement(self.all_outputs, 'meson-coverage-text', 'CUSTOM_COMMAND', '') - elem.add_item('COMMAND', [gcovr_exe, '-r', self.environment.get_source_dir(), + elem.add_item('COMMAND', [gcovr_exe, '-r', rootdir, '-o', os.path.join(self.environment.get_log_dir(), 'coverage.txt')]) elem.add_item('DESC', 'Generating text coverage report.') elem.write(outfile) diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index ccd85d53e..099a3b3a9 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -77,19 +77,31 @@ cflags_mapping = {'c': 'CFLAGS', 'd': 'DFLAGS', 'vala': 'VALAFLAGS'} +def detect_gcovr(version='3.1', log=False): + gcovr_exe = 'gcovr' + try: + p, found = Popen_safe([gcovr_exe, '--version'])[0:2] + except (FileNotFoundError, PermissionError): + # Doesn't exist in PATH or isn't executable + return + found = search_version(found) + if p.returncode == 0: + if log: + mlog.log('Found gcovr-{} at {}'.format(found, shlex.quote(shutil.which(gcovr_exe)))) + return gcovr_exe, mesonlib.version_compare(found, '>=' + version) def find_coverage_tools(): - gcovr_exe = 'gcovr' + gcovr_exe, gcovr_3_1 = detect_gcovr() + lcov_exe = 'lcov' genhtml_exe = 'genhtml' - if not mesonlib.exe_exists([gcovr_exe, '--version']): - gcovr_exe = None if not mesonlib.exe_exists([lcov_exe, '--version']): lcov_exe = None if not mesonlib.exe_exists([genhtml_exe, '--version']): genhtml_exe = None - return gcovr_exe, lcov_exe, genhtml_exe + + return gcovr_exe, gcovr_3_1, lcov_exe, genhtml_exe def detect_ninja(version='1.5', log=False): for n in ['ninja', 'ninja-build']: diff --git a/mesonbuild/scripts/coverage.py b/mesonbuild/scripts/coverage.py index 47f4cda29..4746134e0 100644 --- a/mesonbuild/scripts/coverage.py +++ b/mesonbuild/scripts/coverage.py @@ -17,15 +17,20 @@ from mesonbuild import environment import sys, os, subprocess, pathlib def coverage(source_root, build_root, log_dir): - (gcovr_exe, lcov_exe, genhtml_exe) = environment.find_coverage_tools() + (gcovr_exe, gcovr_3_1, lcov_exe, genhtml_exe) = environment.find_coverage_tools() if gcovr_exe: + # gcovr >= 3.1 interprets rootdir differently + if gcovr_3_1: + rootdir = build_root + else: + rootdir = source_root subprocess.check_call([gcovr_exe, '-x', - '-r', source_root, + '-r', rootdir, '-o', os.path.join(log_dir, 'coverage.xml'), ]) subprocess.check_call([gcovr_exe, - '-r', source_root, + '-r', rootdir, '-o', os.path.join(log_dir, 'coverage.txt'), ]) if lcov_exe and genhtml_exe: