Let Cargo put data into platform-specific directories #1615

Open
wants to merge 5 commits into
from

Projects

None yet
@tbu-
Contributor
tbu- commented May 14, 2016

(rendered)

@tbu-
Contributor
tbu- commented May 14, 2016

There's a stale pull request to do something like this: rust-lang/cargo#2127, I'll gladly update it if it is desired.

I figured that it might be big enough of a change to justify an RFC.

@steveklabnik steveklabnik commented on the diff May 14, 2016
text/1615-cargo-platform-standards.md
+```
+
+## Other unixy systems (Linux, BSDs)
+
+Here, we're following the XDG spec:
+
+```
+cache: .cache/cargo
+config .config/cargo
+binaries: .local/bin
+```
+# Drawbacks
+
+* This increases the complexity of where to find the files Cargo uses. This can
+ be alleviated by providing library functions for Cargo related tools and a
+ command line to tell which paths are in use.
@steveklabnik
steveklabnik May 14, 2016 Contributor

It's not just this though; it's also things like documentation, explaining how cargo works to the user, etc

@tbu-
tbu- May 14, 2016 Contributor

Good point, added to the section.

@plietar plietar and 2 others commented on an outdated diff May 16, 2016
text/1615-cargo-platform-standards.md
+
+## OS X
+
+```
+cache: Library/Caches/Cargo
+config: Library/Cargo
+binaries: Library/Cargo/bin
+```
+
+## Other unixy systems (Linux, BSDs)
+
+Here, we're following the XDG spec:
+
+```
+cache: .cache/cargo
+config .config/cargo
@plietar
plietar May 16, 2016

These should use the XDG_CONFIG_HOME and XDG_CACHE_HOME environment variables

@tbu-
tbu- May 16, 2016 Contributor

They are, perhaps I should clarify that a little. We're following the XDG spec, and by default it's these directories.

@Ericson2314
Ericson2314 May 17, 2016 Contributor

+1 on clarification.

@tbu-
tbu- May 18, 2016 Contributor

Done.

@withoutboats withoutboats and 3 others commented on an outdated diff May 16, 2016
text/1615-cargo-platform-standards.md
+
+## Windows
+
+We'll obtain each of the following directories using the correct API.
+
+```
+cache: AppData\Local\Temp\Cargo
+config: AppData\Roaming\Cargo
+binaries: AppData\Local\Programs\Cargo
+```
+
+## OS X
+
+```
+cache: Library/Caches/Cargo
+config: Library/Cargo
@withoutboats
withoutboats May 16, 2016

I'm currently using OS X, and the config for all of the CLI tools I have any interest in configuring are stored somewhere under my home directory. I've never touched a config file under Library.

@tbu-
tbu- May 16, 2016 Contributor

I don't know a lot about OS X. Isn't there a Library folder in the home directory as well?

@Sean1708
Sean1708 May 16, 2016

Others may disagree but in my experience the unwritten rule of OSX is that GUI apps use ~/Library and CLI apps use unixy locations.

@withoutboats
withoutboats May 16, 2016

My CLI tools configs and caches are all at the same location as they'd be on Linux, including some that are following XDG.

@plietar
plietar May 16, 2016

Homebrew uses /Library/Caches/Homebrew/ and pip ~/Library/Caches/pip/, so I guess both could be valid.
On the other hand, configuration should definitely use XDG.

@withoutboats

I personally think all CLI tools should adopt XDG on all *nix platforms as the only reasonable attempt at a standard that anyone's produced. There's no actual standard on any *nix platform as far as I know, and I don't see a way that storing the files in the way specified by XDG is worse than storing them in ~/.cargo and ~/.rustup.

I don't think that Rust tools should do something different on OS X from what they do on other *nixen, for the reasons cited in the issue.

@tbu-
Contributor
tbu- commented May 16, 2016

@withoutboats Indeed, and that's also what pip does. I've written this alternative down in the Alternatives section.

@excaliburHisSheath excaliburHisSheath and 1 other commented on an outdated diff May 16, 2016
text/1615-cargo-platform-standards.md
+Currently, Cargo puts all its files in a directory named `.cargo` below the
+home directory of the user. Using this proposal, it would reuse existing
+standard directories of the host platform. This allows other tools oblivious to
+Cargo to function in the best way. Using standard directories is the best way
+to go unless there are concrete reasons for not doing so, otherwise Cargo just
+adds complexity to all systems that try to interoperate with it. Benefits
+include:
+
+* Using a standard directory for binary outputs can allow the user to execute
+ Cargo-installed binaries without modifying their `PATH` variable. E.g. on
+ Fedora this is apparantly already the case, in Debian there's a ticket to
+ include it.
+* Putting caches in designated cache directories allows backup tools to ignore
+ them.
+* Using a `.cargo` directory on Windows is not idiomatic at all, no programs
+ for Windows would such a directory.
@excaliburHisSheath
excaliburHisSheath May 16, 2016

Typo: "no programs for Windows would such a directory".

@tbu-
tbu- May 16, 2016 Contributor

Fixed.

tbu- added some commits May 16, 2016
@tbu- tbu- Fix a typo 170edb7
@tbu- tbu- Use XDG on OS X as well
This swaps an alternative with the appropiate section in detailed
design.
38f82c4
@tbu-
Contributor
tbu- commented May 16, 2016 edited

@withoutboats I exchanged the plan for OS X with one of the alternatives. Now everything is the same across non-Windows platforms and only Windows differs.

@fenhl
fenhl commented May 18, 2016

Another huge upside to this is that it removes clutter from ~.

@liigo
Contributor
liigo commented May 20, 2016 edited

so it interacts well with other tools on that platform

Could you elabrate? What tools will interacts well (better) with Cargo, and why?

Edit: cache or disk cleanup tools will benifit at least, as the motivation section said.

@alexcrichton
Member

One drawback that may want to be added to this is that there are a good number of other apps and such which don't follow the XDG spec on Linux, and likely for their own "good reasons". This in turn means that if one day the spec becomes widely adopted it will likely need to be changed in one form or another. Put another way, many other major projects aren't following this spec, and to follow the spec it's quite likely that it'll need some sort of breaking change in one way or another. It's seems like it may be risky to hitch ourselves to this bandwagon?

Also, are there any other apps which follow XDG on OSX? Is the spec even defined for OSX? I'd be quite hesitant to follow a Linux spec on OSX as it seems like we'd just be winding up in the same situation of OSX users thinking that we're not doing the "native thing"

@sfackler
Member

@alexcrichton On my MacBook, I have "configstore", "fish", "git', "gtk-2.0", "htop", and "nvim" directories in my ~/.config.

@Ericson2314
Contributor

On Linux, my impression is that all per-app dotfiles/dotdirs either predate or are done in ignorance of the XDG spec. Separating configuration from caching is quite useful and I cannot envision any downsides.

@reddraggone9

On Linux, my impression is that all per-app dotfiles/dotdirs either predate or are done in ignorance of the XDG spec.

That's been my experience as well. @alexcrichton Are you aware of any projects that would follow the spec if some sort breaking change were implemented? Most cases I've seen where it was brought up and rejected were due to inertia.

@jmesmon
jmesmon commented May 24, 2016 edited

@alexcrichton on linux:

% ls .config 
Trolltech.conf  d-feet   gconf     gtk-2.0  i3status      octave    radare2     xbuild
chromium        dconf    git       htop     menus         pianobar  systemd     xfce4
configstore     freerdp  gpicview  i3       monitors.xml  pulse
% ls .cache 
bower                                                                            fontconfig     mozilla
chromium                                                                         g-ir-scanner   msmtp.log
dconf                                                                            gitg           pacaur
dmenu_run                                                                        gstreamer-1.0  pip
event-sound-cache.tdb.4e8b8a8a9ece45529a7ea0bb66e3f2b7.x86_64-unknown-linux-gnu  guile          xsession-errors-:0.0
event-sound-cache.tdb.two.x86_64-unknown-linux-gnu                               jedi

Is there a specific program with issues with xdg that you're thinking of?

@liigo
Contributor
liigo commented Jun 21, 2016 edited

From the RFC text:

Benefits include:

  • [1] Using a standard directory for binary outputs can allow the user to execute Cargo-installed binaries without modifying their PATH variable. E.g. on Fedora this is apparantly already the case, in Debian there's a ticket to include it.
  • [2] Putting caches in designated cache directories allows backup tools to ignore them.
  • [3] Using a .cargo directory on Windows is not idiomatic at all, no programs for Windows would use such a directory.
  • [4] Platform specific clean-up tools such as the Disk Cleanup Wizard work with Cargo (it wouldn't be very useful to try to modify the Wizard instead of Cargo to make this work).

[1]: the installer can/already do this (one off job). not a benefit.
[2]: to make 3rd-party tools happy.
[3]: git uses .git, difficult to say it's wrong. not a benefit.
[4]: to make 3rd-party tools happy.

So, there is only one benefit: to make 3rd-party tools happy, to help them find/clean cargo's cache data.

And this is not a benefit for us, the users and developers of cargo. We get little benefit on this.

But it will make difficulty to our life: we must remember more dirs, if we want to find them; we must do more os-specific work to implement it and maintain it; we can't easily create a portable cargo that all in one directory.

One more thing: it's not clear what will be put into cache directory. (e.g. Will .cargo\registry in cache? Will some of target/debug/* in cache?)

(XDG spec is nice. But what's the benefit if we follow it?)

@fenhl
fenhl commented Jun 21, 2016

@liigo It is not the only benefit. See my comment from earlier. This should also be added to the RFC text.

@tbu-
Contributor
tbu- commented Jun 21, 2016 edited

@liigo

[1]: the installer can/already do this (one off job). not a benefit.
[2]: to make 3rd-party tools happy.
[3]: git uses .git, difficult to say it's wrong. not a benefit.
[4]: to make 3rd-party tools happy.

[1] is a benefit because that way, you don't end up with a path in $PATH for each package manager you have.
[3] Just because git does it wrong, doesn't mean that we can't do it right.
[2] and [4] is not to make 3rd party tools happy, but to make Cargo work with them.

I think it's pretty clear that all of these are benefits. Whether they're worth the trade-off is what the RFC discussion should be about, but claiming that they aren't benefits isn't really helping.

EDIT: Regarding making 3rd party tools happy vs interacting with them: I as a user would be happy if the backup tool would know to ignore the Cargo cache. This is not for the benefit of the 3rd party tool, but for the benefit of me, the user of Cargo.

@withoutboats

@liigo as a cargo user who sometimes uses other tools also, making cargo interoperate with them better definitely makes my life better. :-)

@alexcrichton
Member

@reddraggone9

@alexcrichton Are you aware of any projects that would follow the spec if some sort breaking change were implemented?

To me it seems like everyone would want to implement the change but may not be able to. If no one actually implements it then no one's following the spec, which seems to defeat the purpose of having it in the first place?

It seems to me that if updates can't happen, then the spec is frozen as-is today. Then if it's frozen as-is there are major tools which have good reasons for not following it, and there's little hope for those reasons to get resolved?


@jmesmon

Is there a specific program with issues with xdg that you're thinking of?

Looking in my home folder, programs which don't follow xdg include:

  • ssh
  • rubygems
  • bundler
  • npm
  • git (maybe)
  • zsh/bash
  • pip
  • docker
  • cmake
  • ccache

Notably including many other languages' package managers.


I forget if this has been brought up before, but I've at least discussed it with others. The point about operating with third-party programs is also an interesting one. There are programs which don't follow XDG, so any robust third-party program would already have to handle non-conforming programs with some heuristics. In that sense you may not actually get any benefit at all if Cargo follows XDG because the heuristics are already correctly classifying Cargo. If Cargo isn't falling in the right bucket but could easily do so for some popular programs, that would also be a reasonable course of action I think.

@tbu-
Contributor
tbu- commented Jul 5, 2016

Both pip and git support XDG.

The point about operating with third-party programs is also an interesting one. There are programs which don't follow XDG, so any robust third-party program would already have to handle non-conforming programs with some heuristics.

I use rsnapshot for backups. The heuristic is the user adding exceptions on their own. It would be much nicer if Cargo didn't need an exception.


I mentioned advantages and disadvantages in the RFC. It seems that at least the advantages are real for some users. Maybe the discussion should focus on how to weigh these arguments against each other. Especially on Windows, there seems little resistance against using the Windows-specific directories.

@reddraggone9

@alexcrichton

To me it seems like everyone would want to implement the change but may not be able to.

Not everyone. For some programs which have been around longer than I've been alive, following the XDG spec as a fallback would be a change in functionality that has worked for decades. Inertia gets in the way there. "If it ain't broke, don't fix it." I'm not aware of any project that has been told about the spec and decided not to follow it but would have followed it if the spec had X changed where X wasn't just keep doing what already works.

If no one actually implements it then no one's following the spec, which seems to defeat the purpose of having it in the first place?

People do implement it:

$ ls .config
abrt                          goa-1.0        Pinta
anjuta                        google-chrome  ppsspp
autostart                     gtk-2.0        pulse
beets                         gtk-3.0        QtProject.conf
cef_user_data                 gvbam          ranger
Clementine                    hexchat        retroarch
CuteMarkEd Project            htop           Rygel
dconf                         ibus           rygel.conf
dleyna-renderer-service.conf  imsettings     sealert.conf
dleyna-server-service.conf    inkscape       sonata
easytag                       insta-site     syncthing
enchant                       jstest-gtk     systemd
eog                           keepnote       tilda
epiphany                      libreoffice    tomboy
evince                        libvirt        totem
evolution                     markdownlint   tracker
filezilla                     menus          Trolltech.conf
gambatte                      mimeapps.list  unity3d
gconf                         monitors.xml   user-dirs.dirs
gedit                         mono.addins    user-dirs.locale
gespeaker                     MonoGame       VirtualBox
git                           mopidy         vlc
gnome-boxes                   mpv            watch-later
gnome-builder                 mupen64plus    yelp
gnome-control-center          myapp          youtube-dl
gnome-initial-setup-done      nautilus       Zeal
gnome-session                 nvim
gnote                         PCSX2

Just not everyone:

$ ls -d .?*
..              .git-credential-cache  .lastpass        .rbtools-cookies
.adobe          .gitk                  .lesshst         .sdkman
.bash_aliases   .gnome                 .local           .serverauth.22085
.bash_history   .gnupg                 .m2              .serverauth.4384
.bash_logout    .gradle                .macromedia      .speech-dispatcher
.bashrc         .grails                .mozilla         .ssh
.cache          .grails_history        .multirust       .subversion
.cargo          .groovy                .netrc           .Xauthority
.config         .gstreamer-0.10        .npm             .xinitrc
.emacs.d        .ICEauthority          .nvimlog         .xsel.log
.esd_auth       .idlerc                .pki             .zshrc
.exercism.json  .inputrc               .profile
.gimp-2.8       .java                  .python_history

It seems to me that if updates can't happen, then the spec is frozen as-is today. Then if it's frozen as-is there are major tools which have good reasons for not following it, and there's little hope for those reasons to get resolved?

If you're going to make that argument, having at least one example would be nice. You have a point about most other languages' package managers though. You can add sdkman to the list.

@jmesmon
jmesmon commented Jul 5, 2016

@alexcrichton

I asked about programs that have issues with XDG, not ones simply that don't impliment it. I'm looking for a downside, a complication, that would cause a program to actively avoid XDG.

Right now one hasn't been presented.

there are major tools which have good reasons for not following it

I don't believe that is the case. At the least, no one has noted a reason (other than a program being old or inertia) that things don't impliment it. Please let us know if there is some reason you're aware of.

@brson
Contributor
brson commented Jul 12, 2016

My opinions on this subject (not commenting directly on the content of the RFC, which I've only skimmed - sorry).

I think we should change where .cargo is located on windows. With back-compat code to support old installs. We chose the wrong place to put this directory. It should keep the .cargo name for consistency across platforms.

It's important for consistency that users can find Rust tools in expected places. There is no universal agreement on Unixes about the future of the XDG spec, and we should not use it by default. For those that want XDG we should consider making it optional.

@rkjnsn
Contributor
rkjnsn commented Jul 14, 2016

@brson

we should not use it by default

Why not? On Linux, at least, it seems to be quite popular. I've seen several applications I use move toward using it, and I haven't noticed any moving away. It keeps my home directory much less cluttered.

@jmesmon
jmesmon commented Jul 14, 2016 edited

@brson

The xdg directory spec (for user configuration and caching) isn't really something that needs support from the OS.

It'd be really unfortunate to hurt our manageability on all unixes just because OS X doesn't explicitly support XDG (that is what "no universal agreement" is referring to, right? I haven't seen any thing that is actually hostile to the xdg directory spec).

@Ericson2314
Contributor
Ericson2314 commented Jul 14, 2016 edited

People could use the XDG environment variables to stick their mac config in the Library directory (or where it normally goes, I don't have a mac). Then we both have a single Unix policy and everything is in its proper place. Win, win!

@withoutboats
withoutboats commented Jul 14, 2016 edited

It's important for consistency that users can find Rust tools in expected places. There is no universal agreement on Unixes about the future of the XDG spec, and we should not use it by default. For those that want XDG we should consider making it optional.

I don't understand this argument. Why do we care if OS X doesn't "support" it? Applications that conform to XDG work fine on Mac OS X, which has no consistent policy about where these files should go.

I agree that all Unixes should use the same location (which is what the RFC currently proposes as I recall); I see no argument in favor of making that location not the location specified by XDG.

@brson
Contributor
brson commented Jul 14, 2016

Why not? On Linux, at least, it seems to be quite popular. I've seen several applications I use move toward using it, and I haven't noticed any moving away. It keeps my home directory much less cluttered.

I have said this many, many times. It makes it harder for users to predict where their cargo stuff is. If every platform puts their stuff in a different place it makes for a less consistent experience. It makes life more difficult for people using Rust on many platforms (which is something we expect - Rust is aggressively cross-platform).

@Ericson2314
Contributor
Ericson2314 commented Jul 14, 2016 edited

@brson I think one point people are making, is that on unix (linux, mac or otherwise) ~/.config/foo is no less predicable---standards aside both forms are common at this point and people expect either. You mention "there is no universal agreement on Unixes about the future of the XDG spec", but to the best of my knowledge, the unices have a horrible track record of agreeing on any new functionality, and so as a practical matter such "universal agreement" will never occur.

I think we should change where .cargo is located on windows. With back-compat code to support old installs. It should keep the .cargo name for consistency across platforms.

Furthermore If we adopted ~/.config/cargo/ everywhere on Unix by default, then we could also drop the . on windows---being both consistent across platform observing the conventions of Windows at the same time. The universal convention in fact would be <personal config location>/cargo.

@nagisa
Contributor
nagisa commented Jul 14, 2016 edited

I get to scan the output of ls -alh on my ~ more often than I really should – many times more than I have to edit cargo config (0 times so far) or look at cargo’s cache (2 or 3 times so far) – and lack of .cargo in there would certainly help me with having to scan 1 line less every time I have to do it.

I even use Windows once in a while to run cargo and I really couldn’t care less if cargo stuff there isn’t in %userprofile%/.cargo, or that it isn’t in ~/.cargo on OS X, because I have no expectation of it being there in the first place.

@withoutboats
withoutboats commented Jul 14, 2016 edited

I have said this many, many times. It makes it harder for users to predict where their cargo stuff is. If every platform puts their stuff in a different place it makes for a less consistent experience.

The RFC proposes putting these files in the XDG compliant location on all UNIX platforms. It does not propose fragmenting the location of these files more than UNIX vs Windows.

I already have programs following XDG on both my Mac and my Arch systems (more on Arch).

@Diggsey
Contributor
Diggsey commented Jul 16, 2016

This is clearly the right thing to do for windows platforms.

I strongly disagree with the argument that "not everyone else follows the spec, so we shouldn't either" - if there were no history behind this choice, the XDG spec would clearly be a better option than the alternative. If we're going to favour tradition above the many benefits it provides, shouldn't we all still be using C++?

Postponing this transition is just going to make things harder in the future - I think it's inevitable that we'll want to make this change eventually.

@tbu- tbu- referenced this pull request in rust-lang/cargo Jul 16, 2016
Closed

Make Cargo obey platform-specific directory standards #2127

@iliekturtles

I'm in favor. I don't like ~ being filled with each application's own special directory and Windows has well defined locations. If folders are in the appropriate location for the host OS I think that would be easier for a user to predict.

@Alexander--
Alexander-- commented Jul 16, 2016 edited

As I previously stated in the #2127 , there are multiple issues with this RFC.

It mixes up concepts of XDG user directories (open standard, fully configurable by user via environment variables), Windows "standard" directories (serves different purposes, may sometimes be configurable via registry) and SystemD standard directories (why would anyone want to use these?) Consequently, individual points are poorly researched. The answer to "How do Cargo users benefit from this RFC" sounds unsatisfactory for me.

As a precedent, this RFC mentions a couple of software projects, implementing parts of some of the listed standards. Yet, it fails to mention overwhelming amount of software, which does not follow either all or some of listed proposals. Specifically, this RFC does not deal with, nor mention the fact, that many cross-platform programs will keep using XDG or their homebrew conventions on Windows, but no known cross-platform programs will use Windows conventions on Mac or Linux. In my opinion there may be a few reasons for that:

  1. Sometimes consistency and predictable behavior are of huge value by themselves.
  2. Many will pick and adopt things they find reasonable from standards without blindly following every advice they come across (for instance using .config and, to lesser extent .cache directories is very widespread, while practice of placing anything under .local/bin is nearly non-existent).
  3. Different platform conventions have different goals in mind. XDG have historically followed the path of configurability and aimed to simplify life of users, where by "users" one would mean "anyone, capable of using environment variables". The goals behind Windows and SystemD conventions aren't as clear for me, but their target auditory and purposes are understandably different.

As someone, who is forced to use Windows alongside with Linux on regular basis, and occasionally would use Mac (but, probably, not for Rust development), I would be rather inconvenienced, if this RFC got implemented in it's current state.

In my opinion, the only way to work around the shortcomings of this RFC is splitting it into separate RFCs, dealing with individual issues at hand: an RFC about XFG directory layout, one about Windows directory layout, another for Mac directory layout, SystemD directory layout etc. That would allow those proposals to better reach their target audience and make possible constructive discussion of their technical sides (as opposite to whatever is currently going on in this thread).

@SShrike
SShrike commented Jul 16, 2016 edited

@Alexander--

It mixes up concepts of XDG user directories [...] SystemD standard directories (why would anyone want to use these?)

What "SystemD standard directories" are you talking about may I ask?

All I see in the RFC are .cache/cargo, .config/cargo, and .local/bin, with the first two being part of the BaseDir specification and the last one being an emerging informal addition to the specification (used by the likes of Python's Pip as stated in the RFC).

@Alexander--
Alexander-- commented Jul 17, 2016 edited

@SShrike

When some software project does something their own way, that does not automatically become "informal addition" to any specifications. Even if that "someone" is (behold!) one of Python packaging frameworks. At most, that's a local quirk, unless proven otherwise.

A specification by definition must have a body and endorsers.

The mentioned local quirk does not belong to XDG standard body and, as far as I am aware, have never been proposed to XDG mailing lists (and IMO, it wouldn't have stood a critical review, if it were). Whoever calls it a "part of XDG" is trying to ride on XDG name, when, in fact, you have no basis to do so.

On other hand, the only documentation of such quick so far is found in SystemD manuals. The largest party, that "endorses" such behavior is Red Hat, by putting a single reference to .local/bin into user's .skel files of it's Fedora Linux distribution. And we all know, that Red Hat software development team and authors of SystemD are the same people.

How does any of this make .local/bin an XDG directory? Honestly, I am already giving it too much credit by calling that a "SystemD sdandard". In practice, it is more likely a personal preference of author of this RFC.

@SShrike
SShrike commented Jul 17, 2016 edited

@Alexander-- I think simply answering the question along the lines of "The only documentation found endorsing ~/.local/bin is the SystemD manual" would've sufficed.

@Alexander--
Alexander-- commented Jul 17, 2016 edited

@SShrike interestingly, the author of this RFC have previously referred to use of .local/bin as if it was a prominent addition to XDG spec in this discussion. Seems like using the same domain for hosting both XDG specification and SystemD documentation have lead multiple people to make this kind of false assumptions.

@tbu-
Contributor
tbu- commented Jul 17, 2016

interestingly, the author of this RFC have previously referred to use of .local/bin as if it was a prominent addition to XDG spec in this discussion.

Duh. The systemd thing was linked in the original post, and I forgot to include it in this RFC (the discussion has been going on for more than half a year already, it's not that unlikely that things will get lost).

The .local/bin feels like the natural extension of .local/share, which is mentioned in the XDG standard; akin to /usr/bin to /usr/share. Somewhere in this thread is a reference that Fedora (?) wants to put .local/bin into the path, which would make Cargo executables callable by default, on other distributions the user can decide on their own whether they want that, and in that respect is no worse than .cargo/bin.

@ollie27 ollie27 commented on the diff Jul 17, 2016
text/1615-cargo-platform-standards.md
+2. Otherwise, if the platform-specific directories exist, use them.
+3. If that's not the case, check whether the legacy directory exists (`.cargo`)
+ and use it in that case.
+4. If everything else fails, create the platform-specific directories and use
+ them.
+
+This makes Cargo use platform-specific directories for new installs while
+retaining compatibility for the old directory layout. It also allows one to
+keep all Cargo related data in one place if one wishes to.
+
+## Windows
+
+We'll obtain each of the following directories using the correct API.
+
+```
+cache: AppData\Local\Temp\Cargo
@ollie27
ollie27 Jul 17, 2016

I think this should be %LOCALAPPDATA%\Cargo as I think %TEMP% is more for things that will be deleted by the time the program closes but the Cargo cache is useful for subsequent executions.

@tbu-
tbu- Jul 17, 2016 Contributor

Using %TEMP% has the advantage that disk cleaners know about this directory.

@ollie27
ollie27 Jul 17, 2016

That's true but I would hope that Cargo can manage it's own cache. Do you have any examples of other software using %TEMP% like this? For example Firefox and pip both store their caches in %LOCALAPPDATA%.

@tbu-
tbu- Jul 17, 2016 Contributor

Dunno, maybe look at Internet Explorer or Edge.

@ollie27
ollie27 Jul 17, 2016

IE's cache is in %LOCALAPPDATA%\Microsoft\Windows\INetCache and Edge's is in %LOCALAPPDATA%\Packages\Microsoft.MicrosoftEdge_8wekyb3d8bbwe.

@ollie27 ollie27 referenced this pull request in rust-lang-nursery/rustup.rs Jul 17, 2016
Open

Consider moving to platform-specific configuration directories #247

@Alexander--
Alexander-- commented Jul 18, 2016 edited

The .local/bin feels like the natural extension of .local/share, which is mentioned in the XDG standard;

Not quite. As far as this practical application go, this is a natural extension of so-called "DLL hell", a well-known design decision to put all your independently managed executables in single directory. Because what can possibly go wrong?

@Ericson2314
Contributor
Ericson2314 commented Jul 18, 2016 edited

@Alexander-- I think it's a little harsh to call a directory of executables dynamic linked library hell. executable are not loaded by other executable.

@Alexander--

@Ericson2314 Indeed, because this is actually worse, than classic DLL hell. Thanks to existence of sonames, reenacting classic DLL hell from early 90's era with dynamic libraries would be rather hard. But if we talk about executables…

@jonas-schievink

Because what can possibly go wrong?

Well, what can go wrong? Can you elaborate a bit, @Alexander--?

@brson
Contributor
brson commented Jul 18, 2016

@brson I think one point people are making, is that on unix (linux, mac or otherwise) ~/.config/foo is no less predicable---standards aside both forms are common at this point and people expect either. You mention "there is no universal agreement on Unixes about the future of the XDG spec", but to the best of my knowledge, the unices have a horrible track record of agreeing on any new functionality, and so as a practical matter such "universal agreement" will never occur.

@Ericson2314 Huh, replacing ~/.cargo/config with ~/.config/cargo with the intent of conforming to XDG seems particularly weird to me. Cargo's scheme with .cargo/config is more intricate than just looking in $HOME/.cargo/config - it traverses the file system looking for this file. So even if cargo used that naming scheme it would be going beyond that and putting that same file in places that XDG does not specify. Conflating the XDG-mandated behavior with the Cargo-mandated behavior seems like a recipe for confusion.

Furthermore If we adopted ~/.cargo/config everywhere on Unix by default, then we could also drop the . on windows---being both consistent across platform observing the conventions of Windows at the same time. The universal convention in fact would be /cargo.

I think you must have meant ~/.config/cargo here, but I don't follow your conclusion. Cargo stores more than just the contents of the config file and they have to go somewhere. And furthermore, we can drop the . on windows regardless of the unix scheme.

The RFC proposes putting these files in the XDG compliant location on all UNIX platforms. It does not propose fragmenting the location of these files more than UNIX vs Windows.

I appreciate that following the same scheme on Unix allows for consistency everywhere except Windows, but why do you think following XDG on Macs, and every Unix system, is the right thing to do? Certainly the XDG scheme is not the official config scheme on macs. @tbu- can you add a drawback, that this uses a non-standard configuration scheme on mac?

It mixes up concepts of XDG user directories (open standard, fully configurable by user via environment variables), Windows "standard" directories (serves different purposes, may sometimes be configurable via registry) and SystemD standard directories (why would anyone want to use these?) Consequently, individual points are poorly researched. The answer to "How do Cargo users benefit from this RFC" sounds unsatisfactory for me.

@Alexander-- can you say more about how it conflates these concepts? It's not obvious to me. Particular re systemd - the RFC doesn't mention it.

@brson
Contributor
brson commented Jul 18, 2016

@tbu- re the first motivation bullet:

Using a standard directory for binary outputs can allow the user to execute Cargo-installed binaries without modifying their PATH variable. E.g. on Fedora this is apparantly already the case, in Debian there's a ticket to include it.

ISTM from both your own writing here and other comments that .local/bin is not well-supported by distros. Can you add that as a drawback please? Would be good to have more concrete info about which OSes support this or plan to (I'm guessing Mac never will).

@tbu-
Contributor
tbu- commented Jul 18, 2016

@brson Cargo has a special case for looking at ~/.cargo/config, it looks there even if it is not a parent directory of the current working directory.

Is there a official config scheme on Mac that people can agree on? It seems XDG is one valid choice, see e.g. git.

Re .local/bin not being in everyone's PATH by default: The location is surely better than .cargo/bin which might only be in PATH for current Cargo users. How is it a disadvantage?

@tbu-
Contributor
tbu- commented Jul 18, 2016

@brson For the link to systemd, see the PR that this RFC spawned off from. .local/bin is not mentioned in the XDG spec, it's "only" the natural extension and mentioned in said systemd document. I will update the RFC to include that when I find the time.

@frewsxcv
Member

Is there a official config scheme on Mac that people can agree on? It seems XDG is one valid choice, see e.g. git.

If you're looking for opinions here, I vote ~/.cargo. I don't see any downsides to keeping it directly in the home directory.

@tbu-
Contributor
tbu- commented Jul 18, 2016

@frewsxcv I'm explicitly not looking for opinions. I'm saying that XDG is a possible standard for Mac, and that I don't know of any standard that everyone can agree on.

@frewsxcv
Member
frewsxcv commented Jul 18, 2016 edited

I don't know of any standard that everyone can agree on.

Neither do I, and I don't think Apple has a standard regarding this. They do seem to have recommendations for directories for Apps (like /Library/Application Support) which we should definitely not follow in my opinion.

@fenhl
fenhl commented Jul 18, 2016

If you're looking for opinions here, I vote ~/.cargo. I don't see any downsides to keeping it directly in the home directory.

@frewsxcv It adds clutter to the home directory, which is a downside if you uss the shell or have Finder configured to show all files, and at the same time the configuration files are missing from the expected location.

@jmesmon
jmesmon commented Jul 18, 2016

@brson

regarding

.local/bin is not well-supported

It should be noted that it has the potential for more support than .cargo/bin. While fedora is (based on the discussion here) considering adding .local/bin to the path, I'm very doubtful that there is any plan to add language package manager specific paths to PATH. Might want to note that as a downside of using .cargo/bin (ie: using .local/bin is strictly an improvement when considering os/distro support).

@Ericson2314
Contributor
Ericson2314 commented Jul 18, 2016 edited

@brson

Huh, replacing ~/.cargo/config with ~/.config/cargo with the intent of conforming to XDG seems particularly weird to me..

@brson Cargo has a special case for looking at ~/.cargo/config, it looks there even if it is not a parent directory of the current working directory.

Wow! I once wondered about whether that special case existed---the docs at http://doc.crates.io/config.html#hierarchical-structure are extremely unclear as to that point. I think using a different naming scheme for the home directory would make the special casing a lot more intuitive---@tbu- IMO this de-obfuscation is worth adding to the RFC as extra motivation.

I think you must have meant ~/.config/cargo here, but I don't follow your conclusion.

Haha yes I did, edited in OP.

Cargo stores more than just the contents of the config file and they have to go somewhere. And furthermore, we can drop the . on windows regardless of the unix scheme.

I was referencing your earlier post which said:

"I think we should change where .cargo is located on windows. With back-compat code to support old installs. We chose the wrong place to put this directory. It should keep the .cargo name for consistency across platforms."

The point being with this RFC we can be consistent and compliant with respect to .cargo vs cargo. Based on the above discussion of per-directory config, and git's precedent, I think .cargo on all platforms for that.

I appreciate that following the same scheme on Unix allows for consistency everywhere except Windows, but why do you think following XDG on Macs, and every Unix system, is the right thing to do? Certainly the XDG scheme is not the official config scheme on macs.

Standards, conformity, etc aside, I think the config vs cache distinction is just useful. For example the college I went to has extremely tiny home directory quotas. So its common for students to go around deleting dot files willy-nilly when they need more space for a soon-due assignment. It's annoying to be without configuration you forget you set (and thus can't easily reset) when you just want to empty some caches.

