Skip to content
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

Allow the creation of relative symlinks on Windows #24213

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

fmeum
Copy link
Collaborator

@fmeum fmeum commented Nov 5, 2024

Fixes #14224

RELNOTES: Symlinks created via ctx.actions.symlink(..., target_path = "...") with --windows_enable_symlinks can now be relative on Windows.

@fmeum fmeum force-pushed the 14224-windows-absolute-symlinks branch from 075e5c5 to 7f91c3a Compare November 5, 2024 16:32
@fmeum fmeum changed the title Test creation of relative non-existent symlinks on Windows Allow the creation of relative symlinks on Windows Nov 6, 2024
@tomdegoede
Copy link
Contributor

Thanks for working on this!

I recently observed some weird behavior with relative symlinks created in pwsh.exe on windows. It went something like this:
a/b/c/external/file.x
a/b/c/out/x64/bin/link.x -> ../../../external/file.x
a/b/c/bin -> out/x64/bin
get-content bin/link.x : Error: a/external/file.x does not exist. (Ignoring the fact that link.x lives inside it symlink itself)

I'm not sure if this also works like this on linux and under which specific circumstances this occurs. Maybe the symlinks were made absolute for this reason. We have changed our PowerShell script to produce absolute symlinks (and disabled caching) to fix bazel-bin invocations.

@fmeum
Copy link
Collaborator Author

fmeum commented Nov 6, 2024

@meteorcloudy Do you happen to know what's up with relative symlinks on Windows? I can add more test cases.

@meteorcloudy
Copy link
Member

meteorcloudy commented Nov 6, 2024

I recently observed some weird behavior with relative symlinks created in pwsh.exe on windows. It went something like this:
a/b/c/external/file.x
a/b/c/out/x64/bin/link.x -> ../../../external/file.x
a/b/c/bin -> out/x64/bin
get-content bin/link.x : Error: a/external/file.x does not exist. (Ignoring the fact that link.x lives inside it symlink itself)

This is probably due to

if (OS.getCurrent() == OS.WINDOWS) {
// On Windows, symlinks are resolved differently.
// Given <external>/repo_foo/link,
// where <external>/repo_foo points to <vendor dir>/repo_foo in vendor mode
// and repo_foo/link points to a relative path ../bazel-external/repo_bar/data.
// Windows won't resolve `repo_foo` before resolving `link`, which causes
// <external>/repo_foo/link to be resolved to <external>/bazel-external/repo_bar/data
// To work around this, we create a symlink <external>/bazel-external -> <external>.
FileSystemUtils.ensureSymbolicLink(
externalRoot.getChild(VendorManager.EXTERNAL_ROOT_SYMLINK_NAME), externalRoot);
}

So given:

pcloudy@bazel-windows-playground:~/workdir/symlink_test
$ tree .
.
├── external
│   ├── bar -> /c/Users/pcloudy/workdir/symlink_test/vendor/bar
│   └── foo -> /c/Users/pcloudy/workdir/symlink_test/vendor/foo
└── vendor
    ├── bar
    │   └── file
    ├── external -> /c/Users/pcloudy/workdir/symlink_test/external
    └── foo
        └── link -> ../external/bar/file

We got different results based on which style of file path you use for cat (probably affects how symlinks in the path was resolved?).

pcloudy@bazel-windows-playground:~/workdir/symlink_test
$ cat c:/Users/pcloudy/workdir/symlink_test/external/foo/link
cat: 'c:/Users/pcloudy/workdir/symlink_test/external/foo/link': No such file or directory
pcloudy@bazel-windows-playground:~/workdir/symlink_test
$ cat /c/Users/pcloudy/workdir/symlink_test/external/foo/link
hi

So basically c:/Users/pcloudy/workdir/symlink_test/external/foo/link is resolved to

=> c:/Users/pcloudy/workdir/symlink_test/external/foo/../external/bar/file
=> c:/Users/pcloudy/workdir/symlink_test/external/external/bar/file ❌

but /c/Users/pcloudy/workdir/symlink_test/external/foo/link is resolved to

=> /c/Users/pcloudy/workdir/symlink_test/vendor/foo/link
=> /c/Users/pcloudy/workdir/symlink_test/vendor/foo/../external/bar/file
=> /c/Users/pcloudy/workdir/symlink_test/vendor/external/bar/file
=> /c/Users/pcloudy/workdir/symlink_test/external/bar/file
=> /c/Users/pcloudy/workdir/symlink_test/vendor/bar/file ✅

I think we might want to be a bit careful on opening up relative symlinks on Windows since they behave different due to this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ctx.actions.symlink doesn't make relative symlink, contrary to docs
3 participants