Skip to content

Commit

Permalink
The [sources] subtarget should copy files for generated targets
Browse files Browse the repository at this point in the history
Summary:
The `[sources]` subtarget (added in D41708907) creates a directory called `__srcs/` for IDEs to see the Rust files without running a full build. This directory uses symlinks with `mapped_srcs`.

Unfortunately, VS Code always expands symlinks in LSP. This is fine for normal code, but for generated code we end up in files like `buck-out/...elided.../foo.thrift__/out/gen-rust/types.rs`. This `gen-rust` directory may not be a valid crate (no lib.rs), and won't match the paths in the rust-analyzer configuration. This issue is more visible after D67817956.

Instead, always copy files into `__srcs/` for generated targets.

Reviewed By: JakobDegen

Differential Revision: D68132425

fbshipit-source-id: 0b81439b68a6968021f560fd83bae8ae3dd55471
  • Loading branch information
Wilfred authored and facebook-github-bot committed Jan 14, 2025
1 parent d41a6c6 commit bbbb7b5
Showing 1 changed file with 26 additions and 12 deletions.
38 changes: 26 additions & 12 deletions prelude/rust/build.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -104,20 +104,34 @@ def compile_context(ctx: AnalysisContext, binary: bool = False) -> CompileContex
srcs.update({k: v for v, k in ctx.attrs.mapped_srcs.items()})

# Decide whether to use symlinked_dir or copied_dir.
#
# If a source is a prefix of any other source, use copied_dir. This supports
# e.g. `srcs = [":foo.crate"]` where :foo.crate is an http_archive, together
# with a `mapped_srcs` which overlays additional generated files into that
# directory. Symlinked_dir would error in this situation.
prefixes = {}
symlinked_srcs = None
for src in sorted(srcs.keys(), key = len, reverse = True):
if src in prefixes:
symlinked_srcs = ctx.actions.copied_dir("__srcs", srcs)
break
components = src.split("/")
for i in range(1, len(components)):
prefixes["/".join(components[:i])] = None

if "generated" in ctx.attrs.labels:
# For generated code targets, we always want to copy files in the [sources]
# subtarget, never symlink.
#
# This ensures that IDEs that open the generated file always see the correct
# directory structure.
#
# VS Code will expand symlinks when doing go-to-definition. In normal source
# files this takes us back to the correct path, but for generated files the
# expanded path may not be a well-formed crate layout.
symlinked_srcs = ctx.actions.copied_dir("__srcs", srcs)
else:
# If a source is a prefix of any other source, use copied_dir. This supports
# e.g. `srcs = [":foo.crate"]` where :foo.crate is an http_archive, together
# with a `mapped_srcs` which overlays additional generated files into that
# directory. Symlinked_dir would error in this situation.
for src in sorted(srcs.keys(), key = len, reverse = True):
if src in prefixes:
symlinked_srcs = ctx.actions.copied_dir("__srcs", srcs)
break
components = src.split("/")
for i in range(1, len(components)):
prefixes["/".join(components[:i])] = None

# Otherwise, symlink it.
if not symlinked_srcs:
symlinked_srcs = ctx.actions.symlinked_dir("__srcs", srcs)

Expand Down

0 comments on commit bbbb7b5

Please sign in to comment.