diff options
| author | Nigel Kukard <nkukard@lbsd.net> | 2023-10-09 00:00:39 +0000 |
|---|---|---|
| committer | Eli Schwartz <eschwartz93@gmail.com> | 2023-10-08 23:13:06 -0400 |
| commit | 2c4a1b6324b1c069f713f089d22d1a0ea70cf222 (patch) | |
| tree | ba962f5abe92d6aebe2b0aee214898cbdc729fce | |
| parent | 583d2815d1a130227f0f4db47e4ab2e80ebb6a61 (diff) | |
| download | meson-2c4a1b6324b1c069f713f089d22d1a0ea70cf222.tar.gz | |
Add support for lcov 2.0
lcov 2.0 deprecates `--rc lcov_branch_coverage=1` for `--rc branch_coverage=1` and
gives an error when an exclude is used on a non existing directory.
I added a version check for lcov and removed the subprojects directory from the
exclusion list if it does not exist.
Fixes #11995
| -rw-r--r-- | mesonbuild/backend/ninjabackend.py | 2 | ||||
| -rw-r--r-- | mesonbuild/environment.py | 22 | ||||
| -rw-r--r-- | mesonbuild/scripts/coverage.py | 20 |
3 files changed, 32 insertions, 12 deletions
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index a994d7388..29883bac7 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -640,7 +640,7 @@ class NinjaBackend(backends.Backend): key = OptionKey('b_coverage') if (key in self.environment.coredata.options and self.environment.coredata.options[key].value): - gcovr_exe, gcovr_version, lcov_exe, genhtml_exe, _ = environment.find_coverage_tools() + gcovr_exe, gcovr_version, lcov_exe, lcov_version, 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) diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 7bd8c2ca6..2ba20548f 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -96,6 +96,20 @@ def detect_gcovr(min_version: str = '3.3', log: bool = False): return gcovr_exe, found return None, None +def detect_lcov(log: bool = False): + lcov_exe = 'lcov' + try: + p, found = Popen_safe([lcov_exe, '--version'])[0:2] + except (FileNotFoundError, PermissionError): + # Doesn't exist in PATH or isn't executable + return None, None + found = search_version(found) + if p.returncode == 0 and found: + if log: + mlog.log('Found lcov-{} at {}'.format(found, quote_arg(shutil.which(lcov_exe)))) + return lcov_exe, found + return None, None + def detect_llvm_cov(): tools = get_llvm_tool_names('llvm-cov') for tool in tools: @@ -103,20 +117,18 @@ def detect_llvm_cov(): return tool return None -def find_coverage_tools() -> T.Tuple[T.Optional[str], T.Optional[str], T.Optional[str], T.Optional[str], T.Optional[str]]: +def find_coverage_tools() -> T.Tuple[T.Optional[str], T.Optional[str], T.Optional[str], T.Optional[str], T.Optional[str], T.Optional[str]]: gcovr_exe, gcovr_version = detect_gcovr() llvm_cov_exe = detect_llvm_cov() - lcov_exe = 'lcov' + lcov_exe, lcov_version = detect_lcov() genhtml_exe = 'genhtml' - 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, gcovr_version, lcov_exe, genhtml_exe, llvm_cov_exe + return gcovr_exe, gcovr_version, lcov_exe, lcov_version, 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 cb865d08d..4c0f81e8a 100644 --- a/mesonbuild/scripts/coverage.py +++ b/mesonbuild/scripts/coverage.py @@ -22,7 +22,7 @@ def coverage(outputs: T.List[str], source_root: str, subproject_root: str, build outfiles = [] exitcode = 0 - (gcovr_exe, gcovr_version, lcov_exe, genhtml_exe, llvm_cov_exe) = environment.find_coverage_tools() + (gcovr_exe, gcovr_version, lcov_exe, lcov_version, genhtml_exe, llvm_cov_exe) = environment.find_coverage_tools() # load config files for tools if available in the source tree # - lcov requires manually specifying a per-project config @@ -35,6 +35,11 @@ def coverage(outputs: T.List[str], source_root: str, subproject_root: str, build else: lcov_config = [] + if lcov_exe and mesonlib.version_compare(lcov_version, '>=2.0'): + lcov_exe_rc_branch_coverage = ['--rc', 'branch_coverage=1'] + else: + lcov_exe_rc_branch_coverage = ['--rc', 'lcov_branch_coverage=1'] + gcovr_config = ['-e', re.escape(subproject_root)] # gcovr >= 4.2 requires a different syntax for out of source builds @@ -90,6 +95,9 @@ def coverage(outputs: T.List[str], source_root: str, subproject_root: str, build initial_tracefile = covinfo + '.initial' run_tracefile = covinfo + '.run' raw_tracefile = covinfo + '.raw' + lcov_subpoject_exclude = [] + if os.path.exists(subproject_root): + lcov_subpoject_exclude.append(os.path.join(subproject_root, '*')) if use_llvm_cov: # Create a shim to allow using llvm-cov as a gcov tool. if mesonlib.is_windows(): @@ -117,26 +125,26 @@ def coverage(outputs: T.List[str], source_root: str, subproject_root: str, build '--capture', '--output-file', run_tracefile, '--no-checksum', - '--rc', 'lcov_branch_coverage=1'] + + *lcov_exe_rc_branch_coverage] + lcov_config + gcov_tool_args) # Join initial and test results. subprocess.check_call([lcov_exe, '-a', initial_tracefile, '-a', run_tracefile, - '--rc', 'lcov_branch_coverage=1', + *lcov_exe_rc_branch_coverage, '-o', raw_tracefile] + lcov_config) # Remove all directories outside the source_root from the covinfo subprocess.check_call([lcov_exe, '--extract', raw_tracefile, os.path.join(source_root, '*'), - '--rc', 'lcov_branch_coverage=1', + *lcov_exe_rc_branch_coverage, '--output-file', covinfo] + lcov_config) # Remove all directories inside subproject dir subprocess.check_call([lcov_exe, '--remove', covinfo, - os.path.join(subproject_root, '*'), - '--rc', 'lcov_branch_coverage=1', + *lcov_subpoject_exclude, + *lcov_exe_rc_branch_coverage, '--output-file', covinfo] + lcov_config) subprocess.check_call([genhtml_exe, '--prefix', build_root, |
