diff --git a/src/bootstrap/build/doc.rs b/src/bootstrap/build/doc.rs new file mode 100644 index 00000000000..937a234bec8 --- /dev/null +++ b/src/bootstrap/build/doc.rs @@ -0,0 +1,104 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::path::Path; +use std::fs::{self, File}; +use std::io::prelude::*; + +use build::{Build, Compiler}; +use build::util::up_to_date; + +pub fn rustbook(build: &Build, stage: u32, host: &str, name: &str, out: &Path) { + t!(fs::create_dir_all(out)); + + let out = out.join(name); + let compiler = Compiler::new(stage, host); + let src = build.src.join("src/doc").join(name); + let index = out.join("index.html"); + let rustbook = build.tool(&compiler, "rustbook"); + if up_to_date(&src, &index) && up_to_date(&rustbook, &index) { + return + } + println!("Rustbook stage{} ({}) - {}", stage, host, name); + let _ = fs::remove_dir_all(&out); + build.run(build.tool_cmd(&compiler, "rustbook") + .arg("build") + .arg(&src) + .arg(out)); +} + +pub fn standalone(build: &Build, stage: u32, host: &str, out: &Path) { + println!("Documenting stage{} standalone ({})", stage, host); + t!(fs::create_dir_all(out)); + + let compiler = Compiler::new(stage, host); + + let favicon = build.src.join("src/doc/favicon.inc"); + let footer = build.src.join("src/doc/footer.inc"); + let full_toc = build.src.join("src/doc/full-toc.inc"); + t!(fs::copy(build.src.join("src/doc/rust.css"), out.join("rust.css"))); + + let version_input = build.src.join("src/doc/version_info.html.template"); + let version_info = out.join("version_info.html"); + + if !up_to_date(&version_input, &version_info) { + let mut info = String::new(); + t!(t!(File::open(&version_input)).read_to_string(&mut info)); + let blank = String::new(); + let short = build.short_ver_hash.as_ref().unwrap_or(&blank); + let hash = build.ver_hash.as_ref().unwrap_or(&blank); + let info = info.replace("VERSION", &build.release) + .replace("SHORT_HASH", short) + .replace("STAMP", hash); + t!(t!(File::create(&version_info)).write_all(info.as_bytes())); + } + + for file in t!(fs::read_dir(build.src.join("src/doc"))) { + let file = t!(file); + let path = file.path(); + let filename = path.file_name().unwrap().to_str().unwrap(); + if !filename.ends_with(".md") || filename == "README.md" { + continue + } + + let html = out.join(filename).with_extension("html"); + let rustdoc = build.tool(&compiler, "rustdoc"); + if up_to_date(&path, &html) && + up_to_date(&footer, &html) && + up_to_date(&favicon, &html) && + up_to_date(&full_toc, &html) && + up_to_date(&version_info, &html) && + up_to_date(&rustdoc, &html) { + continue + } + + let mut cmd = build.tool_cmd(&compiler, "rustdoc"); + cmd.arg("--html-after-content").arg(&footer) + .arg("--html-before-content").arg(&version_info) + .arg("--html-in-header").arg(&favicon) + .arg("--markdown-playground-url") + .arg("https://play.rust-lang.org/") + .arg("-o").arg(out) + .arg(&path); + + if filename == "reference.md" { + cmd.arg("--html-in-header").arg(&full_toc); + } + + if filename == "not_found.md" { + cmd.arg("--markdown-no-toc") + .arg("--markdown-css") + .arg("https://doc.rust-lang.org/rust.css"); + } else { + cmd.arg("--markdown-css").arg("rust.css"); + } + build.run(&mut cmd); + } +} diff --git a/src/bootstrap/build/mod.rs b/src/bootstrap/build/mod.rs index 92043ee3f25..2bb169a5ebc 100644 --- a/src/bootstrap/build/mod.rs +++ b/src/bootstrap/build/mod.rs @@ -33,6 +33,7 @@ mod channel; mod clean; mod compile; mod config; +mod doc; mod flags; mod native; mod sanity; @@ -133,6 +134,7 @@ impl Build { self.update_submodules(); for target in step::all(self) { + let doc_out = self.out.join(&target.target).join("doc"); match target.src { Llvm { _dummy } => { native::llvm(self, target.target); @@ -149,6 +151,21 @@ impl Build { Rustc { stage } => { println!("ok, rustc stage{} in {}", stage, target.target); } + DocBook { stage } => { + doc::rustbook(self, stage, target.target, "book", &doc_out); + } + DocNomicon { stage } => { + doc::rustbook(self, stage, target.target, "nomicon", + &doc_out); + } + DocStyle { stage } => { + doc::rustbook(self, stage, target.target, "style", + &doc_out); + } + DocStandalone { stage } => { + doc::standalone(self, stage, target.target, &doc_out); + } + Doc { .. } => {} // pseudo-step } } } diff --git a/src/bootstrap/build/step.rs b/src/bootstrap/build/step.rs index 2fbf1a6ad1d..d82c62b3667 100644 --- a/src/bootstrap/build/step.rs +++ b/src/bootstrap/build/step.rs @@ -26,6 +26,11 @@ macro_rules! targets { (librustc, Librustc { stage: u32, compiler: Compiler<'a> }), (llvm, Llvm { _dummy: () }), (compiler_rt, CompilerRt { _dummy: () }), + (doc, Doc { stage: u32 }), + (doc_book, DocBook { stage: u32 }), + (doc_nomicon, DocNomicon { stage: u32 }), + (doc_style, DocStyle { stage: u32 }), + (doc_standalone, DocStandalone { stage: u32 }), } } } @@ -88,6 +93,7 @@ fn top_level(build: &Build) -> Vec { src: Source::Llvm { _dummy: () }, target: &build.config.build, }; + targets.push(t.doc(stage)); for host in build.config.host.iter() { if !build.flags.host.contains(host) { continue @@ -121,6 +127,11 @@ fn add_steps<'a>(build: &'a Build, "rustc" => targets.push(host.rustc(stage)), "llvm" => targets.push(target.llvm(())), "compiler-rt" => targets.push(target.compiler_rt(())), + "doc-style" => targets.push(host.doc_style(stage)), + "doc-standalone" => targets.push(host.doc_standalone(stage)), + "doc-nomicon" => targets.push(host.doc_nomicon(stage)), + "doc-book" => targets.push(host.doc_book(stage)), + "doc" => targets.push(host.doc(stage)), _ => panic!("unknown build target: `{}`", step), } } @@ -172,6 +183,16 @@ impl<'a> Step<'a> { vec![self.llvm(()).target(&build.config.build)] } Source::Llvm { _dummy } => Vec::new(), + Source::DocBook { stage } | + Source::DocNomicon { stage } | + Source::DocStyle { stage } | + Source::DocStandalone { stage } => { + vec![self.rustc(stage)] + } + Source::Doc { stage } => { + vec![self.doc_book(stage), self.doc_nomicon(stage), + self.doc_style(stage), self.doc_standalone(stage)] + } } } } diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in index bd29fd8612d..fa3dee2f358 100644 --- a/src/bootstrap/mk/Makefile.in +++ b/src/bootstrap/mk/Makefile.in @@ -24,3 +24,15 @@ all: clean: $(Q)$(BOOTSTRAP) --clean + +docs: doc +doc: + $(Q)$(BOOTSTRAP) --step doc +style: + $(Q)$(BOOTSTRAP) --step doc-style +nomicon: + $(Q)$(BOOTSTRAP) --step doc-nomicon +book: + $(Q)$(BOOTSTRAP) --step doc-book +standalone-docs: + $(Q)$(BOOTSTRAP) --step doc-standalone diff --git a/src/doc/rustc-ux-guidelines.md b/src/doc/rustc-ux-guidelines.md index 563614f873d..6fc7219cdb3 100644 --- a/src/doc/rustc-ux-guidelines.md +++ b/src/doc/rustc-ux-guidelines.md @@ -1,3 +1,5 @@ +% Rustc UX guidelines + Don't forget the user. Whether human or another program, such as an IDE, a good user experience with the compiler goes a long way into making developer lives better. We don't want users to be baffled by compiler output or @@ -70,4 +72,4 @@ understandable compiler scripts. * The `--verbose` flag is for adding verbose information to `rustc` output when not compiling a program. For example, using it with the `--version` flag gives information about the hashes of the code. -* Experimental flags and options must be guarded behind the `-Z unstable-options` flag. \ No newline at end of file +* Experimental flags and options must be guarded behind the `-Z unstable-options` flag.