diff --git a/scripts/pylib/twister/twisterlib.py b/scripts/pylib/twister/twisterlib.py index f261f0617b701b..1548cc7c066dd4 100755 --- a/scripts/pylib/twister/twisterlib.py +++ b/scripts/pylib/twister/twisterlib.py @@ -2791,6 +2791,9 @@ def __init__(self, board_root_list=[], testcase_roots=[], outdir=None): # run integration tests only self.integration = False + # used during creating shorter build paths + self.link_dir_counter = 0 + self.pipeline = None self.version = "NA" @@ -3877,6 +3880,48 @@ def verify_platforms_existence(self, platform_names_to_verify, log_info=""): logger.error(f"{log_info} - unrecognized platform - {platform}") sys.exit(2) + def create_build_dir_links(self): + """ + Iterate through all no-skipped instances in suite and create links + for each one build directories. Those links will be passed in the next + steps to the CMake command. + """ + + links_dir_name = "twister_links" # folder for all links + links_dir_path = os.path.join(self.outdir, links_dir_name) + if not os.path.exists(links_dir_path): + os.mkdir(links_dir_path) + + for instance in self.instances.values(): + if instance.status != "skipped": + self._create_build_dir_link(links_dir_path, instance) + + def _create_build_dir_link(self, links_dir_path, instance): + """ + Create build directory with original "long" path. Next take shorter + path and link them with original path - create link. At the end + replace build_dir to created link. This link will be passed to CMake + command. This action helps to limit path length which can be + significant during building by CMake on Windows OS. + """ + + os.makedirs(instance.build_dir, exist_ok=True) + + link_name = f"test_{self.link_dir_counter}" + link_path = os.path.join(links_dir_path, link_name) + + if os.name == "nt": # if OS is Windows + command = ["mklink", "/J", f"{link_path}", f"{instance.build_dir}"] + subprocess.call(command, shell=True) + else: # for Linux and MAC OS + os.symlink(instance.build_dir, link_path) + + # Here original build directory is replaced with symbolic link. It will + # be passed to CMake command + instance.build_dir = link_path + + self.link_dir_counter += 1 + class CoverageTool: """ Base class for every supported coverage tool diff --git a/scripts/twister b/scripts/twister index d228abcfb7aa0b..2988d0c0661310 100755 --- a/scripts/twister +++ b/scripts/twister @@ -569,7 +569,8 @@ structure in the main Zephyr tree: boards///""") parser.add_argument( "-N", "--ninja", action="store_true", - help="Use the Ninja generator with CMake.") + help="Use the Ninja generator with CMake.", + required="--short-build-path" in sys.argv) parser.add_argument( "-n", "--no-clean", action="store_true", @@ -684,6 +685,16 @@ structure in the main Zephyr tree: boards///""") help="Execute time-consuming test cases that have been marked " "as 'slow' in testcase.yaml. Normally these are only built.") + parser.add_argument( + "--short-build-path", + action="store_true", + help="Create shorter build directory paths based on symbolic links. " + "The shortened build path will be used by CMake for generating " + "the build system and executing the build. Use this option if " + "you experience build failures related to path length, for " + "example on Windows OS. This option can be used only with " + "'--ninja' argument (to use Ninja build generator).") + parser.add_argument( "--show-footprint", action="store_true", help="Show footprint statistics and deltas since last release." @@ -1236,6 +1247,9 @@ def main(): logger.info("Completed in %d seconds" % (duration)) return + if options.short_build_path: + suite.create_build_dir_links() + retries = options.retry_failed + 1 completed = 0