-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
ctx.actions.symlink doesn't make relative symlink, contrary to docs #14224
Comments
I ran into this as well. The issue is that, despite the documentation saying otherwise, the first thing I don't know what the right answer to fix this is, but I think that's the reason for the issue. |
My fix was to use the |
This is surprising and contrary to documentation, though I will note that making symlinks to paths (as opposed to artifacts) is still experimental. |
@lberki @brandjon I'm currently working on resolving the cluster of issues around symlinks. Would you support adding a new basic operation to Bazel's file system abstraction that allows creating unnormalized symlinks (taking a |
@fmeum I think there isn't another way to fix this bug, think so please go ahead (unless @haxorz objects but I don't think he will) My guess is that this comes from the time when I'd much rather you replace |
@lberki The only alternative I see is to specify the allowed operations on a |
Yeah, strictly speaking, that's an alternative, but that one has a larger blast radius than a change localized to The normalization was forcibly added in a729b9b with the reasoning that it would help RAM use. I don't know more history. @meisterT maybe you remember something I don't? There is also 775d3a9 which replaced |
@meteorcloudy While working on @lberki's recommendation to make
Do you know whether using symlinks for directories (e.g., under the Bazel convenience symlinks) instead of junctions has any drawbacks? |
While working on a PR for this, I noticed https://cs.opensource.google/bazel/bazel/+/5d75c08d9542d35d90047369059cad2e03c6a1d4:src/main/java/com/google/devtools/build/lib/windows/WindowsFileOperations.java;l=229, which is an error raised when trying to create a symlink to a directory. https://cs.opensource.google/bazel/bazel/+/cffd417a4c4ec4d082f815f57a771ad1010972dd does not contain any explanation for why that should be an error though. |
@fmeum Please see https://docs.google.com/document/d/17YIqUdffxpwcKP-0whHM6TFELN8VohTpjiiEIbbRfts/edit#heading=h.hw82qobcal5z Basically, creating symlinks on Windows requires some extra privilege, so we decided to always use junction for "directory symlink" and only when In generally, I think it's safe to change the behaviour to what you described (IIUC):
|
Thanks for the information, I got with that approach then. @meteorcloudy Do you know whether symlinks on Windows can use forward slash paths? If not, then I should probably translate the path style in |
@fmeum I think the CreateSymbolicLink API itself doesn't support forward slash paths. But we do translate the paths first before passing to the JNI functions. See https://cs.opensource.google/bazel/bazel/+/master:src/main/java/com/google/devtools/build/lib/windows/WindowsFileOperations.java;l=225 |
@meteorcloudy Thanks for pointing me to that function, that was the missing piece. Unfortunately, I don't think that the current |
Can we use |
We could if we wanted to create a resolvable symlink, but in this particular case we might very well want to create a symlink pointing to I actually think that we should just commit to the following restriction: On Windows,
@gregmagolan Die PNPM rely on unresolved file symlinks in any way? |
I did some experiments with
It looks like it actually works if a directory symlink or junction pointing to a file. So I guess yes, I agree with "On Windows, ctx.actions.symlink(target_path=...) will always create a directory symlink if the target doesn't exist". But maybe we keep the current behaviour of creating a junction since it doesn't require admin right? |
@meteorcloudy Thanks for the experiment, that's really helpful.
Can a junction point to a relative path though? I thought that wasn't possible, but could you maybe give it a try (I don't have access to a Windows machine). Admin access should no longer be required if we use |
Oh, yeah, junction can only take absolute path, see https://superuser.com/questions/343074/directory-junction-vs-directory-symbolic-link
Correct, but IIRC turning on developer mode requires admin right 😅. Anyway, I'm fine with creating directory symlink if |
The documentation of `ctx.actions.symlink(target_path = ...)` states that the given path is used as the symlink target without any changes, but in reality this path has so far always been converted into an absolute path by prepending the exec root. This is changed by this commit, which gets very close to the documented behavior by preserving the target path as is except for the standard normalization applied by `PathFragment`. Improving the situation even further would require modifying or adding to Bazel's core file system API, which may be done in a follow-up PR. Since relative symlinks only resolve correctly at the location they were originally created, the logic for staging symlinks as runfiles in the sandbox necessarily becomes more complicated: Analogously to the case of local unsandboxed execution, symlinks in runfiles are now staged as symlinks to the original exec path of the relative symlink under the sandboxed exec root as well as the relative symlink itself in that location. As a side-effect of the switch to relative symlinks, this commit resolves a non-hermeticity issue observed in bazelbuild#10298 (comment) Integration tests are added to verify that symlinks staged in the sandbox are no longer resolved non-hermetically, including the case where they are contained in runfiles. Fixes bazelbuild#14224
The documentation of `ctx.actions.symlink(target_path = ...)` states that the given path is used as the symlink target without any changes, but in reality this path has so far always been converted into an absolute path by prepending the exec root. This is changed by this commit, which gets very close to the documented behavior by preserving the target path as is except for the standard normalization applied by `PathFragment`. Improving the situation even further would require modifying or adding to Bazel's core file system API, which may be done in a follow-up PR. Since relative symlinks only resolve correctly at the location they were originally created, they have to be handled specially when staged as runfiles. This commit adds a new `declared_symlinks` parameter to the rule context's `runfiles` method that takes in symlink artifacts declared via `ctx.actions.declare_symlink`. These symlinks are staged at their runfiles path directly, with no further processing of their target and without any intermediate runfiles pointing back to the artifact's location under the exec root. This has to main benefits: * With local execution, symlinks are resolved within the runfiles tree, which is more hermetic than following the runfiles symlink back into the exec root and resolving the symlink artifact there. * Actions can expect symlink artifacts to be stages as is without intermediate symlinks with local and sandboxed execution, both inside and outside the runfiles tree. This is important for packaging actions as well as rulesets sensitive to symlinks (e.g. rules_js). As a side-effect of the switch to relative symlinks, this commit resolves a non-hermeticity issue observed in bazelbuild#10298 (comment) Integration tests are added to verify that symlinks staged in the sandbox are no longer resolved non-hermetically. Fixes bazelbuild#14224
The documentation of `ctx.actions.symlink(target_path = ...)` states that the given path is used as the symlink target without any changes, but in reality this path has so far always been converted into an absolute path by prepending the exec root. This is changed by this commit, which gets very close to the documented behavior by preserving the target path as is except for the standard normalization applied by `PathFragment`. Improving the situation even further would require modifying or adding to Bazel's core file system API, which may be done in a follow-up PR. Since relative symlinks only resolve correctly at the location they were originally created, they have to be handled specially when staged as runfiles. This commit adds a new `declared_symlinks` parameter to the rule context's `runfiles` method that takes in symlink artifacts declared via `ctx.actions.declare_symlink`. These symlinks are staged at their runfiles path directly, with no further processing of their target and without any intermediate runfiles pointing back to the artifact's location under the exec root. This has to main benefits: * With local execution, symlinks are resolved within the runfiles tree, which is more hermetic than following the runfiles symlink back into the exec root and resolving the symlink artifact there. * Actions can expect symlink artifacts to be stages as is without intermediate symlinks with local and sandboxed execution, both inside and outside the runfiles tree. This is important for packaging actions as well as rulesets sensitive to symlinks (e.g. rules_js). As a side-effect of the switch to relative symlinks, this commit resolves a non-hermeticity issue observed in bazelbuild#10298 (comment) Integration tests are added to verify that symlinks staged in the sandbox are no longer resolved non-hermetically. Fixes bazelbuild#14224
The documentation of `ctx.actions.symlink(target_path = ...)` states that the given path is used as the symlink target without any changes, but in reality this path has so far always been converted into an absolute path by prepending the exec root. This is changed by this commit, which gets very close to the documented behavior by preserving the target path as is except for the standard normalization applied by `PathFragment`. Improving the situation even further would require modifying or adding to Bazel's core file system API, which may be done in a follow-up PR. Since relative symlinks only resolve correctly at the location they were originally created, they have to be handled specially when staged as runfiles. This commit adds a new `declared_symlinks` parameter to the rule context's `runfiles` method that takes in symlink artifacts declared via `ctx.actions.declare_symlink`. These symlinks are staged at their runfiles path directly, with no further processing of their target and without any intermediate runfiles pointing back to the artifact's location under the exec root. This has to main benefits: * With local execution, symlinks are resolved within the runfiles tree, which is more hermetic than following the runfiles symlink back into the exec root and resolving the symlink artifact there. * Actions can expect symlink artifacts to be stages as is without intermediate symlinks with local and sandboxed execution, both inside and outside the runfiles tree. This is important for packaging actions as well as rulesets sensitive to symlinks (e.g. rules_js). As a side-effect of the switch to relative symlinks, this commit resolves a non-hermeticity issue observed in bazelbuild#10298 (comment) Integration tests are added to verify that symlinks staged in the sandbox are no longer resolved non-hermetically. Fixes bazelbuild#14224
The documentation of `ctx.actions.symlink(target_path = ...)` states that the given path is used as the symlink target without any changes, but in reality this path has so far always been converted into an absolute path by prepending the exec root. This is changed by this commit, which gets very close to the documented behavior by preserving the target path as is except for the standard normalization applied by `PathFragment`. Improving the situation even further would require modifying or adding to Bazel's core file system API, which may be done in a follow-up PR. Since relative symlinks only resolve correctly at the location they were originally created, they have to be handled specially when staged as runfiles. This commit adds a new `declared_symlinks` parameter to the rule context's `runfiles` method that takes in symlink artifacts declared via `ctx.actions.declare_symlink`. These symlinks are staged at their runfiles path directly, with no further processing of their target and without any intermediate runfiles pointing back to the artifact's location under the exec root. This has to main benefits: * With local execution, symlinks are resolved within the runfiles tree, which is more hermetic than following the runfiles symlink back into the exec root and resolving the symlink artifact there. * Actions can expect symlink artifacts to be stages as is without intermediate symlinks with local and sandboxed execution, both inside and outside the runfiles tree. This is important for packaging actions as well as rulesets sensitive to symlinks (e.g. rules_js). As a side-effect of the switch to relative symlinks, this commit resolves a non-hermeticity issue observed in bazelbuild#10298 (comment) Integration tests are added to verify that symlinks staged in the sandbox are no longer resolved non-hermetically. Fixes bazelbuild#14224
Thank you for contributing to the Bazel repository! This issue has been marked as stale since it has not had any activity in the last 1+ years. It will be closed in the next 90 days unless any other activity occurs. If you think this issue is still relevant and should stay open, please post any comment here and the issue will no longer be marked as stale. |
We are running into issues due to this as well. The symlinks created by rules_js are invalidated for each We only run into this problem for |
It looks like Bazel ends up creating symlinks as absolute paths on Windows, which is not the same issue, but still a bug. Cc @tjgq for your linked PR |
ctx.actions.symlink always makes absolute symlinks when target_path is used, regardless of whether target_path is absolute.
Bugs: what's the simplest, easiest way to reproduce this bug? Please provide a minimal example if possible.
WORKSAPCE.bazel
BUILD.bazel
rules.bzl
I expected both symlinks to be ''../.." but only the latter (using executable ln) is.
Documentation: https://docs.bazel.build/versions/main/skylark/lib/actions.html#symlink
What operating system are you running Bazel on?
Ubuntu 18.04
What's the output of
bazel info release
?4.2.1
The text was updated successfully, but these errors were encountered: