Skip to content

Implement ToolTarget and port RemoteTestServer and WasmComponentLd to it #143581

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

Closed
wants to merge 7 commits into from

Conversation

Kobzol
Copy link
Member

@Kobzol Kobzol commented Jul 7, 2025

We have a set of tools (such as the various linker wrappers - LLD/WASM/LLVM linkers) that behave like bootstrap tools when not cross-compiling, and like std tools when cross-compiling. Before, various modes were used for them (currently - ModeStd for WasmComponentLd and LldWrapper and ToolRustc for LlvmBitcodeLinker). This was wasteful, if you did a stage 2 non-cross-compiled build, WasmComponentLd would be built twice, even though we can just build it once using the stage0 compiler.

I would like to unify these. This PR is the first step towards that. I started what I considered to be the simplest linker step out of the three.

r? @jieyouxu

@rustbot rustbot added A-testsuite Area: The testsuite used to check the correctness of rustc S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap) labels Jul 7, 2025
@bjorn3
Copy link
Member

bjorn3 commented Jul 7, 2025

I don't think cross-compiling should result in a different binary at stage2 that native compilation. Nor should a local rebuild (using the current rustc version as bootstrap compiler) result in a different binary at stage2 than using the previous rustc version as bootstrap compiler.

Copy link
Member

@jieyouxu jieyouxu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I think this design seems like a "most correct" approach to address the nuisance of these tools. I do have a question.