While mac doesn't have official guidance, I consider .foo and .config/foo equally non-standard. Mac cases about the letter of POSIX not the spirit, and to my knowledge POSIX doesn't mention dotfiles whatsoever.

@brson
Contributor
brson commented Jul 19, 2016

Is there a official config scheme on Mac that people can agree on? It seems XDG is one valid choice, see e.g. git.

@tbu- Your previous PR suggested "On OS X, use ~/Library/Caches/Cargo for cache files, ~/Library/Cargo for config files and ~/Library/Cargo/bin for binary files." which looks more consistent with OS X norms.

Re .local/bin not being in everyone's PATH by default: The location is surely better than .cargo/bin which might only be in PATH for current Cargo users. How is it a disadvantage?

hm, I suppose it's not a disadvantage compared to the status quo, but it does not accomplish the stated goal of the RFC that "using a standard directory for binary outputs can allow the user to execute Cargo-installed binaries without modifying their PATH variable". Because we can't rely on having the system run bins in ~/local/.bin this claimed advantage is largely inactionable in practice - rustup will still have to arrange for the path to be represented in PATH. So I guess I'd prefer to remove that language from the RFC, or at least make it clear that our primary distribution mechanism - rustup - will have difficulty taking advantage of it and will not be able to simplify installation because of it.

@brson For the link to systemd, see the PR that this RFC spawned off from. .local/bin is not mentioned in the XDG spec, it's "only" the natural extension and mentioned in said systemd document. I will update the RFC to include that when I find the time.

Thanks.

It should be noted that it has the potential for more support than .cargo/bin. While fedora is (based on the discussion here) considering adding .local/bin to the path, I'm very doubtful that there is any plan to add language package manager specific paths to PATH. Might want to note that as a downside of using .cargo/bin (ie: using .local/bin is strictly an improvement when considering os/distro support).

Good point, but I think it would be good to get insight from a distro packager. Other language packagers have done similar things for local installations.

@brson Cargo has a special case for looking at ~/.cargo/config, it looks there even if it is not a parent directory of the current working directory.

Wow! I once wondered about whether that special case existed---the docs at http://doc.crates.io/config.html#hierarchical-structure are extremely unclear as to that point. I think using a different naming scheme for the home directory would make the special casing a lot more intuitive---@tbu- IMO this de-obfuscation is worth adding to the RFC as extra motivation.

@Ericson2314 I don't follow why this special case matters. In this new design wouldn't cargo still be looking either in ~/.config/cargo or .config/cargo (up the tree)? Or are you suggesting that Cargo would continue to look in ./cargo/config as well as ~/.config/cargo?

@jmesmon
jmesmon commented Jul 19, 2016 edited

@brson

wouldn't cargo still be looking either in ~/.config/cargo or .config/cargo (up the tree)? Or are you suggesting that Cargo would continue to look in ./cargo/config as well as ~/.config/cargo?

