diff --git a/src/lib.rs b/src/lib.rs
index 8dd19e10d..cbf1c6fa2 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -197,6 +197,7 @@ pub struct Tool {
     cc_wrapper_args: Vec<OsString>,
     args: Vec<OsString>,
     env: Vec<(OsString, OsString)>,
+    env_remove: Vec<OsString>,
     family: ToolFamily,
     cuda: bool,
     removed_args: Vec<OsString>,
@@ -1516,12 +1517,8 @@ impl Build {
         let (mut cmd, name) = if is_assembler_msvc {
             self.msvc_macro_assembler()?
         } else {
-            let mut cmd = compiler.to_command();
-            for &(ref a, ref b) in self.env.iter() {
-                cmd.env(a, b);
-            }
             (
-                cmd,
+                compiler.to_command(),
                 compiler
                     .path
                     .file_name()
@@ -1552,9 +1549,6 @@ impl Build {
             cmd.arg("--");
         }
         cmd.arg(&obj.src);
-        if cfg!(target_os = "macos") {
-            self.fix_env_for_apple_os(&mut cmd)?;
-        }
 
         Ok((cmd, name))
     }
@@ -1563,9 +1557,7 @@ impl Build {
     pub fn try_expand(&self) -> Result<Vec<u8>, Error> {
         let compiler = self.try_get_compiler()?;
         let mut cmd = compiler.to_command();
-        for &(ref a, ref b) in self.env.iter() {
-            cmd.env(a, b);
-        }
+
         cmd.arg("-E");
 
         assert!(
@@ -1711,6 +1703,19 @@ impl Build {
             cmd.push_cc_arg(warnings_to_errors_flag);
         }
 
+        for (k, v) in self.env.iter() {
+            cmd.env.push((k.to_os_string(), v.to_os_string()));
+        }
+
+        if cfg!(target_os = "macos") {
+            for (k, v) in self.fixed_env_for_apple_os()? {
+                match v {
+                    Some(v) => cmd.env.push((k, v)),
+                    None => cmd.env_remove.push(k),
+                }
+            }
+        }
+
         Ok(cmd)
     }
 
@@ -3343,9 +3348,11 @@ impl Build {
         }
     }
 
-    fn fix_env_for_apple_os(&self, cmd: &mut Command) -> Result<(), Error> {
+    fn fixed_env_for_apple_os(&self) -> Result<HashMap<OsString, Option<OsString>>, Error> {
         let target = self.get_target()?;
         let host = self.get_host()?;
+        let mut env = HashMap::new();
+
         if host.contains("apple-darwin") && target.contains("apple-darwin") {
             // If, for example, `cargo` runs during the build of an XCode project, then `SDKROOT` environment variable
             // would represent the current target, and this is the problem for us, if we want to compile something
@@ -3357,15 +3364,16 @@ impl Build {
             if let Ok(sdkroot) = env::var("SDKROOT") {
                 if !sdkroot.contains("MacOSX") {
                     let macos_sdk = self.apple_sdk_root("macosx")?;
-                    cmd.env("SDKROOT", macos_sdk);
+                    env.insert("SDKROOT".into(), Some(macos_sdk));
                 }
             }
             // Additionally, `IPHONEOS_DEPLOYMENT_TARGET` must not be set when using the Xcode linker at
             // "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld",
             // although this is apparently ignored when using the linker at "/usr/bin/ld".
-            cmd.env_remove("IPHONEOS_DEPLOYMENT_TARGET");
+            env.insert("IPHONEOS_DEPLOYMENT_TARGET".into(), None);
         }
-        Ok(())
+
+        Ok(env)
     }
 
     fn apple_sdk_root(&self, sdk: &str) -> Result<OsString, Error> {
@@ -3431,6 +3439,7 @@ impl Tool {
             cc_wrapper_args: Vec::new(),
             args: Vec::new(),
             env: Vec::new(),
+            env_remove: Vec::new(),
             family: family,
             cuda: false,
             removed_args: Vec::new(),
@@ -3462,6 +3471,7 @@ impl Tool {
             cc_wrapper_args: Vec::new(),
             args: Vec::new(),
             env: Vec::new(),
+            env_remove: Vec::new(),
             family: family,
             cuda: cuda,
             removed_args: Vec::new(),
@@ -3550,9 +3560,14 @@ impl Tool {
             .collect::<Vec<_>>();
         cmd.args(&value);
 
-        for &(ref k, ref v) in self.env.iter() {
+        for (k, v) in self.env.iter() {
             cmd.env(k, v);
         }
+
+        for k in self.env_remove.iter() {
+            cmd.env_remove(k);
+        }
+
         cmd
     }
 
@@ -3572,12 +3587,16 @@ impl Tool {
 
     /// Returns the set of environment variables needed for this compiler to
     /// operate.
-    ///
-    /// This is typically only used for MSVC compilers currently.
     pub fn env(&self) -> &[(OsString, OsString)] {
         &self.env
     }
 
+    /// Returns the set of environment variables needed to be removed for this
+    /// compiler to operate.
+    pub fn env_remove(&self) -> &[OsString] {
+        &self.env_remove
+    }
+
     /// Returns the compiler command in format of CC environment variable.
     /// Or empty string if CC env was not present
     ///