diff --git a/scripts/pylib/twister/twisterlib/coverage.py b/scripts/pylib/twister/twisterlib/coverage.py index 3aba6705a8a..42cbc1c9806 100644 --- a/scripts/pylib/twister/twisterlib/coverage.py +++ b/scripts/pylib/twister/twisterlib/coverage.py @@ -4,6 +4,7 @@ # SPDX-License-Identifier: Apache-2.0 import contextlib +import filecmp import glob import logging import os @@ -502,6 +503,45 @@ class Gcovr(CoverageTool): return ret, { 'report': coverage_file, 'ztest': ztest_file, 'summary': coverage_summary } +def try_making_symlink(source: str, link: str): + """ + Attempts to create a symbolic link from source to link. + If the link already exists: + - If it's a symlink pointing to a different source, it's replaced. + - If it's a regular file with the same content, no action is taken. + - If it's a regular file with different content, it's replaced with a + symlink (if possible, otherwise a copy). + If symlinking fails for any reason (other than the link already existing and + being correct), it attempts to copy the source to the link. + + Args: + source (str): The path to the source file. + link (str): The path where the symbolic link should be created. + """ + if os.path.exists(link): + if os.path.islink(link): + if os.readlink(link) == source: + # Link is already set up + return + # Link is pointing to the wrong file, fall below this if/else and + # it will be replaced + elif filecmp.cmp(source, link): + # File contents are the same + return + + # link exists, but points to a different file, remove the link. We'll + # try to create a new one below + os.remove(link) + + # Create the symlink + try: + os.symlink(source, link) + except OSError as e: + logger.error( + "Error creating symlink: %s, attempting to copy.". str(e) + ) + shutil.copy(source, link) + def choose_gcov_tool(options, is_system_gcov): gcov_tool = None @@ -516,10 +556,7 @@ def choose_gcov_tool(options, is_system_gcov): 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) + try_making_symlink(llvm_cov, gcov_lnk) gcov_tool = gcov_lnk elif is_system_gcov: gcov_tool = "gcov"