From 5bd4d2ea7a75b915d70112731e815ed835a683e8 Mon Sep 17 00:00:00 2001 From: Jack Moffitt Date: Wed, 27 Nov 2013 20:05:12 -0700 Subject: [PATCH 1/3] Fix missing code map entry for uses of `include_str!`. --- src/libsyntax/ext/source_util.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs index c0c5c6c6c079c..2fcf6f1cad025 100644 --- a/src/libsyntax/ext/source_util.rs +++ b/src/libsyntax/ext/source_util.rs @@ -80,6 +80,7 @@ pub fn expand_mod(cx: @ExtCtxt, sp: Span, tts: &[ast::token_tree]) pub fn expand_include(cx: @ExtCtxt, sp: Span, tts: &[ast::token_tree]) -> base::MacResult { let file = get_single_str_from_tts(cx, sp, tts, "include!"); + // The file will be added to the code map by the parser let p = parse::new_sub_parser_from_file( cx.parse_sess(), cx.cfg(), &res_rel_file(cx, sp, &Path::new(file)), sp); @@ -99,7 +100,20 @@ pub fn expand_include_str(cx: @ExtCtxt, sp: Span, tts: &[ast::token_tree]) Ok(bytes) => bytes, }; match str::from_utf8_owned_opt(bytes) { - Some(s) => base::MRExpr(cx.expr_str(sp, s.to_managed())), + Some(s) => { + let s = s.to_managed(); + // Add this input file to the code map to make it available as + // dependency information + cx.parse_sess.cm.files.push(@codemap::FileMap { + name: file.display().to_str().to_managed(), + substr: codemap::FssNone, + src: s, + start_pos: codemap::BytePos(0), + lines: @mut ~[], + multibyte_chars: @mut ~[], + }); + base::MRExpr(cx.expr_str(sp, s)) + } None => { cx.span_fatal(sp, format!("{} wasn't a utf-8 file", file.display())); } From 9365375c7fe0c7dac1a6dfea3cdfa99a92027b97 Mon Sep 17 00:00:00 2001 From: Jack Moffitt Date: Wed, 27 Nov 2013 20:06:35 -0700 Subject: [PATCH 2/3] Add --dep-info to write Makefile-compatible dependency info. When --dep-info is given, rustc will write out a `$input_base.d` file in the output directory that contains Makefile compatible dependency information for use with tools like make and ninja. --- src/librustc/back/link.rs | 12 +++++++++--- src/librustc/driver/driver.rs | 31 ++++++++++++++++++++++++++++--- src/librustc/driver/session.rs | 3 +++ src/librustpkg/util.rs | 5 +++-- src/libsyntax/codemap.rs | 4 ++++ 5 files changed, 47 insertions(+), 8 deletions(-) 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 { From b2ccd4c3ec099b57fbcdb7dbc36cdb08c9016b4a Mon Sep 17 00:00:00 2001 From: Jack Moffitt Date: Wed, 11 Dec 2013 13:08:23 -0700 Subject: [PATCH 3/3] Add test for --dep-info. --- src/test/run-make/dep-info/Makefile | 11 +++++++++++ src/test/run-make/dep-info/Makefile.foo | 11 +++++++++++ src/test/run-make/dep-info/bar.rs | 1 + src/test/run-make/dep-info/foo.rs | 1 + src/test/run-make/dep-info/lib.rs | 4 ++++ 5 files changed, 28 insertions(+) create mode 100644 src/test/run-make/dep-info/Makefile create mode 100644 src/test/run-make/dep-info/Makefile.foo create mode 100644 src/test/run-make/dep-info/bar.rs create mode 100644 src/test/run-make/dep-info/foo.rs create mode 100644 src/test/run-make/dep-info/lib.rs diff --git a/src/test/run-make/dep-info/Makefile b/src/test/run-make/dep-info/Makefile new file mode 100644 index 0000000000000..535cda4d80b9e --- /dev/null +++ b/src/test/run-make/dep-info/Makefile @@ -0,0 +1,11 @@ +-include ../tools.mk +all: + $(RUSTC) --dep-info --lib lib.rs + sleep 1 + touch foo.rs + -rm -f $(TMPDIR)/done + $(MAKE) -f Makefile.foo + rm $(TMPDIR)/done + pwd + $(MAKE) -df Makefile.foo + rm $(TMPDIR)/done && exit 1 || exit 0 diff --git a/src/test/run-make/dep-info/Makefile.foo b/src/test/run-make/dep-info/Makefile.foo new file mode 100644 index 0000000000000..3e009828c0c49 --- /dev/null +++ b/src/test/run-make/dep-info/Makefile.foo @@ -0,0 +1,11 @@ +ifeq ($(shell uname),Darwin) +LIBEXT=dylib +else +LIBEXT=so +endif + +$(TMPDIR)/libfoo-b517899a-0.1.$(LIBEXT): + $(RUSTC) --dep-info --lib lib.rs + touch $(TMPDIR)/done + +-include $(TMPDIR)/lib.d diff --git a/src/test/run-make/dep-info/bar.rs b/src/test/run-make/dep-info/bar.rs new file mode 100644 index 0000000000000..c5c0bc606cd69 --- /dev/null +++ b/src/test/run-make/dep-info/bar.rs @@ -0,0 +1 @@ +pub fn bar() {} diff --git a/src/test/run-make/dep-info/foo.rs b/src/test/run-make/dep-info/foo.rs new file mode 100644 index 0000000000000..b76b4321d62aa --- /dev/null +++ b/src/test/run-make/dep-info/foo.rs @@ -0,0 +1 @@ +pub fn foo() {} diff --git a/src/test/run-make/dep-info/lib.rs b/src/test/run-make/dep-info/lib.rs new file mode 100644 index 0000000000000..d08a0fbcb6079 --- /dev/null +++ b/src/test/run-make/dep-info/lib.rs @@ -0,0 +1,4 @@ +#[pkgid="foo#0.1"]; + +pub mod foo; +pub mod bar;