mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-26 11:59:49 +00:00
Remember the difference between 'sysroot root' and 'sysroot src root', start looking in there for a rust-analyzer-proc-macro-srv binary
This commit is contained in:
parent
4364531c2f
commit
dadb83282d
5 changed files with 63 additions and 12 deletions
|
@ -17,6 +17,9 @@ use crate::cfg_flag::CfgFlag;
|
||||||
/// Roots and crates that compose this Rust project.
|
/// Roots and crates that compose this Rust project.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct ProjectJson {
|
pub struct ProjectJson {
|
||||||
|
/// e.g. `path/to/sysroot`
|
||||||
|
pub(crate) sysroot: Option<AbsPathBuf>,
|
||||||
|
/// e.g. `path/to/sysroot/lib/rustlib/src/rust`
|
||||||
pub(crate) sysroot_src: Option<AbsPathBuf>,
|
pub(crate) sysroot_src: Option<AbsPathBuf>,
|
||||||
project_root: AbsPathBuf,
|
project_root: AbsPathBuf,
|
||||||
crates: Vec<Crate>,
|
crates: Vec<Crate>,
|
||||||
|
@ -52,6 +55,7 @@ impl ProjectJson {
|
||||||
/// configuration.
|
/// configuration.
|
||||||
pub fn new(base: &AbsPath, data: ProjectJsonData) -> ProjectJson {
|
pub fn new(base: &AbsPath, data: ProjectJsonData) -> ProjectJson {
|
||||||
ProjectJson {
|
ProjectJson {
|
||||||
|
sysroot: data.sysroot.map(|it| base.join(it)),
|
||||||
sysroot_src: data.sysroot_src.map(|it| base.join(it)),
|
sysroot_src: data.sysroot_src.map(|it| base.join(it)),
|
||||||
project_root: base.to_path_buf(),
|
project_root: base.to_path_buf(),
|
||||||
crates: data
|
crates: data
|
||||||
|
@ -122,6 +126,7 @@ impl ProjectJson {
|
||||||
|
|
||||||
#[derive(Deserialize, Debug, Clone)]
|
#[derive(Deserialize, Debug, Clone)]
|
||||||
pub struct ProjectJsonData {
|
pub struct ProjectJsonData {
|
||||||
|
sysroot: Option<PathBuf>,
|
||||||
sysroot_src: Option<PathBuf>,
|
sysroot_src: Option<PathBuf>,
|
||||||
crates: Vec<CrateData>,
|
crates: Vec<CrateData>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ use crate::{utf8_stdout, ManifestPath};
|
||||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
pub struct Sysroot {
|
pub struct Sysroot {
|
||||||
root: AbsPathBuf,
|
root: AbsPathBuf,
|
||||||
|
src_root: AbsPathBuf,
|
||||||
crates: Arena<SysrootCrateData>,
|
crates: Arena<SysrootCrateData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +36,15 @@ impl ops::Index<SysrootCrate> for Sysroot {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sysroot {
|
impl Sysroot {
|
||||||
|
/// Returns sysroot directory, where `bin/`, `etc/`, `lib/`, `libexec/`
|
||||||
|
/// subfolder live, like:
|
||||||
|
/// `$HOME/.rustup/toolchains/nightly-2022-07-23-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library`
|
||||||
|
pub fn src_root(&self) -> &AbsPath {
|
||||||
|
&self.src_root
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns sysroot "src" directory, where stdlib sources are located, like:
|
||||||
|
/// `$HOME/.rustup/toolchains/nightly-2022-07-23-x86_64-unknown-linux-gnu`
|
||||||
pub fn root(&self) -> &AbsPath {
|
pub fn root(&self) -> &AbsPath {
|
||||||
&self.root
|
&self.root
|
||||||
}
|
}
|
||||||
|
@ -61,7 +71,7 @@ impl Sysroot {
|
||||||
tracing::debug!("Discovering sysroot for {}", dir.display());
|
tracing::debug!("Discovering sysroot for {}", dir.display());
|
||||||
let sysroot_dir = discover_sysroot_dir(dir)?;
|
let sysroot_dir = discover_sysroot_dir(dir)?;
|
||||||
let sysroot_src_dir = discover_sysroot_src_dir(&sysroot_dir, dir)?;
|
let sysroot_src_dir = discover_sysroot_src_dir(&sysroot_dir, dir)?;
|
||||||
let res = Sysroot::load(sysroot_src_dir)?;
|
let res = Sysroot::load(sysroot_dir, sysroot_src_dir)?;
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,14 +81,15 @@ impl Sysroot {
|
||||||
discover_sysroot_dir(current_dir).ok().and_then(|sysroot_dir| get_rustc_src(&sysroot_dir))
|
discover_sysroot_dir(current_dir).ok().and_then(|sysroot_dir| get_rustc_src(&sysroot_dir))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load(sysroot_src_dir: AbsPathBuf) -> Result<Sysroot> {
|
pub fn load(sysroot_dir: AbsPathBuf, sysroot_src_dir: AbsPathBuf) -> Result<Sysroot> {
|
||||||
let mut sysroot = Sysroot { root: sysroot_src_dir, crates: Arena::default() };
|
let mut sysroot =
|
||||||
|
Sysroot { root: sysroot_dir, src_root: sysroot_src_dir, crates: Arena::default() };
|
||||||
|
|
||||||
for path in SYSROOT_CRATES.trim().lines() {
|
for path in SYSROOT_CRATES.trim().lines() {
|
||||||
let name = path.split('/').last().unwrap();
|
let name = path.split('/').last().unwrap();
|
||||||
let root = [format!("{}/src/lib.rs", path), format!("lib{}/lib.rs", path)]
|
let root = [format!("{}/src/lib.rs", path), format!("lib{}/lib.rs", path)]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|it| sysroot.root.join(it))
|
.map(|it| sysroot.src_root.join(it))
|
||||||
.filter_map(|it| ManifestPath::try_from(it).ok())
|
.filter_map(|it| ManifestPath::try_from(it).ok())
|
||||||
.find(|it| fs::metadata(it).is_ok());
|
.find(|it| fs::metadata(it).is_ok());
|
||||||
|
|
||||||
|
@ -119,7 +130,7 @@ impl Sysroot {
|
||||||
};
|
};
|
||||||
anyhow::bail!(
|
anyhow::bail!(
|
||||||
"could not find libcore in sysroot path `{}`{}",
|
"could not find libcore in sysroot path `{}`{}",
|
||||||
sysroot.root.as_path().display(),
|
sysroot.src_root.as_path().display(),
|
||||||
var_note,
|
var_note,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,8 +75,11 @@ fn get_test_path(file: &str) -> PathBuf {
|
||||||
|
|
||||||
fn get_fake_sysroot() -> Sysroot {
|
fn get_fake_sysroot() -> Sysroot {
|
||||||
let sysroot_path = get_test_path("fake-sysroot");
|
let sysroot_path = get_test_path("fake-sysroot");
|
||||||
let sysroot_src_dir = AbsPathBuf::assert(sysroot_path);
|
// there's no `libexec/` directory with a `proc-macro-srv` binary in that
|
||||||
Sysroot::load(sysroot_src_dir).unwrap()
|
// fake sysroot, so we give them both the same path:
|
||||||
|
let sysroot_dir = AbsPathBuf::assert(sysroot_path);
|
||||||
|
let sysroot_src_dir = sysroot_dir.clone();
|
||||||
|
Sysroot::load(sysroot_dir, sysroot_src_dir).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rooted_project_json(data: ProjectJsonData) -> ProjectJson {
|
fn rooted_project_json(data: ProjectJsonData) -> ProjectJson {
|
||||||
|
|
|
@ -230,8 +230,14 @@ impl ProjectWorkspace {
|
||||||
project_json: ProjectJson,
|
project_json: ProjectJson,
|
||||||
target: Option<&str>,
|
target: Option<&str>,
|
||||||
) -> Result<ProjectWorkspace> {
|
) -> Result<ProjectWorkspace> {
|
||||||
let sysroot = match &project_json.sysroot_src {
|
let sysroot = match project_json.sysroot_src.clone() {
|
||||||
Some(path) => Some(Sysroot::load(path.clone())?),
|
Some(sysroot_src) => {
|
||||||
|
// if `sysroot` isn't specified (only `sysroot_src`), we won't have
|
||||||
|
// a real sysroot path, that's fine. it's just used to discover
|
||||||
|
// the standalone `proc-macro-srv` binary.
|
||||||
|
let sysroot = project_json.sysroot.clone().unwrap_or_else(|| sysroot_src.clone());
|
||||||
|
Some(Sysroot::load(sysroot, sysroot_src)?)
|
||||||
|
}
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
let rustc_cfg = rustc_cfg::get(None, target);
|
let rustc_cfg = rustc_cfg::get(None, target);
|
||||||
|
@ -345,7 +351,7 @@ impl ProjectWorkspace {
|
||||||
})
|
})
|
||||||
.chain(sysroot.iter().map(|sysroot| PackageRoot {
|
.chain(sysroot.iter().map(|sysroot| PackageRoot {
|
||||||
is_local: false,
|
is_local: false,
|
||||||
include: vec![sysroot.root().to_path_buf()],
|
include: vec![sysroot.src_root().to_path_buf()],
|
||||||
exclude: Vec::new(),
|
exclude: Vec::new(),
|
||||||
}))
|
}))
|
||||||
.chain(rustc.iter().flat_map(|rustc| {
|
.chain(rustc.iter().flat_map(|rustc| {
|
||||||
|
|
|
@ -305,8 +305,34 @@ impl GlobalState {
|
||||||
|
|
||||||
if self.proc_macro_clients.is_empty() {
|
if self.proc_macro_clients.is_empty() {
|
||||||
if let Some((path, args)) = self.config.proc_macro_srv() {
|
if let Some((path, args)) = self.config.proc_macro_srv() {
|
||||||
self.proc_macro_clients = (0..self.workspaces.len())
|
self.proc_macro_clients = self
|
||||||
.map(|_| {
|
.workspaces
|
||||||
|
.iter()
|
||||||
|
.map(|ws| {
|
||||||
|
let mut path = path.clone();
|
||||||
|
if let ProjectWorkspace::Cargo { sysroot, .. } = ws {
|
||||||
|
tracing::info!("Found a cargo workspace...");
|
||||||
|
if let Some(sysroot) = sysroot.as_ref() {
|
||||||
|
tracing::info!("Found a cargo workspace with a sysroot...");
|
||||||
|
let server_path = sysroot
|
||||||
|
.root()
|
||||||
|
.join("libexec")
|
||||||
|
.join("rust-analyzer-proc-macro-srv");
|
||||||
|
if std::fs::metadata(&server_path).is_ok() {
|
||||||
|
tracing::info!(
|
||||||
|
"And the server exists at {}",
|
||||||
|
server_path.display()
|
||||||
|
);
|
||||||
|
path = server_path;
|
||||||
|
} else {
|
||||||
|
tracing::info!(
|
||||||
|
"And the server does not exist at {}",
|
||||||
|
server_path.display()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ProcMacroServer::spawn(path.clone(), args.clone()).map_err(|err| {
|
ProcMacroServer::spawn(path.clone(), args.clone()).map_err(|err| {
|
||||||
let error = format!(
|
let error = format!(
|
||||||
"Failed to run proc_macro_srv from path {}, error: {:?}",
|
"Failed to run proc_macro_srv from path {}, error: {:?}",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue