mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-13 21:54:42 +00:00
Add config for supplying sysroot path
This commit is contained in:
parent
bf5cad8e77
commit
5424c51158
10 changed files with 88 additions and 41 deletions
|
@ -94,9 +94,8 @@ pub struct CargoConfig {
|
||||||
pub features: CargoFeatures,
|
pub features: CargoFeatures,
|
||||||
/// rustc target
|
/// rustc target
|
||||||
pub target: Option<String>,
|
pub target: Option<String>,
|
||||||
/// Don't load sysroot crates (`std`, `core` & friends). Might be useful
|
/// Sysroot loading behavior
|
||||||
/// when debugging isolated issues.
|
pub sysroot: Option<RustcSource>,
|
||||||
pub no_sysroot: bool,
|
|
||||||
/// 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
|
||||||
|
|
|
@ -67,11 +67,14 @@ impl Sysroot {
|
||||||
pub fn crates<'a>(&'a self) -> impl Iterator<Item = SysrootCrate> + ExactSizeIterator + 'a {
|
pub fn crates<'a>(&'a self) -> impl Iterator<Item = SysrootCrate> + ExactSizeIterator + 'a {
|
||||||
self.crates.iter().map(|(id, _data)| id)
|
self.crates.iter().map(|(id, _data)| id)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Sysroot {
|
||||||
pub fn discover(dir: &AbsPath, extra_env: &FxHashMap<String, String>) -> Result<Sysroot> {
|
pub fn discover(dir: &AbsPath, extra_env: &FxHashMap<String, String>) -> Result<Sysroot> {
|
||||||
tracing::debug!("Discovering sysroot for {}", dir.display());
|
tracing::debug!("Discovering sysroot for {}", dir.display());
|
||||||
let sysroot_dir = discover_sysroot_dir(dir, extra_env)?;
|
let sysroot_dir = discover_sysroot_dir(dir, extra_env)?;
|
||||||
let sysroot_src_dir = discover_sysroot_src_dir(&sysroot_dir, dir, extra_env)?;
|
let sysroot_src_dir =
|
||||||
|
discover_sysroot_src_dir_or_add_component(&sysroot_dir, dir, extra_env)?;
|
||||||
let res = Sysroot::load(sysroot_dir, sysroot_src_dir)?;
|
let res = Sysroot::load(sysroot_dir, sysroot_src_dir)?;
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
@ -87,6 +90,14 @@ impl Sysroot {
|
||||||
.and_then(|sysroot_dir| get_rustc_src(&sysroot_dir))
|
.and_then(|sysroot_dir| get_rustc_src(&sysroot_dir))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn with_sysroot_dir(sysroot_dir: AbsPathBuf) -> Result<Sysroot> {
|
||||||
|
let sysroot_src_dir = discover_sysroot_src_dir(&sysroot_dir).ok_or_else(|| {
|
||||||
|
format_err!("can't load standard library from sysroot {}", sysroot_dir.display())
|
||||||
|
})?;
|
||||||
|
let res = Sysroot::load(sysroot_dir, sysroot_src_dir)?;
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn load(sysroot_dir: AbsPathBuf, sysroot_src_dir: AbsPathBuf) -> Result<Sysroot> {
|
pub fn load(sysroot_dir: AbsPathBuf, sysroot_src_dir: AbsPathBuf) -> Result<Sysroot> {
|
||||||
let mut sysroot =
|
let mut sysroot =
|
||||||
Sysroot { root: sysroot_dir, src_root: sysroot_src_dir, crates: Arena::default() };
|
Sysroot { root: sysroot_dir, src_root: sysroot_src_dir, crates: Arena::default() };
|
||||||
|
@ -162,23 +173,28 @@ fn discover_sysroot_dir(
|
||||||
Ok(AbsPathBuf::assert(PathBuf::from(stdout)))
|
Ok(AbsPathBuf::assert(PathBuf::from(stdout)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn discover_sysroot_src_dir(
|
fn discover_sysroot_src_dir(sysroot_path: &AbsPathBuf) -> Option<AbsPathBuf> {
|
||||||
|
if let Ok(path) = env::var("RUST_SRC_PATH") {
|
||||||
|
if let Ok(path) = AbsPathBuf::try_from(path.as_str()) {
|
||||||
|
let core = path.join("core");
|
||||||
|
if fs::metadata(&core).is_ok() {
|
||||||
|
tracing::debug!("Discovered sysroot by RUST_SRC_PATH: {}", path.display());
|
||||||
|
return Some(path);
|
||||||
|
}
|
||||||
|
tracing::debug!("RUST_SRC_PATH is set, but is invalid (no core: {:?}), ignoring", core);
|
||||||
|
} else {
|
||||||
|
tracing::debug!("RUST_SRC_PATH is set, but is invalid, ignoring");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get_rust_src(sysroot_path)
|
||||||
|
}
|
||||||
|
fn discover_sysroot_src_dir_or_add_component(
|
||||||
sysroot_path: &AbsPathBuf,
|
sysroot_path: &AbsPathBuf,
|
||||||
current_dir: &AbsPath,
|
current_dir: &AbsPath,
|
||||||
extra_env: &FxHashMap<String, String>,
|
extra_env: &FxHashMap<String, String>,
|
||||||
) -> Result<AbsPathBuf> {
|
) -> Result<AbsPathBuf> {
|
||||||
if let Ok(path) = env::var("RUST_SRC_PATH") {
|
discover_sysroot_src_dir(sysroot_path)
|
||||||
let path = AbsPathBuf::try_from(path.as_str())
|
|
||||||
.map_err(|path| format_err!("RUST_SRC_PATH must be absolute: {}", path.display()))?;
|
|
||||||
let core = path.join("core");
|
|
||||||
if fs::metadata(&core).is_ok() {
|
|
||||||
tracing::debug!("Discovered sysroot by RUST_SRC_PATH: {}", path.display());
|
|
||||||
return Ok(path);
|
|
||||||
}
|
|
||||||
tracing::debug!("RUST_SRC_PATH is set, but is invalid (no core: {:?}), ignoring", core);
|
|
||||||
}
|
|
||||||
|
|
||||||
get_rust_src(sysroot_path)
|
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
let mut rustup = Command::new(toolchain::rustup());
|
let mut rustup = Command::new(toolchain::rustup());
|
||||||
rustup.envs(extra_env);
|
rustup.envs(extra_env);
|
||||||
|
|
|
@ -188,17 +188,26 @@ impl ProjectWorkspace {
|
||||||
})?;
|
})?;
|
||||||
let cargo = CargoWorkspace::new(meta);
|
let cargo = CargoWorkspace::new(meta);
|
||||||
|
|
||||||
let sysroot = if config.no_sysroot {
|
let sysroot = match &config.sysroot {
|
||||||
None
|
Some(RustcSource::Path(path)) => {
|
||||||
} else {
|
Some(Sysroot::with_sysroot_dir(path.clone()).with_context(|| {
|
||||||
Some(Sysroot::discover(cargo_toml.parent(), &config.extra_env).with_context(
|
|
||||||
|| {
|
|
||||||
format!(
|
format!(
|
||||||
|
"Failed to find sysroot for Cargo.toml file {}.",
|
||||||
|
cargo_toml.display()
|
||||||
|
)
|
||||||
|
})?)
|
||||||
|
}
|
||||||
|
Some(RustcSource::Discover) => Some(
|
||||||
|
Sysroot::discover(cargo_toml.parent(), &config.extra_env).with_context(
|
||||||
|
|| {
|
||||||
|
format!(
|
||||||
"Failed to find sysroot for Cargo.toml file {}. Is rust-src installed?",
|
"Failed to find sysroot for Cargo.toml file {}. Is rust-src installed?",
|
||||||
cargo_toml.display()
|
cargo_toml.display()
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
)?)
|
)?,
|
||||||
|
),
|
||||||
|
None => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let rustc_dir = match &config.rustc_source {
|
let rustc_dir = match &config.rustc_source {
|
||||||
|
|
|
@ -24,7 +24,7 @@ use ide_db::base_db::{
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use oorandom::Rand32;
|
use oorandom::Rand32;
|
||||||
use profile::{Bytes, StopWatch};
|
use profile::{Bytes, StopWatch};
|
||||||
use project_model::{CargoConfig, ProjectManifest, ProjectWorkspace};
|
use project_model::{CargoConfig, ProjectManifest, ProjectWorkspace, RustcSource};
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use rustc_hash::FxHashSet;
|
use rustc_hash::FxHashSet;
|
||||||
use stdx::format_to;
|
use stdx::format_to;
|
||||||
|
@ -55,7 +55,10 @@ impl flags::AnalysisStats {
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut cargo_config = CargoConfig::default();
|
let mut cargo_config = CargoConfig::default();
|
||||||
cargo_config.no_sysroot = self.no_sysroot;
|
cargo_config.sysroot = match self.no_sysroot {
|
||||||
|
true => None,
|
||||||
|
false => Some(RustcSource::Discover),
|
||||||
|
};
|
||||||
let load_cargo_config = LoadCargoConfig {
|
let load_cargo_config = LoadCargoConfig {
|
||||||
load_out_dirs_from_check: !self.disable_build_scripts,
|
load_out_dirs_from_check: !self.disable_build_scripts,
|
||||||
with_proc_macro: !self.disable_proc_macros,
|
with_proc_macro: !self.disable_proc_macros,
|
||||||
|
|
|
@ -94,8 +94,13 @@ config_data! {
|
||||||
cargo_features: CargoFeaturesDef = "[]",
|
cargo_features: CargoFeaturesDef = "[]",
|
||||||
/// Whether to pass `--no-default-features` to cargo.
|
/// Whether to pass `--no-default-features` to cargo.
|
||||||
cargo_noDefaultFeatures: bool = "false",
|
cargo_noDefaultFeatures: bool = "false",
|
||||||
/// Internal config for debugging, disables loading of sysroot crates.
|
/// Relative path to the sysroot, or "discover" to try to automatically find it via
|
||||||
cargo_noSysroot: bool = "false",
|
/// "rustc --print sysroot".
|
||||||
|
///
|
||||||
|
/// Unsetting this disables sysroot loading.
|
||||||
|
///
|
||||||
|
/// This option does not take effect until rust-analyzer is restarted.
|
||||||
|
cargo_sysroot: Option<String> = "\"discover\"",
|
||||||
/// Compilation target override (target triple).
|
/// Compilation target override (target triple).
|
||||||
cargo_target: Option<String> = "null",
|
cargo_target: Option<String> = "null",
|
||||||
/// Unsets `#[cfg(test)]` for the specified crates.
|
/// Unsets `#[cfg(test)]` for the specified crates.
|
||||||
|
@ -1030,6 +1035,13 @@ impl Config {
|
||||||
RustcSource::Path(self.root_path.join(rustc_src))
|
RustcSource::Path(self.root_path.join(rustc_src))
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
let sysroot = self.data.cargo_sysroot.as_ref().map(|sysroot| {
|
||||||
|
if sysroot == "discover" {
|
||||||
|
RustcSource::Discover
|
||||||
|
} else {
|
||||||
|
RustcSource::Path(self.root_path.join(sysroot))
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
CargoConfig {
|
CargoConfig {
|
||||||
features: match &self.data.cargo_features {
|
features: match &self.data.cargo_features {
|
||||||
|
@ -1040,7 +1052,7 @@ impl Config {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
target: self.data.cargo_target.clone(),
|
target: self.data.cargo_target.clone(),
|
||||||
no_sysroot: self.data.cargo_noSysroot,
|
sysroot,
|
||||||
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,
|
||||||
|
|
|
@ -59,7 +59,7 @@ use std::collections::Spam;
|
||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
.with_config(serde_json::json!({
|
.with_config(serde_json::json!({
|
||||||
"cargo": { "noSysroot": false }
|
"cargo": { "sysroot": "discover" }
|
||||||
}))
|
}))
|
||||||
.server()
|
.server()
|
||||||
.wait_until_workspace_is_loaded();
|
.wait_until_workspace_is_loaded();
|
||||||
|
@ -614,7 +614,7 @@ fn main() {{}}
|
||||||
librs, libs
|
librs, libs
|
||||||
))
|
))
|
||||||
.with_config(serde_json::json!({
|
.with_config(serde_json::json!({
|
||||||
"cargo": { "noSysroot": false }
|
"cargo": { "sysroot": "discover" }
|
||||||
}))
|
}))
|
||||||
.server()
|
.server()
|
||||||
.wait_until_workspace_is_loaded();
|
.wait_until_workspace_is_loaded();
|
||||||
|
@ -742,7 +742,7 @@ fn main() {
|
||||||
"buildScripts": {
|
"buildScripts": {
|
||||||
"enable": true
|
"enable": true
|
||||||
},
|
},
|
||||||
"noSysroot": true,
|
"sysroot": null,
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
.server()
|
.server()
|
||||||
|
@ -900,7 +900,7 @@ pub fn foo(_input: TokenStream) -> TokenStream {
|
||||||
"buildScripts": {
|
"buildScripts": {
|
||||||
"enable": true
|
"enable": true
|
||||||
},
|
},
|
||||||
"noSysroot": true,
|
"sysroot": null,
|
||||||
},
|
},
|
||||||
"procMacro": {
|
"procMacro": {
|
||||||
"enable": true,
|
"enable": true,
|
||||||
|
|
|
@ -34,7 +34,7 @@ impl<'a> Project<'a> {
|
||||||
config: serde_json::json!({
|
config: serde_json::json!({
|
||||||
"cargo": {
|
"cargo": {
|
||||||
// Loading standard library is costly, let's ignore it by default
|
// Loading standard library is costly, let's ignore it by default
|
||||||
"noSysroot": true,
|
"sysroot": null,
|
||||||
// Can't use test binary as rustc wrapper.
|
// Can't use test binary as rustc wrapper.
|
||||||
"buildScripts": {
|
"buildScripts": {
|
||||||
"useRustcWrapper": false
|
"useRustcWrapper": false
|
||||||
|
|
|
@ -98,7 +98,7 @@ After I am done with the fix, I use `cargo xtask install --client` to try the ne
|
||||||
If I need to fix something in the `rust-analyzer` crate, I feel sad because it's on the boundary between the two processes, and working there is slow.
|
If I need to fix something in the `rust-analyzer` crate, I feel sad because it's on the boundary between the two processes, and working there is slow.
|
||||||
I usually just `cargo xtask install --server` and poke changes from my live environment.
|
I usually just `cargo xtask install --server` and poke changes from my live environment.
|
||||||
Note that this uses `--release`, which is usually faster overall, because loading stdlib into debug version of rust-analyzer takes a lot of time.
|
Note that this uses `--release`, which is usually faster overall, because loading stdlib into debug version of rust-analyzer takes a lot of time.
|
||||||
To speed things up, sometimes I open a temporary hello-world project which has `"rust-analyzer.cargo.noSysroot": true` in `.code/settings.json`.
|
To speed things up, sometimes I open a temporary hello-world project which has `"rust-analyzer.cargo.sysroot": null` in `.code/settings.json`.
|
||||||
This flag causes rust-analyzer to skip loading the sysroot, which greatly reduces the amount of things rust-analyzer needs to do, and makes printf's more useful.
|
This flag causes rust-analyzer to skip loading the sysroot, which greatly reduces the amount of things rust-analyzer needs to do, and makes printf's more useful.
|
||||||
Note that you should only use the `eprint!` family of macros for debugging: stdout is used for LSP communication, and `print!` would break it.
|
Note that you should only use the `eprint!` family of macros for debugging: stdout is used for LSP communication, and `print!` would break it.
|
||||||
|
|
||||||
|
|
|
@ -64,10 +64,15 @@ Set this to `"all"` to pass `--all-features` to cargo.
|
||||||
--
|
--
|
||||||
Whether to pass `--no-default-features` to cargo.
|
Whether to pass `--no-default-features` to cargo.
|
||||||
--
|
--
|
||||||
[[rust-analyzer.cargo.noSysroot]]rust-analyzer.cargo.noSysroot (default: `false`)::
|
[[rust-analyzer.cargo.sysroot]]rust-analyzer.cargo.sysroot (default: `"discover"`)::
|
||||||
+
|
+
|
||||||
--
|
--
|
||||||
Internal config for debugging, disables loading of sysroot crates.
|
Relative path to the sysroot, or "discover" to try to automatically find it via
|
||||||
|
"rustc --print sysroot".
|
||||||
|
|
||||||
|
Unsetting this disables sysroot loading.
|
||||||
|
|
||||||
|
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`)::
|
||||||
+
|
+
|
||||||
|
|
|
@ -468,10 +468,13 @@
|
||||||
"default": false,
|
"default": false,
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"rust-analyzer.cargo.noSysroot": {
|
"rust-analyzer.cargo.sysroot": {
|
||||||
"markdownDescription": "Internal config for debugging, disables loading of sysroot crates.",
|
"markdownDescription": "Relative path to the sysroot, or \"discover\" to try to automatically find it via\n\"rustc --print sysroot\".\n\nUnsetting this disables sysroot loading.\n\nThis option does not take effect until rust-analyzer is restarted.",
|
||||||
"default": false,
|
"default": "discover",
|
||||||
"type": "boolean"
|
"type": [
|
||||||
|
"null",
|
||||||
|
"string"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"rust-analyzer.cargo.target": {
|
"rust-analyzer.cargo.target": {
|
||||||
"markdownDescription": "Compilation target override (target triple).",
|
"markdownDescription": "Compilation target override (target triple).",
|
||||||
|
|
Loading…
Reference in a new issue