• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use std::collections::HashMap;
2 use std::path::Path;
3 use std::process::Command;
4 
5 use anyhow::anyhow;
6 use runfiles::Runfiles;
7 
8 mod aquery;
9 mod rust_project;
10 
11 const SYSROOT_SRC_FILE_RUNFILES_PREFIX: &str = "rules_rust";
12 
generate_crate_info( bazel: impl AsRef<Path>, workspace: impl AsRef<Path>, rules_rust: impl AsRef<str>, targets: &[String], ) -> anyhow::Result<()>13 pub fn generate_crate_info(
14     bazel: impl AsRef<Path>,
15     workspace: impl AsRef<Path>,
16     rules_rust: impl AsRef<str>,
17     targets: &[String],
18 ) -> anyhow::Result<()> {
19     log::debug!("Building rust_analyzer_crate_spec files for {:?}", targets);
20 
21     let output = Command::new(bazel.as_ref())
22         .current_dir(workspace.as_ref())
23         .env_remove("BAZELISK_SKIP_WRAPPER")
24         .env_remove("BUILD_WORKING_DIRECTORY")
25         .env_remove("BUILD_WORKSPACE_DIRECTORY")
26         .arg("build")
27         .arg("--norun_validations")
28         .arg(format!(
29             "--aspects={}//rust:defs.bzl%rust_analyzer_aspect",
30             rules_rust.as_ref()
31         ))
32         .arg("--output_groups=rust_analyzer_crate_spec")
33         .args(targets)
34         .output()?;
35 
36     if !output.status.success() {
37         return Err(anyhow!(
38             "bazel build failed:({})\n{}",
39             output.status,
40             String::from_utf8_lossy(&output.stderr)
41         ));
42     }
43 
44     Ok(())
45 }
46 
write_rust_project( bazel: impl AsRef<Path>, workspace: impl AsRef<Path>, rules_rust_name: &impl AsRef<str>, targets: &[String], execution_root: impl AsRef<Path>, output_base: impl AsRef<Path>, rust_project_path: impl AsRef<Path>, ) -> anyhow::Result<()>47 pub fn write_rust_project(
48     bazel: impl AsRef<Path>,
49     workspace: impl AsRef<Path>,
50     rules_rust_name: &impl AsRef<str>,
51     targets: &[String],
52     execution_root: impl AsRef<Path>,
53     output_base: impl AsRef<Path>,
54     rust_project_path: impl AsRef<Path>,
55 ) -> anyhow::Result<()> {
56     let crate_specs = aquery::get_crate_specs(
57         bazel.as_ref(),
58         workspace.as_ref(),
59         execution_root.as_ref(),
60         targets,
61         rules_rust_name.as_ref(),
62     )?;
63 
64     let workspace_name = match rules_rust_name.as_ref().trim_start_matches('@') {
65         "" => SYSROOT_SRC_FILE_RUNFILES_PREFIX,
66         s => s,
67     };
68     let toolchain_info_path = format!(
69         "{workspace_name}/rust/private/rust_analyzer_detect_sysroot.rust_analyzer_toolchain.json"
70     );
71     let r = Runfiles::create()?;
72     let path = r.rlocation(toolchain_info_path);
73     let toolchain_info: HashMap<String, String> =
74         serde_json::from_str(&std::fs::read_to_string(path)?)?;
75 
76     let sysroot_src = &toolchain_info["sysroot_src"];
77     let sysroot = &toolchain_info["sysroot"];
78 
79     let rust_project = rust_project::generate_rust_project(sysroot, sysroot_src, &crate_specs)?;
80 
81     rust_project::write_rust_project(
82         rust_project_path.as_ref(),
83         execution_root.as_ref(),
84         output_base.as_ref(),
85         &rust_project,
86     )?;
87 
88     Ok(())
89 }
90