in src/compiler/diab.rs [405:455]
fn next(&mut self) -> Option<OsString> {
loop {
let arg = self.stack.pop()?;
// Just return non @ arguments
if !arg.starts_with("-@") {
return Some(arg);
}
let value = match arg.split_prefix("-@") {
Some(arg) => arg,
None => return Some(arg),
};
// Return options that produce additional output and are not cacheable
if value.starts_with("E") || value.starts_with("O") || value.starts_with("@") {
return Some(arg);
}
// According to diab [1], @file means:
// Read command line options from either a file or an environment
// variable. When -@name is encountered on the command line, the
// driver first looks for an environment variable with the given
// name and substitutes its value. If an environment variable is
// not found then the driver tries to open a file with given name
// and substitutes the contents of the file. If neither an
// environment variable or a file can be found, an error message
// is issued and the driver terminates.
//
// [1]: http://www.vxdev.com/docs/vx55man/diab5.0ppc/c-invoke.htm#3000619
//
// The environment variable feature is *not* supported by sccache
// since this would raise the need for the clients environment
// and not just env::var. This is technically possible, but
// considered as a unneeded edge case for now.
let mut contents = String::new();
let file = self.cwd.join(&value);
let res = File::open(file).and_then(|mut f| f.read_to_string(&mut contents));
if res.is_err() {
// Failed to read the file, so return the argument as it is.
// This will result in a CannotCache.
return Some(arg);
}
if contents.contains('"') || contents.contains('\'') {
return Some(arg);
}
let new_args = contents.split_whitespace().collect::<Vec<_>>();
self.stack.extend(new_args.iter().rev().map(|s| s.into()));
}
}