Add option to disable cross compilation env variables

Some packages use build.rs scripts to compile C++ code. In some
cases this is intented to run on the target, in others to run on
the host. As long as both are not needed at the same time this
flag can help a fargo user successfully compile some crates
like Vulkano.

Also did some cleanup around how options are passed to run_cargo.

Also got randomly different formatting from rustfmt.

Change-Id: I52e7f5c935f2cdaeaac39855eade1a087ff8f91a
diff --git a/README.md b/README.md
index 1ad8cb0..83004fc 100644
--- a/README.md
+++ b/README.md
@@ -7,10 +7,12 @@
         fargo [FLAGS] [OPTIONS] [SUBCOMMAND]
 
     FLAGS:
-            --debug-os    Use debug user.bootfs and ssh keys
-        -h, --help        Prints help information
-        -V, --version     Prints version information
-        -v, --verbose     Print verbose output while performing commands
+            --debug-os             Use debug user.bootfs and ssh keys
+            --disable-cross-env    Disable the setting of CC, AR and such environmental
+                                   variables.
+        -h, --help                 Prints help information
+        -V, --version              Prints version information
+        -v, --verbose              Print verbose output while performing commands
 
     OPTIONS:
         -N, --device-name <device-name>
@@ -30,8 +32,7 @@
         configure            Run a configure script for the cross compilation
                              environment
         enable-networking    Enable networking for a running emulator
-        help                 Prints this message or the help of the given
-                             subcommand(s)
+        help                 Prints this message or the help of the given subcommand(s)
         list-devices         List visible Fuchsia devices
         load-driver          Build driver and load it on Fuchsia device or emulator.
         pkg-config           Run pkg-config for the cross compilation environment
@@ -160,6 +161,10 @@
     LDFLAGS, PKG_CONFIG_PATH, PKG_CONFIG_LIBDIR,
     PKG_CONFIG_ALL_STATIC
 
+The `--disable-cross-env` option will prevent these environmental variables from
+being set when invoking cargo. This is useful when the components being built
+by C or C++ are intended for the host, not the target.
+
 ## Fargo roadmap
 
 The goal is to transition fargo to using something like an SDK instead.
diff --git a/src/cross.rs b/src/cross.rs
index 2a37eca..e6f06d8 100644
--- a/src/cross.rs
+++ b/src/cross.rs
@@ -23,7 +23,7 @@
 }
 
 pub fn run_pkg_config(
-    verbose: bool, args: &[&str], target_options: &TargetOptions
+    verbose: bool, args: &[&str], target_options: &TargetOptions,
 ) -> Result<i32, Error> {
     let mut cmd = Command::new("pkg-config");
 
@@ -45,7 +45,7 @@
 }
 
 pub fn run_configure(
-    verbose: bool, use_host: bool, args: &[&str], target_options: &TargetOptions
+    verbose: bool, use_host: bool, args: &[&str], target_options: &TargetOptions,
 ) -> Result<bool, Error> {
     let cwd = fs::canonicalize(env::current_dir()?)
         .context("run_configure: canonicalize working directory")?;
diff --git a/src/device.rs b/src/device.rs
index 89f72c2..71e28f9 100644
--- a/src/device.rs
+++ b/src/device.rs
@@ -228,7 +228,7 @@
 }
 
 pub fn start_emulator(
-    with_graphics: bool, with_networking: bool, target_options: &TargetOptions
+    with_graphics: bool, with_networking: bool, target_options: &TargetOptions,
 ) -> Result<(), Error> {
     let fuchsia_dir = fuchsia_dir(target_options)?;
     let fx_script = fx_path(target_options)?;
diff --git a/src/lib.rs b/src/lib.rs
index 0eaa163..fdd788b 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -25,15 +25,15 @@
 use failure::{err_msg, Error, ResultExt};
 pub use sdk::TargetOptions;
 use sdk::{cargo_out_dir, cargo_path, clang_archiver_path, clang_c_compiler_path,
-          clang_cpp_compiler_path, clang_linker_path, clang_ranlib_path, rustc_path,
-          shared_libraries_path, sysroot_path, target_gen_dir, FuchsiaConfig, fidl2_target_gen_dir};
+          clang_cpp_compiler_path, clang_linker_path, clang_ranlib_path, fidl2_target_gen_dir,
+          rustc_path, shared_libraries_path, sysroot_path, target_gen_dir, FuchsiaConfig};
 use std::fs;
 use std::path::PathBuf;
 use std::process::Command;
 use utils::strip_binary;
 
 fn copy_to_target(
-    source_path: &PathBuf, verbose: bool, target_options: &TargetOptions
+    source_path: &PathBuf, verbose: bool, target_options: &TargetOptions,
 ) -> Result<String, Error> {
     let netaddr = netaddr(verbose, target_options)?;
     if verbose {
@@ -96,7 +96,9 @@
 use std::sync::mpsc::channel;
 use std::time::Duration;
 
-fn autotest(verbose: bool, release: bool, target_options: &TargetOptions) -> Result<(), Error> {
+fn autotest(
+    run_cargo_options: RunCargoOptions, target_options: &TargetOptions,
+) -> Result<(), Error> {
     let (tx, rx) = channel();
     let mut watcher: RecommendedWatcher =
         Watcher::new(tx, Duration::from_secs(1)).context("autotest: watcher creation failed")?;
@@ -122,7 +124,7 @@
                 // TODO(raggi): provide a fuller ignore flag/pattern match solution here.
                 if !path.starts_with(&tgt) && !path.starts_with(&git) {
                     println!("autotest: running tests because {:?}", path);
-                    run_tests(verbose, release, false, target_options, "", &[], None).ok();
+                    run_tests(run_cargo_options, false, target_options, "", &[], None).ok();
                 }
             }
             _ => {}
@@ -131,11 +133,10 @@
 }
 
 fn build_tests(
-    verbose: bool, release: bool, target_options: &TargetOptions, test_target: &str
+    run_cargo_options: RunCargoOptions, target_options: &TargetOptions, test_target: &str,
 ) -> Result<bool, Error> {
     run_tests(
-        verbose,
-        release,
+        run_cargo_options,
         true,
         target_options,
         test_target,
@@ -146,8 +147,8 @@
 }
 
 fn run_tests(
-    verbose: bool, release: bool, no_run: bool, target_options: &TargetOptions, test_target: &str,
-    params: &[&str], target_params: Option<&str>,
+    run_cargo_options: RunCargoOptions, no_run: bool, target_options: &TargetOptions,
+    test_target: &str, params: &[&str], target_params: Option<&str>,
 ) -> Result<(), Error> {
     let mut args = vec![];
 
@@ -167,11 +168,7 @@
     if target_params.is_some() {
         let formatted_target_params = format!("--args={}", target_params.unwrap());
         run_cargo(
-            RunCargoOptions {
-                verbose,
-                release,
-                set_root_view: false,
-            },
+            run_cargo_options,
             "test",
             &args,
             target_options,
@@ -179,32 +176,17 @@
             Some(&formatted_target_params),
         )?;
     } else {
-        run_cargo(
-            RunCargoOptions {
-                verbose,
-                release,
-                set_root_view: false,
-            },
-            "test",
-            &args,
-            target_options,
-            None,
-            None,
-        )?;
+        run_cargo(run_cargo_options, "test", &args, target_options, None, None)?;
     }
 
     Ok(())
 }
 
 fn build_binary(
-    verbose: bool, release: bool, target_options: &TargetOptions, params: &[&str]
+    run_cargo_options: RunCargoOptions, target_options: &TargetOptions, params: &[&str],
 ) -> Result<(), Error> {
     run_cargo(
-        RunCargoOptions {
-            verbose,
-            release,
-            set_root_view: false,
-        },
+        run_cargo_options,
         "build",
         params,
         target_options,
@@ -214,14 +196,10 @@
 }
 
 fn check_binary(
-    verbose: bool, release: bool, target_options: &TargetOptions, params: &[&str]
+    run_cargo_options: RunCargoOptions, target_options: &TargetOptions, params: &[&str],
 ) -> Result<(), Error> {
     run_cargo(
-        RunCargoOptions {
-            verbose,
-            release,
-            set_root_view: false,
-        },
+        run_cargo_options,
         "check",
         params,
         target_options,
@@ -231,32 +209,18 @@
 }
 
 fn run_binary(
-    verbose: bool, release: bool, set_root_view: bool, target_options: &TargetOptions,
-    params: &[&str],
+    run_cargo_options: RunCargoOptions, target_options: &TargetOptions, params: &[&str],
 ) -> Result<(), Error> {
-    run_cargo(
-        RunCargoOptions {
-            verbose,
-            release,
-            set_root_view,
-        },
-        "run",
-        params,
-        target_options,
-        None,
-        None,
-    )?;
+    run_cargo(run_cargo_options, "run", params, target_options, None, None)?;
     Ok(())
 }
 
-fn load_driver(verbose: bool, release: bool, target_options: &TargetOptions) -> Result<(), Error> {
+fn load_driver(
+    run_cargo_options: RunCargoOptions, target_options: &TargetOptions,
+) -> Result<(), Error> {
     let args = vec![];
     run_cargo(
-        RunCargoOptions {
-            verbose,
-            release,
-            set_root_view: false,
-        },
+        run_cargo_options,
         "build",
         &args,
         target_options,
@@ -269,19 +233,59 @@
         .to_str()
         .ok_or(err_msg("Invalid current directory"))?;
     let filename = cargo_out_dir(target_options)?.join(format!("lib{}.so", package));
-    let destination_path = copy_to_target(&filename, verbose, target_options)?;
+    let destination_path = copy_to_target(&filename, run_cargo_options.verbose, target_options)?;
     let command_string = format!("dm add-driver:{}", destination_path);
-    if verbose {
+    if run_cargo_options.verbose {
         println!("running {}", command_string);
     }
-    ssh(verbose, target_options, &command_string)?;
+    ssh(run_cargo_options.verbose, target_options, &command_string)?;
     Ok(())
 }
 
+#[derive(Debug, Copy, Clone)]
 pub struct RunCargoOptions {
     pub verbose: bool,
     pub release: bool,
     pub set_root_view: bool,
+    pub disable_cross: bool,
+}
+
+impl RunCargoOptions {
+    pub fn new(verbose: bool, release: bool) -> RunCargoOptions {
+        RunCargoOptions {
+            verbose,
+            release,
+            set_root_view: false,
+            disable_cross: false,
+        }
+    }
+
+    pub fn disable_cross(&self, disable_cross: bool) -> RunCargoOptions {
+        RunCargoOptions {
+            verbose: self.verbose,
+            release: self.release,
+            set_root_view: self.set_root_view,
+            disable_cross,
+        }
+    }
+
+    pub fn release(&self, release: bool) -> RunCargoOptions {
+        RunCargoOptions {
+            verbose: self.verbose,
+            release: release,
+            set_root_view: self.set_root_view,
+            disable_cross: self.disable_cross,
+        }
+    }
+
+    pub fn set_root_view(&self, set_root_view: bool) -> RunCargoOptions {
+        RunCargoOptions {
+            verbose: self.verbose,
+            release: self.release,
+            set_root_view: set_root_view,
+            disable_cross: self.disable_cross,
+        }
+    }
 }
 
 /// Runs the cargo tool configured to target Fuchsia. When used as a library,
@@ -300,6 +304,7 @@
 ///         verbose: false,
 ///         release: true,
 ///         set_root_view: false,
+///         disable_cross: false,
 ///     },
 ///     "help",
 ///     &[],
@@ -348,11 +353,9 @@
         fs::canonicalize(std::env::current_exe()?)?
     };
 
-    let mut runner_args = vec![
-        fargo_path
-            .to_str()
-            .ok_or_else(|| err_msg("unable to convert path to utf8 encoding"))?,
-    ];
+    let mut runner_args = vec![fargo_path
+        .to_str()
+        .ok_or_else(|| err_msg("unable to convert path to utf8 encoding"))?];
 
     if options.verbose {
         runner_args.push("-v");
@@ -397,8 +400,14 @@
         println!("runner_env_name: {:?}", runner_env_name);
         println!("rustflags_env_name: {:?}", rustflags_env_name);
         println!("linker_env_name: {:?}", linker_env_name);
-        println!("rustc_path: {:?}", rustc_path(target_options)?.to_str().unwrap());
-        println!("cargo_path: {:?}", cargo_path(target_options)?.to_str().unwrap());
+        println!(
+            "rustc_path: {:?}",
+            rustc_path(target_options)?.to_str().unwrap()
+        );
+        println!(
+            "cargo_path: {:?}",
+            cargo_path(target_options)?.to_str().unwrap()
+        );
     }
 
     cmd.env(runner_env_name, fargo_command)
@@ -415,34 +424,33 @@
             linker_env_name,
             clang_linker_path(target_options)?.to_str().unwrap(),
         )
-        .env(
-            "RUSTC",
-            rustc_path(target_options)?.to_str().unwrap(),
-        )
-        .env(
-            "CC",
-            clang_c_compiler_path(target_options)?.to_str().unwrap(),
-        )
-        .env(
-            "CXX",
-            clang_cpp_compiler_path(target_options)?.to_str().unwrap(),
-        )
-        .env("CFLAGS", format!("--sysroot={}", sysroot_as_str))
-        .env("AR", clang_archiver_path(target_options)?.to_str().unwrap())
-        .env(
-            "RANLIB",
-            clang_ranlib_path(target_options)?.to_str().unwrap(),
-        )
-        .env("PKG_CONFIG_ALL_STATIC", "1")
-        .env("PKG_CONFIG_ALLOW_CROSS", "1")
-        .env("PKG_CONFIG_PATH", "")
-        .env("PKG_CONFIG_LIBDIR", pkg_path)
+        .env("RUSTC", rustc_path(target_options)?.to_str().unwrap())
         .env("FUCHSIA_GEN_ROOT", target_gen_dir(target_options)?)
         .env("FIDL_GEN_ROOT", fidl2_target_gen_dir(target_options)?)
         .arg(subcommand)
         .args(target_args)
         .args(args);
 
+    if !options.disable_cross {
+        cmd.env(
+            "CC",
+            clang_c_compiler_path(target_options)?.to_str().unwrap(),
+        ).env(
+                "CXX",
+                clang_cpp_compiler_path(target_options)?.to_str().unwrap(),
+            )
+            .env("CFLAGS", format!("--sysroot={}", sysroot_as_str))
+            .env("AR", clang_archiver_path(target_options)?.to_str().unwrap())
+            .env(
+                "RANLIB",
+                clang_ranlib_path(target_options)?.to_str().unwrap(),
+            )
+            .env("PKG_CONFIG_ALL_STATIC", "1")
+            .env("PKG_CONFIG_ALLOW_CROSS", "1")
+            .env("PKG_CONFIG_PATH", "")
+            .env("PKG_CONFIG_LIBDIR", pkg_path);
+    }
+
     if options.verbose {
         println!("cargo cmd: {:?}", cmd);
     }
@@ -468,6 +476,8 @@
 
 static SUBCOMMAND: &str = "subcommand";
 
+static DISABLE_CROSS_ENV: &str = "disable-cross-env";
+
 #[doc(hidden)]
 pub fn run() -> Result<(), Error> {
     let matches = App::new("fargo")
@@ -486,6 +496,11 @@
                 .help("Use debug user.bootfs and ssh keys"),
         )
         .arg(
+            Arg::with_name(DISABLE_CROSS_ENV)
+                .long(DISABLE_CROSS_ENV)
+                .help("Disable the setting of CC, AR and such environmental variables."),
+        )
+        .arg(
             Arg::with_name(TARGET_CPU)
                 .long(TARGET_CPU)
                 .short("T")
@@ -508,8 +523,8 @@
             SubCommand::with_name("autotest")
                 .about("Auto build and test in Fuchsia device or emulator")
                 .arg(
-                    Arg::with_name("release")
-                        .long("release")
+                    Arg::with_name(RELEASE)
+                        .long(RELEASE)
                         .help("Build release"),
                 ),
         )
@@ -523,8 +538,8 @@
                         .help("Test only the specified test target"),
                 )
                 .arg(
-                    Arg::with_name("release")
-                        .long("release")
+                    Arg::with_name(RELEASE)
+                        .long(RELEASE)
                         .help("Build release"),
                 ),
         )
@@ -532,8 +547,8 @@
             SubCommand::with_name("test")
                 .about("Run unit tests on Fuchsia device or emulator")
                 .arg(
-                    Arg::with_name("release")
-                        .long("release")
+                    Arg::with_name(RELEASE)
+                        .long(RELEASE)
                         .help("Build release"),
                 )
                 .arg(
@@ -554,8 +569,8 @@
             SubCommand::with_name("build")
                 .about("Build binary targeting Fuchsia device or emulator")
                 .arg(
-                    Arg::with_name("release")
-                        .long("release")
+                    Arg::with_name(RELEASE)
+                        .long(RELEASE)
                         .help("Build release"),
                 )
                 .arg(
@@ -590,8 +605,8 @@
             SubCommand::with_name("run")
                 .about("Run binary on Fuchsia device or emulator")
                 .arg(
-                    Arg::with_name("release")
-                        .long("release")
+                    Arg::with_name(RELEASE)
+                        .long(RELEASE)
                         .help("Build release"),
                 )
                 .arg(
@@ -610,8 +625,8 @@
             SubCommand::with_name("load-driver")
                 .about("Build driver and load it on Fuchsia device or emulator.")
                 .arg(
-                    Arg::with_name("release")
-                        .long("release")
+                    Arg::with_name(RELEASE)
+                        .long(RELEASE)
                         .help("Build release"),
                 ),
         )
@@ -694,12 +709,21 @@
         .get_matches();
 
     let verbose = matches.is_present("verbose");
+    let disable_cross = matches.is_present(DISABLE_CROSS_ENV);
+    let release = !matches.is_present("debug-os");
     let target_options = TargetOptions::new(
-        !matches.is_present("debug-os"),
+        release,
         matches.value_of(TARGET_CPU).unwrap(),
         matches.value_of("device-name"),
     );
 
+    let run_cargo_options = RunCargoOptions {
+        verbose,
+        release: false,
+        set_root_view: false,
+        disable_cross,
+    };
+
     if verbose {
         println!("target_options = {:#?}", target_options);
     }
@@ -711,8 +735,7 @@
 
     if let Some(autotest_matches) = matches.subcommand_matches("autotest") {
         return autotest(
-            verbose,
-            autotest_matches.is_present("release"),
+            run_cargo_options.release(autotest_matches.is_present(RELEASE)),
             &target_options,
         );
     }
@@ -725,8 +748,7 @@
         let test_target = test_matches.value_of("test").unwrap_or("");
         let test_args = test_matches.value_of("test_args");
         return run_tests(
-            verbose,
-            test_matches.is_present("release"),
+            run_cargo_options.release(test_matches.is_present(RELEASE)),
             false,
             &target_options,
             test_target,
@@ -747,8 +769,7 @@
         }
 
         build_binary(
-            verbose,
-            build_matches.is_present("release"),
+            run_cargo_options.release(build_matches.is_present(RELEASE)),
             &target_options,
             &params,
         )?;
@@ -767,8 +788,7 @@
         }
 
         check_binary(
-            verbose,
-            check_matches.is_present(RELEASE),
+            run_cargo_options.release(check_matches.is_present(RELEASE)),
             &target_options,
             &params,
         )?;
@@ -783,9 +803,9 @@
         }
 
         return run_binary(
-            verbose,
-            run_matches.is_present("release"),
-            run_matches.is_present(SET_ROOT_VIEW),
+            run_cargo_options
+                .release(run_matches.is_present(RELEASE))
+                .set_root_view(run_matches.is_present(SET_ROOT_VIEW)),
             &target_options,
             &params,
         );
@@ -793,8 +813,7 @@
 
     if let Some(load_driver_matches) = matches.subcommand_matches("load-driver") {
         return load_driver(
-            verbose,
-            load_driver_matches.is_present("release"),
+            run_cargo_options.release(load_driver_matches.is_present(RELEASE)),
             &target_options,
         );
     }
@@ -802,8 +821,7 @@
     if let Some(build_test_matches) = matches.subcommand_matches("build-tests") {
         let test_target = build_test_matches.value_of("test").unwrap_or("");
         build_tests(
-            verbose,
-            build_test_matches.is_present("release"),
+            run_cargo_options.release(build_test_matches.is_present(RELEASE)),
             &target_options,
             test_target,
         )?;
@@ -862,6 +880,7 @@
                 verbose,
                 release: false,
                 set_root_view: false,
+                disable_cross: disable_cross,
             },
             subcommand,
             &cargo_params,
diff --git a/src/sdk.rs b/src/sdk.rs
index faa62cc..314aa88 100644
--- a/src/sdk.rs
+++ b/src/sdk.rs
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-use X64;
 use failure::Error;
 use std::env;
 use std::fs::File;
 use std::io::Read;
 use std::path::PathBuf;
 use utils::is_mac;
+use X64;
 
 /// The `TargetOptions` struct bundles together a number of parameters specific to
 /// the Fuchsia target that need to be passed through various internal functions. For
@@ -34,7 +34,7 @@
     /// ```
 
     pub fn new(
-        release_os: bool, target_cpu: &'a str, device_name: Option<&'b str>
+        release_os: bool, target_cpu: &'a str, device_name: Option<&'b str>,
     ) -> TargetOptions<'a, 'b> {
         TargetOptions {
             release_os: release_os,
@@ -96,7 +96,7 @@
 }
 
 pub fn possible_target_out_dir(
-    fuchsia_dir: &PathBuf, options: &TargetOptions
+    fuchsia_dir: &PathBuf, options: &TargetOptions,
 ) -> Result<PathBuf, Error> {
     let out_dir_name_prefix = if options.release_os {
         "release"