-
Notifications
You must be signed in to change notification settings - Fork 356
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Build dependencies without codegen ("cargo check") where possible #1057
Comments
So, as already mentioned I generally agree that we want "cargo check". However, I am not quite sure about the approach you chose to distinguish, inside Right now, we are using the presence of the flags passed via Also @ehuss is there any chance cargo could tell us a bit more ("inside" |
There's no way to combine |
But we could do |
@RalfJung: I tried that at first - it turned out to require even more hacks that this current PR does. |
How do Using Also, what about using the crate type (bin vs lib) to distinguish things? Assuming we already recognize build dependencies because we use |
I gave up on
Does that work when you use |
Yes, cargo is dumb :) |
Things like that are why I'd (eventually) like to get Cargo to explicitly give us the information we need via an environment variable. I'm worried that Cargo could accidentally or deliberately break any of the weird quirks we might want to rely on, leaving us with no path forward. |
Indeed, |
Xargo and rustc's build system currently depend on this to prevent build dependencies (linked to a different libstd) from becoming part of the sysroot. |
Ah, okay. If we're already depending on that, I guess it doesn't matter if we add another dependency on it (at least for the time being). I'll see if I can update check to use that. |
@Aaron1011's |
Fixes rust-lang#1057 I'm using my original approach from PR rust-lang#1048. Ideally, we would distinguish between build-deps/dependencies/'final crate' via a different approach (e.g. the target directory). However, I haven't been able to get that to work just yet. However, everything should be working with the approach I'm using. At a minimum, we can use this PR to verify that everything works as expected when we don't actually produce native build outputs.
Fixes rust-lang#1057 I'm using my original approach from PR rust-lang#1048. Ideally, we would distinguish between build-deps/dependencies/'final crate' via a different approach (e.g. the target directory). However, I haven't been able to get that to work just yet. However, everything should be working with the approach I'm using. At a minimum, we can use this PR to verify that everything works as expected when we don't actually produce native build outputs.
Fixes rust-lang#1057 I'm using my original approach from PR rust-lang#1048. Ideally, we would distinguish between build-deps/dependencies/'final crate' via a different approach (e.g. the target directory). However, I haven't been able to get that to work just yet. However, everything should be working with the approach I'm using. At a minimum, we can use this PR to verify that everything works as expected when we don't actually produce native build outputs.
Fixes rust-lang#1057 Since we are no longer using "cargo rustc", we now use the rustc arguments passed by Cargo to determine whether we are building a build dependency, normal dependency, or "target" (final binary or test) crate.
Fixes rust-lang#1057 Since we are no longer using "cargo rustc", we now use the rustc arguments passed by Cargo to determine whether we are building a build dependency, normal dependency, or "target" (final binary or test) crate.
Use 'cargo check' to build the sysroot and target crate Fixes #1057 I'm using my original approach from PR #1048. Ideally, we would distinguish between build-deps/dependencies/'final crate' via a different approach (e.g. the target directory). However, I haven't been able to get that to work just yet. However, everything should be working with the approach I'm using. At a minimum, we can use this PR to verify that everything works as expected when we don't actually produce native build outputs.
Use 'cargo check' to build the sysroot and target crate Fixes #1057 I'm using my original approach from PR #1048. Ideally, we would distinguish between build-deps/dependencies/'final crate' via a different approach (e.g. the target directory). However, I haven't been able to get that to work just yet. However, everything should be working with the approach I'm using. At a minimum, we can use this PR to verify that everything works as expected when we don't actually produce native build outputs.
It would be great if we could build libstd as well as dependent crates (in
cargo miri
) without codegen ("check" mode). This would (a) save time, (b) avoid having to generate MIR that works both in Miri and when compiled normally, and (c) hopefully drastically simplify cross-building.@Aaron1011 looked into this mostly due to (b), as this turned into quite a challenge for unwinding. I am copying from his post:
The long-term solution is to switch to using
cargo check
. This completely disables codegen in a way that's built into the compiler. We will no longer need to worry about any assumptions made by the codegen backend, since that code will simply never be executed.However, this turned out to be more complicated than I anticipated. There are several moving parts here:
xargo
runcargo check
Currently,
xargo
unconditionally usescargo build
when compilinglibstd
. I've opened a PR to add acargo_mode = "check"
option toXargo.toml
: japaric/xargo#267cargo-miri
runcargo check
.This is complicated by the fact that we currently run
cargo rustc
in order to pass arguments to the last (and only to the last) invocation ofrustc
. Sadly, there appears to be no way to combinecargo check
andcargo rustc
- you can either usecargo rustc
and have no way to skip codegen, or usecargo check
and have no way to pass final-crate-specific rustc arguments.To work around this issue, I've added a hack to serialize arguments to an environment variable. When we compile the final crate, we deserialize these arguments from the environment variable, and manually pass them to the
rustc
invocation.libstd
.This is by far the trickiest part of this entire PR. When Cargo invokes our
cargo-miri
wrapper, we have three cases to worry about:Build dependencies (including build scripts): We pass through all arguments completely unmodified to rustc. Miri does not interact in any way with build scripts, so we want to treat them as if we were doing a normal run of cargo.
Normal dependencies: We add our custom sysroot, but still invoke rustc. Since we are in cargo check mode, this will cause rustc to produce metadata for the normal dependenices of our runtime crate, using our custom libstd.
The target itself (e.g. a test or a binary): We invoke miri, and actually begin execution.
Handles these three cases ensures that build dependencies are built using the normal platform
libstd
(as ifcargo-miri
did not exist), while normal dependencies and our target crate are built against our custom libstd).Unfortunately, distinguishing between these three cases is a huge pain. I'm currently relying on the following tricks:
CARGO_MANIFEST_DIR
to detect when our target crate is being built.The
CARGO_MANIFEST_DIR
is set by Cargo to the directory containing the manifest of the package currently being built. During the initial, non-wrapper invocation ofcargo miri
(e.g. when the user typescargo miri run
on the command line), we determine the manifest directly for the crate they are building. We then compare this toCARGO_MANIFEST_DIR
when we are being invoked by Cargo as a wrapper.However, this fails to distinguish between a
build.rs
and the actual compilation, since both use the same manifest directory. This brings us to the second trick.--emit=
flag passed torustc
byCargo.
This trick relies on the fact that we are using
cargo check
to build the crate. When Cargo compiles a build dependency, the--emit=
flag will always containlink
- this is because we always need to produce a runnable binary for build scripts.When we are building normal dependencies, the
--emit=
flag will not containlink
. This is howcargo check
tellsrustc
not to perform codegen - the--emit=
flag will be--emit=dep-info,metadata
.By checking for the presence of
link
, we can determine whether or not Cargo is trying to compile a build dependency. Note that the same crate could theoretically be build as both - e.g. you could add[dependencies] cc=x.y.z
and[build-dependencies] cc=x.y.z
to yourCargo.toml
.Adding more information to Cargo
While I believe assumptions behind the above Cargo hacks are fairly sound, this is not really a viable long-term solution. For example, Cargo could choose to stop passing the
--emit
flag ifrustc
would have it default to what Cargo already wanted.Ideally, Cargo would set an environment variable to let us know which of the three cases we are in - target crate, build dependency, or normal dependency. I'm currently working on a PR that does just that.
Conclusion
I think our best path forward is to:
cargo check
support inxargo
eh_catch_typeinfo
hack intorustc
so that nightly users can have a (somewhat) working Miri againThe text was updated successfully, but these errors were encountered: