diff --git a/.gitmodules b/.gitmodules index a9210cfc69e..5c0ab737f63 100644 --- a/.gitmodules +++ b/.gitmodules @@ -41,3 +41,6 @@ [submodule "src/doc/embedded-book"] path = src/doc/embedded-book url = https://github.com/rust-embedded/book.git +[submodule "src/tools/rust-analyzer"] + path = src/tools/rust-analyzer + url = https://github.com/rust-analyzer/rust-analyzer.git diff --git a/rustfmt.toml b/rustfmt.toml index 9b2c0820036..c76a75fa07b 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -27,6 +27,7 @@ ignore = [ "src/tools/clippy", "src/tools/miri", "src/tools/rls", + "src/tools/rust-analyzer", "src/tools/rust-installer", "src/tools/rustfmt", diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 1949d70e5de..1dfa635c694 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -869,7 +869,7 @@ class RustBuild(object): # the rust git repository is updated. Normal development usually does # not use vendoring, so hopefully this isn't too much of a problem. if self.use_vendored_sources and not os.path.exists(vendor_dir): - run([self.cargo(), "vendor"], + run([self.cargo(), "vendor", "--sync=./src/tools/rust-analyzer/Cargo.toml"], verbose=self.verbose, cwd=self.rust_root) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index f9403260f77..3cbecbbaa06 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -368,6 +368,7 @@ macro_rules! describe { tool::RustInstaller, tool::Cargo, tool::Rls, + tool::RustAnalyzer, tool::Rustdoc, tool::Clippy, tool::CargoClippy, @@ -462,6 +463,7 @@ macro_rules! describe { dist::PlainSourceTarball, dist::Cargo, dist::Rls, + dist::RustAnalyzer, dist::Rustfmt, dist::Clippy, dist::Miri, @@ -474,6 +476,7 @@ macro_rules! describe { install::Std, install::Cargo, install::Rls, + install::RustAnalyzer, install::Rustfmt, install::Clippy, install::Miri, diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 28430b56ee5..5d2fcba7fea 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -30,6 +30,8 @@ pub fn pkgname(builder: &Builder<'_>, component: &str) -> String { format!("{}-{}", component, builder.cargo_package_vers()) } else if component == "rls" { format!("{}-{}", component, builder.rls_package_vers()) + } else if component == "rust-analyzer" { + format!("{}-{}", component, builder.rust_analyzer_package_vers()) } else if component == "clippy" { format!("{}-{}", component, builder.clippy_package_vers()) } else if component == "miri" { @@ -1107,7 +1109,10 @@ fn run(self, builder: &Builder<'_>) -> PathBuf { if builder.rust_info.is_git() { // Vendor all Cargo dependencies let mut cmd = Command::new(&builder.initial_cargo); - cmd.arg("vendor").current_dir(&plain_dst_src); + cmd.arg("vendor") + .arg("--sync") + .arg(builder.src.join("./src/tools/rust-analyzer/Cargo.toml")) + .current_dir(&plain_dst_src); builder.run(&mut cmd); } @@ -1337,6 +1342,93 @@ fn run(self, builder: &Builder<'_>) -> Option { } } +#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] +pub struct RustAnalyzer { + pub compiler: Compiler, + pub target: Interned, +} + +impl Step for RustAnalyzer { + type Output = PathBuf; + const ONLY_HOSTS: bool = true; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.path("rust-analyzer") + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(RustAnalyzer { + compiler: run.builder.compiler_for( + run.builder.top_stage, + run.builder.config.build, + run.target, + ), + target: run.target, + }); + } + + fn run(self, builder: &Builder<'_>) -> PathBuf { + let compiler = self.compiler; + let target = self.target; + assert!(builder.config.extended); + + let src = builder.src.join("src/tools/rust-analyzer"); + let release_num = builder.release_num("rust-analyzer/crates/rust-analyzer"); + let name = pkgname(builder, "rust-analyzer"); + let version = builder.rust_analyzer_info.version(builder, &release_num); + + let tmp = tmpdir(builder); + let image = tmp.join("rust-analyzer-image"); + drop(fs::remove_dir_all(&image)); + builder.create_dir(&image); + + // Prepare the image directory + // We expect rust-analyer to always build, as it doesn't depend on rustc internals + // and doesn't have associated toolstate. + let rust_analyzer = builder + .ensure(tool::RustAnalyzer { compiler, target, extra_features: Vec::new() }) + .expect("rust-analyzer always builds"); + + builder.install(&rust_analyzer, &image.join("bin"), 0o755); + let doc = image.join("share/doc/rust-analyzer"); + builder.install(&src.join("README.md"), &doc, 0o644); + builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644); + builder.install(&src.join("LICENSE-MIT"), &doc, 0o644); + + // Prepare the overlay + let overlay = tmp.join("rust-analyzer-overlay"); + drop(fs::remove_dir_all(&overlay)); + t!(fs::create_dir_all(&overlay)); + builder.install(&src.join("README.md"), &overlay, 0o644); + builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644); + builder.install(&src.join("LICENSE-MIT"), &doc, 0o644); + builder.create(&overlay.join("version"), &version); + + // Generate the installer tarball + let mut cmd = rust_installer(builder); + cmd.arg("generate") + .arg("--product-name=Rust") + .arg("--rel-manifest-dir=rustlib") + .arg("--success-message=rust-analyzer-ready-to-serve.") + .arg("--image-dir") + .arg(&image) + .arg("--work-dir") + .arg(&tmpdir(builder)) + .arg("--output-dir") + .arg(&distdir(builder)) + .arg("--non-installed-overlay") + .arg(&overlay) + .arg(format!("--package-name={}-{}", name, target)) + .arg("--legacy-manifest-dirs=rustlib,cargo") + .arg("--component-name=rust-analyzer-preview"); + + builder.info(&format!("Dist rust-analyzer stage{} ({})", compiler.stage, target)); + let _time = timeit(builder); + builder.run(&mut cmd); + distdir(builder).join(format!("{}-{}.tar.gz", name, target)) + } +} + #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] pub struct Clippy { pub compiler: Compiler, @@ -1656,6 +1748,7 @@ fn run(self, builder: &Builder<'_>) { let cargo_installer = builder.ensure(Cargo { compiler, target }); let rustfmt_installer = builder.ensure(Rustfmt { compiler, target }); let rls_installer = builder.ensure(Rls { compiler, target }); + let rust_analyzer_installer = builder.ensure(RustAnalyzer { compiler, target }); let llvm_tools_installer = builder.ensure(LlvmTools { target }); let clippy_installer = builder.ensure(Clippy { compiler, target }); let miri_installer = builder.ensure(Miri { compiler, target }); @@ -1690,6 +1783,7 @@ fn run(self, builder: &Builder<'_>) { tarballs.push(rustc_installer); tarballs.push(cargo_installer); tarballs.extend(rls_installer.clone()); + tarballs.push(rust_analyzer_installer.clone()); tarballs.push(clippy_installer); tarballs.extend(miri_installer.clone()); tarballs.extend(rustfmt_installer.clone()); @@ -1767,6 +1861,7 @@ fn filter(contents: &str, marker: &str) -> String { if rls_installer.is_none() { contents = filter(&contents, "rls"); } + contents = filter(&contents, "rust-analyzer"); if miri_installer.is_none() { contents = filter(&contents, "miri"); } @@ -1813,6 +1908,7 @@ fn filter(contents: &str, marker: &str) -> String { if rls_installer.is_some() { prepare("rls"); } + prepare("rust-analyzer"); if miri_installer.is_some() { prepare("miri"); } @@ -1846,6 +1942,8 @@ fn filter(contents: &str, marker: &str) -> String { format!("{}-{}", name, target) } else if name == "rls" { "rls-preview".to_string() + } else if name == "rust-analyzer" { + "rust-analyzer-preview".to_string() } else if name == "clippy" { "clippy-preview".to_string() } else if name == "miri" { @@ -1868,6 +1966,7 @@ fn filter(contents: &str, marker: &str) -> String { if rls_installer.is_some() { prepare("rls"); } + prepare("rust-analyzer"); if miri_installer.is_some() { prepare("miri"); } @@ -1967,6 +2066,23 @@ fn filter(contents: &str, marker: &str) -> String { .arg(etc.join("msi/remove-duplicates.xsl")), ); } + builder.run( + Command::new(&heat) + .current_dir(&exe) + .arg("dir") + .arg("rust-analyzer") + .args(&heat_flags) + .arg("-cg") + .arg("RustAnalyzerGroup") + .arg("-dr") + .arg("RustAnalyzer") + .arg("-var") + .arg("var.RustAnalyzerDir") + .arg("-out") + .arg(exe.join("RustAnalyzerGroup.wxs")) + .arg("-t") + .arg(etc.join("msi/remove-duplicates.xsl")), + ); builder.run( Command::new(&heat) .current_dir(&exe) @@ -2060,6 +2176,7 @@ fn filter(contents: &str, marker: &str) -> String { if rls_installer.is_some() { cmd.arg("-dRlsDir=rls"); } + cmd.arg("-dRustAnalyzerDir=rust-analyzer"); if miri_installer.is_some() { cmd.arg("-dMiriDir=miri"); } @@ -2079,6 +2196,7 @@ fn filter(contents: &str, marker: &str) -> String { if rls_installer.is_some() { candle("RlsGroup.wxs".as_ref()); } + candle("RustAnalyzerGroup.wxs".as_ref()); if miri_installer.is_some() { candle("MiriGroup.wxs".as_ref()); } @@ -2116,6 +2234,7 @@ fn filter(contents: &str, marker: &str) -> String { if rls_installer.is_some() { cmd.arg("RlsGroup.wixobj"); } + cmd.arg("RustAnalyzerGroup.wixobj"); if miri_installer.is_some() { cmd.arg("MiriGroup.wixobj"); } @@ -2209,6 +2328,7 @@ fn run(self, builder: &Builder<'_>) { cmd.arg(addr); cmd.arg(builder.package_vers(&builder.release_num("cargo"))); cmd.arg(builder.package_vers(&builder.release_num("rls"))); + cmd.arg(builder.package_vers(&builder.release_num("rust-analyzer/crates/rust-analyzer"))); cmd.arg(builder.package_vers(&builder.release_num("clippy"))); cmd.arg(builder.package_vers(&builder.release_num("miri"))); cmd.arg(builder.package_vers(&builder.release_num("rustfmt"))); diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index fbdef9d8272..7026b25d1b9 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -32,6 +32,9 @@ pub fn install_cargo(builder: &Builder<'_>, stage: u32, host: Interned) pub fn install_rls(builder: &Builder<'_>, stage: u32, host: Interned) { install_sh(builder, "rls", "rls", stage, Some(host)); } +pub fn install_rust_analyzer(builder: &Builder<'_>, stage: u32, host: Interned) { + install_sh(builder, "rust-analyzer", "rust-analyzer", stage, Some(host)); +} pub fn install_clippy(builder: &Builder<'_>, stage: u32, host: Interned) { install_sh(builder, "clippy", "clippy", stage, Some(host)); } @@ -216,6 +219,16 @@ fn run($sel, $builder: &Builder<'_>) { ); } }; + RustAnalyzer, "rust-analyzer", Self::should_build(_config), only_hosts: true, { + builder.ensure(dist::RustAnalyzer { compiler: self.compiler, target: self.target }); + if Self::should_install(builder) { + install_rust_analyzer(builder, self.compiler.stage, self.target); + } else { + builder.info( + &format!("skipping Install rust-analyzer stage{} ({})", self.compiler.stage, self.target), + ); + } + }; Clippy, "clippy", Self::should_build(_config), only_hosts: true, { builder.ensure(dist::Clippy { compiler: self.compiler, target: self.target }); if Self::should_install(builder) { diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index b611af54565..b9738894486 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -225,6 +225,7 @@ pub struct Build { rust_info: channel::GitInfo, cargo_info: channel::GitInfo, rls_info: channel::GitInfo, + rust_analyzer_info: channel::GitInfo, clippy_info: channel::GitInfo, miri_info: channel::GitInfo, rustfmt_info: channel::GitInfo, @@ -349,6 +350,8 @@ pub fn new(config: Config) -> Build { let rust_info = channel::GitInfo::new(ignore_git, &src); let cargo_info = channel::GitInfo::new(ignore_git, &src.join("src/tools/cargo")); let rls_info = channel::GitInfo::new(ignore_git, &src.join("src/tools/rls")); + let rust_analyzer_info = + channel::GitInfo::new(ignore_git, &src.join("src/tools/rust-analyzer")); let clippy_info = channel::GitInfo::new(ignore_git, &src.join("src/tools/clippy")); let miri_info = channel::GitInfo::new(ignore_git, &src.join("src/tools/miri")); let rustfmt_info = channel::GitInfo::new(ignore_git, &src.join("src/tools/rustfmt")); @@ -405,6 +408,7 @@ pub fn new(config: Config) -> Build { rust_info, cargo_info, rls_info, + rust_analyzer_info, clippy_info, miri_info, rustfmt_info, @@ -1034,6 +1038,11 @@ fn rls_package_vers(&self) -> String { self.package_vers(&self.release_num("rls")) } + /// Returns the value of `package_vers` above for rust-analyzer + fn rust_analyzer_package_vers(&self) -> String { + self.package_vers(&self.release_num("rust-analyzer/crates/rust-analyzer")) + } + /// Returns the value of `package_vers` above for clippy fn clippy_package_vers(&self) -> String { self.package_vers(&self.release_num("clippy")) diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 45f5073f431..450b534d5df 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -641,7 +641,7 @@ fn run(mut $sel, $builder: &Builder<'_>) -> Option { } } -// Note: tools need to be also added to `Builder::get_step_descriptions` in `build.rs` +// Note: tools need to be also added to `Builder::get_step_descriptions` in `builder.rs` // to make `./x.py build ` work. tool_extended!((self, builder), Cargofmt, rustfmt, "src/tools/rustfmt", "cargo-fmt", stable=true, {}; @@ -658,6 +658,7 @@ fn run(mut $sel, $builder: &Builder<'_>) -> Option { self.extra_features.push("clippy".to_owned()); }; Rustfmt, rustfmt, "src/tools/rustfmt", "rustfmt", stable=true, {}; + RustAnalyzer, rust_analyzer, "src/tools/rust-analyzer/crates/rust-analyzer", "rust-analyzer", stable=false, {}; ); impl<'a> Builder<'a> { diff --git a/src/tools/rust-analyzer b/src/tools/rust-analyzer new file mode 160000 index 00000000000..f5a4a4b46e7 --- /dev/null +++ b/src/tools/rust-analyzer @@ -0,0 +1 @@ +Subproject commit f5a4a4b46e706697abe4bd136503ecc09aa23b61 diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index be1e598d8d4..b4aafb815fc 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -56,6 +56,7 @@ fn filter_dirs(path: &Path) -> bool { "src/tools/clippy", "src/tools/miri", "src/tools/rls", + "src/tools/rust-analyzer", "src/tools/rust-installer", "src/tools/rustfmt", "src/doc/book",