Skip to content

Commit

Permalink
Merge pull request #421 from rust-lang-nursery/host-triple
Browse files Browse the repository at this point in the history
Configurable host triple
  • Loading branch information
brson committed May 17, 2016
2 parents 66af8c1 + 4adf0e3 commit 27f6475
Show file tree
Hide file tree
Showing 15 changed files with 236 additions and 31 deletions.
6 changes: 6 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions src/rustup-cli/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ mod help;
use std::env;
use std::path::PathBuf;
use errors::*;
use rustup_dist::dist::TargetTriple;

fn main() {
if let Err(ref e) = run_multirust() {
Expand Down Expand Up @@ -102,6 +103,7 @@ fn run_multirust() -> Result<()> {
// `self install` as the arguments. FIXME: Verify this
// works.
let opts = self_update::InstallOpts {
default_host_triple: TargetTriple::from_host_or_build().to_string(),
default_toolchain: "stable".to_string(),
no_modify_path: false,
};
Expand Down
28 changes: 28 additions & 0 deletions src/rustup-cli/rustup_mode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ pub fn main() -> Result<()> {
(_, _) => unreachable!(),
}
}
("set", Some(c)) => {
match c.subcommand() {
("default-host", Some(m)) => try!(set_default_host_triple(&cfg, m)),
(_, _) => unreachable!(),
}
}
(_, _) => unreachable!(),
}

Expand Down Expand Up @@ -263,6 +269,13 @@ pub fn cli() -> App<'static, 'static> {
.about("Disable rustup telemetry"))
.subcommand(SubCommand::with_name("analyze")
.about("Analyze stored telemetry")))
.subcommand(SubCommand::with_name("set")
.about("Alter rustup settings")
.setting(AppSettings::SubcommandRequiredElseHelp)
.subcommand(SubCommand::with_name("default-host")
.about("Set host triple.")
.arg(Arg::with_name("host_triple")
.required(true))))
}

fn maybe_upgrade_data(cfg: &Cfg, m: &ArgMatches) -> Result<bool> {
Expand Down Expand Up @@ -348,6 +361,16 @@ fn which(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
}

fn show(cfg: &Cfg) -> Result<()> {
// Print host triple
{
let mut t = term2::stdout();
let _ = t.attr(term2::Attr::Bold);
let _ = write!(t, "Default host: ");
let _ = t.reset();
println!("{}", try!(cfg.get_default_host_triple()));
println!("");
}

let ref cwd = try!(utils::current_dir());
let installed_toolchains = try!(cfg.list_toolchains());
let active_toolchain = try!(cfg.find_override_toolchain_or_default(cwd));
Expand Down Expand Up @@ -549,3 +572,8 @@ fn analyze_telemetry(cfg: &Cfg) -> Result<()> {
let analysis = try!(cfg.analyze_telemetry());
common::show_telemetry(analysis)
}

fn set_default_host_triple(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
try!(cfg.set_default_host_triple(m.value_of("host_triple").expect("")));
Ok(())
}
17 changes: 13 additions & 4 deletions src/rustup-cli/self_update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ use tempdir::TempDir;
use term2;

pub struct InstallOpts {
pub default_host_triple: String,
pub default_toolchain: String,
pub no_modify_path: bool,
}
Expand Down Expand Up @@ -219,7 +220,7 @@ pub fn install(no_prompt: bool, verbose: bool,
if !opts.no_modify_path {
try!(do_add_to_path(&get_add_path_methods()));
}
try!(maybe_install_rust(&opts.default_toolchain, verbose));
try!(maybe_install_rust(&opts.default_toolchain, &opts.default_host_triple, verbose));

if cfg!(unix) {
let ref env_file = try!(utils::cargo_home()).join("env");
Expand Down Expand Up @@ -392,9 +393,11 @@ fn current_install_opts(opts: &InstallOpts) -> String {
format!(
r"Current installation options:
- ` `default host triple: `{}`
- ` `default toolchain: `{}`
- modify PATH variable: `{}`
",
opts.default_host_triple,
opts.default_toolchain,
if !opts.no_modify_path { "yes" } else { "no" }
)
Expand All @@ -409,6 +412,10 @@ fn customize_install(mut opts: InstallOpts) -> Result<InstallOpts> {

println!("");

opts.default_host_triple = try!(common::question_str(
"Default host triple?",
&opts.default_host_triple));

opts.default_toolchain = try!(common::question_str(
"Default toolchain? (stable/beta/nightly)",
&opts.default_toolchain));
Expand Down Expand Up @@ -475,14 +482,16 @@ fn install_bins() -> Result<()> {
Ok(())
}

fn maybe_install_rust(toolchain_str: &str, verbose: bool) -> Result<()> {
fn maybe_install_rust(toolchain_str: &str, default_host_triple: &str, verbose: bool) -> Result<()> {
let ref cfg = try!(common::set_globals(verbose));

// If there is already an install, then `toolchain_str` may not be
// a toolchain the user actually wants. Don't do anything. FIXME:
// This logic should be part of InstallOpts so that it isn't
// possible to select a toolchain then have it not be installed.
if try!(cfg.find_default()).is_none() {
// Set host triple first as it will affect resolution of toolchain_str
try!(cfg.set_default_host_triple(default_host_triple));
let toolchain = try!(cfg.get_toolchain(toolchain_str, false));
let status = try!(toolchain.install_from_dist());
try!(cfg.set_default(toolchain_str));
Expand Down Expand Up @@ -1069,8 +1078,8 @@ pub fn prepare_update() -> Result<Option<PathBuf>> {
try!(utils::remove_file("setup", setup_path));
}

// Get host triple
let triple = dist::TargetTriple::from_host();
// Get build triple
let triple = dist::TargetTriple::from_build();

let update_root = env::var("RUSTUP_UPDATE_ROOT")
.unwrap_or(String::from(UPDATE_ROOT));
Expand Down
13 changes: 11 additions & 2 deletions src/rustup-cli/setup_mode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::env;
use self_update::{self, InstallOpts};
use errors::*;
use clap::{App, Arg, AppSettings};
use rustup_dist::dist::TargetTriple;
use common;

pub fn main() -> Result<()> {
Expand All @@ -13,9 +14,9 @@ pub fn main() -> Result<()> {
return self_update::self_replace();
}

let cli = App::new("multirust-setup")
let cli = App::new("rustup-init")
.version(common::version())
.about("The installer for multirust")
.about("The installer for rustup")
.setting(AppSettings::DeriveDisplayOrder)
.arg(Arg::with_name("verbose")
.short("v")
Expand All @@ -24,6 +25,10 @@ pub fn main() -> Result<()> {
.arg(Arg::with_name("no-prompt")
.short("y")
.help("Disable confirmation prompt."))
.arg(Arg::with_name("default-host")
.long("default-host")
.takes_value(true)
.help("Choose a default host triple"))
.arg(Arg::with_name("default-toolchain")
.long("default-toolchain")
.takes_value(true)
Expand All @@ -36,10 +41,14 @@ pub fn main() -> Result<()> {
let matches = cli.get_matches();
let no_prompt = matches.is_present("no-prompt");
let verbose = matches.is_present("verbose");
let default_host = matches.value_of("default-host").map(|s| s.to_owned()).unwrap_or_else(|| {
TargetTriple::from_host_or_build().to_string()
});
let default_toolchain = matches.value_of("default-toolchain").unwrap_or("stable");
let no_modify_path = matches.is_present("no-modify-path");

let opts = InstallOpts {
default_host_triple: default_host,
default_toolchain: default_toolchain.to_owned(),
no_modify_path: no_modify_path,
};
Expand Down
10 changes: 10 additions & 0 deletions src/rustup-dist/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,15 @@ rustup-utils = { path = "../rustup-utils", version = "0.1.12" }
error-chain = { path = "../error-chain", version = "0.1.12" }
rustup-mock = { path = "../rustup-mock", version = "0.1.12" }

[target."cfg(windows)".dependencies]
winapi = "0.2.4"
winreg = "0.3.2"
user32-sys = "0.1.2"
kernel32-sys = "0.2.1"
gcc = "0.3.28"

[target."cfg(not(windows))".dependencies]
libc = "0.2.0"

[lib]
name = "rustup_dist"
92 changes: 90 additions & 2 deletions src/rustup-dist/src/dist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use manifestation::{Manifestation, UpdateStatus, Changes};

use std::path::Path;
use std::fmt;
use std::env;

use regex::Regex;
use sha2::{Sha256, Digest};
Expand Down Expand Up @@ -71,13 +72,100 @@ impl TargetTriple {
TargetTriple(name.to_string())
}

pub fn from_host() -> Self {
if let Some(triple) = option_env!("RUSTUP_OVERRIDE_HOST_TRIPLE") {
pub fn from_build() -> Self {
if let Some(triple) = option_env!("RUSTUP_OVERRIDE_BUILD_TRIPLE") {
TargetTriple::from_str(triple)
} else {
TargetTriple::from_str(include_str!(concat!(env!("OUT_DIR"), "/target.txt")))
}
}

pub fn from_host() -> Option<Self> {
#[cfg(windows)]
fn inner() -> Option<TargetTriple> {
use gcc::windows_registry;
use kernel32::GetNativeSystemInfo;
use std::mem;

// First detect architecture
const PROCESSOR_ARCHITECTURE_AMD64: u16 = 9;
const PROCESSOR_ARCHITECTURE_INTEL: u16 = 0;

let mut sys_info;
unsafe {
sys_info = mem::zeroed();
GetNativeSystemInfo(&mut sys_info);
}

let arch = match sys_info.wProcessorArchitecture {
PROCESSOR_ARCHITECTURE_AMD64 => "x86_64",
PROCESSOR_ARCHITECTURE_INTEL => "i686",
_ => return None
};

// Now try to find an installation of msvc, using the gcc crate to do the hard work
let msvc_triple = format!("{}-pc-windows-msvc", arch);
let gnu_triple = format!("{}-pc-windows-gnu", arch);
if let Some(_) = windows_registry::find_tool(&msvc_triple, "cl.exe") {
// Found msvc, so default to the msvc triple
Some(TargetTriple(msvc_triple))
} else {
// No msvc found, so use gnu triple as a fallback
Some(TargetTriple(gnu_triple))
}
}

#[cfg(not(windows))]
fn inner() -> Option<TargetTriple> {
use libc;
use std::mem;
use std::ffi::CStr;

let mut sys_info;
let (sysname, machine) = unsafe {
sys_info = mem::zeroed();
if libc::uname(&mut sys_info) != 0 {
return None;
}

(
CStr::from_ptr(sys_info.sysname.as_ptr()).to_bytes(),
CStr::from_ptr(sys_info.machine.as_ptr()).to_bytes(),
)
};

let host_triple = match (sysname, machine) {
(b"Linux", b"x86_64") => Some("x86_64-unknown-linux-gnu"),
(b"Linux", b"i686") => Some("i686-unknown-linux-gnu"),
(b"Linux", b"mips") => Some("mips-unknown-linux-gnu"),
(b"Linux", b"mipsel") => Some("mipsel-unknown-linux-gnu"),
(b"Linux", b"arm") => Some("arm-unknown-linux-gnueabi"),
(b"Linux", b"aarch64") => Some("aarch64-unknown-linux-gnu"),
(b"Darwin", b"x86_64") => Some("x86_64-apple-darwin"),
(b"Darwin", b"i686") => Some("i686-apple-darwin"),
(b"FreeBSD", b"x86_64") => Some("x86_64-unknown-freebsd"),
(b"FreeBSD", b"i686") => Some("i686-unknown-freebsd"),
(b"OpenBSD", b"x86_64") => Some("x86_64-unknown-openbsd"),
(b"OpenBSD", b"i686") => Some("i686-unknown-openbsd"),
(b"NetBSD", b"x86_64") => Some("x86_64-unknown-netbsd"),
(b"NetBSD", b"i686") => Some("i686-unknown-netbsd"),
(b"DragonFly", b"x86_64") => Some("x86_64-unknown-dragonfly"),
_ => None
};

host_triple.map(TargetTriple::from_str)
}

if let Ok(triple) = env::var("RUSTUP_OVERRIDE_HOST_TRIPLE") {
Some(TargetTriple(triple))
} else {
inner()
}
}

pub fn from_host_or_build() -> Self {
Self::from_host().unwrap_or_else(Self::from_build)
}
}

impl PartialTargetTriple {
Expand Down
13 changes: 13 additions & 0 deletions src/rustup-dist/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,19 @@ extern crate rustup_utils;
extern crate error_chain;
extern crate sha2;

#[cfg(windows)]
extern crate winapi;
#[cfg(windows)]
extern crate winreg;
#[cfg(windows)]
extern crate user32;
#[cfg(windows)]
extern crate kernel32;
#[cfg(windows)]
extern crate gcc;
#[cfg(not(windows))]
extern crate libc;

pub use errors::*;
pub use notifications::{Notification, NotifyHandler};

Expand Down
8 changes: 7 additions & 1 deletion src/rustup-mock/src/clitools.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,11 @@ pub fn setup(s: Scenario, f: &Fn(&Config)) {
fs::hard_link(rustup_path, rustc_path).unwrap();
fs::hard_link(rustup_path, cargo_path).unwrap();

// Make sure the host triple matches the build triple. Otherwise testing a 32-bit build of
// rustup on a 64-bit machine will fail, because the tests do not have the host detection
// functionality built in.
run(&config, "rustup", &["set", "host", &this_host_triple()], &[]);

// Create some custom toolchains
create_custom_toolchains(&config.customdir);

Expand Down Expand Up @@ -208,6 +213,7 @@ pub fn env(config: &Config, cmd: &mut Command) {
cmd.env("RUSTUP_HOME", config.rustupdir.to_string_lossy().to_string());
cmd.env("RUSTUP_DIST_ROOT", format!("file://{}", config.distdir.join("dist").to_string_lossy()));
cmd.env("CARGO_HOME", config.cargodir.to_string_lossy().to_string());
cmd.env("RUSTUP_OVERRIDE_HOST_TRIPLE", this_host_triple());

// This is only used for some installation tests on unix where CARGO_HOME
// above is unset
Expand Down Expand Up @@ -389,7 +395,7 @@ fn build_mock_channel(s: Scenario, channel: &str, date: &str,
}

pub fn this_host_triple() -> String {
if let Some(triple) = option_env!("RUSTUP_OVERRIDE_HOST_TRIPLE") {
if let Some(triple) = option_env!("RUSTUP_OVERRIDE_BUILD_TRIPLE") {
triple.to_owned()
} else {
let arch = if cfg!(target_arch = "x86") { "i686" }
Expand Down
Loading

0 comments on commit 27f6475

Please sign in to comment.