-
Notifications
You must be signed in to change notification settings - Fork 6.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
twister: add option to create shorter build paths #41930
twister: add option to create shorter build paths #41930
Conversation
7f7b97d
to
d395d38
Compare
scripts/twister
Outdated
@@ -584,6 +584,12 @@ structure in the main Zephyr tree: boards/<arch>/<board_name>/""") | |||
"This directory will be cleaned unless '--no-clean' is set. " | |||
"The '--clobber-output' option controls what cleaning does.") | |||
|
|||
parser.add_argument( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please put this argument in alpha-beta order, this is starting from s
, and shall not put before o
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, yes, you're right, I replaced it in correct place :)
scripts/pylib/twister/twisterlib.py
Outdated
@@ -1887,7 +1887,10 @@ class TestInstance(DisablePyTestCollectionMixin): | |||
out directory used is <outdir>/<platform>/<test case name> | |||
""" | |||
|
|||
def __init__(self, testcase, platform, outdir): | |||
# used for creating shorter build paths | |||
shortcut_dir_counter = 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it is not our practice to add a class variable, why it can not be a instant variable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I agree with you, that this is not the best practice, but I need this variable, which works as a global counter (it is used to create unique folder name) and this value need to be shared between instances of TestInstance
class. If you have better idea how to create such global variable, I am open for propositions :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the class instance only count in one process or twister instance, if you really care about the possible conflect, maybe use filelock would be more safe
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, you are right, I do not predict this case when two Twister instances are run simultaneously (especially when --subset
option is used). So I have to refactor this approach. Thank you for your comment!
scripts/pylib/twister/twisterlib.py
Outdated
shortcut_path = os.path.join(shortcuts_dir_path, shortcut_name) | ||
TestInstance.shortcut_dir_counter += 1 | ||
|
||
os.system(f"mklink /J {shortcut_path} {self.build_dir}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this would be only works in windows.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it will, but I add check if this code is run on Windows at the beginning of this method:
def create_build_dir_shortcut(self):
"""
Create build directory with original "long" path. Next take shorter
path (based on TestInstance class internal counter) and link them with
original path - create shortcut. At the end replace build_dir to
shorter path. This action helps to limit path length which can be
significant during building by CMake on Windows OS.
"""
if os.name != "nt": # if OS is not Windows
logger.warning("Creating shorter build paths available only on "
"Windows OS")
return
--short-build-path
can be used only on Windows OS (what is described in option's help). Only on Windows OS exists problem with too long directory paths. So, I do not see any sense to extend this option to Linux OS where this problem does not exist.
d395d38
to
4541a07
Compare
db1e4ed
to
eb7fb10
Compare
scripts/pylib/twister/twisterlib.py
Outdated
while not shortcut_created_flag: | ||
shortcut_name = self.get_new_shortcut_name(shortcuts_dir_path) | ||
shortcut_path = os.path.join(shortcuts_dir_path, shortcut_name) | ||
command = ["mklink", "/J", f"{shortcut_path}", f"{self.build_dir}"] | ||
result = subprocess.call(command, shell=True) | ||
if result == 0: | ||
shortcut_created_flag = True |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't we need any break condition to prevent infinite loops here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think running multiple twister instances is a real use case as it doesn't bring any value, since twister already handles parallelization internally. Also, each instance will create its own output dir, so if shortcuts are there, there won't be any conflict between shortcuts from multiple instances. Running multiple twister instances for subset is AFAIK used either in parallel on separate agents or on a single agent sequentially.
I am not sure if the proposed mechanism will prevent race conditions which might cause mess in links when build processes run in parallel within a single twister instance.
What do you think about using locks? E.g. the counter variable is define at the twister initialization and has getter/setter methods with a lock. When a shortcut is created, the variable is locked, the counter is increased, shortcut created, and the lock is released? Using such approach might also optimize the code a bit, since you won't need to scan the whole catalog looking for the last number and instead get it from the counter immediately. You can check here how it was implemented for counting test cases: https://github.com/zephyrproject-rtos/zephyr/blob/main/scripts/pylib/twister/twisterlib.py#L94
scripts/pylib/twister/twisterlib.py
Outdated
while not shortcut_created_flag: | ||
shortcut_name = self.get_new_shortcut_name(shortcuts_dir_path) | ||
shortcut_path = os.path.join(shortcuts_dir_path, shortcut_name) | ||
command = ["mklink", "/J", f"{shortcut_path}", f"{self.build_dir}"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why isn't os.symlink
used (or pathlib
symlink)?
eb7fb10
to
fa585b0
Compare
With recently changes I move creating shortcuts methods to
@gmarull I tried to use os.symlink and pathlib symlink but both solutions demand Administrator privilege to create symlink. So I decided to stay with @PerMac proposed also idea to remove |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why invent yet another term, shortcut
?
Let's use link
, which is a term familiar to developers, after all, that's what we are creating:
There are three types of file links supported in the NTFS file system: hard links, junctions, and symbolic links.
and
A junction (also called a soft link) differs from a hard link in that the storage objects it references are separate directories,
https://docs.microsoft.com/en-us/windows/win32/fileio/hard-links-and-junctions
and the command is name mklink
scripts/pylib/twister/twisterlib.py
Outdated
if os.name != "nt": # if OS is not Windows | ||
logger.warning("Creating shorter build paths available only on " | ||
"Windows OS") | ||
return |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
any particular reason this cannot work on other OS'es ?
On macOS / Linux we could create symlinks instead.
That will allow users to pass on --short-build-path
regardless of the platform on which they are executing.
scripts/pylib/twister/twisterlib.py
Outdated
"Windows OS") | ||
return | ||
|
||
shortcuts_dir_name = "scs" # folder for all shortcuts |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume this suddenly means that no one can create a board named scs
.
How about twister_links
?
Reasons:
twister
is already used for other twister generated files, liketwister.csv
,twister.log
, etc.
Sotwister
can already today be considered reserved name._links
are clearer in its intention to the reader thanscs
.
and twister_links
are still short, compared to existing behavior.
scripts/pylib/twister/twisterlib.py
Outdated
command = ["mklink", "/J", f"{shortcut_path}", f"{instance.build_dir}"] | ||
subprocess.call(command, shell=True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should also support ln -s
here for other OS'es.
I see no reasons why this new argument should not be supported on all platforms.
scripts/pylib/twister/twisterlib.py
Outdated
if instance.status != "skipped": | ||
self._create_build_dir_shortcut(shortcuts_dir_path, instance) | ||
|
||
def _create_build_dir_shortcut(self, shortcuts_dir_path, instance): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why invent yet another term, shortcut
?
Let's use link
, which is a term familiar to developers, after all, that's what we are creating:
There are three types of file links supported in the NTFS file system: hard links, junctions, and symbolic links.
and
A junction (also called a soft link) differs from a hard link in that the storage objects it references are separate directories,
https://docs.microsoft.com/en-us/windows/win32/fileio/hard-links-and-junctions
and the command is name mklink
One more question. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One more question. I would expect that CMake had to be invoked with the link as its build directory, or does that happen automatically ?
Guess the answer is here: #41930 (comment)
thank to that shorter path can be pass to CMake
So where in code does this happen ?
Cause I can't spot that location.
CMake is call in Twister exactly here: zephyr/scripts/pylib/twister/twisterlib.py Line 2180 in 677ffc8
Few lines earlier the command with CMake is built and there the build directory (which is the link, when zephyr/scripts/pylib/twister/twisterlib.py Line 2151 in 677ffc8
|
419aa34
to
5b7e539
Compare
Since this is a very widespread problem when running twister on Windows (thanks to how twister creates a bunch of directories with very long names), I think it would make sense to display that warning by default on Windows when We can get rid of this behaviour when all the Windows build tools are updated to support long paths in the future. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Verified working on Linux, macOS and Windows build environments:
https://github.com/stephanosio/gha-runner-zephyr-test/actions/runs/1835838884
squash! [nrf fromlist] twister: add option to create shorter build paths This changes was introduced to this open Upstream PR: zephyrproject-rtos/zephyr#41930 Signed-off-by: Piotr Golyzniak <piotr.golyzniak@nordicsemi.no>
Thanks for testing @stephanosio! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
squash! [nrf fromlist] twister: add option to create shorter build paths This changes was introduced to this open Upstream PR: zephyrproject-rtos/zephyr#41930 Signed-off-by: Piotr Golyzniak <piotr.golyzniak@nordicsemi.no>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does not work for me on Linux...
i9:zephyr((HEAD detached at upstream/pull/41930)): twister -T samples/hello_world/ --short-build-path
Renaming output directory to /home/nashif/Work/zephyrproject/zephyr/twister-out.2
INFO - Zephyr version: v3.0.0-rc3-2-g5b7e539480ea
INFO - JOBS: 20
INFO - Using 'zephyr' toolchain.
INFO - Selecting default platforms per test case
INFO - Building initial testcase list...
INFO - 1 test scenarios (39 configurations) selected, 14 configurations discarded due to filters.
INFO - Adding tasks to the queue...
INFO - Added initial list of jobs to queue
ERROR - qemu_malta samples/hello_world/sample.basic.helloworld FAILED: Build failure
ERROR - see: /home/nashif/Work/zephyrproject/zephyr/twister-out/qemu_malta/samples/hello_world/sample.basic.helloworld/build.log
INFO - Total complete: 1/ 25 4% skipped: 14, failed: 1
ERROR - qemu_nios2 samples/hello_world/sample.basic.helloworld FAILED: Build failure
ERROR - see: /home/nashif/Work/zephyrproject/zephyr/twister-out/qemu_nios2/samples/hello_world/sample.basic.helloworld/build.log
INFO - Total complete: 2/ 25 8% skipped: 14, failed: 2
ERROR - qemu_malta_be samples/hello_world/sample.basic.helloworld FAILED: Build failure
ERROR - see: /home/nashif/Work/zephyrproject/zephyr/twister-out/qemu_malta_be/samples/hello_world/sample.basic.helloworld/build.log
INFO - Total complete: 3/ 25 12% skipped: 14, failed: 3
ERROR - m2gl025_miv samples/hello_world/sample.basic.helloworld FAILED: Build failure
ERROR - see: /home/nashif/Work/zephyrproject/zephyr/twister-out/m2gl025_miv/samples/hello_world/sample.basic.helloworld/build.log
INFO - Total complete: 4/ 25 16% skipped: 14, failed: 4
ERROR - qemu_arc_em samples/hello_world/sample.basic.helloworld FAILED: Build failure
ERROR - see: /home/nashif/Work/zephyrproject/zephyr/twister-out/qemu_arc_em/samples/hello_world/sample.basic.helloworld/build.log
error log:
-- Found assembler: /home/nashif/bin/zephyr-sdk-0.13.2/nios2-zephyr-elf/bin/nios2-zephyr-elf-gcc
-- Configuring done
-- Generating done
-- Build files have been written to: /home/nashif/Work/zephyrproject/zephyr/twister-out/twister_links/test_21
[ 1%] Generating misc/generated/syscalls.json, misc/generated/struct_tags.json
[ 2%] Built target parse_syscalls_target
gmake[2]: *** No rule to make target '../../../scripts/gen_kobject_list.py', needed by 'zephyr/include/generated/kobj-types-enum.h'. Stop.
gmake[1]: *** [CMakeFiles/Makefile2:2643: zephyr/CMakeFiles/kobj_types_h_target.dir/all] Error 2
gmake: *** [Makefile:91: all] Error 2
Hmmmmm, yes, now I observe, that |
5b7e539
to
c3d655e
Compare
@nashif I added checking if I tried to find if there is any solution to pass directory link to |
scripts/pylib/twister/twisterlib.py
Outdated
else: # for Linux and MAC OS | ||
os.symlink(instance.build_dir, link_path) | ||
|
||
# Here symbolic link is replaced with original build directory. It will |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isn't this the other way round?
original build directory is replaced with the symbolic link...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, you are right - I corrected it.
ok, that works. |
Add possibility to create shorter build paths when --short-build-path option is enabled. This can help during run Twister on Windows OS and building programs by CMake which has a problem when paths with building files are too long. The solution based on symbolic links which help to connect "traditional" long paths with shorter one like: "twister_links/test_0". Fixes zephyrproject-rtos#41929 Signed-off-by: Piotr Golyzniak <piotr.golyzniak@nordicsemi.no>
c3d655e
to
4856a24
Compare
Proposition in this PR are strictly connected with problem described here: #41929
Originally when Twister is call by following command:
It create following build folder:
C:\tb\nrf5340dk_nrf5340_cpuapp\samples\subsys\portability\cmsis_rtos_v1\timer_synchronization\sample.portability.cmsis_rtos_v1.timer_synchronization
which is problematic for CMake on Windows OS.Thanks to add
--short-build-path
option to Twister command:Twister create originally build directory, but moreover it create also new directory with shorter path
C:\tb\twister_links\test_0
and next create link between those two directories. Thank to that shorter path can be pass to CMake which allow to remove problem with too long path and at once build results can be found on originally longer path.Without this feature I am not able to use Twister during testing Zephyr's samples and tests on Windows OS.
Fixes #41929