Skip to content

Commit

Permalink
Support -showIncludes on MSVC
Browse files Browse the repository at this point in the history
Track the `-showIncludes` flag being passed down to the compilation itself, and
then also be sure to thread the entire output of the preprocessor down to
compilations instead of just stdout. Once that was done support was implemented
by simply prepending the preprocessor stderr to the compiler stderr if the
`-showIncludes` flag was passed.
  • Loading branch information
alexcrichton committed Mar 13, 2017
1 parent 8f2fc2d commit b61570d
Show file tree
Hide file tree
Showing 5 changed files with 441 additions and 214 deletions.
79 changes: 49 additions & 30 deletions src/compiler/clang.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ pub fn argument_takes_value(arg: &str) -> bool {

pub fn compile<T>(creator: &T,
compiler: &Compiler,
preprocessor_output: Vec<u8>,
preprocessor_result: process::Output,
parsed_args: &ParsedArguments,
cwd: &str,
pool: &CpuPool)
Expand All @@ -65,7 +65,7 @@ pub fn compile<T>(creator: &T,
Some(name) => name,
None => return future::err("missing input filename".into()).boxed(),
};
write_temp_file(pool, filename.as_ref(), preprocessor_output)
write_temp_file(pool, filename.as_ref(), preprocessor_result.stdout)
};
let input = parsed_args.input.clone();
let out_file = match parsed_args.outputs.get("obj") {
Expand Down Expand Up @@ -133,36 +133,53 @@ mod test {

#[test]
fn test_parse_arguments_simple() {
match _parse_arguments(&stringvec!["-c", "foo.c", "-o", "foo.o"]) {
CompilerArguments::Ok(ParsedArguments { input, extension, depfile: _depfile, outputs, preprocessor_args, common_args }) => {
assert!(true, "Parsed ok");
assert_eq!("foo.c", input);
assert_eq!("c", extension);
assert_map_contains!(outputs, ("obj", "foo.o"));
//TODO: fix assert_map_contains to assert no extra keys!
assert_eq!(1, outputs.len());
assert!(preprocessor_args.is_empty());
assert!(common_args.is_empty());
}
o @ _ => assert!(false, format!("Got unexpected parse result: {:?}", o)),
}
let args = stringvec!["-c", "foo.c", "-o", "foo.o"];
let ParsedArguments {
input,
extension,
depfile: _depfile,
outputs,
preprocessor_args,
msvc_show_includes,
common_args,
} = match _parse_arguments(&args) {
CompilerArguments::Ok(args) => args,
o @ _ => panic!("Got unexpected parse result: {:?}", o),
};
assert!(true, "Parsed ok");
assert_eq!("foo.c", input);
assert_eq!("c", extension);
assert_map_contains!(outputs, ("obj", "foo.o"));
//TODO: fix assert_map_contains to assert no extra keys!
assert_eq!(1, outputs.len());
assert!(preprocessor_args.is_empty());
assert!(common_args.is_empty());
assert!(!msvc_show_includes);
}

#[test]
fn test_parse_arguments_values() {
match _parse_arguments(&stringvec!["-c", "foo.cxx", "-arch", "xyz", "-fabc","-I", "include", "-o", "foo.o", "-include", "file"]) {
CompilerArguments::Ok(ParsedArguments { input, extension, depfile: _depfile, outputs, preprocessor_args, common_args }) => {
assert!(true, "Parsed ok");
assert_eq!("foo.cxx", input);
assert_eq!("cxx", extension);
assert_map_contains!(outputs, ("obj", "foo.o"));
//TODO: fix assert_map_contains to assert no extra keys!
assert_eq!(1, outputs.len());
assert!(preprocessor_args.is_empty());
assert_eq!(stringvec!["-arch", "xyz", "-fabc", "-I", "include", "-include", "file"], common_args);
}
o @ _ => assert!(false, format!("Got unexpected parse result: {:?}", o)),
}
let args = stringvec!["-c", "foo.cxx", "-arch", "xyz", "-fabc","-I", "include", "-o", "foo.o", "-include", "file"];
let ParsedArguments {
input,
extension,
depfile: _depfile,
outputs,
preprocessor_args,
msvc_show_includes,
common_args,
} = match _parse_arguments(&args) {
CompilerArguments::Ok(args) => args,
o @ _ => panic!("Got unexpected parse result: {:?}", o),
};
assert!(true, "Parsed ok");
assert_eq!("foo.cxx", input);
assert_eq!("cxx", extension);
assert_map_contains!(outputs, ("obj", "foo.o"));
//TODO: fix assert_map_contains to assert no extra keys!
assert_eq!(1, outputs.len());
assert!(preprocessor_args.is_empty());
assert_eq!(stringvec!["-arch", "xyz", "-fabc", "-I", "include", "-include", "file"], common_args);
}

#[test]
Expand All @@ -177,14 +194,15 @@ mod test {
outputs: vec![("obj", "foo.o".to_owned())].into_iter().collect::<HashMap<&'static str, String>>(),
preprocessor_args: vec!(),
common_args: vec!(),
msvc_show_includes: false,
};
let compiler = Compiler::new(f.bins[0].to_str().unwrap(),
CompilerKind::Clang).unwrap();
// Compiler invocation.
next_command(&creator, Ok(MockChild::new(exit_status(0), "", "")));
let (cacheable, _) = compile(&creator,
&compiler,
vec!(),
empty_output(),
&parsed_args,
f.tempdir.path().to_str().unwrap(),
&pool).wait().unwrap();
Expand All @@ -205,6 +223,7 @@ mod test {
outputs: vec![("obj", "foo.o".to_owned())].into_iter().collect::<HashMap<&'static str, String>>(),
preprocessor_args: vec!(),
common_args: stringvec!("-c", "-o", "foo.o", "-Werror=blah", "foo.c"),
msvc_show_includes: false,
};
let compiler = Compiler::new(f.bins[0].to_str().unwrap(),
CompilerKind::Clang).unwrap();
Expand All @@ -214,7 +233,7 @@ mod test {
next_command(&creator, Ok(MockChild::new(exit_status(0), "", "")));
let (cacheable, output) = compile(&creator,
&compiler,
vec!(),
empty_output(),
&parsed_args,
f.tempdir.path().to_str().unwrap(),
&pool).wait().unwrap();
Expand Down
18 changes: 12 additions & 6 deletions src/compiler/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,17 +104,17 @@ impl CompilerKind {
pub fn compile<T>(&self,
creator: &T,
compiler: &Compiler,
preprocessor_output: Vec<u8>,
preprocessor_result: process::Output,
parsed_args: &ParsedArguments,
cwd: &str,
pool: &CpuPool)
-> SFuture<(Cacheable, process::Output)>
where T: CommandCreatorSync,
{
match *self {
CompilerKind::Gcc => gcc::compile(creator, compiler, preprocessor_output, parsed_args, cwd, pool),
CompilerKind::Clang => clang::compile(creator, compiler, preprocessor_output, parsed_args, cwd, pool),
CompilerKind::Msvc { .. } => msvc::compile(creator, compiler, preprocessor_output, parsed_args, cwd, pool),
CompilerKind::Gcc => gcc::compile(creator, compiler, preprocessor_result, parsed_args, cwd, pool),
CompilerKind::Clang => clang::compile(creator, compiler, preprocessor_result, parsed_args, cwd, pool),
CompilerKind::Msvc { .. } => msvc::compile(creator, compiler, preprocessor_result, parsed_args, cwd, pool),
}
}
}
Expand All @@ -135,6 +135,8 @@ pub struct ParsedArguments {
pub preprocessor_args: Vec<String>,
/// Commandline arguments for the preprocessor or the compiler.
pub common_args: Vec<String>,
/// Whether, for MSVC, the `-showIncludes` flag is passed.
pub msvc_show_includes: bool,
}

impl ParsedArguments {
Expand Down Expand Up @@ -421,11 +423,15 @@ impl Compiler {
-> SFuture<(CompileResult, process::Output)>
where T: CommandCreatorSync,
{
let process::Output { stdout, .. } = preprocessor_result;
let start = Instant::now();
let out_file = parsed_args.output_file().into_owned();

let compile = self.kind.compile(creator, self, stdout, &parsed_args, cwd, &pool);
let compile = self.kind.compile(creator,
self,
preprocessor_result,
&parsed_args,
cwd,
&pool);
Box::new(compile.and_then(move |(cacheable, compiler_result)| {
let duration = start.elapsed();
if !compiler_result.status.success() {
Expand Down
Loading

0 comments on commit b61570d

Please sign in to comment.