Auto merge of #14091 - Veykril:workspace-sysroot, r=Veykril

Support sysroot library source being defined inside the workspace

With this you can now specify `cargo.sysrootSrc`. This is required for the rust workspace such that the `library` folder inside the workspace can be used as the sysroot library sources. We now also recognize if these sources are inside the workspace, tagging the as workspace members.

This does duplicate the sysroot crates still, but I don't think that causes too many problems.
This commit is contained in:
bors 2023-02-06 14:24:51 +00:00
commit 62523024d3
6 changed files with 68 additions and 9 deletions

View File

@ -96,6 +96,7 @@ pub struct CargoConfig {
pub target: Option<String>,
/// Sysroot loading behavior
pub sysroot: Option<RustcSource>,
pub sysroot_src: Option<AbsPathBuf>,
/// rustc private crate source
pub rustc_source: Option<RustcSource>,
/// 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 {
/// Attempts to discover the toolchain's sysroot from the given `dir`.
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))
}
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(
cargo_toml: &ManifestPath,
extra_env: &FxHashMap<String, String>,

View File

@ -190,8 +190,8 @@ impl ProjectWorkspace {
})?;
let cargo = CargoWorkspace::new(meta);
let sysroot = match &config.sysroot {
Some(RustcSource::Path(path)) => {
let sysroot = match (&config.sysroot, &config.sysroot_src) {
(Some(RustcSource::Path(path)), None) => {
match Sysroot::with_sysroot_dir(path.clone()) {
Ok(it) => Some(it),
Err(e) => {
@ -200,7 +200,7 @@ impl ProjectWorkspace {
}
}
}
Some(RustcSource::Discover) => {
(Some(RustcSource::Discover), None) => {
match Sysroot::discover(cargo_toml.parent(), &config.extra_env) {
Ok(it) => Some(it),
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 {
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 root is a member of the current workspace
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 {
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()],
exclude: Vec::new(),
})
@ -457,7 +480,7 @@ impl ProjectWorkspace {
})
.collect::<FxHashSet<_>>()
.into_iter()
.chain(mk_sysroot(sysroot.as_ref()))
.chain(mk_sysroot(sysroot.as_ref(), Some(project.path())))
.collect::<Vec<_>>(),
ProjectWorkspace::Cargo {
cargo,
@ -507,7 +530,7 @@ impl ProjectWorkspace {
}
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| {
rustc.packages().map(move |krate| PackageRoot {
is_local: false,
@ -524,7 +547,7 @@ impl ProjectWorkspace {
include: vec![detached_file.clone()],
exclude: Vec::new(),
})
.chain(mk_sysroot(sysroot.as_ref()))
.chain(mk_sysroot(sysroot.as_ref(), None))
.collect(),
}
}

View File

@ -117,6 +117,11 @@ config_data! {
///
/// This option does not take effect until rust-analyzer is restarted.
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).
// FIXME(@poliorcetics): move to multiple targets here too, but this will need more work
// than `checkOnSave_target`
@ -1103,6 +1108,8 @@ impl Config {
RustcSource::Path(self.root_path.join(sysroot))
}
});
let sysroot_src =
self.data.cargo_sysrootSrc.as_ref().map(|sysroot| self.root_path.join(sysroot));
CargoConfig {
features: match &self.data.cargo_features {
@ -1114,6 +1121,7 @@ impl Config {
},
target: self.data.cargo_target.clone(),
sysroot,
sysroot_src,
rustc_source,
unset_test_crates: UnsetTestCrates::Only(self.data.cargo_unsetTest.clone()),
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.
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.
--
[[rust-analyzer.cargo.target]]rust-analyzer.cargo.target (default: `null`)::

View File

@ -539,6 +539,14 @@
"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": {
"markdownDescription": "Compilation target override (target triple).",
"default": null,