Support sysroot library source being defined inside the workspace

This commit is contained in:
Lukas Wirth 2023-02-06 12:07:33 +01:00
parent 0b32b65ca6
commit cb9a5b9549
6 changed files with 68 additions and 9 deletions

View file

@ -96,6 +96,7 @@ pub struct CargoConfig {
pub target: Option<String>, pub target: Option<String>,
/// Sysroot loading behavior /// Sysroot loading behavior
pub sysroot: Option<RustcSource>, pub sysroot: Option<RustcSource>,
pub sysroot_src: Option<AbsPathBuf>,
/// rustc private crate source /// rustc private crate source
pub rustc_source: Option<RustcSource>, pub rustc_source: Option<RustcSource>,
/// crates to disable `#[cfg(test)]` on /// crates to disable `#[cfg(test)]` on

View file

@ -76,6 +76,7 @@ impl Sysroot {
} }
} }
// FIXME: Expose a builder api as loading the sysroot got way too modular and complicated.
impl Sysroot { impl Sysroot {
/// Attempts to discover the toolchain's sysroot from the given `dir`. /// Attempts to discover the toolchain's sysroot from the given `dir`.
pub fn discover(dir: &AbsPath, extra_env: &FxHashMap<String, String>) -> Result<Sysroot> { pub fn discover(dir: &AbsPath, extra_env: &FxHashMap<String, String>) -> Result<Sysroot> {
@ -86,6 +87,16 @@ impl Sysroot {
Ok(Sysroot::load(sysroot_dir, sysroot_src_dir)) Ok(Sysroot::load(sysroot_dir, sysroot_src_dir))
} }
pub fn discover_with_src_override(
dir: &AbsPath,
extra_env: &FxHashMap<String, String>,
src: AbsPathBuf,
) -> Result<Sysroot> {
tracing::debug!("discovering sysroot for {}", dir.display());
let sysroot_dir = discover_sysroot_dir(dir, extra_env)?;
Ok(Sysroot::load(sysroot_dir, src))
}
pub fn discover_rustc( pub fn discover_rustc(
cargo_toml: &ManifestPath, cargo_toml: &ManifestPath,
extra_env: &FxHashMap<String, String>, extra_env: &FxHashMap<String, String>,

View file

@ -190,8 +190,8 @@ impl ProjectWorkspace {
})?; })?;
let cargo = CargoWorkspace::new(meta); let cargo = CargoWorkspace::new(meta);
let sysroot = match &config.sysroot { let sysroot = match (&config.sysroot, &config.sysroot_src) {
Some(RustcSource::Path(path)) => { (Some(RustcSource::Path(path)), None) => {
match Sysroot::with_sysroot_dir(path.clone()) { match Sysroot::with_sysroot_dir(path.clone()) {
Ok(it) => Some(it), Ok(it) => Some(it),
Err(e) => { Err(e) => {
@ -200,7 +200,7 @@ impl ProjectWorkspace {
} }
} }
} }
Some(RustcSource::Discover) => { (Some(RustcSource::Discover), None) => {
match Sysroot::discover(cargo_toml.parent(), &config.extra_env) { match Sysroot::discover(cargo_toml.parent(), &config.extra_env) {
Ok(it) => Some(it), Ok(it) => Some(it),
Err(e) => { Err(e) => {
@ -213,8 +213,29 @@ impl ProjectWorkspace {
} }
} }
} }
None => None, (Some(RustcSource::Path(sysroot)), Some(sysroot_src)) => {
Some(Sysroot::load(sysroot.clone(), sysroot_src.clone()))
}
(Some(RustcSource::Discover), Some(sysroot_src)) => {
match Sysroot::discover_with_src_override(
cargo_toml.parent(),
&config.extra_env,
sysroot_src.clone(),
) {
Ok(it) => Some(it),
Err(e) => {
tracing::error!(
%e,
"Failed to find sysroot for Cargo.toml file {}. Is rust-src installed?",
cargo_toml.display()
);
None
}
}
}
(None, _) => None,
}; };
if let Some(sysroot) = &sysroot { if let Some(sysroot) = &sysroot {
tracing::info!(src_root = %sysroot.src_root().display(), root = %sysroot.root().display(), "Using sysroot"); tracing::info!(src_root = %sysroot.src_root().display(), root = %sysroot.root().display(), "Using sysroot");
} }
@ -440,9 +461,11 @@ impl ProjectWorkspace {
/// The return type contains the path and whether or not /// The return type contains the path and whether or not
/// the root is a member of the current workspace /// the root is a member of the current workspace
pub fn to_roots(&self) -> Vec<PackageRoot> { pub fn to_roots(&self) -> Vec<PackageRoot> {
let mk_sysroot = |sysroot: Option<&Sysroot>| { let mk_sysroot = |sysroot: Option<&Sysroot>, project_root: Option<&AbsPath>| {
sysroot.map(|sysroot| PackageRoot { sysroot.map(|sysroot| PackageRoot {
is_local: false, // mark the sysroot as mutable if it is located inside of the project
is_local: project_root
.map_or(false, |project_root| sysroot.src_root().starts_with(project_root)),
include: vec![sysroot.src_root().to_path_buf()], include: vec![sysroot.src_root().to_path_buf()],
exclude: Vec::new(), exclude: Vec::new(),
}) })
@ -457,7 +480,7 @@ impl ProjectWorkspace {
}) })
.collect::<FxHashSet<_>>() .collect::<FxHashSet<_>>()
.into_iter() .into_iter()
.chain(mk_sysroot(sysroot.as_ref())) .chain(mk_sysroot(sysroot.as_ref(), Some(project.path())))
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
ProjectWorkspace::Cargo { ProjectWorkspace::Cargo {
cargo, cargo,
@ -507,7 +530,7 @@ impl ProjectWorkspace {
} }
PackageRoot { is_local, include, exclude } PackageRoot { is_local, include, exclude }
}) })
.chain(mk_sysroot(sysroot.as_ref())) .chain(mk_sysroot(sysroot.as_ref(), Some(cargo.workspace_root())))
.chain(rustc.iter().flat_map(|rustc| { .chain(rustc.iter().flat_map(|rustc| {
rustc.packages().map(move |krate| PackageRoot { rustc.packages().map(move |krate| PackageRoot {
is_local: false, is_local: false,
@ -524,7 +547,7 @@ impl ProjectWorkspace {
include: vec![detached_file.clone()], include: vec![detached_file.clone()],
exclude: Vec::new(), exclude: Vec::new(),
}) })
.chain(mk_sysroot(sysroot.as_ref())) .chain(mk_sysroot(sysroot.as_ref(), None))
.collect(), .collect(),
} }
} }

View file

@ -117,6 +117,11 @@ config_data! {
/// ///
/// This option does not take effect until rust-analyzer is restarted. /// This option does not take effect until rust-analyzer is restarted.
cargo_sysroot: Option<String> = "\"discover\"", cargo_sysroot: Option<String> = "\"discover\"",
/// Relative path to the sysroot library sources. If left unset, this will default to
/// `{cargo.sysroot}/lib/rustlib/src/rust/library`.
///
/// This option does not take effect until rust-analyzer is restarted.
cargo_sysrootSrc: Option<String> = "null",
/// Compilation target override (target triple). /// Compilation target override (target triple).
// FIXME(@poliorcetics): move to multiple targets here too, but this will need more work // FIXME(@poliorcetics): move to multiple targets here too, but this will need more work
// than `checkOnSave_target` // than `checkOnSave_target`
@ -1103,6 +1108,8 @@ impl Config {
RustcSource::Path(self.root_path.join(sysroot)) RustcSource::Path(self.root_path.join(sysroot))
} }
}); });
let sysroot_src =
self.data.cargo_sysrootSrc.as_ref().map(|sysroot| self.root_path.join(sysroot));
CargoConfig { CargoConfig {
features: match &self.data.cargo_features { features: match &self.data.cargo_features {
@ -1114,6 +1121,7 @@ impl Config {
}, },
target: self.data.cargo_target.clone(), target: self.data.cargo_target.clone(),
sysroot, sysroot,
sysroot_src,
rustc_source, rustc_source,
unset_test_crates: UnsetTestCrates::Only(self.data.cargo_unsetTest.clone()), unset_test_crates: UnsetTestCrates::Only(self.data.cargo_unsetTest.clone()),
wrap_rustc_in_build_scripts: self.data.cargo_buildScripts_useRustcWrapper, wrap_rustc_in_build_scripts: self.data.cargo_buildScripts_useRustcWrapper,

View file

@ -97,6 +97,14 @@ Relative path to the sysroot, or "discover" to try to automatically find it via
Unsetting this disables sysroot loading. Unsetting this disables sysroot loading.
This option does not take effect until rust-analyzer is restarted.
--
[[rust-analyzer.cargo.sysrootSrc]]rust-analyzer.cargo.sysrootSrc (default: `null`)::
+
--
Relative path to the sysroot library sources. If left unset, this will default to
`{cargo.sysroot}/lib/rustlib/src/rust/library`.
This option does not take effect until rust-analyzer is restarted. This option does not take effect until rust-analyzer is restarted.
-- --
[[rust-analyzer.cargo.target]]rust-analyzer.cargo.target (default: `null`):: [[rust-analyzer.cargo.target]]rust-analyzer.cargo.target (default: `null`)::

View file

@ -539,6 +539,14 @@
"string" "string"
] ]
}, },
"rust-analyzer.cargo.sysrootSrc": {
"markdownDescription": "Relative path to the sysroot library sources. If left unset, this will default to\n`{cargo.sysroot}/lib/rustlib/src/rust/library`.\n\nThis option does not take effect until rust-analyzer is restarted.",
"default": null,
"type": [
"null",
"string"
]
},
"rust-analyzer.cargo.target": { "rust-analyzer.cargo.target": {
"markdownDescription": "Compilation target override (target triple).", "markdownDescription": "Compilation target override (target triple).",
"default": null, "default": null,