twister: Set a default gcov-tool for llvm

When using llvm we need to set the gcov-tool to "llvm-cov gcov" but
the lcov tool is incapable of passing arguments to the gcov-tool. i.e.
the following cannot work:

$ lcov --gcov-tool "llvm-cov gcov" ...

Instead, create a symlink to llvm-cov prefixed as `gcov` which by the
documentation of llvm-cov will alias to `llvm-cov gcov` subcommand.

Signed-off-by: Yuval Peress <peress@google.com>
This commit is contained in:
Yuval Peress 2022-11-29 11:18:06 -07:00 committed by Carles Cufí
parent fcfb7f30ed
commit 47b675c6ee
3 changed files with 41 additions and 15 deletions

View file

@ -153,3 +153,18 @@ which produces a report in the same location as non-unit testing.
.. _gcov:
https://gcc.gnu.org/onlinedocs/gcc/Gcov.html
Using different toolchains
==========================
Twister looks at the environment variable ``ZEPHYR_TOOLCHAIN_VARIANT``
to check which gcov tool to use by default. The following are used as the
default for the Twister ``--gcov-tool`` argument default:
+-----------+-----------------------+
| Toolchain | ``--gcov-tool`` value |
+-----------+-----------------------+
| host | ``gcov`` |
| llvm | ``llvm-cov gcov`` |
| zephyr | ``gcov`` |
+-----------+-----------------------+

View file

@ -5,6 +5,8 @@
import os
import logging
import pathlib
import shutil
import subprocess
import glob
import re
@ -125,7 +127,7 @@ class Lcov(CoverageTool):
def _generate(self, outdir, coveragelog):
coveragefile = os.path.join(outdir, "coverage.info")
ztestfile = os.path.join(outdir, "ztest.info")
cmd = ["lcov", "--gcov-tool", self.gcov_tool,
cmd = ["lcov", "--gcov-tool", str(self.gcov_tool),
"--capture", "--directory", outdir,
"--rc", "lcov_branch_coverage=1",
"--output-file", coveragefile]
@ -195,8 +197,10 @@ class Gcovr(CoverageTool):
# We want to remove tests/* and tests/ztest/test/* but save tests/ztest
cmd = ["gcovr", "-r", self.base_dir, "--gcov-executable",
self.gcov_tool, "-e", "tests/*"] + excludes + ["--json", "-o",
coveragefile, outdir]
str(self.gcov_tool), "-e", "tests/*"] + excludes + ["--json",
"-o",
coveragefile,
outdir]
cmd_str = " ".join(cmd)
logger.debug(f"Running {cmd_str}...")
subprocess.call(cmd, stdout=coveragelog)
@ -234,18 +238,25 @@ class Gcovr(CoverageTool):
def run_coverage(testplan, options):
if not options.gcov_tool:
use_system_gcov = False
for plat in options.coverage_platform:
ts_plat = testplan.get_platform(plat)
if ts_plat and (ts_plat.type in {"native", "unit"}):
use_system_gcov = True
if use_system_gcov or "ZEPHYR_SDK_INSTALL_DIR" not in os.environ:
options.gcov_tool = "gcov"
else:
options.gcov_tool = os.path.join(os.environ["ZEPHYR_SDK_INSTALL_DIR"],
zephyr_sdk_gcov_tool = os.path.join(
os.environ.get("ZEPHYR_SDK_INSTALL_DIR", default=""),
"x86_64-zephyr-elf/bin/x86_64-zephyr-elf-gcov")
if os.environ.get("ZEPHYR_TOOLCHAIN_VARIANT") == "llvm":
llvm_path = os.environ.get("LLVM_TOOLCHAIN_PATH")
if llvm_path is not None:
llvm_path = os.path.join(llvm_path, "bin")
llvm_cov = shutil.which("llvm-cov", path=llvm_path)
llvm_cov_ext = pathlib.Path(llvm_cov).suffix
gcov_lnk = os.path.join(options.outdir, f"gcov{llvm_cov_ext}")
try:
os.symlink(llvm_cov, gcov_lnk)
except OSError:
shutil.copy(llvm_cov, gcov_lnk)
options.gcov_tool = gcov_lnk
elif os.path.exists(zephyr_sdk_gcov_tool):
options.gcov_tool = zephyr_sdk_gcov_tool
else:
options.gcov_tool = "gcov"
logger.info("Generating coverage files...")
coverage_tool = CoverageTool.factory(options.coverage_tool)

View file

@ -340,7 +340,7 @@ structure in the main Zephyr tree: boards/<arch>/<board_name>/""")
help="Do not filter based on toolchain, use the set "
" toolchain unconditionally")
parser.add_argument("--gcov-tool", default=None,
parser.add_argument("--gcov-tool", type=Path, default=None,
help="Path to the gcov tool to use for code coverage "
"reports")