Change:
I manage to successfully build the latest master revision of rustc, but then when I try to build it incrementally as , I get the following error. Apparently, this is broken for others as well, as has been for a while.
Stopgap: helps you get to a good state.
Yeah I know, but then I have to compile from scratch, and it takes forever. :-(
I think I see one way this happens. I think the issue is that  only knows about one output directory, but it does not consider the host directory (for stage1) where proc-macros and build scripts are located. Here is one way to repro this: a change to libstd that will modify the SVH. I a module, but there's probably an easier way. a proc macro to get rebuilt: The last step should fail in stage1 to build because one of its dependencies () was compiled with an older libstd, but itself was not rebuilt. I think the solution is to clear the host directory, although care should be taken so it is not cleared multiple times if there are multiple targets. I'm not super familiar with rustbuild, but maybe or know more about this. One way to get this particular example back on track is to . Some similar issues: , EDIT: Other things like codegen have to be cleaned out too, like .
Do you know who works on incremental compilation in the compiler team? This seems like a pretty high-priority bug, so maybe we should tag them. :-)
I believe and have been involved with incremental compilation at one point or another.
Based on the error message, this likely has nothing to do with the compiler -- it's most likely purely a problem inside rustbuild (i.e., rustbuild is broken).
Yea, this is only related to rustbuild. The issue is that cargo does not track libstd as a dependency, so rustbuild needs to be careful to force rebuilding of crates when libstd changes. It does that currently (via ), but it is missing the directory for proc-macros and build scripts.
Ah okay. So it should be quite a straightforward fix for someone who knows how rustbuild works, eh?
Actually quite difficult, but yes, in theory it's a fairly easy fix.
triage: leaving I-nominated for discussion of prioritization at T-compiler meeting itself. (My personal inclination is to assign this P-medium priority, and if no one takes it on at the meeting or shortly thereafter, I may self-assign.)
discussed at T-compiler meeting. Assigning P-medium priority, since this is essentially an internal tooling issue that we would like to fix, but does not take precedence over customer P-high matters.
Sounds reasonable enough. It's probably P-high by rustc developer standards, but when you consider the scale has to include end-users too, P-medium makes more sense.
Currently I'm not able to build the Rust project. Even running in the project root the run (with latest commits from GitHub). I received this error: EDIT: It might be related that I'm setting . <details<summaryFull stdout when running </summaryrust % check Updating only changed submodules Submodules updated in 0.04 seconds downloading extracting downloading extracting downloading extracting Compiling proc-macro2 v0.4.24 Compiling unicode-xid v0.1.0 Compiling ryu v0.2.7 Compiling libc v0.2.51 Compiling serde v1.0.82 Compiling itoa v0.4.3 Compiling fixedbitset v0.1.9 Compiling cc v1.0.28 Compiling cfg-if v0.1.6 Compiling ordermap v0.3.5 Compiling buildhelper v0.1.0 () Compiling lazystatic v0.2.11 Compiling getopts v0.2.17 Compiling cmake v0.1.33 Compiling petgraph v0.4.13 Compiling quote v0.6.10 Compiling numcpus v1.8.0 Compiling filetime v0.2.4 Compiling time v0.1.40 Compiling serdejson v1.0.33 Compiling toml v0.4.10 Compiling syn v0.15.22 Compiling serdederive v1.0.81 Compiling bootstrap v0.0.0 () Finished dev [unoptimized] target(s) in 1m 28s Checking rustdoc artifacts (x8664-unknown-linux-gnu -x8664-unknown-linux-gnu) Checking std artifacts (x8664-unknown-linux-gnu -x8664-unknown-linux-gnu) Compiling cc v1.0.28 Checking core v0.0.0 () Compiling libc v0.2.51 Compiling unwind v0.0.0 () Compiling buildhelper v0.1.0 () Compiling compilerbuiltins v0.1.8 Compiling cmake v0.1.33 Compiling backtrace-sys v0.1.27 Compiling std v0.0.0 () Checking rustc-std-workspace-core v1.0.0 () Compiling rustcasan v0.0.0 () Compiling rustclsan v0.0.0 () Compiling rustctsan v0.0.0 () Compiling rustcmsan v0.0.0 () Checking alloc v0.0.0 () Checking rustc-demangle v0.1.10 Checking panicabort v0.0.0 () Checking panicunwind v0.0.0 () Finished release [optimized] target(s) in 32.12s Checking test artifacts (x8664-unknown-linux-gnu -x8664-unknown-linux-gnu) Checking rustcterm v0.0.1 Checking getopts v0.2.17 Checking procmacro v0.0.0 () Checking libtest v0.0.1 error[E0460]: found possibly newer version of crate which depends onest -- | 34 | use getopts; | ^^^^^^^ | = note: perhaps that crate needs to be recompiled? = note: the following crate versions were found: crate : crate : error: aborting due to previous error For more information about this error, try . error: Could not compile . To learn more, run the command again with --verbose. command did not execute successfully: "" "check" "--target" "x86_64-unknown-linux-gnu" "-j" "1" "--release" "--manifest-path" "" "--message-format" "json" expected success, got: exit code: 101 failed to run: check Build completed unsuccessfully in 0:02:23 </details
I get this error with . However, worked. The output of the build command follows. My first build was done from a new cloned repo on an empty directory. The first build command was:
Any progress on this lately? Did you want to self-assign?
Just bumped onto this with , even after :

Discussion:
let mut cargo = Command::new(&self.initial_cargo); let out_dir = self.stage_out(compiler, mode); <del> // command specific path, we call clear_if_dirty with this let mut my_out = match cmd { "build" => self.cargo_out(compiler, mode, target), // This is the intended out directory for crate documentation. "doc" | "rustdoc" =>  self.crate_doc_out(target), _ => self.stage_out(compiler, mode), }; // This is for the original compiler, but if we're forced to use stage 1, then // std/test/rustc stamps won't exist in stage 2, so we need to get those from stage 1, since // we copy the libs forward. let cmp = self.compiler_for(compiler.stage, compiler.host, target); let libstd_stamp = match cmd { "check" | "clippy" | "fix" => check::libstd_stamp(self, cmp, target), _ => compile::libstd_stamp(self, cmp, target), }; let libtest_stamp = match cmd { "check" | "clippy" | "fix" => check::libtest_stamp(self, cmp, target), _ => compile::libtest_stamp(self, cmp, target), }; let librustc_stamp = match cmd { "check" | "clippy" | "fix" => check::librustc_stamp(self, cmp, target), _ => compile::librustc_stamp(self, cmp, target), }; </del> <ins> // Codegen backends are not yet tracked by -Zbinary-dep-depinfo, // so we need to explicitly clear out if they've been updated. for backend in self.codegen_backends(compiler) { self.clear_if_dirty(&out_dir, &backend); } </ins> if cmd == "doc" || cmd == "rustdoc" { <del> if mode == Mode::Rustc || mode == Mode::ToolRustc || mode == Mode::Codegen { </del> <ins> let my_out = match mode { </ins> // This is the intended out directory for compiler documentation. <del> my_out = self.compiler_doc_out(target); } </del> <ins> Mode::Rustc | Mode::ToolRustc | Mode::Codegen => self.compiler_doc_out(target), _ => self.crate_doc_out(target), }; </ins> let rustdoc = self.rustdoc(compiler); self.clear_if_dirty(&my_out, &rustdoc); <del> } else if cmd != "test" { match mode { Mode::Std => { self.clear_if_dirty(&my_out, &self.rustc(compiler)); for backend in self.codegen_backends(compiler) { self.clear_if_dirty(&my_out, &backend); } }, Mode::Test => { self.clear_if_dirty(&my_out, &libstd_stamp); }, Mode::Rustc => { self.clear_if_dirty(&my_out, &self.rustc(compiler)); self.clear_if_dirty(&my_out, &libstd_stamp); self.clear_if_dirty(&my_out, &libtest_stamp); }, Mode::Codegen => { self.clear_if_dirty(&my_out, &librustc_stamp); }, Mode::ToolBootstrap => { }, Mode::ToolStd => { self.clear_if_dirty(&my_out, &libstd_stamp); }, Mode::ToolTest => { self.clear_if_dirty(&my_out, &libstd_stamp); self.clear_if_dirty(&my_out, &libtest_stamp); }, Mode::ToolRustc => { self.clear_if_dirty(&my_out, &libstd_stamp); self.clear_if_dirty(&my_out, &libtest_stamp); self.clear_if_dirty(&my_out, &librustc_stamp); }, } </del> } cargo

}, } <ins> // This tells Cargo (and in turn, rustc) to output more complete // dependency information.  Most importantly for rustbuild, this // includes sysroot artifacts, like libstd, which means that we don't // need to track those in rustbuild (an error prone process!). This // feature is currently unstable as there may be some bugs and such, but // it represents a big improvement in rustbuild's reliability on // rebuilds, so we're using it here. // // For some additional context, see #63470 (the PR originally adding // this), as well as #63012 which is the tracking issue for this // feature on the rustc side. cargo.arg("-Zbinary-dep-depinfo"); </ins> cargo.arg("-j").arg(self.jobs().to_string()); // Remove make-related flags to ensure Cargo can correctly set things up cargo.env_remove("MAKEFLAGS");

