Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions rust/private/rust_analyzer.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ given targets. This file can be consumed by rust-analyzer as an alternative
to Cargo.toml files.
"""

load("//rust/platform:triple_mappings.bzl", "system_to_dylib_ext", "triple_to_system")
load("//rust/platform:triple_mappings.bzl", "system_to_dylib_ext")
load("//rust/private:common.bzl", "rust_common")
load("//rust/private:providers.bzl", "RustAnalyzerGroupInfo", "RustAnalyzerInfo")
load("//rust/private:rustc.bzl", "BuildInfo")
Expand Down Expand Up @@ -195,14 +195,13 @@ def find_proc_macro_dylib(toolchain, target):
if crate_info.type != "proc-macro":
return None

dylib_ext = system_to_dylib_ext(triple_to_system(toolchain.target_triple))
# Use the exec ext: rust-analyzer (host) is what loads the dylib.
dylib_ext = system_to_dylib_ext(toolchain.exec_triple.system)
for action in target.actions:
for output in action.outputs.to_list():
if output.extension == dylib_ext[1:]:
return output

# Failed to find the dylib path inside a proc-macro crate.
# TODO: Should this be an error?
return None

rust_analyzer_aspect = aspect(
Expand Down
13 changes: 13 additions & 0 deletions test/rust_analyzer/proc_macro_dylib_test/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
load("@rules_rust//rust:defs.bzl", "rust_proc_macro")
load(":proc_macro_dylib_test.bzl", "exec_triple_selects_dylib_test")

rust_proc_macro(
name = "test_proc_macro",
srcs = ["test_proc_macro.rs"],
edition = "2021",
)

exec_triple_selects_dylib_test(
name = "exec_triple_selects_dylib",
target_under_test = ":test_proc_macro",
)
51 changes: 51 additions & 0 deletions test/rust_analyzer/proc_macro_dylib_test/proc_macro_dylib_test.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"""Regression test: find_proc_macro_dylib must key off exec_triple.

Proc-macros are loaded by the host rust-analyzer process, so the dylib
extension used to locate the compiled artifact must match the exec platform,
not the target — otherwise a cross-compile spec points at an unloadable
artifact (e.g. `.wasm` or `.dll` on a Linux host).
"""

load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")

# buildifier: disable=bzl-visibility
load("@rules_rust//rust/private:rust_analyzer.bzl", "find_proc_macro_dylib")

_ProcMacroDylibProbeInfo = provider(
doc = "Captures find_proc_macro_dylib results across mock exec triples.",
fields = ["by_system"],
)

def _probe_aspect_impl(target, ctx):
if ctx.rule.kind != "rust_proc_macro":
return []

# Pairwise-distinct dylib extensions: .so / .dylib / .dll / .wasm.
by_system = {
system: find_proc_macro_dylib(
struct(exec_triple = struct(system = system)),
target,
)
for system in ["linux", "macos", "windows", "wasi"]
}
return [_ProcMacroDylibProbeInfo(by_system = by_system)]

_probe_aspect = aspect(implementation = _probe_aspect_impl)

def _exec_triple_selects_dylib_impl(ctx):
env = analysistest.begin(ctx)
probe = analysistest.target_under_test(env)[_ProcMacroDylibProbeInfo]

hits = [s for s, d in probe.by_system.items() if d != None]
asserts.equals(
env,
1,
len(hits),
"Expected exactly one exec_triple.system to find the host proc-macro dylib; got {}".format(probe.by_system),
)
return analysistest.end(env)

exec_triple_selects_dylib_test = analysistest.make(
_exec_triple_selects_dylib_impl,
extra_target_under_test_aspects = [_probe_aspect],
)
8 changes: 8 additions & 0 deletions test/rust_analyzer/proc_macro_dylib_test/test_proc_macro.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
extern crate proc_macro;

use proc_macro::TokenStream;

#[proc_macro_derive(Marker)]
pub fn marker(_input: TokenStream) -> TokenStream {
TokenStream::new()
}
Loading