Skip to content

Commit 5b19a9b

Browse files
yperesskartben
authored andcommitted
twister: Better manage gcov sym link
In twister coverage runs we create the gcov sym link to llvm-cov executable. This code runs multiple times which causes errors with the current implementation since creating the symlink will fail; then copying will also fail because we're using the symlink (self copy the file). Add a helper function to `try_making_symlink` which will handle the following cases: 1. If the symlink already exists and is correct, do nothing. 2. If the symlink exists but points to the wrong file, replace it. 3. If the symlink doesn't exist create it. 4. If creating a symlink fails, just copy the file. Signed-off-by: Yuval Peress <[email protected]>
1 parent 3cf4e2f commit 5b19a9b

File tree

1 file changed

+41
-4
lines changed

1 file changed

+41
-4
lines changed

scripts/pylib/twister/twisterlib/coverage.py

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
# SPDX-License-Identifier: Apache-2.0
55

66
import contextlib
7+
import filecmp
78
import glob
89
import logging
910
import os
@@ -502,6 +503,45 @@ def _generate(self, outdir, coveragelog, build_dirs=None):
502503

503504
return ret, { 'report': coverage_file, 'ztest': ztest_file, 'summary': coverage_summary }
504505

506+
def try_making_symlink(source: str, link: str):
507+
"""
508+
Attempts to create a symbolic link from source to link.
509+
If the link already exists:
510+
- If it's a symlink pointing to a different source, it's replaced.
511+
- If it's a regular file with the same content, no action is taken.
512+
- If it's a regular file with different content, it's replaced with a
513+
symlink (if possible, otherwise a copy).
514+
If symlinking fails for any reason (other than the link already existing and
515+
being correct), it attempts to copy the source to the link.
516+
517+
Args:
518+
source (str): The path to the source file.
519+
link (str): The path where the symbolic link should be created.
520+
"""
521+
if os.path.exists(link):
522+
if os.path.islink(link):
523+
if os.readlink(link) == source:
524+
# Link is already set up
525+
return
526+
# Link is pointing to the wrong file, fall below this if/else and
527+
# it will be replaced
528+
elif filecmp.cmp(source, link):
529+
# File contents are the same
530+
return
531+
532+
# link exists, but points to a different file, remove the link. We'll
533+
# try to create a new one below
534+
os.remove(link)
535+
536+
# Create the symlink
537+
try:
538+
os.symlink(source, link)
539+
except OSError as e:
540+
logger.error(
541+
"Error creating symlink: %s, attempting to copy.". str(e)
542+
)
543+
shutil.copy(source, link)
544+
505545

506546
def choose_gcov_tool(options, is_system_gcov):
507547
gcov_tool = None
@@ -516,10 +556,7 @@ def choose_gcov_tool(options, is_system_gcov):
516556
llvm_cov = shutil.which("llvm-cov", path=llvm_path)
517557
llvm_cov_ext = pathlib.Path(llvm_cov).suffix
518558
gcov_lnk = os.path.join(options.outdir, f"gcov{llvm_cov_ext}")
519-
try:
520-
os.symlink(llvm_cov, gcov_lnk)
521-
except OSError:
522-
shutil.copy(llvm_cov, gcov_lnk)
559+
try_making_symlink(llvm_cov, gcov_lnk)
523560
gcov_tool = gcov_lnk
524561
elif is_system_gcov:
525562
gcov_tool = "gcov"

0 commit comments

Comments
 (0)