rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
98.03k stars 12.68k forks source link

Support installing multiple release channels #19263

Closed SimonSapin closed 9 years ago

SimonSapin commented 9 years ago

Rust is going to have three release channels: stable, beta, and nightly. Each of them has its use (that’s why they exist), so it will probably be common to have more than one of them installed at the same time on the same machine (such as a developer’s laptop).

Currently, this it is possible to install multiple rusts at different locations, and set up the PATH and (since the [rpath removal]) LD_LIBRARY_PATH environment variables to pick one of them. However this is error-prone and not very convenient.

It would be better if multiple versions could be installed in the same "prefix" (e.g. /usr, where the default environment variables Just Work®). Executables could have a suffix to distinguish them, for example /usr/bin/rustc (stable), /usr/bin/rustc-beta and /usr/bin/rustc-nightly. Other files would have to be namespaced somehow to avoid conflicts.

(Corresponding Cargo issue: https://github.com/rust-lang/cargo/issues/967)

pnkfelix commented 9 years ago

Semi-related: I have been wondering whether we should start distributing a wrapper script for invoking bin/rustc that sets up the [DY]LD_LIBRARY_PATH and other environment variables appropriately.

I saw a user recently who untarred the tar.gz binary package and tried to copy bin/rustc into a different location. I advised them to "just install it globally", but I would prefer to have some support for the use case where you do not install the distribution into /usr/.... I have been maintaining my own private script for supporting this, but it would probably be good to determine what our general attitude is about this. (That is, if the team thinks we can stomach supporting a wrapper script, then I can work on making my own script more robust and making it distributable. If the team hates the idea of a wrapper script ... well, then that's unfortunate given that we've also discarded using rpaths...)


Update: Oh, the reason that this is related to this topic is that a wrapper script can be written to support multiple release channels, either by having multiple scripts that point to the different spots as necessary, or by having a single script that reflectively dispatches on $0, i.e. guessing based on whether we see beta or nightly in the script's name.

steveklabnik commented 9 years ago

There is endless precedence for this kind of tooling in the Ruby/Python worlds, and it's quite useful.

SimonSapin commented 9 years ago

@steveklabnik, right. At some point we might also want to do this by version numbers (e.g. have Rust 1.3 next to 1.4) in addition to release channels.

brson commented 9 years ago

The obvious problem with putting a bunch of same-named libraries next to each other is that they are going to cause resolution conflicts. We might resolve that by attaching a unique id to each build of the compiler and associating every library with that build. That will have some impact on distributing binary libs (which presumably nobody does currently).

The docs are also going to cause naming conflicts as well as some of the other supplementary files.

Have to consider all the different ways of installing Rust and whether and how to make them all compatible with multi-rust.

alexcrichton commented 9 years ago

Note that our makefiles specify a 'extra filename' paramter to be mixed into all filenames: https://github.com/rust-lang/rust/blob/7222ba965038897168f4f4abe9a464bc36266982/mk/main.mk#L18

We could tweak that per-release channel in theory. The binaries themselves won't have it mixed in, though (just the libs).

nodakai commented 9 years ago

I agree with @pnkfelix . It should suffice to extract as many TAR archives as the user wish under the common "base" directory in a parallel manner. They can coexist and uninstalling one of them is as simple as rm -rf.

*nix

We can simply provide a wrapper shell script to choose one of multiple installations:

$ ls /tmp/rust/*
/tmp/rust/rustc*

/tmp/rust/rust-0.12:
bin/  etc/  lib/  share/

/tmp/rust/rust-nightly-2014-11-25:
bin/  etc/  lib/  share/

$ /tmp/rust/rustc hello-rust.rs && ./hello-rust
Hello, world!
#! /bin/sh

basedir=${0%/*}
rustdir=`ls -td $basedir/rust-* | head -n 1` # the simplest logic to choose one
if [ -z "$rustdir" ]; then echo "no installation found"; exit 10; fi
bindir=$rustdir/bin
libdir=$rustdir/lib

LD_LIBRARY_PATH=$libdir $bindir/rustc "$@"

We can enhance this wrapper following battle-tested tools such as rvm (Ruby), pyenv (Python), or nvm (Node.js) (Several similar tools exist for each language; I'm not claiming they are the best ones for their languages.)

To those who likes nitpicking: not setting $0 properly is caller's fault.

Windows

The idea is the same as the *nix case. Instead of $0, we can implement a wrapper executable which calls GetModuleFileName() to locate the base directory:

pnkfelix commented 9 years ago

@nodakai another option for Windows is a wrapper .bat script. You can use the variable %~dp0 which expands (~) into the drive (d) and path (p) for the batch file (%0). See also: http://stackoverflow.com/questions/5034076/what-does-dp0-mean-and-how-does-it-work

(I do not do much Windows hacking; I just remembered that we used a trick like this in the Larceny project: larceny.bat, and I think a batch file will be easier for end-users to modify/maintain than a wrapper executable.)

SimonSapin commented 9 years ago

Have to consider all the different ways of installing Rust and whether and how to make them all compatible with multi-rust.

It’s maybe not as essential that all of the ways to install support this, as long as some of them do.

In particular, the packages for Rust release and nightly in my distribution currently conflict, and I’d like them not to :) IMO it’s ok if packagers need to do a small amount of work (like passing the right configure flags) to make this happen.

brson commented 9 years ago

I have a project that supports installation of multiple Rusts https://github.com/brson/multirust. It depends a bit on the upcoming release channel and installer infrastructure.

williamh commented 9 years ago

Hello,

I am a co-maintainer of rust on Gentoo.

Are there any updates on this issue? What is the appropriate way to install multiple release channels?

Thanks much,

William

SimonSapin commented 9 years ago

I believe the compiler itself can add support for things (though I’m not sure what exactly) to make this easier. In the meantime:

Brian has been working on https://github.com/brson/multirust , which I believe is the best we can do right now. You probably don’t want to import it as-is into the Gentoo packaging system, but you could take ideas. Specifically, it "installs" different Rust versions in different directories. (It just extracts tarballs with pre-built binaries, but I believe it’s equivalent to building with ./configure --prefix=/something.) Then, wrapper scripts run executables from one install or another after setting up the environment, most importantly the LD_LIBRARY_PATH variable.

steveklabnik commented 9 years ago

Triage: multirust has matured significantly.

paulp commented 9 years ago

Here's one unfortunate case where multirust doesn't help, and other than bringing back rtool I'm not sure what will. It seems like it should be a non-negotiable requirement that one can run a program after building it without having to invoke any black magic between build and run.

% multirust run nightly cargo build
   Compiling regex v0.1.30
   Compiling libc v0.1.8
   Compiling log v0.3.1
   Compiling rand v0.3.8
   Compiling getopts v0.2.11
   Compiling tempfile v0.3.0
   Compiling env_logger v0.3.1
   Compiling rusti v0.0.1 (file:///l/src/rust/rusti)

% ./target/debug/rusti
dyld: Library not loaded: x86_64-apple-darwin/stage2/lib/rustlib/x86_64-apple-darwin/lib/librustc_driver-11582ce5.dylib
  Referenced from: /l/src/rust/rusti/./target/debug/rusti
  Reason: image not found
Trace/BPT trap: 5 (core dumped)

% multirust run nightly bash
% ./target/debug/rusti
rusti=>
benaryorg commented 9 years ago

@williamh Just to mention it, Gentoo deals with multiple rust installations already and names them e.g. /usr/bin/rustc-9999 and manages a symlink using eselect.

So there is the overlay called rust (obviously) which contains the special versions rust-9999 (git) and rust-999 (nightly).

Would it be possible to have rust (binary named *-stable), rust-beta and rust-nightly in this repo? Then I could manage my versions (which are updated as expected by the package manager) using eselect for the default compiler and still use rustc-beta and rustc-nightly or rustc-9999 for the other versions.

This way I could test libraries much more easily for stable/beta/nightly compatibility.

Edit: Sorry, I did not see before that the portage (non-overlay) is also rust:stable and the rust-999 of the overlay is rust:nightly. Still, the beta is missing.

alexcrichton commented 9 years ago

I believe multirust is basically our answer here, so closing, yay!

retep998 commented 9 years ago

Now if only we had a Windows equivalent!