Second one. ~/.config/* in xdg is single location only, not each directory. git (which @Ericson2314 mentioned) operates like this: ./.git/* is used for repo-local things (ie: it's scattered throughout), ~/.git/* (for backwards compat) and ~/.config/git/* are used for user level (rather than repo-level) config. Cargo can follow essentially the same pattern.

Note that the current ~/.cargo/config file would likely become ~/.config/cargo/config to allow other potential future user-level configuration-ish items for cargo to be created (most items in ~/.config/ are per-program directories).

@withoutboats
withoutboats commented Jul 19, 2016 edited

@tbu- Your previous PR suggested "On OS X, use ~/Library/Caches/Cargo for cache files, ~/Library/Cargo for config files and ~/Library/Cargo/bin for binary files." which looks more consistent with OS X norms.

Further investigation showed that command line applications on Mac OS X almost universally do not follow this scheme, and it would be outside of the norms for cargo to follow it.

I don't want to accuse you of arguing in bad faith, but I can't help but notice that you are having it both ways here. Before you were against putting cargo files in in Library because it would be inconsistent across platforms, now you are suggesting that we should. Surely .cargo is no more consistent with this convention than XDG is.

@Ericson2314
Contributor

@brson yeah @jmesmon said it better than myself.

@Abdillah
Abdillah commented Oct 8, 2016

I know a transition would not come easy. But, the longer this status quo will be, the harder the implementation will be (expired patch, etc). The given patch has all the steps necessary steps for transition. So, I propose we should implement the XDG standard at least for Linux, as it is the XDG standard platform origin.

I wonder those who disagree with this RFC is using Linux. Coz, having too much dotfiles on the $HOME is no benefit at all 😢 . It's like when Windows user get their desktop full of hidden folders. You may be argued that $HOME and desktop is different thing. But, for Linux users (especially some who came and comment up there), $HOME is our desktop, which is the first place we land when opening up file manager or terminal.

In addition, some linux desktops now targeted to casual user (which still far from expectation). And actually this "Dot files problem", is going to be a barrier to them.

Hope the Best,
Abdillah

@tbu-
Contributor
tbu- commented Oct 28, 2016

Could we move this RFC into FCP? It's been almost a year since the initial pull request (2015-11-09), and the discussion is no longer active.

Preferrably, the answer from the core team would be one of these:

  1. We don't want to put Cargo's data anywhere else than ~/.cargo on unixy platforms, and UserDirectory.cargo on Windows. (status quo)
  2. We would move the Cargo directory (maybe just on some platforms), but we don't agree with the paths proposed here.
  3. We would move the Cargo directories to the paths specified here. (the RFC)

For 1), we can just close the corresponding issues in Cargo (rust-lang/cargo#1734, rust-lang/cargo#1976), for 2) motivated people could try to figure out what is wanted, for 3) we just implement this.

@tbu-
Contributor
tbu- commented Oct 28, 2016

My personal opinion in a different comment: I hope we don't close this as "too late", because the chance to merge this earlier was there for a long time... This change would probably also convince Cargo-related tools to store their things in the platform-specific directories. :)

Also, on unixy operating systems, the XDG spec is not only respected by desktop applications: E.g. fish, git, neovim (not the original vim though), rr (the Mozilla record&replay debugger), ... :)

@liigo
Contributor
liigo commented Oct 29, 2016

An explicit uniform root directory is great for Cargo and Rust, so people can find everything inside it easily. We should keep using .cargo(CARGOHOME). Symlinks may be created for subdirectories, then the real positions can be everywhere, then it's possible to implement xdg spec (or not, which I don't care). XDG isn't a mandatory spec.

@flying-sheep

don't restart the discussion please. people want this, the only reason @tbu- mentioned fish, git, neovim, and rr is because nobody brought that before – your argument has been brought and debunked before.

@tbu-
Contributor
tbu- commented Oct 30, 2016

The argument has indeed been brought up before, and is listed in the Disadvantages section in the RFC text.

@flying-sheep

and i still don't buy it.

  1. having binaries in a non-standard path is useless – they have to be specified by full path (who wants that) or be in your PATH, which works best with fewer entries. and ~/.local/bin is more universal than XDG (python does it, and ./config --prefix=~/.local is common)
  2. ~/.cache is ideal. having several infinitely growing directories in HOME would suck. please tell me cargo doesn’t use ~/.cargo for its cache, that would be real bad
  3. all that remains is ~/.config/cargo which i much prefer to ~/.cargo: easier backup/share tool configs, says what it is, not in the same directory as Documents/…
@jonas-schievink jonas-schievink referenced this pull request in rust-lang/cargo Nov 13, 2016
Closed

Clean separation of cache and user data #3290

@tbu-
Contributor
tbu- commented Nov 16, 2016

We're now over a year old.

@alexcrichton What needs to be done for this to progress? Can we move this into FCP? What is missing for this?

@petrochenkov
Contributor

@tbu-

We're now over a year old.

I hope we don't close this as "too late", because the chance to merge this earlier was there for a long time...

<tin_foil_hat=on>What if that is the plan. Wait long enough, then close it as "too late".</tin_foil_hat>

@flying-sheep

no, they’d never do that, they’re an honest bunch

@nikomatsakis
Contributor
nikomatsakis commented Nov 22, 2016 edited

So I've been trying to catch up on this thread (and on the background issues: I had never heard of XDG before). Since this conversation has been going on now for over a year -- and a significant part of it seems to have taken place in a PR -- I want to produce a kind of summary that I think captures the current state of the conversation. This writeup is not intended to reflect my personal POV; after posting this comment, I will also post my own thoughts.

The status quo

Cargo has a need to store various bits of data. Currently, except for configuration, this is always stored in ~/.cargo, where ~ represents the home directory of the current user. The location of configuration files is more complex and will be described shortly.

Of the files in ~/.cargo, two of them are "known to the user":

  • ~/.cargo/config: user configuration (user may want to edit this)
  • ~/.cargo/bin: binaries compiled by cargo install, as well as the toolchain installed by rustup (user probably wants this on their path, though rustup tries to add it automatically)

There are two additional directories containing internal cargo state. Both of these are caches, in that the data in them can always be reconstructed by downloading stuff from the internet.

  • ~/.cargo/git: cache for git data containined dependency sources
  • ~/.cargo/registry: a clone of the registry plus some add'l stuff

Locating cargo configuration. In addition to the "user configuration" in their home directory, cargo also allows directories to override the configuration at any point. To find the config file, then, it first traverses the directory hierarchy. If no configuration is found anywhere, then it ultimately checks the user's home directory (note that this is typically visted when traversing the parents of the current directory, but not necessarily).

Relation to other programs

This RFC does not discuss other programs. However, changes to the status quo will naturally affect other programs. The most obvious one of these is rustup. rustup manipulates the files in ~/.cargo as follows:

  • it installs its own rustc, cargo, etc in the ~/.cargo/bin directory
    • these are shims which read rustup configuration and redirect to ~/.multirust/<toolchain> as needed

The problem

There are some downsides to the current setup:

  • This layout is specific to cargo. As a consequence, the user may have to intervene to make everything work:
    • ~/.cargo/bin is not automatically on their PATH; rustup must add it
    • backup programs won't skip over ~/.cargo/git and ~/.cargo/registry automatically
    • hapless university students that apparently delete files at random may, well, delete their files
      • sorry, I found this sort of amusing: somebody tell those poor students about du!
  • This layout clutters the home directory. The impact of this varies by platform.
    • On Windows, in particular, .foo files are uncommon and not treated specially by Explorer. So this feels alien.
      • Point of information: What do other tools, such as PIP, do?
    • On Unix, it can be annoying, but it's not atypical (after all, the traditional Unix "standard" has been "put something in ~ that starts with .", and hence ls, glob expansion, etc ignore . files by default)
    • On Mac, these files are hidden in the Finder, so it's not any more annoying than Unix.

Proposed solution

The proposed solution is try and adopt the conventions of the host platform, if they exist. Frequently, this means taking the data that was combined into ~/.cargo and separating it. More specifically:

  • On linux, adopt the "PIP flavor" of the XDG specification:
    • configuration data in ~/.config/cargo
    • git/registry caches in ~/.cache/cargo/git and ~/.cache/cargo/registry respectively, I imagine
    • binaries in ~/.local/bin
  • On windows, put data in a location that is relative to %LOCALAPPDATA% or something
    • there seems to be some dispute about what is the best source; since I don't even know what %LOCALAPPDATA% refers to (some environment variable? is it always set? is there a default value?) I am clearly not qualified to adjudicate, but this should be settled.
    • at minimum, though, my take on these comments is that Windows does not have a standard way to separate "long-lived" caches from other configuration, since IE (for example) seems to just stick caches in amongst other state.

Fallback. The RFC is a bit loose about legacy compatibility, the interaction with the "find configuration" search, and the interaction with other tools. It does suggest that we would use the new directories in preference to the old ones, which I have tried to reflect below (I think the particulars of this choice are worth discussing, more later).

  • for the git and repository caches, as well as the bin directory, all three of which are always found relative to the user's home directory:
    • check for the new directories given above, and use them if found
    • otherwise, check for ~/.cargo/{git,repository}, and use those if found
    • otherwise, create the new directories given above and populate them
  • for the configuration:
    • search up the list of directories
    • if nothing is found, check if the new directory given above is present
    • if not, check ~/.cargo/config
    • if nothing is found, create a base config (or whatever we do) in the new directory

Pros and cons

If we were to adopt this proposal, would it address the stated problems? The answer varies by platform.

  • Will backup programs skip cargo caches by default?
    • Linux: 👍, presumably they know about XDG by now
    • Windows: 👎, it seems like there aren't clear conventions here (as I discussed earlier; happy to be corrected)
  • Will home directories be less cluttered?
    • 👍 yes!
    • 😕 but we should talk about rustup, which isn't explicitly discussed in this RFC
  • Will we need to muck about with PATH so that users can find executables?
    • 😕 Seems like yes, most of the time:
      • Fedora has it, but other distros don't; some users will
      • Windows probably doesn't have a clear convention here either?

What are other impacts?

  • Behavior is less predictable across platforms
  • Even within a platform, finding the right path for cargo stuff is more complex and must accomodate legacy behavior
    • (see more below)
  • Potential risk if XDG were to change in the future
    • though no one has an example of such a change

Points of information

There were various things that were not clear to me in writing this write-up. I have mentioned a few as I went, but I wanted to collect those here at the end, and also add a few other points.

  • What do other language package managers do (besides PIP)?
  • Will adopting XDG interfere with any tools? Particularly on Mac? (I'm guessing no)
  • Are there tools beyond rustup that would be affected by this change?
    • The drawback does mention ways to help such tools; without knowing how many of them there are, it's hard to tell how urgent this is.
  • In general, what is the interaction of this RFC with rustup?
    • As of this writing, the RFC text explicitly mentions rustup only to say that its strategy is "do what Cargo does".
  • Where does rustup stores its files on Windows?
  • What are the Windows conventions regarding caches / binaries (if any)?
    • What do PIP and other language package managers do?
  • In the XDG specification, is there a proposed (or ratified) alternative to ~/.local/bin?
@nikomatsakis
Contributor
nikomatsakis commented Nov 22, 2016 edited

OK, let me speak personally now. Honestly, I have no real dog in this race. I don't care very much where my cargo files go as long as I can find them. I'm old enough that ~/.cargo is what I would expect (i.e., like ~/.ssh, and ~/.emacs, and whatever), but I can adapt to XDG too. I guess that based on my read, using XDG-conventions seems like it would have been a slight win initially, but I don't know if the win is enough to merit changing, which carries some cost.

That said, I do have some concerns about the quality of the RFC text itself. In general, it seems pretty light on specifics, and I think it could use more background. I don't think that reading this RFC would be sufficient for a user of cargo to know where their data is found. Also, I think it should absolutely discuss rustup -- this whole conversation feels pretty incomplete with that. So, if it were up to me, I'd want to see the RFC beefed up a little before accepting.

Some specific comments:

  • I think it should document the current behavior of rustup, as well as discussing what rustup should do after this change.
    • I took my best shot at this in the summary, but I've left a few holes in there (e.g., the current behavior on windows)
  • I think it should document the existing conventions more thoroughly
    • this doesn't have to mean paragraphs and paragraphs!
    • but, for example, the RFC should mention that ~/.local/bin is a convention adopted by PIP (and others? if so, whom?) that is meant to echo ~/.local/share
    • the coverage is particularly light on Windows
      • what do other programs do?
      • what the heck is "AppData\Local\Programs\Cargo"? is that a relative path?
      • the RFC says "we'll obtain each of the following directories using the correct API" -- what API is that?
      • in general, some links to Microsoft documentation about what programs should do would be great
  • I am confused why the "new directories" are being given preference over the existing ones
    • my expectation would be that we would first search just like we do today and then just add the new directores as the "next place" to search, if the legacy directories are not found
    • surely we don't want user's code to stop working just because they happen to have executed touch ~/.config/cargo at some point?
    • another alternative would be to error out (or warn) if both directories exist
    • presumably, though, new rustup installations would follow the newer conventions
@flying-sheep
flying-sheep commented Nov 22, 2016 edited

awesome writeup, many thanks!

a thing to add: some people might have ~/.local/bin not only because they’re python users, but:

  1. at least fedora and ubuntu have it AFAIK. this is ubuntu’s /etc/skel/.profile, i.e. default ~/.profile, adding both ~/bin and ~/.local/bin to the $PATH
  2. manually installing software via ./configure --prefix="$HOME/.local" && make install is something at least I do, others might as well.
@jminer
jminer commented Nov 23, 2016 edited

Great summary. I can answer some of the Windows questions.

The best way to get the location of directories like AppData on Windows is to call the SHGetFolderPath function or SHGetKnownFolderPath if you don't care about Windows XP support. There is a list of special folders that you can get the path of.

  • On windows, put data in a location that is relative to %LOCALAPPDATA% or something
    • there seems to be some dispute about what is the best source; since I don't even know what %LOCALAPPDATA% refers to (some environment variable? is it always set? is there a default value?) I am clearly not qualified to adjudicate, but this should be settled.

Yes, %LOCALAPPDATA% is an environment variable, and it is always set. That is an OK way to get the location, but I would use the SHGetKnownFolderPath function, passing in FOLDERID_LocalAppData.

  • at minimum, though, my take on these comments is that Windows does not have a standard way to separate "long-lived" caches from other configuration, since IE (for example) seems to just stick caches in amongst other state.

I would say Windows does have standards for settings vs cache, although you somewhat have to infer them. AppData is a folder in the user's home directory. Windows has two folders in AppData: Local and Roaming. When a user logs out of a computer on a domain, Windows will sync everything in Roaming to the server. When they log into another computer, it will download the Roaming directory from the server. Configuration should definitely go into Roaming so it is synced, and caches should probably go into Local to not waste time syncing stuff that can be redownloaded. Firefox, for example, correctly splits settings and cache into Roaming and Local. (Edit: fixed /Roaming/Local/ typo)

Putting cache files in AppData\Local\Temp\Cargo like the RFC states seems inconsistent to me. It would be the equivalent of Cargo putting them in /var/tmp on Linux, which it is not doing.

What are the Windows conventions regarding caches / binaries (if any)?
what the heck is "AppData\Local\Programs\Cargo"? is that a relative path?

That's a relative path. For a long time, Windows had no guidelines for user binaries. However, since Windows 7, FOLDERID_UserProgramFiles is one of the special folders in the list I linked above. Calling SHGetKnownFolderPath(&FOLDERID_UserProgramFiles, ...) returns a path like C:\Users\jminer\AppData\Local\Programs. So creating a Cargo subfolder there seems like the correct place to put user binaries.

Folder Example
FOLDERID_LocalAppData C:\Users\jminer\AppData\Local
FOLDERID_RoamingAppData C:\Users\jminer\AppData\Roaming
FOLDERID_UserProgramFiles C:\Users\jminer\AppData\Local\Programs

I can't find much more Microsoft documentation on this at the moment (I've seen it before), but I'll keep looking.

I don't think it matters much what other programs do on Windows, even Microsoft programs. Even if some other team inside Microsoft doesn't follow Windows' guidelines, it isn't an excuse for Rust not to.

@ollie27
ollie27 commented Nov 23, 2016

Regarding rustup, I wrote a proposal rust-lang-nursery/rustup.rs#247 (comment) to move to OS standard directories. I don't think rustup should be using Cargo's bin directory at all. Earlier in that thread @brson says he thinks it's more important for rustup to follow Cargo than the OS and other programs running on it. I disagree with that but if that's the case then I guess rustup changes will need to be shoehorned into this RFC as well. The good thing about rustup is that as it's still in beta we don't have to worry too hard about a migration strategy and can drop support for the legacy directories entirely.

@Sean1708

Something I haven't seen anyone talk about in this thread (though it is quite a long thread by now) is why don't we only follow XDG iff the user has the relevent XDG env vars set? That way the XDG behaviour essentially becomes opt-in, and (unless I'm missing something) to me that seems like a win-win.

Obviously doesn't really help on Windows though.

@fenhl
fenhl commented Nov 24, 2016

XDG is supposed to work without the envars. I don't have them set because I use the defaults.

@Sean1708

Well obviously, but it's the only compromise that I can see that would make both groups not entirely unhappy.

@tbu-
Contributor
tbu- commented Nov 24, 2016

@Sean1708 XDG variables are usually not set. They are only set in the exceptional case that you want the directories somewhere nonstandard. This is a bit similar to how CARGO_HOME is usually not set, unless you want a nonstandard cargo home.

@Screwtapello

Headings are quotes from @nikomatsakis above.

~/.local/bin is a convention adopted by PIP (and others? if so, whom?)

The "XDG Base Directory specification", is hyper-focussed on things that third-party software vendors might care about once their software is already installed. However, It doesn't address larger questions like where to put that third-party software to begin with.

As it turns out, there is a group of people who want solid, cross-distro conventions they can use and recommend to others: the systemd project. file-hierarchy(7) is (as far as per-user directories go) a straight-forward combination of the XDG Base Directory spec and traditional Unix conventions. Among other things, it describes:

  • ~/.local/bin (binaries that should be on $PATH)
  • ~/.local/lib/cargo (private, portable data)
  • ~/.local/lib/x86_64-linux-gnu (shared libraries, other target tuples are fine too)
  • ~/.local/lib/x86_64-linux-gnu/cargo (private, platform-specific data, maybe like helper binaries)

The fact that this convention is mentioned in systemd documentation would be enough to scuttle the idea in some technical communities; while opinions differ on systemd as a project, I think there's a lot of good ideas in the file-hierachy document, and following any existing convention should be better than doing Yet Another New Thing.

What are the Windows conventions regarding caches / binaries (if any)? What do PIP and other language package managers do?

As far as binaries and libraries are concerned, Pip installs things into the Python "user base directory", as returned by site.USER_BASE. The docs say:

Default value is ~/.local for UNIX and Mac OS X non-framework builds, ~/Library/Python/X.Y for Mac framework builds, and %APPDATA%\Python for Windows.

(in this context, a "Mac framework build" is a copy of Python built to be linked into a GUI app, while a "non-framework build" is designed to be a command-line tool)

As far as caches are concerned, the Pip documentation on caching says:

The default location for the cache directory depends on the Operating System:
Unix: ~/.cache/pip and it respects the XDG_CACHE_HOME directory.
macOS: ~/Library/Caches/pip
Windows: <CSIDL_LOCAL_APPDATA>\pip\Cache

I believe that <CSIDL_LOCAL_APPDATA> is supposed to mean the same as %LOCALAPPDATA% discussed above.

In the XDG specification, is there a proposed (or ratified) alternative to ~/.local/bin?

No.

@joshtriplett
Member

I'd very much like to see this change, for many reasons:

  • To make it more likely that binaries will go on the user's $PATH by default.
  • To have cargo's cache files excluded from backups by default.
  • To reduce the number of dotfiles in $HOME.

To answer what seems to have become a FAQ at this point: ~/.local/bin originated from treating ~/.local as the per-user analogue of /usr/local (since ~/.local/share existed) and doing ./configure --prefix=~/.local && make install and similar. Various people independently started following that convention; some software (including pip) started following suit, and some Linux distributions added it to the default $PATH when it exists. That long pre-dates anyone attempting to document that de-facto convention.

@petrochenkov
Contributor

Meanwhile rustup is being bumped to 1.0.

@flying-sheep flying-sheep referenced this pull request in rust-lang-nursery/rustup.rs Dec 15, 2016
Merged

Bump version to 1.0 #857

@brson
Contributor
brson commented Dec 16, 2016 edited

I said this on the rustup PR, but there's no reason that rustup 1.0 precludes changing how it stores data. Whatever the version number, that ship has sailed, and it will require the same amount of work to make changes.

I understand that people are passionate about this issue, and angry at the inaction. There's not much to be done about that now I suppose. Untangling this issue is going to take enormous effort since there are many distinct issues and strong emotions. It's hard to picture when that will happen and how.

@tbu-
Contributor
tbu- commented Dec 16, 2016

Sorry to have hijacked that rustup issue.

@flying-sheep

i’m also sorry. congrats to 1.0 and i hope this can be done soon!

an automatic migration of the data should mitigate the problems.

@aturon
Contributor
aturon commented Dec 16, 2016

I've been trying to catch up on this issue some, and @nikomatsakis's summary was extremely helpful.

To boil things down even further, I've been thinking about how to frame this question in terms of basic values. Here are some possibilities:

  • Primary value: making Rust 'consistent' across platforms. That is, we could place high value on Rust working the same way on all the platforms it runs on, and therefore use the same directory location (.cargo) on all platforms (as we do today).

  • Primary value: aligning Rust with platform expectations. That is, we could place high value on Rust's data being stored in the "expected" location on a given platform. One problem is that, on unix platforms, "expected location" is a bit up for grabs.

  • Primary value: making Rust fit into other tooling smoothly. That is, we could place high value on pragmatics, like increasing the chances that no changes to $PATH are needed (see @joshtriplett's comment). As far as I can tell, XDG is strictly more likely to "just work" in this sense than the status quo.

These are all good values; the question, I think, is how to prioritize them.

If we look at where we're trying to head with Rust -- increasing productivity and friendliness to new users -- I feel like the second two values are more important than the first. Why? Using Rust on multiple platforms is a relatively advanced thing to do, and it's reasonable to expect a bit more work for that case than for the simpler case of getting up and running with Rust on your "home" platform.

Now, even if you agree with that, it's not exactly a slam dunk in favor of the XDG approach on unix systems, since unix "platform expectations" don't necessarily match XDG, and tooling doesn't necessarily take it into account. Reasonable people can argue that .cargo is a better match to "platform expectations" for at least many Linux systems. However, even in the Linux world this is at most a loose convention, with plenty of software doing other things, and there's zero chance that tools will automatically understand .cargo in the right way. OTOH, with the XDG approach there's at least some chance that tools will do the right thing.

In short, I tend to agree with @joshtriplett's comment. In a case where there isn't such a clear-cut choice based on principles alone, let's take the most pragmatic approach.


A thought about the cost of changing. Given the algorithm that @nikomatsakis outlined, it seems like this RFC could be implemented in a way that is easily backwards compatible, and the main change would be where to create the directories by default, if they're not found. Am I missing something?


One compromise idea -- which is probably a bad one, but still worth mentioning.

There was a suggestion to switch to XDG based on environment variables, which was shot down. But I wonder if we could do something similar, based on the existence of a .config directory? That is, when we go to create a directory for Cargo on unix systems, if ~/.config exists we make ~/.config/cargo, and otherwise ~/.cargo?

The upside would be "automatic detection" of the "right" platform expectations for a unix system.

But there are several downsides. For one, the existence of ~/.config is not a sure bet; any installed XDG-based software would trigger this situation, even if the user would prefer .cargo. It's also more complicated/finicky. In particular, we wouldn't be able to say something straightforward in the docs about the default location.

@flying-sheep
flying-sheep commented Dec 16, 2016 edited

good summary, but i’d like to add a few things:

on unix platforms, "expected location" is a bit up for grabs

Reasonable people can argue that .cargo is a better match to "platform expectations" for at least many Linux systems.

partly. ~/.name is a convention from times when there was no guideline for user home subdirectories. IMHO for modern software, only the things XDG doesn’t specify are debatably up for grabs, which brings me to…

increasing the chances that no changes to $PATH are needed (see @joshtriplett's comment). As far as I can tell, XDG is strictly more likely to "just work" in this sense than the status quo.

sadly ~/.local/bin is not a part of XDG, but a convention aligning itself to it (as said in the referenced comment), which is being followed by at least python and systemd (they put files there), as well as at least ubuntu and fedora (who have it in their default $PATH).

One compromise idea …

i’d extend it to “if ~/.config exists or the $XDG_CONFIG_HOME environment variable is set”

but i think it’s hard to find a linux system without ~/.config these days. granted, it’s more likely on a GUI-less system, but even there, most people have git, htop, ImageMagick, fontconfig, gconf, dconf, systemd, neovim and a few things I didn’t see in the 104 directories in there (not counting all the *rcs also in there)

@aturon
Contributor
aturon commented Dec 16, 2016

@flying-sheep

~/.name` is a convention from times when there was no guideline for user home subdirectories. IMHO for modern software, only the things XDG doesn’t specify are debatably up for grabs

You mentioned this as a correction, but I don't think we can take that as an agreed-upon fact -- if everybody agreed with that, there wouldn't be a need for debate!

I think a more fair assessment is to say that there are multiple conventions at play, with XDG being more recent and a fair amount of software adopting its conventions, and no single convention being universal.

sadly ~/.local/bin is not a part of XDG, but a convention aligning itself to it

Yep, I was being imprecise and using "XDG" as a proxy for what this RFC proposes to do on unix systems. Mea culpa.

@flying-sheep

ah, i softened it down to “addition” already. but it’s a fact that XDG isn’t a convention: it’s a spec, to be followed or not followed by software. and i see as little motivation in not folloing it as i see motivation in distributing your software as a single directory in /opt/. We have XDG now, and we should use it.

besides, it has tangible benefits. e.g. ~/.cache can be a symlink to a bigger and slower disk, or you can backup ~/.config without carrying along caches and other data.

@aturon
Contributor
aturon commented Dec 16, 2016

@flying-sheep To be clear, I agree with your conclusion and about the benefits, but want to draw a clear line between facts and value judgments.

I didn't mean to use the term "convention" in a disparaging sense; conventions are very important! I don't think it makes a lot of difference, in terms of the values I was listing, whether XDG is formalized as a spec or not. The deeper point for the second value is whether it will match the expectations of users for various unix-y systems. We don't have any hard data on what those expectations are, and it's likely that they'll shift over time as XDG continues to take hold (or doesn't). But I think there's enough software following the XDG approach that us following it by default wouldn't strongly violate expectations.

You mentioned git, which made me curious. I dug around in https://git-scm.com/docs/git-config#FILES a bit, and it looks like global configuration data is by default written to .gitconfig rather than ~/.config/git/config, but I may be misreading. I bring it up in part because XDG support was added on after the fact, and git performs a similar directory traversal to cargo, so it seems like it may provide interesting precedent/data.

@flying-sheep
flying-sheep commented Dec 16, 2016 edited

yeah, git searches ~/.config/git/config first, and falls back to ~/.gitconfig if it doesn’t find it.

if nothing exists, it defaults to creating ~/.gitconfig, though, since that’s what people are accustomed to: as you said, they added XDG afterwards (source)

git’s situation is different from ours:

  • we had this RFC for ages (rust-lang/cargo#2127 is over a year old) and should pretend we had this discussion ages ago.
  • we have less reliance on directly editing the files in .cargo, so few tutorials mention it.
  • git only creates a config during runtime: no binaries, no cache, no libraries, no other data.

i think a fitting comparison to what cargo does might be

  • PIP: platform specific directories; on linux XDG extended (=with ~/.local/bin). see also: pypa/pip#1733
  • pacaur: XDG (A B). i used that exemplary for a system package manager with files in the user home, and chose it because i use it all the time. I didn’t know it uses XDG beforehand
  • npm: no user installs possible, no XDG, which annoys everyone who participated in the “discussion”

AFAIK nobody ever complained that PIP uses platform-specific dirs. i searched a bit in its issues, and everything was about either expanding XDG to OSX or other things, never using ~/.pip

@flying-sheep

look here for how people feel about ~/.rustup 😉

@steveklabnik
Contributor

That's only some people. I strongly prefer ~/.rustup. But I also don't want to argue about it.

@aturon
Contributor
aturon commented Dec 19, 2016

In terms of arguments against this RFC, I'm left still with a couple of questions:

  • Can someone lay out the problems with migrating to new directories? If we follow the algorithm that @nikomatsakis laid out, it seems to me that there's an easy story here: established users won't be affected at all (though can choose to move their configuration), and new users would get the new locations by default. Am I missing something here?

  • Can someone lay out an argument in terms of the values I was mentioning, or something similar, in favor of either the status quo, or some conclusion different from this RFC?

@joshtriplett
Member

@aturon I don't think you've missed anything. Use the new directory if it exists, otherwise use the old directory if it exists, otherwise create and use the new directory. That'll avoid any breakage for existing users, while letting new users get the new directory.

I agree with your argument that Rust should focus on getting along with the rest of the world, rather than keeping a different behavior just to increase consistency across platforms for people who use Rust across multiple platforms. I think "matching platform conventions" provides a form of consistency in its own way: you can always expect Rust to follow platform conventions, so look where you'd look for a native program.

@withoutboats

My impression is that everyone is in favor of changing the directory on Windows. Since this RFC proposes using XDG on all Unix systems, this RFC is not any more fragmented than an RFC which changes only Windows.

For this reason, I really don't see a downside to this RFC other than the transition cost. I think much of the negative attitude is not fully acclimated to the changes to this RFC since the time it proposed putting cargo files in /Libraries or whatever on Mac OS.

I think the benefits of this RFC are not huge, but when accumulated over the fullness of time, among all future Rust users, they justify the immediate costs.

@aturon
Contributor
aturon commented Jan 4, 2017

@alexcrichton @brson when you get a chance, can you give your thoughts on the latest discussion? I think you were the two members of the tools team not in favor of this change in its entirety.

@alexcrichton
Member

@aturon in all honesty I've grown incredibly weary of this topic. There seem to be no strong arguments against this feature that are taking hold, so it sounds like this is the way to go.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment