diff --git a/mk/clean.mk b/mk/clean.mk index bc5961a9981..73813a4b751 100644 --- a/mk/clean.mk +++ b/mk/clean.mk @@ -41,7 +41,6 @@ clean-misc: @$(call E, cleaning) $(Q)rm -f $(RUNTIME_OBJS) $(RUNTIME_DEF) $(Q)rm -f $(RUSTLLVM_LIB_OBJS) $(RUSTLLVM_OBJS_OBJS) $(RUSTLLVM_DEF) - $(Q)rm -Rf $(DOCS) $(Q)rm -Rf $(GENERATED) $(Q)rm -Rf tmp/* $(Q)rm -Rf rust-stage0-*.tar.bz2 $(PKG_NAME)-*.tar.gz $(PKG_NAME)-*.exe dist diff --git a/mk/crates.mk b/mk/crates.mk index 45b6ed1a058..70560d41b8d 100644 --- a/mk/crates.mk +++ b/mk/crates.mk @@ -92,6 +92,7 @@ TOOL_SOURCE_rustc := $(S)src/driver/driver.rs ################################################################################ DOC_CRATES := $(filter-out rustc, $(filter-out syntax, $(CRATES))) +COMPILER_DOC_CRATES := rustc syntax # This macro creates some simple definitions for each crate being built, just # some munging of all of the parameters above. diff --git a/mk/docs.mk b/mk/docs.mk index 7861888482e..f3fd94678ff 100644 --- a/mk/docs.mk +++ b/mk/docs.mk @@ -9,24 +9,93 @@ # except according to those terms. ###################################################################### -# Doc variables and rules +# The various pieces of standalone documentation: guides, tutorial, +# manual etc. +# +# The DOCS variable is their names (with no file extension). +# +# RUSTDOC_FLAGS_xyz variables are extra arguments to pass to the +# rustdoc invocation for xyz. +# +# RUSTDOC_DEPS_xyz are extra dependencies for the rustdoc invocation +# on xyz. +# +# L10N_LANGS are the languages for which the docs have been +# translated. ###################################################################### +DOCS := index tutorial guide-ffi guide-macros guide-lifetimes \ + guide-tasks guide-container guide-pointers \ + complement-cheatsheet guide-runtime \ + rust -DOCS := -CDOCS := -DOCS_L10N := -HTML_DEPS := doc/ +RUSTDOC_DEPS_rust := doc/full-toc.inc +RUSTDOC_FLAGS_rust := --markdown-in-header=doc/full-toc.inc -BASE_DOC_OPTS := --standalone --toc --number-sections -HTML_OPTS = $(BASE_DOC_OPTS) --to=html5 --section-divs --css=rust.css \ - --include-before-body=doc/version_info.html \ - --include-in-header=doc/favicon.inc --include-after-body=doc/footer.inc -TEX_OPTS = $(BASE_DOC_OPTS) --include-before-body=doc/version.md \ - --from=markdown --include-before-body=doc/footer.tex --to=latex -EPUB_OPTS = $(BASE_DOC_OPTS) --to=epub +L10N_LANGS := ja + +# Generally no need to edit below here. + +# The options are passed to the documentation generators. +RUSTDOC_HTML_OPTS = --markdown-css rust.css \ + --markdown-before-content=doc/version_info.html \ + --markdown-in-header=doc/favicon.inc --markdown-after-content=doc/footer.inc + +PANDOC_BASE_OPTS := --standalone --toc --number-sections +PANDOC_TEX_OPTS = $(PANDOC_BASE_OPTS) --include-before-body=doc/version.md \ + --from=markdown --include-before-body=doc/footer.tex --to=latex +PANDOC_EPUB_OPTS = $(PANDOC_BASE_OPTS) --to=epub + + + +# The rustdoc executable... +RUSTDOC_EXE = $(HBIN2_H_$(CFG_BUILD))/rustdoc$(X_$(CFG_BUILD)) +# ...with rpath included in case --disable-rpath was provided to +# ./configure +RUSTDOC = $(RPATH_VAR2_T_$(CFG_BUILD)_H_$(CFG_BUILD)) $(RUSTDOC_EXE) D := $(S)src/doc +DOC_TARGETS := +COMPILER_DOC_TARGETS := +DOC_L10N_TARGETS := + +# If NO_REBUILD is set then break the dependencies on rustdoc so we +# build the documentation without having to rebuild rustdoc. +ifeq ($(NO_REBUILD),) +HTML_DEPS := $(RUSTDOC_EXE) +else +HTML_DEPS := +endif + +# Check for the various external utilities for the EPUB/PDF docs: + +ifeq ($(CFG_PDFLATEX),) + $(info cfg: no pdflatex found, omitting doc/rust.pdf) + NO_PDF_DOCS = 1 +else + ifeq ($(CFG_XETEX),) + $(info cfg: no xetex found, disabling doc/rust.pdf) + NO_PDF_DOCS = 1 + else + ifeq ($(CFG_LUATEX),) + $(info cfg: lacking luatex, disabling pdflatex) + NO_PDF_DOCS = 1 + endif + endif +endif + + +ifeq ($(CFG_PANDOC),) +$(info cfg: no pandoc found, omitting PDF and EPUB docs) +ONLY_HTML_DOCS = 1 +endif + +ifeq ($(CFG_NODE),) +$(info cfg: no node found, omitting PDF and EPUB docs) +ONLY_HTML_DOCS = 1 +endif + + ###################################################################### # Rust version ###################################################################### @@ -46,7 +115,7 @@ doc/version_info.html: $(D)/version_info.html.template $(MKFILE_DEPS) \ GENERATED += doc/version.md doc/version_info.html ###################################################################### -# Docs, from pandoc, rustdoc (which runs pandoc), and node +# Docs, from rustdoc and sometimes pandoc & node ###################################################################### doc/: @@ -75,184 +144,78 @@ doc/footer.tex: $(D)/footer.tex | doc/ @$(call E, cp: $@) $(Q)cp -a $< $@ 2> /dev/null -ifeq ($(CFG_PANDOC),) - $(info cfg: no pandoc found, omitting docs) - NO_DOCS = 1 -endif +# The (english) documentation for each doc item. -ifeq ($(CFG_NODE),) - $(info cfg: no node found, omitting docs) - NO_DOCS = 1 -endif +define DEF_DOC -ifneq ($(NO_DOCS),1) +# HTML (rustdoc) +DOC_TARGETS += doc/$(1).html +doc/$(1).html: $$(D)/$(1).md $$(HTML_DEPS) $$(RUSTDOC_DEPS_$(1)) | doc/ + @$$(call E, rustdoc: $$@) + $$(RUSTDOC) $$(RUSTDOC_HTML_OPTS) $$(RUSTDOC_FLAGS_$(1)) $$< -DOCS += doc/rust.html -doc/rust.html: $(D)/rust.md doc/full-toc.inc $(HTML_DEPS) | doc/ - @$(call E, pandoc: $@) - $(Q)$(CFG_NODE) $(D)/prep.js --highlight $< | \ - $(CFG_PANDOC) $(HTML_OPTS) --include-in-header=doc/full-toc.inc --output=$@ +ifneq ($(ONLY_HTML_DOCS),1) -DOCS += doc/rust.tex -doc/rust.tex: $(D)/rust.md doc/footer.tex doc/version.md | doc/ - @$(call E, pandoc: $@) - $(Q)$(CFG_NODE) $(D)/prep.js $< | \ - $(CFG_PANDOC) $(TEX_OPTS) --output=$@ +# EPUB (pandoc directly) +DOC_TARGETS += doc/$(1).epub +doc/$(1).epub: $$(D)/$(1).md | doc/ + @$$(call E, pandoc: $$@) + $$(Q)$$(CFG_NODE) $$(D)/prep.js --highlight $$< | \ + $$(CFG_PANDOC) $$(PANDOC_EPUB_OPTS) --output=$$@ -DOCS += doc/rust.epub -doc/rust.epub: $(D)/rust.md | doc/ - @$(call E, pandoc: $@) - $(Q)$(CFG_NODE) $(D)/prep.js --highlight $< | \ - $(CFG_PANDOC) $(EPUB_OPTS) --output=$@ +# PDF (md =(pandoc)=> tex =(pdflatex)=> pdf) +DOC_TARGETS += doc/$(1).tex +doc/$(1).tex: $$(D)/$(1).md doc/footer.tex doc/version.md | doc/ + @$$(call E, pandoc: $$@) + $$(Q)$$(CFG_NODE) $$(D)/prep.js $$< | \ + $$(CFG_PANDOC) $$(PANDOC_TEX_OPTS) --output=$$@ -DOCS += doc/rustdoc.html -doc/rustdoc.html: $(D)/rustdoc.md $(HTML_DEPS) - @$(call E, pandoc: $@) - $(Q)$(CFG_NODE) $(D)/prep.js --highlight $< | \ - $(CFG_PANDOC) $(HTML_OPTS) --output=$@ +ifneq ($(NO_PDF_DOCS),1) +DOC_TARGETS += doc/$(1).pdf +doc/$(1).pdf: doc/$(1).tex + @$$(call E, pdflatex: $$@) + $$(Q)$$(CFG_PDFLATEX) \ + -interaction=batchmode \ + -output-directory=doc \ + $$< +endif # NO_PDF_DOCS -DOCS += doc/tutorial.html -doc/tutorial.html: $(D)/tutorial.md $(HTML_DEPS) - @$(call E, pandoc: $@) - $(Q)$(CFG_NODE) $(D)/prep.js --highlight $< | \ - $(CFG_PANDOC) $(HTML_OPTS) --output=$@ +endif # ONLY_HTML_DOCS -DOCS += doc/tutorial.tex -doc/tutorial.tex: $(D)/tutorial.md doc/footer.tex doc/version.md - @$(call E, pandoc: $@) - $(Q)$(CFG_NODE) $(D)/prep.js $< | \ - $(CFG_PANDOC) $(TEX_OPTS) --output=$@ +endef -DOCS += doc/tutorial.epub -doc/tutorial.epub: $(D)/tutorial.md - @$(call E, pandoc: $@) - $(Q)$(CFG_NODE) $(D)/prep.js --highlight $< | \ - $(CFG_PANDOC) $(EPUB_OPTS) --output=$@ +$(foreach docname,$(DOCS),$(eval $(call DEF_DOC,$(docname)))) -DOCS_L10N += doc/l10n/ja/tutorial.html -doc/l10n/ja/tutorial.html: doc/l10n/ja/tutorial.md doc/version_info.html doc/rust.css - @$(call E, pandoc: $@) - $(Q)$(CFG_NODE) $(D)/prep.js --highlight doc/l10n/ja/tutorial.md | \ - $(CFG_PANDOC) --standalone --toc \ - --section-divs --number-sections \ - --from=markdown --to=html5 --css=../../rust.css \ - --include-before-body=doc/version_info.html \ - --output=$@ +# Localized documentation -# Complementary documentation +# FIXME: I (huonw) haven't actually been able to test properly, since +# e.g. (by default) I'm doing an out-of-tree build (#12763), but even +# adjusting for that, the files are too old(?) and are rejected by +# po4a. # -DOCS += doc/index.html -doc/index.html: $(D)/index.md $(HTML_DEPS) - @$(call E, pandoc: $@) - $(Q)$(CFG_NODE) $(D)/prep.js --highlight $< | \ - $(CFG_PANDOC) $(HTML_OPTS) --output=$@ +# As such, I've attempted to get it working as much as possible (and +# switching from pandoc to rustdoc), but preserving the old behaviour +# (e.g. only running on the tutorial) +.PHONY: l10n-mds +l10n-mds: $(D)/po4a.conf \ + $(foreach lang,$(L10N_LANG),$(D)/po/$(lang)/*.md.po) + $(warning WARNING: localized documentation is experimental) + po4a --copyright-holder="The Rust Project Developers" \ + --package-name="Rust" \ + --package-version="$(CFG_RELEASE)" \ + -M UTF-8 -L UTF-8 \ + $(D)/po4a.conf -DOCS += doc/complement-lang-faq.html -doc/complement-lang-faq.html: $(D)/complement-lang-faq.md doc/full-toc.inc $(HTML_DEPS) - @$(call E, pandoc: $@) - $(Q)$(CFG_NODE) $(D)/prep.js --highlight $< | \ - $(CFG_PANDOC) $(HTML_OPTS) --include-in-header=doc/full-toc.inc --output=$@ +define DEF_L10N_DOC +DOC_L10N_TARGETS += doc/l10n/$(1)/$(2).html +doc/l10n/$(1)/$(2).html: l10n-mds $$(HTML_DEPS) $$(RUSTDOC_DEPS_$(2)) + @$$(call E, rustdoc: $$@) + $$(RUSTDOC) $$(RUSTDOC_HTML_OPTS) $$(RUSTDOC_FLAGS_$(1)) doc/l10n/$(1)/$(2).md +endef -DOCS += doc/complement-project-faq.html -doc/complement-project-faq.html: $(D)/complement-project-faq.md $(HTML_DEPS) - @$(call E, pandoc: $@) - $(Q)$(CFG_NODE) $(D)/prep.js --highlight $< | \ - $(CFG_PANDOC) $(HTML_OPTS) --output=$@ +$(foreach lang,$(L10N_LANGS),$(eval $(call DEF_L10N_DOC,$(lang),tutorial))) -DOCS += doc/complement-cheatsheet.html -doc/complement-cheatsheet.html: $(D)/complement-cheatsheet.md doc/full-toc.inc $(HTML_DEPS) - @$(call E, pandoc: $@) - $(Q)$(CFG_NODE) $(D)/prep.js --highlight $< | \ - $(CFG_PANDOC) $(HTML_OPTS) --include-in-header=doc/full-toc.inc --output=$@ - -DOCS += doc/complement-bugreport.html -doc/complement-bugreport.html: $(D)/complement-bugreport.md $(HTML_DEPS) - @$(call E, pandoc: $@) - $(Q)$(CFG_NODE) $(D)/prep.js --highlight $< | \ - $(CFG_PANDOC) $(HTML_OPTS) --output=$@ - -# Guides - -DOCS += doc/guide-macros.html -doc/guide-macros.html: $(D)/guide-macros.md $(HTML_DEPS) - @$(call E, pandoc: $@) - $(Q)$(CFG_NODE) $(D)/prep.js --highlight $< | \ - $(CFG_PANDOC) $(HTML_OPTS) --output=$@ - -DOCS += doc/guide-container.html -doc/guide-container.html: $(D)/guide-container.md $(HTML_DEPS) - @$(call E, pandoc: $@) - $(Q)$(CFG_NODE) $(D)/prep.js --highlight $< | \ - $(CFG_PANDOC) $(HTML_OPTS) --output=$@ - -DOCS += doc/guide-ffi.html -doc/guide-ffi.html: $(D)/guide-ffi.md $(HTML_DEPS) - @$(call E, pandoc: $@) - $(Q)$(CFG_NODE) $(D)/prep.js --highlight $< | \ - $(CFG_PANDOC) $(HTML_OPTS) --output=$@ - -DOCS += doc/guide-testing.html -doc/guide-testing.html: $(D)/guide-testing.md $(HTML_DEPS) - @$(call E, pandoc: $@) - $(Q)$(CFG_NODE) $(D)/prep.js --highlight $< | \ - $(CFG_PANDOC) $(HTML_OPTS) --output=$@ - -DOCS += doc/guide-lifetimes.html -doc/guide-lifetimes.html: $(D)/guide-lifetimes.md $(HTML_DEPS) - @$(call E, pandoc: $@) - $(Q)$(CFG_NODE) $(D)/prep.js --highlight $< | \ - $(CFG_PANDOC) $(HTML_OPTS) --output=$@ - -DOCS += doc/guide-tasks.html -doc/guide-tasks.html: $(D)/guide-tasks.md $(HTML_DEPS) - @$(call E, pandoc: $@) - $(Q)$(CFG_NODE) $(D)/prep.js --highlight $< | \ - $(CFG_PANDOC) $(HTML_OPTS) --output=$@ - -DOCS += doc/guide-pointers.html -doc/guide-pointers.html: $(D)/guide-pointers.md $(HTML_DEPS) - @$(call E, pandoc: $@) - $(Q)$(CFG_NODE) $(D)/prep.js --highlight $< | \ - $(CFG_PANDOC) $(HTML_OPTS) --output=$@ - -DOCS += doc/guide-runtime.html -doc/guide-runtime.html: $(D)/guide-runtime.md $(HTML_DEPS) - @$(call E, pandoc: $@) - $(Q)$(CFG_NODE) $(D)/prep.js --highlight $< | \ - $(CFG_PANDOC) $(HTML_OPTS) --output=$@ - - ifeq ($(CFG_PDFLATEX),) - $(info cfg: no pdflatex found, omitting doc/rust.pdf) - else - ifeq ($(CFG_XETEX),) - $(info cfg: no xetex found, disabling doc/rust.pdf) - else - ifeq ($(CFG_LUATEX),) - $(info cfg: lacking luatex, disabling pdflatex) - else - -DOCS += doc/rust.pdf -doc/rust.pdf: doc/rust.tex - @$(call E, pdflatex: $@) - $(Q)$(CFG_PDFLATEX) \ - -interaction=batchmode \ - -output-directory=doc \ - $< - -DOCS += doc/tutorial.pdf -doc/tutorial.pdf: doc/tutorial.tex - @$(call E, pdflatex: $@) - $(Q)$(CFG_PDFLATEX) \ - -interaction=batchmode \ - -output-directory=doc \ - $< - - endif - endif - endif - -endif # No pandoc / node ###################################################################### # LLnextgen (grammar analysis from refman) @@ -278,50 +241,44 @@ endif # Rustdoc (libstd/extra) ###################################################################### -# The rustdoc executable, rpath included in case --disable-rpath was provided to -# ./configure -RUSTDOC = $(HBIN2_H_$(CFG_BUILD))/rustdoc$(X_$(CFG_BUILD)) # The library documenting macro # # $(1) - The crate name (std/extra) # # Passes --cfg stage2 to rustdoc because it uses the stage2 librustc. -define libdoc -doc/$(1)/index.html: \ - $$(CRATEFILE_$(1)) \ - $$(RSINPUTS_$(1)) \ - $$(RUSTDOC) \ - $$(foreach dep,$$(RUST_DEPS_$(1)), \ - $$(TLIB2_T_$(CFG_BUILD)_H_$(CFG_BUILD))/stamp.$$(dep)) - @$$(call E, rustdoc: $$@) - $$(Q)$$(RPATH_VAR2_T_$(CFG_BUILD)_H_$(CFG_BUILD)) $$(RUSTDOC) \ - --cfg stage2 $$< +define DEF_LIB_DOC +# If NO_REBUILD is set then break the dependencies on rustdoc so we +# build crate documentation without having to rebuild rustdoc. +ifeq ($(NO_REBUILD),) +LIB_DOC_DEP_$(1) = \ + $$(CRATEFILE_$(1)) \ + $$(RSINPUTS_$(1)) \ + $$(RUSTDOC_EXE) \ + $$(foreach dep,$$(RUST_DEPS_$(1)), \ + $$(TLIB2_T_$(CFG_BUILD)_H_$(CFG_BUILD))/stamp.$$(dep)) +else +LIB_DOC_DEP_$(1) = $$(CRATEFILE_$(1)) $$(RSINPUTS_$(1)) +endif + +$(2) += doc/$(1)/index.html +doc/$(1)/index.html: $$(LIB_DOC_DEP_$(1)) + @$$(call E, rustdoc $$@) + $$(Q)$$(RUSTDOC) --cfg stage2 $$< endef -$(foreach crate,$(CRATES),$(eval $(call libdoc,$(crate)))) - -DOCS += $(DOC_CRATES:%=doc/%/index.html) - -CDOCS += doc/rustc/index.html -CDOCS += doc/syntax/index.html +$(foreach crate,$(DOC_CRATES),$(eval $(call DEF_LIB_DOC,$(crate),DOC_TARGETS))) +$(foreach crate,$(COMPILER_DOC_CRATES),$(eval $(call DEF_LIB_DOC,$(crate),COMPILER_DOC_TARGETS))) ifdef CFG_DISABLE_DOCS $(info cfg: disabling doc build (CFG_DISABLE_DOCS)) - DOCS := + DOC_TARGETS := endif -docs: $(DOCS) -compiler-docs: $(CDOCS) +docs: $(DOC_TARGETS) +compiler-docs: $(COMPILER_DOC_TARGETS) -docs-l10n: $(DOCS_L10N) - -doc/l10n/%.md: doc/po/%.md.po doc/po4a.conf - po4a --copyright-holder="The Rust Project Developers" \ - --package-name="Rust" \ - --package-version="$(CFG_RELEASE)" \ - -M UTF-8 -L UTF-8 \ - doc/po4a.conf +docs-l10n: $(DOC_L10N_TARGETS) .PHONY: docs-l10n diff --git a/mk/tests.mk b/mk/tests.mk index c55162d398c..8f48918d31a 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -19,12 +19,6 @@ TEST_DOC_CRATES = $(DOC_CRATES) TEST_HOST_CRATES = $(HOST_CRATES) TEST_CRATES = $(TEST_TARGET_CRATES) $(TEST_HOST_CRATES) -# Markdown files under doc/ that should have their code extracted and run -DOC_TEST_NAMES = tutorial guide-ffi guide-macros guide-lifetimes \ - guide-tasks guide-container guide-pointers \ - complement-cheatsheet guide-runtime \ - rust - ###################################################################### # Environment configuration ###################################################################### @@ -318,7 +312,7 @@ check-stage$(1)-T-$(2)-H-$(3)-doc-crates-exec: \ check-stage$(1)-T-$(2)-H-$(3)-doc-$$(crate)-exec) check-stage$(1)-T-$(2)-H-$(3)-doc-exec: \ - $$(foreach docname,$$(DOC_TEST_NAMES), \ + $$(foreach docname,$$(DOCS), \ check-stage$(1)-T-$(2)-H-$(3)-doc-$$(docname)-exec) check-stage$(1)-T-$(2)-H-$(3)-pretty-exec: \ @@ -662,32 +656,56 @@ $(foreach host,$(CFG_HOST), \ $(foreach pretty-name,$(PRETTY_NAMES), \ $(eval $(call DEF_RUN_PRETTY_TEST,$(stage),$(target),$(host),$(pretty-name))))))) -define DEF_RUN_DOC_TEST -DOC_TEST_ARGS$(1)-T-$(2)-H-$(3)-doc-$(4) := \ - $$(CTEST_COMMON_ARGS$(1)-T-$(2)-H-$(3)) \ - --src-base $(3)/test/doc-$(4)/ \ - --build-base $(3)/test/doc-$(4)/ \ - --mode run-pass - -check-stage$(1)-T-$(2)-H-$(3)-doc-$(4)-exec: $$(call TEST_OK_FILE,$(1),$(2),$(3),doc-$(4)) - -$$(call TEST_OK_FILE,$(1),$(2),$(3),doc-$(4)): \ - $$(TEST_SREQ$(1)_T_$(2)_H_$(3)) \ - doc-$(4)-extract$(3) - @$$(call E, run doc-$(4) [$(2)]: $$<) - $$(Q)$$(call CFG_RUN_CTEST_$(2),$(1),$$<,$(3)) \ - $$(DOC_TEST_ARGS$(1)-T-$(2)-H-$(3)-doc-$(4)) \ - --logfile $$(call TEST_LOG_FILE,$(1),$(2),$(3),doc-$(4)) \ - && touch $$@ +###################################################################### +# Crate & freestanding documentation tests +###################################################################### +define DEF_RUSTDOC +RUSTDOC_EXE_$(1)_T_$(2)_H_$(3) := $$(HBIN$(1)_H_$(3))/rustdoc$$(X_$(3)) +RUSTDOC_$(1)_T_$(2)_H_$(3) := $$(RPATH_VAR$(1)_T_$(2)_H_$(3)) $$(RUSTDOC_EXE_$(1)_T_$(2)_H_$(3)) endef $(foreach host,$(CFG_HOST), \ $(foreach target,$(CFG_TARGET), \ $(foreach stage,$(STAGES), \ - $(foreach docname,$(DOC_TEST_NAMES), \ - $(eval $(call DEF_RUN_DOC_TEST,$(stage),$(target),$(host),$(docname))))))) + $(eval $(call DEF_RUSTDOC,$(stage),$(target),$(host)))))) + +# Freestanding + +define DEF_DOC_TEST + +check-stage$(1)-T-$(2)-H-$(3)-doc-$(4)-exec: $$(call TEST_OK_FILE,$(1),$(2),$(3),doc-$(4)) + +# If NO_REBUILD is set then break the dependencies on everything but +# the source files so we can test documentation without rebuilding +# rustdoc etc. +ifeq ($(NO_REBUILD),) +DOCTESTDEP_$(1)_$(2)_$(3)_$(4) = \ + $$(D)/$(4).md \ + $$(TEST_SREQ$(1)_T_$(2)_H_$(3)) \ + $$(RUSTDOC_EXE_$(1)_T_$(2)_H_$(3)) +else +DOCTESTDEP_$(1)_$(2)_$(3)_$(4) = $$(D)/$(4).md +endif + +ifeq ($(2),$$(CFG_BUILD)) +$$(call TEST_OK_FILE,$(1),$(2),$(3),doc-$(4)): $$(DOCTESTDEP_$(1)_$(2)_$(3)_$(4)) + @$$(call E, run doc-$(4) [$(2)]) + $$(Q)$$(RUSTDOC_$(1)_T_$(2)_H_$(3)) --test $$< --test-args "$$(TESTARGS)" && touch $$@ +else +$$(call TEST_OK_FILE,$(1),$(2),$(3),doc-$(4)): + touch $$@ +endif +endef + +$(foreach host,$(CFG_HOST), \ + $(foreach target,$(CFG_TARGET), \ + $(foreach stage,$(STAGES), \ + $(foreach docname,$(DOCS), \ + $(eval $(call DEF_DOC_TEST,$(stage),$(target),$(host),$(docname))))))) + +# Crates define DEF_CRATE_DOC_TEST @@ -695,21 +713,20 @@ define DEF_CRATE_DOC_TEST # the source files so we can test crate documentation without # rebuilding any of the parent crates. ifeq ($(NO_REBUILD),) -DOCTESTDEP_$(1)_$(2)_$(3)_$(4) = \ +CRATEDOCTESTDEP_$(1)_$(2)_$(3)_$(4) = \ $$(TEST_SREQ$(1)_T_$(2)_H_$(3)) \ $$(CRATE_FULLDEPS_$(1)_T_$(2)_H_$(3)_$(4)) \ - $$(HBIN$(1)_H_$(3))/rustdoc$$(X_$(3)) + $$(RUSTDOC_EXE_$(1)_T_$(2)_H_$(3)) else -DOCTESTDEP_$(1)_$(2)_$(3)_$(4) = $$(RSINPUTS_$(4)) +CRATEDOCTESTDEP_$(1)_$(2)_$(3)_$(4) = $$(RSINPUTS_$(4)) endif check-stage$(1)-T-$(2)-H-$(3)-doc-$(4)-exec: $$(call TEST_OK_FILE,$(1),$(2),$(3),doc-$(4)) ifeq ($(2),$$(CFG_BUILD)) -$$(call TEST_OK_FILE,$(1),$(2),$(3),doc-$(4)): $$(DOCTESTDEP_$(1)_$(2)_$(3)_$(4)) +$$(call TEST_OK_FILE,$(1),$(2),$(3),doc-$(4)): $$(CRATEDOCTESTDEP_$(1)_$(2)_$(3)_$(4)) @$$(call E, run doc-$(4) [$(2)]) - $$(Q)$$(RPATH_VAR$(1)_T_$(2)_H_$(3)) \ - $$(HBIN$(1)_H_$(3))/rustdoc$$(X_$(3)) --test \ + $$(Q)$$(RUSTDOC_$(1)_T_$(2)_H_$(3)) --test \ $$(CRATEFILE_$(4)) --test-args "$$(TESTARGS)" && touch $$@ else $$(call TEST_OK_FILE,$(1),$(2),$(3),doc-$(4)): @@ -724,26 +741,6 @@ $(foreach host,$(CFG_HOST), \ $(foreach crate,$(TEST_DOC_CRATES), \ $(eval $(call DEF_CRATE_DOC_TEST,$(stage),$(target),$(host),$(crate))))))) -###################################################################### -# Extracting tests for docs -###################################################################### - -EXTRACT_TESTS := "$(CFG_PYTHON)" $(S)src/etc/extract-tests.py - -define DEF_DOC_TEST_HOST - -doc-$(2)-extract$(1): - @$$(call E, extract: $(2) tests) - $$(Q)rm -f $(1)/test/doc-$(2)/*.rs - $$(Q)$$(EXTRACT_TESTS) $$(D)/$(2).md $(1)/test/doc-$(2) - -endef - -$(foreach host,$(CFG_HOST), \ - $(foreach docname,$(DOC_TEST_NAMES), \ - $(eval $(call DEF_DOC_TEST_HOST,$(host),$(docname))))) - - ###################################################################### # Shortcut rules ###################################################################### @@ -762,7 +759,7 @@ TEST_GROUPS = \ debuginfo \ codegen \ doc \ - $(foreach docname,$(DOC_TEST_NAMES),doc-$(docname)) \ + $(foreach docname,$(DOCS),doc-$(docname)) \ pretty \ pretty-rpass \ pretty-rpass-full \ @@ -830,9 +827,9 @@ $(foreach stage,$(STAGES), \ $(eval $(call DEF_CHECK_FOR_STAGE_AND_HOSTS_AND_GROUP,$(stage),$(host),$(group)))))) define DEF_CHECK_DOC_FOR_STAGE -check-stage$(1)-docs: $$(foreach docname,$$(DOC_TEST_NAMES),\ +check-stage$(1)-docs: $$(foreach docname,$$(DOCS),\ check-stage$(1)-T-$$(CFG_BUILD)-H-$$(CFG_BUILD)-doc-$$(docname)) \ - $$(foreach crate,$$(DOC_CRATE_NAMES),\ + $$(foreach crate,$$(TEST_DOC_CRATES),\ check-stage$(1)-T-$$(CFG_BUILD)-H-$$(CFG_BUILD)-doc-$$(crate)) endef diff --git a/src/doc/rust.css b/src/doc/rust.css index 17100274688..26681adad6d 100644 --- a/src/doc/rust.css +++ b/src/doc/rust.css @@ -142,25 +142,18 @@ pre code { } /* Code highlighting */ -.cm-s-default span.cm-keyword {color: #8959A8;} -.cm-s-default span.cm-atom {color: #219;} -.cm-s-default span.cm-number {color: #3E999F;} -.cm-s-default span.cm-def {color: #4271AE;} -/*.cm-s-default span.cm-variable {color: #C82829;}*/ -.cm-s-default span.cm-variable-2 {color: #6F906C;} -.cm-s-default span.cm-variable-3 {color: #B76514;} -.cm-s-default span.cm-property {color: black;} -.cm-s-default span.cm-operator {color: black;} -.cm-s-default span.cm-comment {color: #8E908C;} -.cm-s-default span.cm-string {color: #718C00;} -.cm-s-default span.cm-string-2 {color: #866544;} -.cm-s-default span.cm-meta {color: #555;} -/*.cm-s-default span.cm-error {color: #F00;}*/ -.cm-s-default span.cm-qualifier {color: #555;} -.cm-s-default span.cm-builtin {color: #30A;} -.cm-s-default span.cm-bracket {color: #CC7;} -.cm-s-default span.cm-tag {color: #C82829;} -.cm-s-default span.cm-attribute {color: #00C;} +pre.rust .kw { color: #8959A8; } +pre.rust .kw-2, pre.rust .prelude-ty { color: #4271AE; } +pre.rust .number { color: #718C00; } +pre.rust .self { color: #C13928; } +pre.rust .boolval { color: #C13928; } +pre.rust .prelude-val { color: #C13928; } +pre.rust .comment { color: #8E908C; } +pre.rust .doccomment { color: #4D4D4C; } +pre.rust .macro, pre.rust .macro-nonterminal { color: #3E999f; } +pre.rust .string { color: #718C00; } +pre.rust .lifetime { color: #C13928; } +pre.rust .attribute, pre.rust .attribute .ident { color: #C82829; } /* The rest ========================================================================== */ diff --git a/src/etc/extract-tests.py b/src/etc/extract-tests.py deleted file mode 100644 index 2900023ea2b..00000000000 --- a/src/etc/extract-tests.py +++ /dev/null @@ -1,217 +0,0 @@ -# Copyright 2012-2014 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. - -""" -Script for extracting compilable fragments from markdown documentation. See -prep.js for a description of the format recognized by this tool. Expects -a directory fragments/ to exist under the current directory, and writes the -fragments in there as individual .rs files. -""" -from __future__ import print_function -from codecs import open -from collections import deque -from itertools import imap -import os -import re -import sys - -# regexes -CHAPTER_NAME_REGEX = re.compile(r'# (.*)') -CODE_BLOCK_DELIM_REGEX = re.compile(r'~~~') -COMMENT_REGEX = re.compile(r'^# ') -COMPILER_DIRECTIVE_REGEX = re.compile(r'\#\[(.*)\];') -ELLIPSES_REGEX = re.compile(r'\.\.\.') -EXTERN_CRATE_REGEX = re.compile(r'\bextern crate extra\b') -MAIN_FUNCTION_REGEX = re.compile(r'\bfn main\b') -TAGS_REGEX = re.compile(r'\.([\w-]*)') - -# tags to ignore -IGNORE_TAGS = \ - frozenset(["abnf", "ebnf", "field", "keyword", "notrust", "precedence"]) - -# header for code snippet files -OUTPUT_BLOCK_HEADER = '\n'.join(( - "#[ deny(warnings) ];", - "#[ allow(unused_variable) ];", - "#[ allow(dead_assignment) ];", - "#[ allow(unused_mut) ];", - "#[ allow(attribute_usage) ];", - "#[ allow(dead_code) ];", - "#[ feature(macro_rules, globs, struct_variant, managed_boxes) ];\n",)) - - -def add_extern_mod(block): - if not has_extern_mod(block): - # add `extern crate extra;` after compiler directives - directives = [] - while len(block) and is_compiler_directive(block[0]): - directives.append(block.popleft()) - - block.appendleft("\nextern crate extra;\n\n") - block.extendleft(reversed(directives)) - - return block - - -def add_main_function(block): - if not has_main_function(block): - prepend_spaces = lambda x: ' ' + x - block = deque(imap(prepend_spaces, block)) - block.appendleft("\nfn main() {\n") - block.append("\n}\n") - return block - - -def extract_code_fragments(dest_dir, lines): - """ - Extracts all the code fragments from a file that do not have ignored tags - writing them to the following file: - - [dest dir]/[chapter name]_[chapter_index].rs - """ - chapter_name = None - chapter_index = 0 - - for line in lines: - if is_chapter_title(line): - chapter_name = get_chapter_name(line) - chapter_index = 1 - continue - - if not is_code_block_delim(line): - continue - - assert chapter_name, "Chapter name missing for code block." - tags = get_tags(line) - block = get_code_block(lines) - - if tags & IGNORE_TAGS: - continue - - block = add_extern_mod(add_main_function(block)) - block.appendleft(OUTPUT_BLOCK_HEADER) - - if "ignore" in tags: - block.appendleft("//ignore-test\n") - elif "should_fail" in tags: - block.appendleft("//should-fail\n") - - output_filename = os.path.join( - dest_dir, - chapter_name + '_' + str(chapter_index) + '.rs') - - write_file(output_filename, block) - chapter_index += 1 - - -def has_extern_mod(block): - """Checks if a code block has the line `extern crate extra`.""" - find_extern_mod = lambda x: re.search(EXTERN_CRATE_REGEX, x) - return any(imap(find_extern_mod, block)) - - -def has_main_function(block): - """Checks if a code block has a main function.""" - find_main_fn = lambda x: re.search(MAIN_FUNCTION_REGEX, x) - return any(imap(find_main_fn, block)) - - -def is_chapter_title(line): - return re.match(CHAPTER_NAME_REGEX, line) - - -def is_code_block_delim(line): - return re.match(CODE_BLOCK_DELIM_REGEX, line) - - -def is_compiler_directive(line): - return re.match(COMPILER_DIRECTIVE_REGEX, line) - - -def get_chapter_name(line): - """Get the chapter name from a `# Containers` line.""" - return re.sub( - r'\W', - '_', - re.match(CHAPTER_NAME_REGEX, line).group(1)).lower() - - -def get_code_block(lines): - """ - Get a code block surrounded by ~~~, for example: - - 1: ~~~ { .tag } - 2: let u: ~[u32] = ~[0, 1, 2]; - 3: let v: &[u32] = &[0, 1, 2, 3]; - 4: let w: [u32, .. 5] = [0, 1, 2, 3, 4]; - 5: - 6: println!("u: {}, v: {}, w: {}", u.len(), v.len(), w.len()); - 7: ~~~ - - Returns lines 2-6. Assumes line 1 has been consumed by the caller. - """ - strip_comments = lambda x: re.sub(COMMENT_REGEX, '', x) - strip_ellipses = lambda x: re.sub(ELLIPSES_REGEX, '', x) - - result = deque() - - for line in lines: - if is_code_block_delim(line): - break - result.append(strip_comments(strip_ellipses(line))) - return result - - -def get_lines(filename): - with open(filename) as f: - for line in f: - yield line - - -def get_tags(line): - """ - Retrieves all tags from the line format: - ~~~ { .tag1 .tag2 .tag3 } - """ - return set(re.findall(TAGS_REGEX, line)) - - -def write_file(filename, lines): - with open(filename, 'w', encoding='utf-8') as f: - for line in lines: - f.write(unicode(line, encoding='utf-8', errors='replace')) - - -def main(argv=None): - if not argv: - argv = sys.argv - - if len(sys.argv) < 2: - sys.stderr.write("Please provide an input filename.") - sys.exit(1) - elif len(sys.argv) < 3: - sys.stderr.write("Please provide a destination directory.") - sys.exit(1) - - input_file = sys.argv[1] - dest_dir = sys.argv[2] - - if not os.path.exists(input_file): - sys.stderr.write("Input file does not exist.") - sys.exit(1) - - if not os.path.exists(dest_dir): - os.mkdir(dest_dir) - - extract_code_fragments(dest_dir, get_lines(input_file)) - - -if __name__ == "__main__": - sys.exit(main())