Skip to content
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

Create 0000_cargo_standard_directories.md #1

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
119 changes: 119 additions & 0 deletions 0000_cargo_standard_directories.md
@@ -0,0 +1,119 @@
- Feature Name: (fill me in with a unique ident, my_awesome_feature)
- Start Date: (fill me in with today's date, YYYY-MM-DD)
- RFC PR: (leave this empty)
- Cargo Issues:
[rust-lang/cargo#1734](https://github.com/rust-lang/cargo/issues/1734)
[rust-lang/cargo#1976](https://github.com/rust-lang/cargo/issues/1976)
[rust-lang/cargo#2127](https://github.com/rust-lang/cargo/pull/2127)
[rust-lang/cargo#9178](https://github.com/rust-lang/cargo/pull/9178)
- Rustup Issues:
[rust-lang-nursery/rustup.rs#247](https://github.com/rust-lang-nursery/rustup.rs/issues/247)
[rust-lang-nursery/rustup.rs#473](https://github.com/rust-lang-nursery/rustup.rs/issues/473)

# Summary
[summary]: #summary

Improve Cargo's integration with the host operating system by using a set
of standard paths for config files, cache files, and executables. This
provides a more consistent experience to users and enables third-party tools
to integrate with Cargo more easily.


# Motivation
[motivation]: #motivation

Currently Cargo puts all of its files in a directory named `.cargo` in the
user's home directory. Using this proposal it would use existing standard
directories on the host system. This enables other tools to integrate with
Cargo, while making the experience to end-users more consistent and in-line
with other tools they are already using.


# Guide-level explanation
[guide-level-explanation]: #guide-level-explanation

We are going to introduce three new environment variables, and
deprecating the use of `CARGO_HOME`:

- `CARGO_BIN_DIR`
- `CARGO_CACHE_DIR`
- `CARGO_CONFIG_DIR`

As a default these values will be unset, but allow users to customise Cargo paths
independent of how other tools on their system work. For most users this will be
irrelevant however.

## *nix specifics
spacekookie marked this conversation as resolved.
Show resolved Hide resolved

In addition to custom environment variables Cargo will also comply with the [XDG]
specification for application paths which is in active use by many other tools on
MacOS, BSD derivatives, and Linux.
spacekookie marked this conversation as resolved.
Show resolved Hide resolved

By default these paths are as follows.

Choose a reason for hiding this comment

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

Suggested change
By default these paths are as follows.
If the `CARGO_*_DIR` environment variables are not set, Cargo will choose defaults for them based on on the XDG Basedir specification:

Copy link

Choose a reason for hiding this comment

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

That sounds like a good choice, simply linking to the spec/API on all three platforms.

Copy link

Choose a reason for hiding this comment

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

That also sounds good to me. We can update to include the $XDG_BIN_DIR when or if the XDG spec changes to include it.


- `XDG_CONFIG_HOME = $HOME/.config/cargo`
- `XDG_CACHE_HOME = $HOME/.cache/cargo`
- `XDG_BIN_HOME = $HOME/.local/bin/cargo`
Comment on lines +54 to +56
Copy link

Choose a reason for hiding this comment

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

Technically, those aren't the default values of $XDG_CONFIG_HOME, $XDG_CACHE_HOME or $XDG_BIN_HOME. Perhaps it would be clearer to say something like:

Suggested change
- `XDG_CONFIG_HOME = $HOME/.config/cargo`
- `XDG_CACHE_HOME = $HOME/.cache/cargo`
- `XDG_BIN_HOME = $HOME/.local/bin/cargo`
- `CARGO_BIN_DIR` = `$XDG_BIN_HOME`(if set) or `$HOME/.local/bin`
- `CARGO_CACHE_DIR` = `$XDG_CACHE_HOME/cargo` (if set) or `$HOME/.cache/cargo`
- `CARGO_CONFIG_DIR` = `$XDG_CONFIG_HOME/cargo` (if set) or `$HOME/.config/cargo`

EDIT: I forgot suggestions were a thing, sorry!

Choose a reason for hiding this comment

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

Actually, the most official-looking copy of the XDG Basedir spec I can find does not mention $XDG_BIN_HOME, it just hard-codes $HOME/.local/bin.

Copy link

Choose a reason for hiding this comment

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

@Screwtapello

Actually, the most official-looking copy of the XDG Basedir spec I can find does not mention $XDG_BIN_HOME, it just hard-codes $HOME/.local/bin.

I can definitively confirm that this is the current state of affairs with XDG -- there is no $XDG_BIN_HOME, they decided to go with just specifying the location in the XDG Basedir Spec alone. I argued against this throughout the whole discussion, but I didn't have a decisive use-case. That was before the following:

From Issue 1615

One issue that wasn't mentioned before is that $HOME might not be writable at all when an app (e.g. an IDE) is sandboxed in a container, for example flatpak. In these cases, cargo/rustup fails by default. Tinkering with environment variables is needed to make it work. Using XDG variables would make cargo/rustup work without additional configuration.

I ran into this issue when trying to setup Eclipse Corrosion in sandboxed Eclipse (eclipse-corrosion/corrosion#366).

If I'm correct, that's a definitive need for the 1$XDG_BIN_HOME variable. Can anyone else argue otherwise? ..because the XDG people will, and I'd like to be able to shoot those arguments down.

Copy link

@soc soc Mar 24, 2021

Choose a reason for hiding this comment

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

I'm not sure I understand that – XDG's dir for executables is specified to be a sibling subdir of XDG_DATA_HOME, so if some things aren't writable, the binary dir not being writable will be the least of your concerns.

This comment was marked as outdated.

Choose a reason for hiding this comment

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

If I'm correct, that's a definitive need for the $XDG_BIN_HOME variable. Can anyone else argue otherwise? ..because the XDG people will, and I'd like to be able to shoot those arguments down.

One alternative to an $XDG_BIN_HOME variable might be "the first writable entry on $PATH". Then application sandboxes like Flatpak could stick a sandboxed directory at the front of $PATH and be done.

A counter-counter-argument to that counter-argument might be that the same duality already exists between, say $XDG_CONFIG_HOME and $XDG_CONFIG_DIRS:

Config storage Binary storage
$XDG_CONFIG_DIRS $PATH
$XDG_CONFIG_HOME ???

Choose a reason for hiding this comment

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

In the context of this RFC, let's just follow the spec as is and move the discussion about the spec itself to the XDG issue tracker or elsewhere.

For the purposes of cargo, the bin dir would be separately overridable using $CARGO_BIN_DIR anyway

Copy link

@soc soc Mar 26, 2021

Choose a reason for hiding this comment

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

Alternatively, you could use a library that deals with this.

Copy link

Choose a reason for hiding this comment

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

Eh ... sorry ... "subdir" → "derived". The rest of my comment still applies the same though.

@soc The spec hardcodes the bin dir as $HOME/.local/bin not $XDG_DATA_HOME/bin (which would be ~/.local/share/bin).
Even if the bin dir was somehow "derived" from the value of $XDG_DATA_HOME, it could lead to unexpected situations where a write is attempted in the parent dir of $XDG_DATA_HOME
Ie: Attempting to create bin/ in /unwritabledir/ if $XDG_DATA_HOME points to /unwritabledir/userdata/.

Copy link

@soc soc Sep 12, 2021

Choose a reason for hiding this comment

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

@0x5c yeah, saw it, not sure if that was intentional or not. Not sure this is relevant for this PR anymore, as the directory haggling predictably derailed any other work on this PR.

Interestingly they also finally managed to standardize XDG_STATE_HOME after like 10 years ... I will update my libraries to support that.


## Windows specifics

On Windows Cargo will use `%LOCALAPPDATA%\Cargo\Cache`, which is a standard directory
Copy link

@soc soc Mar 24, 2021

Choose a reason for hiding this comment

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

Because %LOCALAPPDATA% gets mentioned times and times again:

Unlike on Linux, Windows doesn't care about the value of %LOCALAPPDATA%, so pretending its value has any kind of meaning on that platform is wrong and broken.

SHGetKnownFolderPath is the sole source of truth.

(Libraries sorted this out already.)

where applications keep their cache files, and

Explain the proposal as if it was already included in the language and you were teaching it
to another Rust programmer. That generally means:

- Introducing new named concepts.
- Explaining the feature largely in terms of examples.
- Explaining how Rust programmers should *think* about the feature, and how it should impact the way they use Rust. It should explain the impact as concretely as possible.
- If applicable, provide sample error messages, deprecation warnings, or migration guidance.
- If applicable, describe the differences between teaching this to existing Rust programmers and new Rust programmers.

For implementation-oriented RFCs (e.g. for compiler internals), this section should focus on how compiler contributors should think about the change, and give examples of its concrete impact. For policy RFCs, this section should provide an example-driven introduction to the policy, and explain its impact in concrete terms.

# Reference-level explanation
[reference-level-explanation]: #reference-level-explanation

This is the technical portion of the RFC. Explain the design in sufficient detail that:

- Its interaction with other features is clear.
- It is reasonably clear how the feature would be implemented.
- Corner cases are dissected by example.

The section should return to the examples given in the previous section, and explain more fully how the detailed proposal makes those examples work.

# Drawbacks
[drawbacks]: #drawbacks

Why should we *not* do this?

# Rationale and alternatives
[rationale-and-alternatives]: #rationale-and-alternatives

- Why is this design the best in the space of possible designs?
- What other designs have been considered and what is the rationale for not choosing them?
- What is the impact of not doing this?

# Prior art
[prior-art]: #prior-art

Discuss prior art, both the good and the bad, in relation to this proposal.
A few examples of what this can include are:

- For language, library, cargo, tools, and compiler proposals: Does this feature exist in other programming languages and what experience have their community had?
- For community proposals: Is this done by some other community and what were their experiences with it?
- For other teams: What lessons can we learn from what other communities have done here?
- Papers: Are there any published papers or great posts that discuss this? If you have some relevant papers to refer to, this can serve as a more detailed theoretical background.

This section is intended to encourage you as an author to think about the lessons from other languages, provide readers of your RFC with a fuller picture.
If there is no prior art, that is fine - your ideas are interesting to us whether they are brand new or if it is an adaptation from other languages.

Note that while precedent set by other languages is some motivation, it does not on its own motivate an RFC.
Please also take into consideration that rust sometimes intentionally diverges from common language features.

# Unresolved questions
[unresolved-questions]: #unresolved-questions

- What parts of the design do you expect to resolve through the RFC process before this gets merged?
- What parts of the design do you expect to resolve through the implementation of this feature before stabilization?
- What related issues do you consider out of scope for this RFC that could be addressed in the future independently of the solution that comes out of this RFC?