Skip to content

Resolve relative manifest targets like the runfiles directory does - #69

Open
fmeum wants to merge 1 commit into
bazel-contrib:mainfrom
fmeum:manifest-relative-symlink-targets
Open

Resolve relative manifest targets like the runfiles directory does#69
fmeum wants to merge 1 commit into
bazel-contrib:mainfrom
fmeum:manifest-relative-symlink-targets

Conversation

@fmeum

@fmeum fmeum commented Aug 13, 2026

Copy link
Copy Markdown
Member

The target of a runfiles manifest entry is an absolute path, except for unresolved symlinks (ctx.actions.declare_symlink), whose target Bazel copies into the manifest verbatim: SourceManifestAction#writeFile writes metadata.getUnresolvedSymlinkTarget(), which may be relative. In a runfiles directory, sandboxes and SymlinkTreeHelper#createRunfilesSymlinks create such an entry textually ("Unresolved symlinks are created textually"), so the file system resolves it relative to the directory containing the symlink.

A manifest-based lookup returned that raw target instead, i.e. a path relative to the current working directory. rlocation thus either failed or, worse, returned an unrelated file that happened to exist relative to the working directory.

This change makes it so that a relative target resolves as an rlocation path relative to the directory of its entry and looks that up in the manifest again, which is what resolving the symlink in a materialized runfiles directory amounts to. Targets that escape the runfiles root cannot be resolved this way and are reported as missing, as are cycles, which are broken after 32 levels.

The test runs the same lookups against both backends: write_relative_symlink_target_layout emits the same set of unresolved symlinks as a manifest and as a materialized runfiles directory, and assert_relative_symlink_target_lookups asserts that each resolves to the same file. Before this change, the directory-backed half passes and the manifest-backed one fails on its first assertion. The only case in which the two cannot agree is a relative target that leaves the runfiles tree, which the file system resolves against the directory's parent; the manifest offers no way to reach it, so it is reported as missing.

@fmeum
fmeum force-pushed the manifest-relative-symlink-targets branch 2 times, most recently from 86e8a1e to 84ac013 Compare August 13, 2026 10:32
The target of a runfiles manifest entry is an absolute path, except for
unresolved symlinks (`ctx.actions.declare_symlink`), whose target Bazel
copies into the manifest verbatim: `SourceManifestAction` writes
`metadata.getUnresolvedSymlinkTarget()`, which may be relative. In a
runfiles directory, `SymlinkTreeHelper#createRunfilesSymlinks` creates
such an entry textually, so the file system resolves it relative to the
directory containing the symlink.

A manifest-based lookup returned that raw target instead, i.e. a path
relative to the current working directory. `rlocation` thus either
failed or, worse, returned an unrelated file that happened to exist
relative to the working directory.

Interpret a relative target as an rlocation path relative to the
directory of its entry and look that up in the manifest again, which is
what resolving the symlink in a materialized runfiles directory amounts
to. Targets that escape the runfiles root cannot be resolved this way
and are reported as missing, as are cycles, which are broken after 32
levels.

Claude-Session: https://claude.ai/code/session_013o72rMrpgYKD9wYYQ2Nr98
@fmeum
fmeum force-pushed the manifest-relative-symlink-targets branch from 84ac013 to 998621d Compare August 13, 2026 10:36
@fmeum
fmeum requested review from Wyverald and meteorcloudy August 13, 2026 10:38
@fmeum
fmeum marked this pull request as ready for review August 13, 2026 10:38
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.

1 participant