Pre-RFC: Presets for Cargo

I wonder if this could be done completely outside of Cargo, e.g. by storing profile templates and other information in some configuration files on disk, for example through GitHub - Kobzol/cargo-wizard: Cargo subcommand for configuring Cargo projects for best performance..

For the use cases I've seen related to presets, it seems like they would be global to the project and not per-user. For example, your motivating vase is for mybackend vs web which seems tied to the project to be shared by everyone. Could you expand on the per-user side of this and why that is the default expectation?

If this were managed through config, there is the config-include feature. One potential idea with that is the ability to include things if present, either through weak-includes or globs. If presets were in config, this would allow maintainers to manually build up support out of existing pieces to allow user-controlled config.

It sounds like solutions like aliases would work here. You define an alias and have each of these tools invoke that instead, right?

Frequently people do version .cargo/config.toml and it is versioned by default in the sense that cargo news .gitignore doesn't exclude it.

1 Like

Want to link this old feature request I wrote for rust-analyzer because I think it's pretty relevant. With the gif from it:

257986133-3a206644-e19a-4a5d-90c8-6d49f1fe200d

To my knowledge, Rust tooling currently doesn't support this kind of IDE interaction for quick feature/target selection the way Visual Studio does for C++ and C#. This makes it rather painful to work for multiple targets, especially mutually exclusive targets (like client vs. server). Having some sort of .sln-like functionality in Rust cargo files that could be read and supported by tooling for fast pulldown toggling would close a usability gap.

In order for this to work, you probably need something more than a makefile. At least, if you want Rust tooling integration for the feature to be common across different IDEs.

2 Likes

RustRover can do this, by the way (https://twitter.com/rustrover/status/1717124628886245523), it allows you to both override the target and enabled features.

1 Like

Right now, the default way to select a specific build configuration is to manually define the right target and feature combination. If presets would need to be defined in Cargo.toml, it would make the usage of presets rely on Cargo.toml having the presets the user want to use defined. Or the user would have to make a pull request, or deal with merge conflicts, rebasing, etc. to maintain their presets in Cargo.toml. There might also be a feature/target combination that the authors of the crate simply didn't think of to include, or don't feel like listing every single possible valid combination as named presets. This again, would make presets unusable if the user couldn't define their desired target/feature combination on their own.

There is definitely an argument for being able to define presets in Cargo.toml, but there should be a way for the user (person building the project) to define their own independent of version tracked Cargo.toml.

Then there is the selection of the default preset. That one definitely does not belong in Cargo.toml, because the user should be able to define which preset they want to use at any time, without having to worry about changing version tracked files.

What do you mean by aliases? Shell aliases? Normal tooling does not invoke shell aliases, they invoke commands, which are not affected by shell aliases. Rust-analyzer for example is not aware of the shell you are using. It just runs cargo from PATH. You would need a cargo wrapper, like the one I made, for tooling to invoke cargo with the right flags.

That's an argument against putting presets in .cargo/config.toml then. There should be a way to define local preferences without having to worry about changing version tracked files.

AFAIK this is only for targets, not for build configurations (client vs. server vs. editor, etc.) on the same target. You would need a build configuration and collection of features, potentially including mutually exclusive features, for the latter, and that would require something like presets to support. Either that or it would come down to each IDE having their own custom tooling/extension to do so.

Please give a concrete use cases where there are not project-common presets that is justifies itself over project-common ones.

Cargo aliases which where talked about both in Zulip and on this thread.

Out of curiosity, are there existing RFCs or pre-RFCs/proposals to add feature support to profiles?

What if a user wants to build for their own exotic target? It's unreasonable to expect project maintainers to make presets for every conceivable target in Cargo.toml

Second, you have to understand that this would be a new feature if it got implemented. Should people who want to use presets submit pull requests to every project not owned by them that they want to work on and use presets on, or have to deal with unmerged changes?

Third, it's not developer friendly to make developers have to deal with people instead of just being able to solve their own local problem and get onto solving real problems. Why force them to write a pull request, and potentially argue with people why they should merge their change, just as I am arguing here? The developer friendly thing to do is let them define their own local preferences, and get on with their lives, and solve real problems that interest them.

Fourth, you ignored my argument about setting defaults, which is an important part of this proposal, and allows the user to conveniently switch between presets. This does not belong to Cargo.toml. The developer should be able to switch between presets at their own convenience, without needing to care about versioned changes.

Fair enough, I haven't really looked at what "cargo aliases" are exactly. Maybe they do help in solving the problem, but I am too exhausted of this topic right now to do research on it.

If you mean Configuration - The Cargo Book, then I don't see how that would help with the problem.

Aliases are not allowed to redefine existing built-in commands.

So you mean define an alias like cargo build-my-backend? How would rust-analyzer know to invoke it? Should rust-analyzer have its own configuration for invoking different aliases of cargo? Sure, it would solve the problem of having the flags being centrally defined in an alias, but it doesn't solve the problem of being able to easily switch between presets, and automatically synchronizing it between all tools, like presets does with the default preset.

What people trying to argue for alternatives should keep in mind: The user should be able to easily switch between presets without:

  1. Having to reconfigure each tool separately (yes, changing what alias it uses counts as reconfiguration)
  2. The user shouldn't have to make a versioned change to switch between presets

If your alternative does not meet these requirements, then it's not a solution for this RFC's motivation, please write a different RFC, thank you.

1 Like

I don't see how your RFC addresses the "set every tool independently" issue - you say it just uses the default preset, but that doesn't seem like a full solution.

You can set a custom check command in rust-analyzer, so you could just set that to the cargo alias. I know that requires some amount of configuration, but switching between presets would require changing the configuration as well.

Would it makes live easier for switching between different preset/custom commands, if Cargo supports loading arguments from files a.k.a argfile?

As far as I can tell, rustc supports @path.

For the sake of tooling I imagine it's better to predefine the options and let the user switch between them as needed rather than having the entire file swap in and out.

It addresses the issue because the tools that use cargo don't have to do any special configuration, because cargo itself is configured to use a specific preset. Once you switch the default preset, any cargo invocation will use that preset. You don't have to do any tool-specific configuration.

Rust-analyzer for example reads the info for what features are active by invoking cargo metadata. When cargo is configured to use a specific preset by default, any invocation of cargo metadata will include the configured features, so you don't have to do any special configuration within Rust-analyzer.

If editing a file every time you want to change the preset for all tools is okay with you, a much simpler solution could be something like a cargoflags or rustflags file:

# mybackend present (default)
--no-default-features --features=window-backend-2

## web preset (disabled)
#--target wasm32-unknown-unknown --no-default-features --features=web-backend

Just toggle comments to change the "preset"

1 Like

Yeah, I agree that's a much less invasive change to Cargo, but it forms the core of a solution that would fit the motivation for this RFC.

And there could be a higher level third party solution on top of that to manage presets.

I might write an RFC for a cargoflags type solution in the future, although not right now, because I'm mentally exhausted from this one.

So if someone thinks that would be a good feature to add to cargo, feel free to write an RFC about it before me.

EDIT: I added an argfile alternative to the alternatives section of the RFC.

Unfortunately, argfiles aren't a solution either, it seems.

1 Like