Open CinchBlue opened 11 months ago
@CinchBlue Hi, thanks for filing this issue!
I share your usage and your concern (I even have cargo +nightly fmt
configured as the formatter in my IDE), but I'm not quite sure if the solution you've proposed aligns with rust-toolchain.toml
's intended role.
@rbtcollins @djc what do you think?
This proposal doesn't make sense to me, as it's not obvious how or when the other-toolchain
gets selected.
This proposal doesn't make sense to me, as it's not obvious how or when the
other-toolchain
gets selected.
Let me clarify this use case a bit: the intention is to tell users to install nightly
only for running cargo +nightly fmt
.
This is useful because cargo +stable fmt
will emit a bunch of warnings in some projects with a non-trivial rustfmt
config, and will happily refuse to format any format-able positions considered as nightly-only (by rustfmt
, not by rustc
).
My personal suggestion for @CinchBlue is this: configure a cargo +nightly fmt
check in your CI (it's recommended to have cargo fmt
checks in any non-trivial Rust repo anyway), so that whoever wants to make non-trivial changes to your code base will at some point install a nightly
toolchain themself to avoid red lights in CI.
Let me clarify this use case a bit: the intention is to tell users to install
nightly
only for runningcargo +nightly fmt
. This is useful becausecargo +stable fmt
will emit a bunch of warnings in some projects with a non-trivialrustfmt
config, and will happily refuse to format any format-able positions considered as nightly-only (byrustfmt
, not byrustc
).
I understand this much. What I don't understand is what the other-toolchain
entry is supposed to mean/do/trigger.
I understand this much. What I don't understand is what the
other-toolchain
entry is supposed to mean/do/trigger.
Oh, nothing more than informing the user that this other-toolchain
will be installed but not activated, if I understand it correctly.
My reasoning is that since there's no ideal way of expressing "we want +nightly
to be the default just for cargo fmt
", this should not be implemented as suggested.
On the other hand, if there were such a way already, nightly
should already have been installed by rustup
for such intentions, exactly like when you run rustup default nightly
without installing nightly
.
If someone wants to design a system tied into the proxies, so that 'cargo fmt' and 'rustfmt' both run the correct toolchain for this multi-toolchain case, then I think we can go through a mini RFP process to figure out all the interactions.
As it is I share @djc 's concern : this extra key is not coupled to any user behaviour - it is no different to documentation, except for this eager-install aspect, and I'm not sure that implicit eager-install is a good idea - outside of disconnected use, I don't understand the benefit today. And the cost is likely substantial.
We are, already, on a slow path to remove implicit install completely.
My personal suggestion for @CinchBlue is this: configure a cargo +nightly fmt check in your CI (it's recommended to have cargo fmt checks in any non-trivial Rust repo anyway), so that whoever wants to make non-trivial changes to your code base will at some point install a nightly toolchain themself to avoid red lights in CI.
This is what I was doing before, but if you tell people to run that, you'll will inevitably end up with multiple versions of nightly
running around per-person, meaning there will be a tug-of-war over which cargo +nightly fmt
is correct, as it can differ between arbitrary nightly versions. (Yes, this is something that has been directly plaguing me and a few other people for months.)
The question is where do you "canonize" the correct Rust toolchain to "pin" for a given repo? Right now, it is rust-toolchain.toml
, yet it only allows pinning 1. Allowing to at least pin 2 would be useful, but there is no reason I shouldn't be able to allow people to pin 10 so we can run CI targets + cross-compile targets for MSVs locally too.
Right now, I manually maintain a Makefile
/justfile
command to pin the version using a script variable to substitute in before all cargo
commands. But this is still manual, and is not ideal for something that "just works."
Right now, I manually maintain a
Makefile
/justfile
command to pin the version using a script variable to substitute in before allcargo
commands. But this is still manual, and is not ideal for something that "just works."
@CinchBlue I understand your disappointment here and I fully recognize that the current situation should be improved. That's why I said it is a personal suggestion: it's a workaround and I'm not satisfied with sticking to it.
However, I think we still need some more thinking in terms of feature design. It certainly cannot be shipped to end users in its current state.
However, I think we still need some more thinking in terms of feature design. It certainly cannot be shipped to end users in its current state.
What is needed to get this to a workable, shippable state? Are there prior issues, threads, or lists I can see or that can be drafted here with discussion?
I'm not aware of any prior issues/threads/lists for this, but maybe others have more context.
I'm open to the idea that there should be options to enable configuring multiple toolchains in rust-toolchain.toml
. (Another use case that seems interesting is to have an msrv
toolchain which can evolve independently over time.) However, I think that would basically require redesigning rust-toolchain.toml
-- in a backward-compatible way -- to cope with an arbitrary number of toolchains, each of which define an "alias" that can be used with the proxies which is only in scope if the proxy is executed from a directory that is a dependent of the directory the rust-toolchain.toml
.
@rbtcollins I think this basically aligns with your notes in https://github.com/rust-lang/rustup/issues/3546#issuecomment-1831292725? Any thoughts/suggestions/caveats/feedback?
Also, you can reproduce inconsistencies with this setup:
$ rustup show -v
Default host: aarch64-unknown-linux-gnu
rustup home: /home/ubuntu/.rustup
installed toolchains
--------------------
nightly-2023-11-24-aarch64-unknown-linux-gnu
rustc 1.76.0-nightly (a1a37735c 2023-11-23)
nightly-2023-11-26-aarch64-unknown-linux-gnu
rustc 1.76.0-nightly (f5dc2653f 2023-11-25)
# .rustfmt.toml
# Which version of the formatting rules to use. Version::One is backwards-compatible with Rustfmt 1.0.
# Other versions are only backwards compatible within a major version number.
version = "Two"
# Set a specific version of cargo-fmt for the CI
# required_version = "1.7.0"
edition = "2021"
unstable_features = true
format_generated_files = false
group_imports = "StdExternalCrate"
reorder_imports = true
imports_granularity = "Crate"
indent_style = "Block"
Running cargo +nightly-2023-11-26
vs. cargo +nightly-2023-11-24
produces a tug-of-war over formatting despite having the same general settings in the rustfmt
configuration file.
As I've explained more in-depth in #3577 (closed as duplicate), another use case for this would be to allow switching between e.g. -windows-gnu
and -windows-msvc
toolchains. It currently locks you in to whichever the default selection is on first run while both toolchains are a valid option for any given channel + version/date combination.
As for using it, rustup will resolve e.g. +nightly-msvc
to either a currently installed nightly-<...>-msvc
or the latest available nightly-<host-triplet>-msvc
toolchains (in that order). Even with a toolchain file, it will currently not resolve +msvc
. This could be changed to checking if a toolchain file is present and using the specified information there to resolve it through +<channel>-msvc
following the existing logical path. If no toolchain file is present, it'd be free to error in the same way it does currently (error: toolchain 'msvc' is not installed
).
My initial proposed fix was adding an entry to the [toolchain]
table, though I'm not averse to the solutions proposed in this issue either. Specifically to match the "main" table, I proposed a backends
array, which would also work with most of the solutions here.
Not sure if it's an issue for people running on other multi-backend platforms such as Linux(-gnu|-musl
), but I think it'd also make it easier to keep projects tested across a larger variety of platforms if it's not required to manually specify them all, but instead manage it in the toolchain file for both dev and CI
I'm not sure exactly what you mean by the backends
array -- it seems like adding yet another concept which doesn't sound attractive to me.
@rami3l the problem there lies in either statically linking a lot of MinGW stuff for it to work on Windows, resulting in much bigger binaries, or having to make sure MSVC can find and process MinGW headers for GNU builds. The latter wouldn't be much of an issue, if a rust-toolchain.toml file would cause it to always default to MSVC. But considering my system is set to default to GNU, I get the bloaty result.
Originally posted by @RivenSkaye in https://github.com/rust-lang/rustup/issues/3577#issuecomment-1851421775
I think you're referring to the problem of compiling to multiple Windows target triples. I think this section of the user guide might help with your situation?
You don't need to switch toolchains to support all windows targets though; a single toolchain supports all four x86 windows targets:
$ rustup target add x86_64-pc-windows-msvc $ rustup target add x86_64-pc-windows-gnu $ rustup target add i686-pc-windows-msvc $ rustup target add i686-pc-windows-gnu
I don't use Windows personally, but I believe you can do all of your development work within the gnu
toolchain. Just pass the correct triple to cargo
with --target=
and you should be good to go.
AFAIK that's what people do when they need musl
binaries on Linux: they stick to the gnu
toolchain and add a musl
target to that toolchain.
I'm not sure exactly what you mean by the
backends
array -- it seems like adding yet another concept which doesn't sound attractive to me.
That was my initial proposed fix in the other issue; similar in idea to the proposed [[other-toolchain]]
here, with the biggest difference being that the fix proposed here would allow for fully customizing one other toolchain instead of allowing for several backends that'd inherit everything from the already existing selectors. Hence the general idea is perfectly compatible with what I initially suggested so it shouldn't need to introduce the extra concept.
I don't use Windows personally, but I believe you can do all of your development work within the gnu toolchain. Just pass the correct triple to cargo with --target= and you should be good to go. AFAIK that's what people do when they need musl binaries on Linux: they stick to the gnu toolchain and add a musl target to that toolchain.
Last I checked, using the GNU toolchain ended up linking in the usual MinGW libraries even on MSVC targets resulting in much bigger binaries. Running new compiles and comparisons to check rn
Well, seems like that is an issue of the past. I'm actually getting slightly smaller binary outputs now with a negligible difference for real-world cases, which made for a pleasant surprise today. That leaves just the angles mentioned in the original question and the additional pinning multiple for CI and collaboration. Sorry for the interruptions here.
For reference, the last time I checked was just before the last big GCC update hit MSYS2/MinGW64 so it has been a while.
@RivenSkaye No worries, glad to hear that your problem is resolved!
Mmh i have just run into this issue myself and reading this gave me an idea: Instead of specifying multiple toolchains globally, what if it was allowed to override the toolchain per component? I think using nightly rustfmt together with stable rust is perfectly valid, so i was thinking about something along the lines of
[toolchain]
channel = "stable" # this is essentially the default toolchain
# channel for this component isn't specified, will use stable
[[toolchain.components]]
name = "clippy"
# channel is nightly, so nightly rust will be used for this component
[[toolchain.components]]
name = "rustfmt"
channel = "nightly"
I imagined this more like named toolchains. Reserved names like "stable", "nightly-YYYY-MM-DD" etc. aren't allowed. Smth like this:
# Default toolchain
[toolchain]
channel = "stable"
# Additional toolchain
[[toolchain.lint]]
channel = "nightly-2024-02-07"
Then, it will be used this way:
# Will use pinned nightly for toolchain "lint"
cargo +lint fmt
I like this idea. I think the key name should be not the same as toolchain
.
@CinchBlue The name's just a stub. Not even sure that the same key can be used as both simple entry and "list" declaration.
I would also really love a way to specify multiple toolchains (with different names, one being the unnamed default) that are all installed (or the named ones could even be lazily installed when the name is first used). In my usecase, I have a workspace that uses stable but builds a few WASM modules using nightly since I need to use -Z build-std
with them to build std
with panic_immediate_abort
(I'm not actually using any nightly features).
@djc msrv is already specified in Cargo.toml; I think something like a virtual toolchain that consults that and then uses that toolchain would be better - otherwise we'd have no source of truth for it.
@juntyr for your case it seems like a rust-toolchain that specifies a nightly version that is stable for your needs, and then build everything with it, would meet your current needs.
For everyone here - the path forward depends on someone sitting down and writing a spec for the desired behaviour.
It needs to take into consideration the following impacts:
be backward compatible in the sense that an existing toolchain files behaviour does not change with newer rustup
work without surprise in:
work with all the tools rustup manages - rustc/cargo/clippy/rust-lldb/rust-gdb/
fit into the config/default/environment variable lookup scheme
and have a clear benefit that outweighs the increased complexity that will affect both developers of rustup and consumers of it
and not introduce any new security concerns - e.g. the additional toolchains added to the file must not be confusable with official channel toolchains
@juntyr for your case it seems like a rust-toolchain that specifies a nightly version that is stable for your needs, and then build everything with it, would meet your current needs.
Thank you for considering my use case! While only using nightly certainly is a way to build the full project using just one toolchain, in this particular project I only want to use stable features (and e.g. https://github.com/rust-lang/rust/issues/120804 has shown that just using a nightly tool chain can produce spooky side effects when some dependency crate detects it and enables nightly features based on it). Aside from the proposed multi-toolchain toml config, other solutions to my use case would be (a) a way to build everything with the nightly compiler but to deny any crate from enabling nightly features [is there a way to do this?] or (b) to link a prebuilt std with immediate panic abort so I can continue using just a stable compiler. Perhaps you know if either of those is already possible?
Problem you are trying to solve
When running a project, often times, one wants to use
nightly
features fromrustfmt
, while also keeping astable
version for builds + deploys.Solution you'd like
Allow a second key called
[[other-toolchain]]
to specify non-default toolchains. This should be backwards-compatible with the currentrust-toolchain
format:Notes
No response