diff options
author | Eli Schwartz <eschwartz@archlinux.org> | 2021-10-31 10:55:21 -0400 |
---|---|---|
committer | Eli Schwartz <eschwartz@archlinux.org> | 2021-11-01 18:57:14 -0400 |
commit | 0f0b1f22d2a1e835d7ee52cb7d391c3e29e9fecc (patch) | |
tree | c53bae58467e2842c1a7186a76cf6adec728d436 | |
parent | 86df7dd6273498e3256f4944b6b584636ae6ffb5 (diff) | |
download | meson-0f0b1f22d2a1e835d7ee52cb7d391c3e29e9fecc.zip meson-0f0b1f22d2a1e835d7ee52cb7d391c3e29e9fecc.tar.gz meson-0f0b1f22d2a1e835d7ee52cb7d391c3e29e9fecc.tar.bz2 |
coverage generator: obey the documentation and only generate supported outputs
We say:
> If version 4.2 or higher of the first is found, targets coverage-text,
> coverage-xml, coverage-sonarqube and coverage-html are generated.
But this is totally untrue. Make it true, by actually checking (and
not generating broken coverage commands when older versions of gcovr are
found).
Fixes #9505
-rw-r--r-- | mesonbuild/backend/ninjabackend.py | 60 | ||||
-rw-r--r-- | mesonbuild/environment.py | 8 | ||||
-rw-r--r-- | mesonbuild/scripts/coverage.py | 12 |
3 files changed, 44 insertions, 36 deletions
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 9bc7f55..ba537b0 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -559,8 +559,14 @@ class NinjaBackend(backends.Backend): key = OptionKey('b_coverage') if (key in self.environment.coredata.options and self.environment.coredata.options[key].value): - self.add_build_comment(NinjaComment('Coverage rules')) - self.generate_coverage_rules() + gcovr_exe, gcovr_version, lcov_exe, genhtml_exe, _ = environment.find_coverage_tools() + if gcovr_exe or (lcov_exe and genhtml_exe): + self.add_build_comment(NinjaComment('Coverage rules')) + self.generate_coverage_rules(gcovr_exe, gcovr_version) + else: + # FIXME: since we explicitly opted in, should this be an error? + # The docs just say these targets will be created "if possible". + mlog.warning('Need gcovr or lcov/genhtml to generate any coverage reports') self.add_build_comment(NinjaComment('Suffix')) self.generate_utils() self.generate_ending() @@ -1070,37 +1076,16 @@ class NinjaBackend(backends.Backend): self.environment.get_log_dir()] + (['--use_llvm_cov'] if use_llvm_cov else [])) - def generate_coverage_rules(self): + def generate_coverage_rules(self, gcovr_exe: T.Optional[str], gcovr_version: T.Optional[str]): e = NinjaBuildElement(self.all_outputs, 'meson-coverage', 'CUSTOM_COMMAND', 'PHONY') self.generate_coverage_command(e, []) e.add_item('description', 'Generates coverage reports') self.add_build(e) # Alias that runs the target defined above self.create_target_alias('meson-coverage') - self.generate_coverage_legacy_rules() - - def generate_coverage_legacy_rules(self): - e = NinjaBuildElement(self.all_outputs, 'meson-coverage-xml', 'CUSTOM_COMMAND', 'PHONY') - self.generate_coverage_command(e, ['--xml']) - e.add_item('description', 'Generates XML coverage report') - self.add_build(e) - # Alias that runs the target defined above - self.create_target_alias('meson-coverage-xml') - - e = NinjaBuildElement(self.all_outputs, 'meson-coverage-sonarqube', 'CUSTOM_COMMAND', 'PHONY') - self.generate_coverage_command(e, ['--sonarqube']) - e.add_item('description', 'Generates Sonarqube XML coverage report') - self.add_build(e) - # Alias that runs the target defined above - self.create_target_alias('meson-coverage-sonarqube') - - e = NinjaBuildElement(self.all_outputs, 'meson-coverage-text', 'CUSTOM_COMMAND', 'PHONY') - self.generate_coverage_command(e, ['--text']) - e.add_item('description', 'Generates text coverage report') - self.add_build(e) - # Alias that runs the target defined above - self.create_target_alias('meson-coverage-text') + self.generate_coverage_legacy_rules(gcovr_exe, gcovr_version) + def generate_coverage_legacy_rules(self, gcovr_exe: T.Optional[str], gcovr_version: T.Optional[str]): e = NinjaBuildElement(self.all_outputs, 'meson-coverage-html', 'CUSTOM_COMMAND', 'PHONY') self.generate_coverage_command(e, ['--html']) e.add_item('description', 'Generates HTML coverage report') @@ -1108,6 +1093,29 @@ class NinjaBackend(backends.Backend): # Alias that runs the target defined above self.create_target_alias('meson-coverage-html') + if gcovr_exe: + e = NinjaBuildElement(self.all_outputs, 'meson-coverage-xml', 'CUSTOM_COMMAND', 'PHONY') + self.generate_coverage_command(e, ['--xml']) + e.add_item('description', 'Generates XML coverage report') + self.add_build(e) + # Alias that runs the target defined above + self.create_target_alias('meson-coverage-xml') + + e = NinjaBuildElement(self.all_outputs, 'meson-coverage-text', 'CUSTOM_COMMAND', 'PHONY') + self.generate_coverage_command(e, ['--text']) + e.add_item('description', 'Generates text coverage report') + self.add_build(e) + # Alias that runs the target defined above + self.create_target_alias('meson-coverage-text') + + if mesonlib.version_compare(gcovr_version, '>=4.2'): + e = NinjaBuildElement(self.all_outputs, 'meson-coverage-sonarqube', 'CUSTOM_COMMAND', 'PHONY') + self.generate_coverage_command(e, ['--sonarqube']) + e.add_item('description', 'Generates Sonarqube XML coverage report') + self.add_build(e) + # Alias that runs the target defined above + self.create_target_alias('meson-coverage-sonarqube') + def generate_install(self): self.create_install_data_files() elem = NinjaBuildElement(self.all_outputs, 'meson-install', 'CUSTOM_COMMAND', 'PHONY') diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 7062c98..5635c8a 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -84,7 +84,7 @@ def _get_env_var(for_machine: MachineChoice, is_cross: bool, var_name: str) -> T return value -def detect_gcovr(min_version='3.3', new_rootdir_version='4.2', log=False): +def detect_gcovr(min_version='3.3', log=False): gcovr_exe = 'gcovr' try: p, found = Popen_safe([gcovr_exe, '--version'])[0:2] @@ -95,7 +95,7 @@ def detect_gcovr(min_version='3.3', new_rootdir_version='4.2', log=False): if p.returncode == 0 and mesonlib.version_compare(found, '>=' + min_version): if log: mlog.log('Found gcovr-{} at {}'.format(found, quote_arg(shutil.which(gcovr_exe)))) - return gcovr_exe, mesonlib.version_compare(found, '>=' + new_rootdir_version) + return gcovr_exe, found return None, None def detect_llvm_cov(): @@ -106,7 +106,7 @@ def detect_llvm_cov(): return None def find_coverage_tools() -> T.Tuple[T.Optional[str], T.Optional[str], T.Optional[str], T.Optional[str], T.Optional[str]]: - gcovr_exe, gcovr_new_rootdir = detect_gcovr() + gcovr_exe, gcovr_version = detect_gcovr() llvm_cov_exe = detect_llvm_cov() @@ -118,7 +118,7 @@ def find_coverage_tools() -> T.Tuple[T.Optional[str], T.Optional[str], T.Optiona if not mesonlib.exe_exists([genhtml_exe, '--version']): genhtml_exe = None - return gcovr_exe, gcovr_new_rootdir, lcov_exe, genhtml_exe, llvm_cov_exe + return gcovr_exe, gcovr_version, lcov_exe, genhtml_exe, llvm_cov_exe def detect_ninja(version: str = '1.8.2', log: bool = False) -> T.List[str]: r = detect_ninja_command_and_version(version, log) diff --git a/mesonbuild/scripts/coverage.py b/mesonbuild/scripts/coverage.py index a9e83c2..bff6499 100644 --- a/mesonbuild/scripts/coverage.py +++ b/mesonbuild/scripts/coverage.py @@ -21,10 +21,10 @@ def coverage(outputs: T.List[str], source_root: str, subproject_root: str, build outfiles = [] exitcode = 0 - (gcovr_exe, gcovr_new_rootdir, lcov_exe, genhtml_exe, llvm_cov_exe) = environment.find_coverage_tools() + (gcovr_exe, gcovr_version, lcov_exe, genhtml_exe, llvm_cov_exe) = environment.find_coverage_tools() # gcovr >= 4.2 requires a different syntax for out of source builds - if gcovr_new_rootdir: + if gcovr_exe and mesonlib.version_compare(gcovr_version, '>=4.2'): gcovr_base_cmd = [gcovr_exe, '-r', source_root, build_root] else: gcovr_base_cmd = [gcovr_exe, '-r', build_root] @@ -35,7 +35,7 @@ def coverage(outputs: T.List[str], source_root: str, subproject_root: str, build gcov_exe_args = [] if not outputs or 'xml' in outputs: - if gcovr_exe: + if gcovr_exe and mesonlib.version_compare(gcovr_version, '>=3.3'): subprocess.check_call(gcovr_base_cmd + ['-x', '-e', re.escape(subproject_root), @@ -47,7 +47,7 @@ def coverage(outputs: T.List[str], source_root: str, subproject_root: str, build exitcode = 1 if not outputs or 'sonarqube' in outputs: - if gcovr_exe: + if gcovr_exe and mesonlib.version_compare(gcovr_version, '>=4.2'): subprocess.check_call(gcovr_base_cmd + ['--sonarqube', '-o', os.path.join(log_dir, 'sonarqube.xml'), @@ -59,7 +59,7 @@ def coverage(outputs: T.List[str], source_root: str, subproject_root: str, build exitcode = 1 if not outputs or 'text' in outputs: - if gcovr_exe: + if gcovr_exe and mesonlib.version_compare(gcovr_version, '>=3.3'): subprocess.check_call(gcovr_base_cmd + ['-e', re.escape(subproject_root), '-o', os.path.join(log_dir, 'coverage.txt') @@ -132,7 +132,7 @@ def coverage(outputs: T.List[str], source_root: str, subproject_root: str, build '--branch-coverage', covinfo]) outfiles.append(('Html', pathlib.Path(htmloutdir, 'index.html'))) - elif gcovr_exe: + elif gcovr_exe and mesonlib.version_compare(gcovr_version, '>=3.3'): htmloutdir = os.path.join(log_dir, 'coveragereport') if not os.path.isdir(htmloutdir): os.mkdir(htmloutdir) |