summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNigel Kukard <nkukard@lbsd.net>2023-10-09 00:00:39 +0000
committerEli Schwartz <eschwartz93@gmail.com>2023-10-08 23:13:06 -0400
commit2c4a1b6324b1c069f713f089d22d1a0ea70cf222 (patch)
treeba962f5abe92d6aebe2b0aee214898cbdc729fce
parent583d2815d1a130227f0f4db47e4ab2e80ebb6a61 (diff)
downloadmeson-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.py2
-rw-r--r--mesonbuild/environment.py22
-rw-r--r--mesonbuild/scripts/coverage.py20
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,