let libdir = builder.sysroot_libdir(compiler, target); let hostdir = builder.sysroot_libdir(compiler, compiler.host); add_to_sysroot(&builder, &libdir, &hostdir, &rustdoc_stamp(builder, compiler, target)); <del> builder.cargo(compiler, Mode::ToolRustc, target, "clean"); </del> } }

use std::process::{Command, Stdio, exit}; use std::str; <del> use build_helper::{output, mtime, t, up_to_date}; </del> <ins> use build_helper::{output, t, up_to_date}; </ins> use filetime::FileTime; use serde::Deserialize; use serde_json;

// for reason why the sanitizers are not built in stage0. copy_apple_sanitizer_dylibs(builder, &builder.native_dir(target), "osx", &libdir); } <del> builder.cargo(target_compiler, Mode::ToolStd, target, "clean"); </del> } }

&builder.sysroot_libdir(target_compiler, compiler.host), &libtest_stamp(builder, compiler, target) ); <del> builder.cargo(target_compiler, Mode::ToolTest, target, "clean"); </del> } }

&builder.sysroot_libdir(target_compiler, compiler.host), &librustc_stamp(builder, compiler, target) ); <del> builder.cargo(target_compiler, Mode::ToolRustc, target, "clean"); </del> } }

deps.push((path_to_add.into(), false)); } <del> // Now we want to update the contents of the stamp file, if necessary. First // we read off the previous contents along with its mtime. If our new // contents (the list of files to copy) is different or if any dep's mtime // is newer then we rewrite the stamp file. </del> deps.sort(); <del> let stamp_contents = fs::read(stamp); let stamp_mtime = mtime(&stamp); </del> let mut new_contents = Vec::new(); <del> let mut max = None; let mut max_path = None; </del> for (dep, proc_macro) in deps.iter() { <del> let mtime = mtime(dep); if Some(mtime) > max { max = Some(mtime); max_path = Some(dep.clone()); } </del> new_contents.extend(if *proc_macro { b"h" } else { b"t" }); new_contents.extend(dep.to_str().unwrap().as_bytes()); new_contents.extend(b"0"); } <del> let max = max.unwrap(); let max_path = max_path.unwrap(); let contents_equal = stamp_contents .map(|contents| contents == new_contents) .unwrap_or_default(); if contents_equal && max <= stamp_mtime { builder.verbose(&format!("not updating {:?}; contents equal and {:?} <= {:?}", stamp, max, stamp_mtime)); return deps.into_iter().map(|(d, _)| d).collect() } if max > stamp_mtime { builder.verbose(&format!("updating {:?} as {:?} changed", stamp, max_path)); } else { builder.verbose(&format!("updating {:?} as deps changed", stamp)); } </del> t!(fs::write(&stamp, &new_contents)); deps.into_iter().map(|(d, _)| d).collect() }