Просмотр исходного кода

Add support for Sphinx documentation builder

Stanislaw Klekot 7 лет назад
Родитель
Сommit
ad88794506
5 измененных файлов с 379 добавлено и 0 удалено
  1. 1 0
      build.config
  2. 2 0
      doc/src/guide/book.asciidoc
  3. 134 0
      doc/src/guide/sphinx.asciidoc
  4. 62 0
      plugins/sphinx.mk
  5. 180 0
      test/plugin_sphinx.mk

+ 1 - 0
build.config

@@ -34,6 +34,7 @@ plugins/eunit
 plugins/proper
 plugins/relx
 plugins/shell
+plugins/sphinx
 plugins/syntastic
 plugins/triq
 plugins/xref

+ 2 - 0
doc/src/guide/book.asciidoc

@@ -41,6 +41,8 @@ include::asciidoc.asciidoc[Asciidoc documentation]
 
 include::edoc.asciidoc[EDoc comments]
 
+include::sphinx.asciidoc[Sphinx documentation]
+
 [[tests]]
 = Tests
 

+ 134 - 0
doc/src/guide/sphinx.asciidoc

@@ -0,0 +1,134 @@
+[[sphinx]]
+== Sphinx documentation
+
+Erlang.mk includes targets for running
+http://www.sphinx-doc.org/[Sphinx documentation generator], which can produce
+documentation in various formats, like HTML, man pages, Texinfo, LaTeX, and
+others.
+
+=== Writing Sphinx documentation
+
+Sphinx generates documentation form a set of
+http://www.sphinx-doc.org/en/stable/rest.html[reST] documents. There is
+a http://www.sphinx-doc.org/en/stable/tutorial.html[quick start guide] on
+Sphinx' website. For Erlang.mk, we'll set up a minimal environment instead.
+
+=== Basic setup
+
+By default, Erlang.mk expects Sphinx documentation to be placed in 'doc'
+directory, with 'doc/conf.py' config file in particular. The file contains
+information about the project, among the other things.
+
+A minimal 'doc/conf.py' will look similar to this:
+
+[source,python]
+----
+project = 'My Project'
+version = '0.0'
+release = '0.0.1'
+master_doc = 'index'
+source_suffix = '.rst'
+----
+
+It points to a 'doc/index.rst' document. A simple skeleton includes a table of
+contents for all documentation, and links to generated index of terms and
+a search page:
+
+[literal]
+----
+My Project
+==========
+
+Contents:
+
+.. toctree::
+   :maxdepth: 2
+
+   other_page
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`search`
+----
+
+The skeleton above has a link to one other page, 'doc/other_page.rst'. Simple
+header with some text will do for now:
+
+[literal]
+----
+Other Page
+==========
+
+Lorem ipsum dolor sit amet...
+----
+
+The files above are enough to build HTML documentation to 'html' directory.
+
+[source,bash]
+$ make docs     # all the docs, including EDoc and AsciiDoc if applicable
+$ make sphinx   # Sphinx docs specifically
+
+=== Erlang.mk configuration
+
+Default Erlang.mk settings are equivalent to adding to project's makefile
+following lines:
+
+[source,make]
+SPHINX_FORMATS = html
+SPHINX_SOURCE = doc
+
+To change the location of Sphinx sources, you need to set `$(SPHINX_SOURCE)`
+variable. 'conf.py' file should also be placed in that directory, unless you
+specify `$(SPHINX_CONFDIR)`.
+
+Variable `$(SPHINX_OPTS)` allows to provide options to `sphinx-build`, which
+is particularly useful for `-D name=value` options. You can even forego
+'doc/conf.py' file, using `-D name=value` in combination with `-C` option,
+though you will need to manually call `make sphinx` or add `sphinx` target to
+dependencies of `docs`.
+
+`$(SPHINX_FORMATS)` variable lists formats to generate. By default only HTML
+is generated, but it can also include man pages or LaTeX document for building
+PDF. See
+http://www.sphinx-doc.org/en/stable/invocation.html#cmdoption-sphinx-build-b[description of `-b` option]
+for `sphinx-build` for list of known formats.
+
+Formats are by default generated to a directory called after the format
+('html' for HTML, 'man' for man pages, and so on). To change this behaviour
+for specific format, you can set `$(sphinx_$(format)_output)` variable, e.g.
+`$(sphinx_html_output)` for 'html' or `$(sphinx_man_output)` for 'man'.
+There are also `$(sphinx_$(format)_opts)` variables for setting `sphinx-build`
+options for a single format only.
+
+=== Generating man pages
+
+To generate man pages, you need to include `man` in `$(SPHINX_FORMATS)` in
+your makefile and define `man_pages` option in 'doc/conf.py':
+
+[source,python]
+----
+man_pages = [
+    ('doc_name', 'page_name', 'Manpage Title', ['Page Author'], 1),
+]
+----
+
+As http://www.sphinx-doc.org/en/stable/config.html#options-for-manual-page-output[Sphinx documentation]
+says, the structure is following:
+
+* 'doc_name' is the path to man page's source (relative `$(SPHINX_SOURCE)`),
+  without the '.rst' suffix
+* 'page_name' is the name of resulting man page, which will be used as a base
+  for output file name and will be included in generated man page
+* 'Manpage Title' is a short, one-line description, which will be included in
+  generated man page on a position that's used by `apropos` command
+* 'Page Author' (or more of them) will be included in autogenerated 'AUTHOR'
+  section, and leaving this field empty disables generating 'AUTHOR' section
+* '1' is the number of section of the man page
+
+With the above configuration (and Erlang.mk defaults), 'doc/doc_name.rst' will
+be used to generate 'man/page_name.1'.
+
+NOTE: You probably want to include a link to the man page in other
+documentation, possibly in 'doc/index.rst'.

