Change:
There's some code for this in cargo now, but it doesn't quite do the right thing. See .
Also worth considering the difference between sysroot and the install prefix - they are not the same. For instance, I never install cargo, always running it out of the build directory, in which case the build directory is sysroot.
I think this is resolved.

Discussion:
import rustc::syntax::{ast, codemap}; import rustc::syntax::parse::parser; import rustc::util::filesearch::{get_cargo_root, get_cargo_root_nearest, <del> get_cargo_sysroot}; </del> <ins> get_cargo_sysroot, libdir}; </ins> import rustc::driver::diagnostic; import std::fs;

}; let test = opt_present(match, "test"); <del> let mode = if opt_present(match, "G") { if opt_present(match, "mode") { fail "--mode and -G both provided"; } if opt_present(match, "g") { fail "-G and -g both provided"; } system_mode } else if opt_present(match, "g") { if opt_present(match, "mode") { fail "--mode and -g both provided"; } if opt_present(match, "G") { fail "-G and -g both provided"; } user_mode } else if opt_present(match, "mode") { alt getopts::opt_str(match, "mode") { "system" { system_mode } "user" { user_mode } "local" { local_mode } _ { fail "argument to `mode` must be one of `system`" + ", `user`, or `normal`"; </del> <ins> let G = opt_present(match, "G"); let g = opt_present(match, "g"); let m = opt_present(match, "mode"); let is_install = vec::len(match.free) > 1u && match.free[1] == "install"; if G && g { fail "-G and -g both provided"; } if g && m { fail "--mode and -g both provided"; } if G && m { fail "--mode and -G both provided"; } let mode = if is_install { if G { system_mode } else if g { user_mode } else if m { alt getopts::opt_str(match, "mode") { "system" { system_mode } "user" { user_mode } "local" { local_mode } _ { fail "argument to `mode` must be one of `system`" + ", `user`, or `local`"; } </ins> } <del> } } else { local_mode }; if mode == system_mode { // FIXME: Per discussion on #1760, we need to think about how // system mode works. It should install files to the normal // sysroot paths, but it also needsd an area to place various // cargo configuration and work files. fail "system mode does not exist yet"; } </del> <ins> } else { local_mode } } else { system_mode }; </ins> {test: test, mode: mode, free: match.free} } fn configure(opts: options) -> cargo { <ins> let syscargo = result::get(get_cargo_sysroot()); </ins> let get_cargo_dir = alt opts.mode { system_mode { get_cargo_sysroot } user_mode { get_cargo_root }

}; let sources = map::new_str_hash::<source>(); <del> try_parse_sources(fs::connect(p, "sources.json"), sources); try_parse_sources(fs::connect(p, "local-sources.json"), sources); </del> <ins> try_parse_sources(fs::connect(syscargo, "sources.json"), sources); try_parse_sources(fs::connect(syscargo, "local-sources.json"), sources); </ins> let c = { pgp: pgp::supported(), root: p, bindir: fs::connect(p, "bin"), libdir: fs::connect(p, "lib"), workdir: fs::connect(p, "work"), <del> sourcedir: fs::connect(p, "sources"), </del> <ins> sourcedir: fs::connect(syscargo, "sources"), </ins> sources: sources, opts: opts };

#debug("  bin: %s", ct); // FIXME: need libstd fs::copy or something run::run_program("cp", [ct, c.bindir]); <ins> if c.opts.mode == system_mode { install_one_crate_to_sysroot(ct, "bin"); } </ins> } else { #debug("  lib: %s", ct); run::run_program("cp", [ct, c.libdir]); <ins> if c.opts.mode == system_mode { install_one_crate_to_sysroot(ct, libdir()); } } } } fn install_one_crate_to_sysroot(ct: str, target: str) { alt os::get_exe_path() { some(_path) { let path = [_path, "..", target]; check vec::is_not_empty(path); let target_dir = fs::normalize(fs::connect_many(path)); let p = run::program_output("cp", [ct, target_dir]); if p.status != 0 { warn(#fmt["Copying %s to %s is failed", ct, target_dir]); } </ins> } <ins> none { } </ins> } }

" init                                          Set up .cargo <del> install [--test] [source/]package-name        Install by name install [--test] uuid:[source/]package-uuid   Install by uuid </del> <ins> install [options] [source/]package-name       Install by name install [options] uuid:[source/]package-uuid  Install by uuid </ins> list [source]                                 List packages search <name | '*'> [tags...]                 Search packages sync                                          Sync all sources

Options: <ins> cargo install </ins> --mode=[system,user,local]   change mode as (system/user/local) -g                           equivalent to --mode=user -G                           equivalent to --mode=system NOTE: <del> This command creates/uses local-level .cargo by default. To create/use user-level .cargo, use option -g/--mode=user. To create/use system-level .cargo, use option -G/--mode=system. </del> <ins> "cargo install" installs bin/libs to local-level .cargo by default. To install them into user-level .cargo,  use option -g/--mode=user. To install them into bin/lib on sysroot, use option -G/--mode=system. </ins> "); }

result::ok(p) { [p] } result::err(p) { [] } } <del> + [fs::connect(fs::connect(self.sysroot, ".cargo"), libdir())] </del> } fn get_target_lib_path() -> fs::path { make_target_lib_path(self.sysroot, self.target_triple)

} fn get_cargo_sysroot() -> result::t<fs::path, str> { <del> result::ok(fs::connect(get_default_sysroot(),  ".cargo")) </del> <ins> let path = [get_default_sysroot(), libdir(), "cargo"]; check vec::is_not_empty(path); result::ok(fs::connect_many(path)) </ins> } fn get_cargo_root() -> result::t<fs::path, str> {