Skip to content

Commit

Permalink
Merge #7643 #7663
Browse files Browse the repository at this point in the history
7643: Automatically detect the rustc-src directory (fixes #3517) r=matklad a=bnjbvr

If the configured rustcSource was not set, then try to automatically
detect a source for the sysroot rustc directory.

I wasn't sure how to do it in the case of the project.json file, though.

7663: Tolerate spaces in nix binary patching r=matklad a=CertainLach

If path to original file contains space (I.e on code insiders, where
default data directory is ~/Code - Insiders/), then there is syntax
error evaluating src arg.

Instead pass path as str, and coerce to path back in nix expression

Co-authored-by: Benjamin Bouvier <[email protected]>
Co-authored-by: Yaroslav Bolyukin <[email protected]>
  • Loading branch information
3 people authored Feb 14, 2021
3 parents 63c5c92 + 4a6e602 + 471795b commit d50a37d
Show file tree
Hide file tree
Showing 8 changed files with 70 additions and 23 deletions.
11 changes: 10 additions & 1 deletion crates/project_model/src/cargo_workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,15 @@ impl ops::Index<Target> for CargoWorkspace {
}
}

/// Describes how to set the rustc source directory.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum RustcSource {
/// Explicit path for the rustc source directory.
Path(AbsPathBuf),
/// Try to automatically detect where the rustc source directory is.
Discover,
}

#[derive(Default, Clone, Debug, PartialEq, Eq)]
pub struct CargoConfig {
/// Do not activate the `default` feature.
Expand All @@ -64,7 +73,7 @@ pub struct CargoConfig {
pub no_sysroot: bool,

/// rustc private crate source
pub rustc_source: Option<AbsPathBuf>,
pub rustc_source: Option<RustcSource>,
}

pub type Package = Idx<PackageData>;
Expand Down
4 changes: 2 additions & 2 deletions crates/project_model/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ use rustc_hash::FxHashSet;
pub use crate::{
build_data::{BuildDataCollector, BuildDataResult},
cargo_workspace::{
CargoConfig, CargoWorkspace, Package, PackageData, PackageDependency, Target, TargetData,
TargetKind,
CargoConfig, CargoWorkspace, Package, PackageData, PackageDependency, RustcSource, Target,
TargetData, TargetKind,
},
project_json::{ProjectJson, ProjectJsonData},
sysroot::Sysroot,
Expand Down
40 changes: 30 additions & 10 deletions crates/project_model/src/sysroot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,18 @@ impl Sysroot {
pub fn discover(cargo_toml: &AbsPath) -> Result<Sysroot> {
log::debug!("Discovering sysroot for {}", cargo_toml.display());
let current_dir = cargo_toml.parent().unwrap();
let sysroot_src_dir = discover_sysroot_src_dir(current_dir)?;
let sysroot_dir = discover_sysroot_dir(current_dir)?;
let sysroot_src_dir = discover_sysroot_src_dir(&sysroot_dir, current_dir)?;
let res = Sysroot::load(&sysroot_src_dir)?;
Ok(res)
}

pub fn discover_rustc(cargo_toml: &AbsPath) -> Option<AbsPathBuf> {
log::debug!("Discovering rustc source for {}", cargo_toml.display());
let current_dir = cargo_toml.parent().unwrap();
discover_sysroot_dir(current_dir).ok().and_then(|sysroot_dir| get_rustc_src(&sysroot_dir))
}

pub fn load(sysroot_src_dir: &AbsPath) -> Result<Sysroot> {
let mut sysroot = Sysroot { crates: Arena::default() };

Expand Down Expand Up @@ -110,7 +117,18 @@ impl Sysroot {
}
}

fn discover_sysroot_src_dir(current_dir: &AbsPath) -> Result<AbsPathBuf> {
fn discover_sysroot_dir(current_dir: &AbsPath) -> Result<AbsPathBuf> {
let mut rustc = Command::new(toolchain::rustc());
rustc.current_dir(current_dir).args(&["--print", "sysroot"]);
log::debug!("Discovering sysroot by {:?}", rustc);
let stdout = utf8_stdout(rustc)?;
Ok(AbsPathBuf::assert(PathBuf::from(stdout)))
}

fn discover_sysroot_src_dir(
sysroot_path: &AbsPathBuf,
current_dir: &AbsPath,
) -> Result<AbsPathBuf> {
if let Ok(path) = env::var("RUST_SRC_PATH") {
let path = AbsPathBuf::try_from(path.as_str())
.map_err(|path| format_err!("RUST_SRC_PATH must be absolute: {}", path.display()))?;
Expand All @@ -122,14 +140,6 @@ fn discover_sysroot_src_dir(current_dir: &AbsPath) -> Result<AbsPathBuf> {
log::debug!("RUST_SRC_PATH is set, but is invalid (no core: {:?}), ignoring", core);
}

let sysroot_path = {
let mut rustc = Command::new(toolchain::rustc());
rustc.current_dir(current_dir).args(&["--print", "sysroot"]);
log::debug!("Discovering sysroot by {:?}", rustc);
let stdout = utf8_stdout(rustc)?;
AbsPathBuf::assert(PathBuf::from(stdout))
};

get_rust_src(&sysroot_path)
.or_else(|| {
let mut rustup = Command::new(toolchain::rustup());
Expand All @@ -149,6 +159,16 @@ try installing the Rust source the same way you installed rustc",
})
}

fn get_rustc_src(sysroot_path: &AbsPath) -> Option<AbsPathBuf> {
let rustc_src = sysroot_path.join("lib/rustlib/rustc-src/rust/compiler/rustc/Cargo.toml");
log::debug!("Checking for rustc source code: {}", rustc_src.display());
if rustc_src.exists() {
Some(rustc_src)
} else {
None
}
}

fn get_rust_src(sysroot_path: &AbsPath) -> Option<AbsPathBuf> {
// Try the new path first since the old one still exists.
let rust_src = sysroot_path.join("lib/rustlib/src/rust");
Expand Down
13 changes: 12 additions & 1 deletion crates/project_model/src/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ impl ProjectWorkspace {
cargo_version
)
})?;

let sysroot = if config.no_sysroot {
Sysroot::default()
} else {
Expand All @@ -125,7 +126,17 @@ impl ProjectWorkspace {
})?
};

let rustc = if let Some(rustc_dir) = &config.rustc_source {
let rustc_dir = if let Some(rustc_source) = &config.rustc_source {
use cargo_workspace::RustcSource;
match rustc_source {
RustcSource::Path(path) => Some(path.clone()),
RustcSource::Discover => Sysroot::discover_rustc(&cargo_toml),
}
} else {
None
};

let rustc = if let Some(rustc_dir) = rustc_dir {
Some(
CargoWorkspace::from_cargo_metadata(&rustc_dir, config, progress)
.with_context(|| {
Expand Down
15 changes: 11 additions & 4 deletions crates/rust-analyzer/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use ide_db::helpers::{
};
use itertools::Itertools;
use lsp_types::{ClientCapabilities, MarkupKind};
use project_model::{CargoConfig, ProjectJson, ProjectJsonData, ProjectManifest};
use project_model::{CargoConfig, ProjectJson, ProjectJsonData, ProjectManifest, RustcSource};
use rustc_hash::FxHashSet;
use serde::{de::DeserializeOwned, Deserialize};
use vfs::AbsPathBuf;
Expand Down Expand Up @@ -177,8 +177,9 @@ config_data! {
/// tests or binaries.\nFor example, it may be `--release`.
runnables_cargoExtraArgs: Vec<String> = "[]",

/// Path to the rust compiler sources, for usage in rustc_private projects.
rustcSource : Option<PathBuf> = "null",
/// Path to the rust compiler sources, for usage in rustc_private projects, or "discover"
/// to try to automatically find it.
rustcSource : Option<String> = "null",

/// Additional arguments to `rustfmt`.
rustfmt_extraArgs: Vec<String> = "[]",
Expand Down Expand Up @@ -473,7 +474,13 @@ impl Config {
self.data.cargo_loadOutDirsFromCheck
}
pub fn cargo(&self) -> CargoConfig {
let rustc_source = self.data.rustcSource.as_ref().map(|it| self.root_path.join(&it));
let rustc_source = self.data.rustcSource.as_ref().map(|rustc_src| {
if rustc_src == "discover" {
RustcSource::Discover
} else {
RustcSource::Path(self.root_path.join(rustc_src))
}
});

CargoConfig {
no_default_features: self.data.cargo_noDefaultFeatures,
Expand Down
2 changes: 1 addition & 1 deletion docs/user/generated_config.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@
[[rust-analyzer.runnables.cargoExtraArgs]]rust-analyzer.runnables.cargoExtraArgs (default: `[]`)::
Additional arguments to be passed to cargo for runnables such as tests or binaries.\nFor example, it may be `--release`.
[[rust-analyzer.rustcSource]]rust-analyzer.rustcSource (default: `null`)::
Path to the rust compiler sources, for usage in rustc_private projects.
Path to the rust compiler sources, for usage in rustc_private projects, or "discover" to try to automatically find it.
[[rust-analyzer.rustfmt.extraArgs]]rust-analyzer.rustfmt.extraArgs (default: `[]`)::
Additional arguments to `rustfmt`.
[[rust-analyzer.rustfmt.overrideCommand]]rust-analyzer.rustfmt.overrideCommand (default: `null`)::
Expand Down
2 changes: 1 addition & 1 deletion editors/code/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -707,7 +707,7 @@
}
},
"rust-analyzer.rustcSource": {
"markdownDescription": "Path to the rust compiler sources, for usage in rustc_private projects.",
"markdownDescription": "Path to the rust compiler sources, for usage in rustc_private projects, or \"discover\" to try to automatically find it.",
"default": null,
"type": [
"null",
Expand Down
6 changes: 3 additions & 3 deletions editors/code/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,10 +246,10 @@ async function patchelf(dest: PathLike): Promise<void> {
},
async (progress, _) => {
const expression = `
{src, pkgs ? import <nixpkgs> {}}:
{srcStr, pkgs ? import <nixpkgs> {}}:
pkgs.stdenv.mkDerivation {
name = "rust-analyzer";
inherit src;
src = /. + srcStr;
phases = [ "installPhase" "fixupPhase" ];
installPhase = "cp $src $out";
fixupPhase = ''
Expand All @@ -262,7 +262,7 @@ async function patchelf(dest: PathLike): Promise<void> {
await fs.rename(dest, origFile);
progress.report({ message: "Patching executable", increment: 20 });
await new Promise((resolve, reject) => {
const handle = exec(`nix-build -E - --arg src '${origFile}' -o ${dest}`,
const handle = exec(`nix-build -E - --argstr srcStr '${origFile}' -o '${dest}'`,
(err, stdout, stderr) => {
if (err != null) {
reject(Error(stderr));
Expand Down

0 comments on commit d50a37d

Please sign in to comment.