+ 62 - 0
plugins/sphinx.mk

@@ -0,0 +1,62 @@
+# Copyright 2017, Stanislaw Klekot <dozzie@jarowit.net>
+# This file is part of erlang.mk and subject to the terms of the ISC License.
+
+.PHONY: distclean-sphinx sphinx
+
+# Configuration.
+
+SPHINX_BUILD ?= sphinx-build
+SPHINX_SOURCE ?= doc
+SPHINX_CONFDIR ?=
+SPHINX_FORMATS ?= html
+SPHINX_DOCTREES ?= $(ERLANG_MK_TMP)/sphinx.doctrees
+SPHINX_OPTS ?=
+
+#sphinx_html_opts =
+#sphinx_html_output = html
+#sphinx_man_opts =
+#sphinx_man_output = man
+#sphinx_latex_opts =
+#sphinx_latex_output = latex
+
+# Helpers.
+
+sphinx_build_0 = @echo " SPHINX" $1; $(SPHINX_BUILD) -N -q
+sphinx_build_1 = $(SPHINX_BUILD) -N
+sphinx_build_2 = set -x; $(SPHINX_BUILD)
+sphinx_build = $(sphinx_build_$(V))
+
+define sphinx.build
+$(call sphinx_build,$1) -b $1 -d $(SPHINX_DOCTREES) $(if $(SPHINX_CONFDIR),-c $(SPHINX_CONFDIR)) $(SPHINX_OPTS) $(sphinx_$1_opts) -- $(SPHINX_SOURCE) $(call sphinx.output,$1)
+
+endef
+
+define sphinx.output
+$(if $(sphinx_$1_output),$(sphinx_$1_output),$1)
+endef
+
+# Targets.
+
+ifneq ($(wildcard $(if $(SPHINX_CONFDIR),$(SPHINX_CONFDIR),$(SPHINX_SOURCE))/conf.py),)
+docs:: sphinx
+distclean:: distclean-sphinx
+endif
+
+help::
+	$(verbose) printf "%s\n" "" \
+		"Sphinx targets:" \
+		"  sphinx      Generate Sphinx documentation." \
+		"" \
+		"ReST sources and 'conf.py' file are expected in directory pointed by" \
+		"SPHINX_SOURCE ('doc' by default). SPHINX_FORMATS lists formats to build (only" \
+		"'html' format is generated by default); target directory can be specified by" \
+		'setting sphinx_$${format}_output, for example: sphinx_html_output = output/html' \
+		"Additional Sphinx options can be set in SPHINX_OPTS."
+
+# Plugin-specific targets.
+
+sphinx:
+	$(foreach F,$(SPHINX_FORMATS),$(call sphinx.build,$F))
+
+distclean-sphinx:
+	$(gen_verbose) rm -rf $(filter-out $(SPHINX_SOURCE),$(foreach F,$(SPHINX_FORMATS),$(call sphinx.output,$F)))

