@$(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
################################################################################
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.
# 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
+
+RUSTDOC_DEPS_rust := doc/full-toc.inc
+RUSTDOC_FLAGS_rust := --markdown-in-header=doc/full-toc.inc
+
+L10N_LANGS := ja
+
+# Generally no need to edit below here.
-DOCS :=
-CDOCS :=
-DOCS_L10N :=
-HTML_DEPS := doc/
+# 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
-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
+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
######################################################################
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/:
@$(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
+
+# 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)) $$<
+
+ifneq ($(ONLY_HTML_DOCS),1)
+
+# 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=$$@
+
+# 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=$$@
+
+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
+
+endif # ONLY_HTML_DOCS
+
+endef
+
+$(foreach docname,$(DOCS),$(eval $(call DEF_DOC,$(docname))))
-ifneq ($(NO_DOCS),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=$@
-
-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=$@
-
-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=$@
-
-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=$@
-
-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=$@
-
-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=$@
-
-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=$@
-
-
-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=$@
-
-# Complementary documentation
+
+# Localized 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=$@
-
-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=$@
-
-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=$@
-
-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
+# 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
+
+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
+
+$(foreach lang,$(L10N_LANGS),$(eval $(call DEF_L10N_DOC,$(lang),tutorial)))
-endif # No pandoc / node
######################################################################
# LLnextgen (grammar analysis from refman)
# 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)), \
+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))
- @$$(call E, rustdoc: $$@)
- $$(Q)$$(RPATH_VAR2_T_$(CFG_BUILD)_H_$(CFG_BUILD)) $$(RUSTDOC) \
- --cfg stage2 $$<
+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-l10n: $(DOCS_L10N)
+docs: $(DOC_TARGETS)
+compiler-docs: $(COMPILER_DOC_TARGETS)
-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
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
######################################################################
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: \
$(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
+######################################################################
+# 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), \
+ $(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))
-$$(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 $$@
+# 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,$(DOC_TEST_NAMES), \
- $(eval $(call DEF_RUN_DOC_TEST,$(stage),$(target),$(host),$(docname)))))))
+ $(foreach docname,$(DOCS), \
+ $(eval $(call DEF_DOC_TEST,$(stage),$(target),$(host),$(docname)))))))
+
+# Crates
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)):
$(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
######################################################################
debuginfo \
codegen \
doc \
- $(foreach docname,$(DOC_TEST_NAMES),doc-$(docname)) \
+ $(foreach docname,$(DOCS),doc-$(docname)) \
pretty \
pretty-rpass \
pretty-rpass-full \
$(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
}
/* 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
========================================================================== */
+++ /dev/null
-# 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 <LICENSE-APACHE or
-# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-# <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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())