diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 786b463c37ec2..d621f82e0fd34 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -720,7 +720,7 @@ pub fn link_binary(sess: Session, trans: &CrateTranslation, obj_filename: &Path, out_filename: &Path, - lm: &LinkMeta) { + lm: &LinkMeta) -> ~[Path] { // If we're generating a test executable, then ignore all other output // styles at all other locations let outputs = if sess.opts.test { @@ -729,8 +729,10 @@ pub fn link_binary(sess: Session, (*sess.outputs).clone() }; + let mut out_filenames = ~[]; for output in outputs.move_iter() { - link_binary_output(sess, trans, output, obj_filename, out_filename, lm); + let out_file = link_binary_output(sess, trans, output, obj_filename, out_filename, lm); + out_filenames.push(out_file); } // Remove the temporary object file and metadata if we aren't saving temps @@ -738,6 +740,8 @@ pub fn link_binary(sess: Session, fs::unlink(obj_filename); fs::unlink(&obj_filename.with_extension("metadata.o")); } + + out_filenames } fn is_writeable(p: &Path) -> bool { @@ -754,7 +758,7 @@ fn link_binary_output(sess: Session, output: session::OutputStyle, obj_filename: &Path, out_filename: &Path, - lm: &LinkMeta) { + lm: &LinkMeta) -> Path { let libname = output_lib_filename(lm); let out_filename = match output { session::OutputRlib => { @@ -805,6 +809,8 @@ fn link_binary_output(sess: Session, link_natively(sess, true, obj_filename, &out_filename); } } + + out_filename } // Create an 'rlib' diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index ec0424994075d..6206b4efa321d 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -384,13 +384,34 @@ pub fn phase_5_run_llvm_passes(sess: Session, /// This should produce either a finished executable or library. pub fn phase_6_link_output(sess: Session, trans: &CrateTranslation, + input: &input, outputs: &OutputFilenames) { - time(sess.time_passes(), "linking", (), |_| + let outputs = time(sess.time_passes(), "linking", (), |_| link::link_binary(sess, trans, &outputs.obj_filename, &outputs.out_filename, &trans.link)); + + // Write out dependency rules to the .d file if requested + if sess.opts.write_dependency_info { + match *input { + file_input(ref input_path) => { + let files: ~[@str] = sess.codemap.files.iter() + .filter_map(|fmap| if fmap.is_real_file() { Some(fmap.name) } else { None }) + .collect(); + let mut output_path = outputs[0].dir_path(); + let filestem = input_path.filestem().expect("input file must have stem"); + output_path.push(Path::new(filestem).with_extension("d")); + let mut file = io::File::create(&output_path); + for output in outputs.iter() { + write!(&mut file as &mut Writer, + "{}: {}\n\n", output.display(), files.connect(" ")); + } + } + str_input(_) => {} + } + } } pub fn stop_after_phase_3(sess: Session) -> bool { @@ -438,7 +459,7 @@ pub fn compile_input(sess: Session, cfg: ast::CrateConfig, input: &input, }; phase_5_run_llvm_passes(sess, &trans, outputs); if stop_after_phase_5(sess) { return; } - phase_6_link_output(sess, &trans, outputs); + phase_6_link_output(sess, &trans, input, outputs); } struct IdentifiedAnnotation { @@ -750,6 +771,7 @@ pub fn build_session_options(binary: @str, let cfg = parse_cfgspecs(matches.opt_strs("cfg"), demitter); let test = matches.opt_present("test"); let android_cross_path = matches.opt_str("android-cross-path"); + let write_dependency_info = matches.opt_present("dep-info"); let custom_passes = match matches.opt_str("passes") { None => ~[], @@ -793,7 +815,8 @@ pub fn build_session_options(binary: @str, parse_only: parse_only, no_trans: no_trans, debugging_opts: debugging_opts, - android_cross_path: android_cross_path + android_cross_path: android_cross_path, + write_dependency_info: write_dependency_info, }; return sopts; } @@ -902,6 +925,8 @@ pub fn optgroups() -> ~[getopts::groups::OptGroup] { or identified (fully parenthesized, AST nodes and blocks with IDs)", "TYPE"), optflag("S", "", "Compile only; do not assemble or link"), + optflag("", "dep-info", + "Output dependency info to .d file after compiling"), optflag("", "save-temps", "Write intermediate files (.bc, .opt.bc, .o) in addition to normal output"), diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs index 30d5b7780cf92..d12e06fab3fc7 100644 --- a/src/librustc/driver/session.rs +++ b/src/librustc/driver/session.rs @@ -170,6 +170,8 @@ pub struct options { no_trans: bool, debugging_opts: uint, android_cross_path: Option<~str>, + // Whether to write .d dependency files + write_dependency_info: bool, } pub struct crate_metadata { @@ -393,6 +395,7 @@ pub fn basic_options() -> @options { no_trans: false, debugging_opts: 0u, android_cross_path: None, + write_dependency_info: false, } } diff --git a/src/librustpkg/util.rs b/src/librustpkg/util.rs index 97fba807c0e60..0f46a1acf87d9 100644 --- a/src/librustpkg/util.rs +++ b/src/librustpkg/util.rs @@ -353,7 +353,8 @@ pub fn compile_crate_from_input(input: &Path, // bad copy debug!("out_dir = {}", out_dir.display()); - let mut outputs = driver::build_output_filenames(&driver::file_input(input.clone()), + let file_input = driver::file_input(input.clone()); + let mut outputs = driver::build_output_filenames(&file_input, &Some(out_dir.clone()), &None, crate.attrs, sess); match what { @@ -388,7 +389,7 @@ pub fn compile_crate_from_input(input: &Path, // -c if driver::stop_after_phase_5(sess) || stop_before == Link || stop_before == Assemble { return Some(outputs.out_filename); } - driver::phase_6_link_output(sess, &translation, outputs); + driver::phase_6_link_output(sess, &translation, &file_input, outputs); // Register dependency on the source file // FIXME (#9639): This needs to handle non-utf8 paths diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index ac89689f00478..0509760120a42 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -260,6 +260,10 @@ impl FileMap { }; self.multibyte_chars.push(mbc); } + + pub fn is_real_file(&self) -> bool { + !(self.name.starts_with("<") && self.name.ends_with(">")) + } } pub struct CodeMap {