+ 180 - 0
test/plugin_sphinx.mk

@@ -0,0 +1,180 @@
+# Sphinx plugin.
+
+SPHINX_CASES = build source-dir formats format-opts
+SPHINX_TARGETS = $(addprefix sphinx-,$(SPHINX_CASES))
+
+.PHONY: sphinx $(SPHINX_TARGETS)
+
+sphinx: $(SPHINX_TARGETS)
+
+sphinx-build: build clean
+
+	$i "Bootstrap a new OTP application named $(APP)"
+	$t mkdir $(APP)/
+	$t cp ../erlang.mk $(APP)/
+	$t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+	$i "Generate Sphinx config"
+	$(call sphinx-generate-doc-skeleton)
+
+	$i "Run Sphinx"
+	$t $(MAKE) -C $(APP) sphinx $v
+
+	$i "Check that documentation was generated"
+	$t test -f $(APP)/html/index.html
+	$t test -f $(APP)/html/manpage.html
+
+	$i "Distclean the application"
+	$t $(MAKE) -C $(APP) distclean $v
+
+	$i "Check that the generated documentation was removed"
+	$t test ! -e $(APP)/html/index.html
+	$t test ! -e $(APP)/html/manpage.html
+
+	$i "Set 'today' macro with command-line options"
+	$t echo "SPHINX_OPTS = -D 'today=erlang_mk_sphinx_today'" >> $(APP)/Makefile
+
+	$i "Run Sphinx"
+	$t $(MAKE) -C $(APP) sphinx $v
+
+	$i "Check that the 'today' macro was defined"
+	$t grep -q erlang_mk_sphinx_today $(APP)/html/manpage.html
+
+sphinx-source-dir: build clean
+
+	$i "Bootstrap a new OTP application named $(APP)"
+	$t mkdir $(APP)/
+	$t cp ../erlang.mk $(APP)/
+	$t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+	$i "Change documentation source directory"
+	$t echo "SPHINX_SOURCE = documentation" >> $(APP)/Makefile
+
+	$i "Generate Sphinx config"
+	$(call sphinx-generate-doc-skeleton,documentation)
+
+	$i "Run Sphinx (html)"
+	$t $(MAKE) -C $(APP) sphinx $v
+
+	$i "Check that documentation was generated"
+	$t test -f $(APP)/html/index.html
+	$t test -f $(APP)/html/manpage.html
+
+sphinx-formats: build clean
+
+	$i "Bootstrap a new OTP application named $(APP)"
+	$t mkdir $(APP)/
+	$t cp ../erlang.mk $(APP)/
+	$t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+	$i "Define formats generated by Sphinx"
+	$t echo "SPHINX_FORMATS = html man" >> $(APP)/Makefile
+
+	$i "Generate Sphinx config"
+	$(call sphinx-generate-doc-skeleton)
+
+	$i "Run Sphinx (html + man)"
+	$t $(MAKE) -C $(APP) sphinx $v
+
+	$i "Check that documentation was generated"
+	$t test -f $(APP)/man/sphinx_$(APP).1
+	$t test -f $(APP)/html/index.html
+	$t test -f $(APP)/html/manpage.html
+
+	$i "Distclean the application"
+	$t $(MAKE) -C $(APP) distclean $v
+
+	$i "Check that the generated documentation was removed"
+	$t test ! -e $(APP)/man/sphinx_$(APP).1
+	$t test ! -e $(APP)/html/index.html
+	$t test ! -e $(APP)/html/manpage.html
+
+	$i "Change documentation output directories"
+	$t echo "sphinx_html_output = sphinx/html_output" >> $(APP)/Makefile
+	$t echo "sphinx_man_output  = sphinx/man_output"  >> $(APP)/Makefile
+
+	$i "Run Sphinx (html + man)"
+	$t $(MAKE) -C $(APP) sphinx $v
+
+	$i "Check that documentation was generated"
+	$t test -f $(APP)/sphinx/man_output/sphinx_$(APP).1
+	$t test -f $(APP)/sphinx/html_output/index.html
+	$t test -f $(APP)/sphinx/html_output/manpage.html
+
+	$i "Distclean the application"
+	$t $(MAKE) -C $(APP) distclean $v
+
+	$i "Check that the generated documentation was removed"
+	$t test ! -e $(APP)/sphinx/man_output/sphinx_$(APP).1
+	$t test ! -e $(APP)/sphinx/html_output/index.html
+	$t test ! -e $(APP)/sphinx/html_output/manpage.html
+
+sphinx-format-opts: build clean
+
+	$i "Bootstrap a new OTP application named $(APP)"
+	$t mkdir $(APP)/
+	$t cp ../erlang.mk $(APP)/
+	$t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+	$i "Define formats generated by Sphinx"
+	$t echo "SPHINX_FORMATS = html man" >> $(APP)/Makefile
+
+	$i "Change format-specific options"
+	$t echo "sphinx_html_opts = -D 'today=erlang_mk_sphinx_html_today'" >> $(APP)/Makefile
+	$t echo "sphinx_man_opts  = -D 'today=erlang_mk_sphinx_man_today'"  >> $(APP)/Makefile
+
+	$i "Generate Sphinx config"
+	$(call sphinx-generate-doc-skeleton)
+
+	$i "Run Sphinx (html + man)"
+	$t $(MAKE) -C $(APP) sphinx $v
+
+	$i "Check that the 'today' macro was defined correctly"
+	$t grep -q erlang_mk_sphinx_html_today $(APP)/html/manpage.html
+	$t grep -q erlang_mk_sphinx_man_today $(APP)/man/sphinx_$(APP).1
+
+
+define sphinx-generate-doc-skeleton
+$t mkdir $(APP)/$(if $1,$1,doc)/
+$t printf "%s\n" \
+	"project = '$(APP)'" \
+	"master_doc = 'index'" \
+	"source_suffix = '.rst'" \
+	"man_pages = [('manpage', 'sphinx_$(APP)', 'Man Page', [], 1)]" \
+	"" > $(APP)/$(if $1,$1,doc)/conf.py
+
+$t printf "%s\n" \
+	"***********" \
+	"Sphinx Docs" \
+	"***********" \
+	"" \
+	"ToC" \
+	"===" \
+	"" \
+	".. toctree::" \
+	"" \
+	"   manpage" \
+	"" \
+	"Indices" \
+	"=======" \
+	"" \
+	'* :ref:`genindex`' \
+	'* :ref:`modindex`' \
+	'* :ref:`search`' \
+	"" > $(APP)/$(if $1,$1,doc)/index.rst
+
+$t printf "%s\n" \
+	"********" \
+	"Man Page" \
+	"********" \
+	"" \
+	"Synopsis" \
+	"========" \
+	"" \
+	".. code-block:: none" \
+	"" \
+	"    erlang-sphinx-mk-man [--help]" \
+	"" \
+	"today = |today|" \
+	"" > $(APP)/$(if $1,$1,doc)/manpage.rst
+endef