@@ -196,7 +196,7 @@ impl Step for ToolBuild {
Kind::Build,
self.mode,
self.tool,
self.build_compiler.stage,
self.build_compiler.stage + 1,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remark: this is because it's a product of the stage 0 rustc that is not the stage 0 library

Comment on lines 368 to 369
/// Returns a compiler that is able to compile a `ToolTarget` tool for the given `target`.
pub(crate) fn get_tool_target_compiler(builder: &Builder<'_>, target: TargetSelection) -> Compiler {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: this isn't quite obvious, because in the cross-compile case, we'll also have to ensure target std as a side-effect, right? I don't have a better name for this just yet, so not a blocker.

I can see why we might want to have some kind of "proof of std artifacts getting built".

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that would indeed be nice, but that's a massive refactoring. I'm continuously thinking about how to approach it. The attachment of a std to Compiler in bootstrap is currently fully implicit, so this just does what the rest of bootstrap does.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this was more of a question, and not a blocking change request.

Comment on lines +976 to +977
extra_features: vec![],
allow_features: "min-specialization",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: hm, might this be a problem if min_specialization ever gets renamed, removed or stabilized? Or rather, the tool now has to be support being built by both stage 0 compiler and stage 1 compiler right? In that situation, the tool would have to cfg(bootstrap) anyway I think.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the feature flag is even needed, the tool compiles with the stable compiler... Unless it does some weird detection in build scripts.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would keep it for now, to leave the previous functionality intact. If it becomes an issue, we can always try to remove it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, that sounds reasonable.

@jieyouxu
Copy link
Member

jieyouxu commented Jul 7, 2025

I don't think cross-compiling should result in a different binary at stage2 that native compilation. Nor should a local rebuild (using the current rustc version as bootstrap compiler) result in a different binary at stage2 than using the previous rustc version as bootstrap compiler.

Hm, as in with this scheme, we would be producing different wasm-component-ld depending on whether it was compiled "for host" or "for target" right?

@bjorn3
Copy link
Member

bjorn3 commented Jul 7, 2025

Hm, as in with this scheme, we would be producing different wasm-component-ld depending on whether it was compiled "for host" or "for target" right?

Yes. And in case it was compiled for the host a local rebuild won't produce an identical executable to a regular bootstrap. The local rebuild case matches when it was compiled for the target.

@Kobzol
Copy link
Member Author

Kobzol commented Jul 7, 2025

Hm, as in with this scheme, we would be producing different wasm-component-ld depending on whether it was compiled "for host" or "for target" right?

Yes. And in case it was compiled for the host a local rebuild won't produce an identical executable to a regular bootstrap. The local rebuild case matches when it was compiled for the target.

But that is the point, right? If we compile rustc for foo, we need to produce wasm-component-ld for foo (not for host), because the rustc will be executing this binary on its host platform. Or not?

@bjorn3
Copy link
Member

bjorn3 commented Jul 7, 2025

I would expect cross-compiling from bar -> foo to produce the exact same executable as compiling natively on foo. Choosing between compiling with the bootstrap compiler and compiling with the local rustc depending on if you are cross-compiling or not causes both cases to produce different executables.

@Kobzol
Copy link
Member Author

Kobzol commented Jul 7, 2025

I would expect cross-compiling from bar -> foo to produce the exact same executable as compiling natively on foo. Choosing between compiling with the bootstrap compiler and compiling with the local rustc depending on if you are cross-compiling or not causes both cases to produce different executables.

Hmm, I see what you mean now. It seems like a noble goal, but do we actually uphold it in practice? I would be very much surprised if bootstrap managed to cross-compile 1:1 bitwise exact binaries, and we don't have tests for this, definitely not for the linker tools. We were also already compiling wasm-component-ld using the stage0 compiler before, we just recompiled it again using the stage1 compiler when doing a stage2 (or cross-compiling) build.

More generally, these should be "normal" Rust tools compilable by a stable compiler. Does it matter so much with what compiler we build them?

@bjorn3
Copy link
Member

bjorn3 commented Jul 7, 2025

We were also already compiling wasm-component-ld using the stage0 compiler before, we just recompiled it again using the stage1 compiler when doing a stage2 (or cross-compiling) build.

We only distribute the stage2 build. It is expected that the stage1 build doesn't exactly match.

It seems like a noble goal, but do we actually uphold it in practice? I would be very much surprised if bootstrap managed to cross-compile 1:1 bitwise exact binaries, and we don't have tests for this, definitely not for the linker tools.

I don't think we currently do it perfectly (especially for cross-compilation), but that doesn't mean we should make it worse. Having cross-compilation produce identical executables is maybe not the most important, but I do think local-rebuild should produce identical executables.

@Kobzol
Copy link
Member Author

Kobzol commented Jul 7, 2025

Hmm, that's unfortunate. We spend ~2 minutes building just WasmComponentLd on each CI dist build that has it enabled, and needlessly recompile it a bunch of times. This was a relatively easy way of reducing that compilation count.

Another alternative would be to distinguish in bootstrap if tools are needed for the intermediate stages, and if not, then skip building them (e.g. if we do a stage 2 build, don't build wasm-component-ld for stage 1 rustc). But that's either a large refactoring or piling more hacks on top of the Assemble step..

but I do think local-rebuild should produce identical executables.

Could you expand on this a bit more? We don't ever use local rebuild for dist builders (right?), and if you compile a "stage 0 bootstrap tool", e.g. opt-dist with local rebuild enabled, it will be different anyway. Why is it so important for WasmComponentLd specifically to be the same? Because we dist it?

@bjorn3
Copy link
Member

bjorn3 commented Jul 7, 2025

Could you expand on this a bit more? We don't ever use local rebuild for dist builders (right?),

Distros do use local rebuild.

and if you compile a "stage 0 bootstrap tool", e.g. opt-dist with local rebuild enabled, it will be different anyway. Why is it so important for WasmComponentLd specifically to be the same? Because we dist it?

Yes, it doesn't really matter for local tools, only for distributed tools.

I believe cargo already has this issue now that I think about it, so I guess this PR doesn't make the problem much worse. So I withdraw my concern about this PR.

@Kobzol
Copy link
Member Author

Kobzol commented Jul 7, 2025

Yeah, since cargo is also compilable by stage0, I wanted to turn it into ToolTarget too. Currently it's ToolRustc, but that's not really needed, as far as I understand.

Well, your concerns are quite interesting, I haven't thought of that. And this PR does add more complexity to bootstrap, although it also makes the behavior of the "target" tools more precise and unified, before they were using ModeStd, ModeBootstrap, ModeRustc kind of randomly.

I would try to land this and see if anyone complaints about the non-identical binaries. I personally expect that our cross-compiles are far from identical anyway though, and that even local rebuild had some issues around this previously. If someone finds this to be an issue, we can still keep the more accurate tool mode, and just revert the change to compile with stage0.

Copy link
Member

@jieyouxu jieyouxu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, the changes look good to me. One comment request re. the reproducibility consideration so a Future Reader ™️ has some more context.

Comment on lines 262 to 274
/// Build a cross-compilable helper tool.
/// - If we compile it for the host, we use the stage0 compiler.
/// - If we compile it for another target, we use local compiler (because stage0 does not have
/// stdlib for the tool available for other targets).
///
/// This mode exists to avoid needless (re)builds of tools that can be compiled with
/// a stable/stage0 compiler. It essentially behaves as `ToolBootstrap` when not
/// cross-compiling, and as `ToolStd` when cross-compiling.
///
/// It is used e.g. for linkers and linker tools invoked by rustc on its host target.
///
/// These tools participate in staging only when required for cross-compilation.
ToolTarget,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: can you leave a comment here about the interesting reproducibility question (that we considered it, but decided that it still seems worth trying this approach) re. we would not be producing the same tool as we use different compilers when the tool is built for host vs for target?

@jieyouxu
Copy link
Member

jieyouxu commented Jul 8, 2025

@rustbot author

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jul 8, 2025
@Kobzol
Copy link
Member Author

Kobzol commented Jul 8, 2025

Done.

@rustbot ready

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Jul 8, 2025
@jieyouxu
Copy link
Member

jieyouxu commented Jul 8, 2025

Thanks.
@bors r+ rollup=never (interesting tool changes)

@bors
Copy link
Collaborator

bors commented Jul 8, 2025

📌 Commit 5c85adc has been approved by jieyouxu

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jul 8, 2025
@rust-log-analyzer

This comment has been minimized.

@Kobzol
Copy link
Member Author

Kobzol commented Jul 8, 2025

@bors r-

sigh

@bors bors added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Jul 8, 2025
@Kobzol Kobzol force-pushed the tool-wasm-component-ld branch from 5c85adc to 4fddfd1 Compare July 8, 2025 08:03
@Kobzol Kobzol marked this pull request as draft July 8, 2025 08:51
@Kobzol
Copy link
Member Author

Kobzol commented Jul 8, 2025

I want to get a bit more opinions on this.

@Kobzol
Copy link
Member Author

Kobzol commented Jul 8, 2025

In addition to the non-identical binaries for cross-compilation and local rebuilds, this would mean that we can't easily ship security fixes to these tools when we dist them. That's not good.

@Kobzol Kobzol closed this Jul 8, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-testsuite Area: The testsuite used to check the correctness of rustc S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants