From 6da479d6d8e9f63ac7a397ae566a02d050a5fb4a Mon Sep 17 00:00:00 2001 From: fedor Date: Mon, 23 Oct 2017 20:26:19 +0300 Subject: [PATCH] env_tool returning additional param for ccache case --- src/lib.rs | 55 +++++++++++++++++++++++++++++++++---------------- tests/cc_env.rs | 20 +++++++++--------- 2 files changed, 47 insertions(+), 28 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 05679ca..430a644 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -148,7 +148,8 @@ impl From for Error { #[derive(Clone, Debug)] pub struct Tool { path: PathBuf, - path_args: Vec, + cc_path: Option, + cc_args: Vec, args: Vec, env: Vec<(OsString, OsString)>, family: ToolFamily @@ -1283,10 +1284,13 @@ impl Build { }; let tool_opt: Option = self.env_tool(env) - .map(|(tool, args)| { + .map(|(tool, cc, args)| { let mut t = Tool::new(PathBuf::from(tool)); + if let Some(cc) = cc { + t.cc_path = Some(PathBuf::from(cc)); + } for arg in args { - t.path_args.push(arg.into()); + t.cc_args.push(arg.into()); } t }) @@ -1403,15 +1407,19 @@ impl Build { } - fn env_tool(&self, name: &str) -> Option<(String, Vec)> { + /// Returns compiler path, optional modifier name from whitelist, and arguments vec + fn env_tool(&self, name: &str) -> Option<(String, Option, Vec)> { self.get_var(name).ok().map(|tool| { let whitelist = ["ccache", "distcc", "sccache"]; + for t in whitelist.iter() { - if tool.starts_with(t) && tool[t.len()..].starts_with(' ') { - return (t.to_string(), vec![tool[t.len()..].trim_left().to_string()]); + if tool.starts_with(t) && tool[t.len()..].starts_with(' ') { + let args = tool.split_whitespace().collect::>(); + + return (args[1].to_string(), Some(t.to_string()), args[2..].iter().map(|s| s.to_string()).collect()); } } - (tool, Vec::new()) + (tool, None, Vec::new()) }) } @@ -1541,7 +1549,8 @@ impl Tool { }; Tool { path: path, - path_args: Vec::new(), + cc_path: None, + cc_args: Vec::new(), args: Vec::new(), env: Vec::new(), family: family @@ -1555,7 +1564,7 @@ impl Tool { /// variables configured. pub fn to_command(&self) -> Command { let mut cmd = Command::new(&self.path); - cmd.args(&self.path_args); + cmd.args(&self.cc_args); cmd.args(&self.args); for &(ref k, ref v) in self.env.iter() { cmd.env(k, v); @@ -1586,20 +1595,30 @@ impl Tool { } /// Returns the compiler command in format of CC environment variable. - /// - /// This is typically used by configure script + /// Or empty string if CC env was not present + /// + /// This is typically used by configure script pub fn cc_env(&self) -> OsString { - let mut cc = self.path.as_os_str().to_owned(); - for arg in self.path_args.iter() { - cc.push(" "); - cc.push(arg); + match self.cc_path { + Some(ref cc_path) => { + let mut cc_env = cc_path.as_os_str().to_owned(); + cc_env.push(" "); + cc_env.push(self.path.to_path_buf().into_os_string()); + for arg in self.cc_args.iter() { + cc_env.push(" "); + cc_env.push(arg); + } + cc_env + }, + None => { + OsString::from("") + } } - cc } /// Returns the compiler flags in format of CFLAGS environment variable. - /// - /// This is typically used by configure script + /// Important here - this will not be CFLAGS from env, its internal gcc's flags to use as CFLAGS + /// This is typically used by configure script pub fn cflags_env(&self) -> OsString { let mut flags = OsString::new(); for (i, arg) in self.args.iter().enumerate() { diff --git a/tests/cc_env.rs b/tests/cc_env.rs index c65f55c..3b35a1e 100644 --- a/tests/cc_env.rs +++ b/tests/cc_env.rs @@ -16,37 +16,37 @@ fn main() { fn ccache() { let test = Test::gnu(); - test.shim("ccache"); - env::set_var("CC", "ccache lol-this-is-not-a-compiler foo"); - test.gcc().file("foo.c").compile("libfoo.a"); + env::set_var("CC", "ccache cc"); + test.gcc().file("foo.c").compile("foo"); test.cmd(0) - .must_have("lol-this-is-not-a-compiler foo") .must_have("foo.c") .must_not_have("ccache"); + test.cmd(1).must_have(test.td.path().join("foo.o")); } fn ccache_spaces() { let test = Test::gnu(); test.shim("ccache"); - env::set_var("CC", "ccache lol-this-is-not-a-compiler foo"); + env::set_var("CC", "ccache cc"); test.gcc().file("foo.c").compile("libfoo.a"); - test.cmd(0).must_have("lol-this-is-not-a-compiler foo"); + test.cmd(0).must_have("foo.c"); + test.cmd(1).must_have(test.td.path().join("foo.o")); } fn distcc() { let test = Test::gnu(); test.shim("distcc"); - env::set_var("CC", "distcc lol-this-is-not-a-compiler foo"); - test.gcc().file("foo.c").compile("libfoo.a"); + env::set_var("CC", "distcc cc"); + test.gcc().file("foo.c").compile("foo"); test.cmd(0) - .must_have("lol-this-is-not-a-compiler foo") .must_have("foo.c") .must_not_have("distcc"); + test.cmd(1).must_have(test.td.path().join("foo.o")); } fn ccache_env_flags() { @@ -58,7 +58,7 @@ fn ccache_env_flags() { env::set_var("CC", "ccache lol-this-is-not-a-compiler"); let compiler = test.gcc().file("foo.c").get_compiler(); - assert_eq!(compiler.path(), Path::new("ccache")); + assert_eq!(compiler.path(), Path::new("lol-this-is-not-a-compiler")); assert_eq!(compiler.cc_env(), OsString::from("ccache lol-this-is-not-a-compiler")); assert!(compiler.cflags_env().into_string().unwrap().contains("ccache") == false); assert!(compiler.cflags_env().into_string().unwrap().contains(" lol-this-is-not-a-compiler") == false);