forked from gentoo/gentoo
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
eclass/docs: setup mkdocs deps and build docs
works with sphinx, mkdocs and doxygen. Based on distutils_enable_sphinx, but unlike distutils also works for non-python packages Package-Manager: Portage-2.3.98, Repoman-2.3.22 Signed-off-by: Andrew Ammerlaan <[email protected]> Signed-off-by: Jason A. Donenfeld <[email protected]>
- Loading branch information
1 parent
98ac498
commit 5d2ed74
Showing
1 changed file
with
354 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,354 @@ | ||
# Copyright 1999-2020 Gentoo Authors | ||
# Distributed under the terms of the GNU General Public License v2 | ||
|
||
# @ECLASS: docs.eclass | ||
# @MAINTAINER: | ||
# Andrew Ammerlaan <[email protected]> | ||
# @AUTHOR: | ||
# Author: Andrew Ammerlaan <[email protected]> | ||
# Based on the work of: Michał Górny <[email protected]> | ||
# @SUPPORTED_EAPIS: 6 7 | ||
# @BLURB: A simple eclass to build documentation. | ||
# @DESCRIPTION: | ||
# A simple eclass providing functions to build documentation. | ||
# | ||
# Please note that docs sets RDEPEND and DEPEND unconditionally | ||
# for you. | ||
# | ||
# This eclass also appends "doc" to IUSE, and sets HTML_DOCS | ||
# to the location of the compiled documentation | ||
# | ||
# The aim of this eclass is to make it easy to add additional | ||
# doc builders. To do this, add a <DOCS_BUILDER>-setup and | ||
# <DOCS_BUILDER>-build function for your doc builder. | ||
# For python based doc builders you can use the | ||
# python_append_deps function to append [${PYTHON_USEDEP}] | ||
# automatically to additional dependencies. | ||
|
||
case "${EAPI:-0}" in | ||
0|1|2|3|4|5) | ||
die "Unsupported EAPI=${EAPI:-0} (too old) for ${ECLASS}" | ||
;; | ||
6|7) | ||
;; | ||
*) | ||
die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}" | ||
;; | ||
esac | ||
|
||
# @ECLASS-VARIABLE: DOCS_BUILDER | ||
# @REQUIRED | ||
# @PRE_INHERIT | ||
# @DESCRIPTION: | ||
# Sets the doc builder to use, currently supports | ||
# sphinx, mkdocs and doxygen. | ||
# PYTHON_COMPAT should be set for python based | ||
# doc builders: sphinx and mkdocs | ||
|
||
# @ECLASS-VARIABLE: DOCS_DIR | ||
# @DESCRIPTION: | ||
# Path containing the doc builder config file(s). | ||
# | ||
# For sphinx this is the location of "conf.py" | ||
# For mkdocs this is the location of "mkdocs.yml" | ||
# | ||
# Note that mkdocs.yml often does not reside | ||
# in the same directory as the actual doc files | ||
# | ||
# Defaults to ${S} | ||
|
||
# @ECLASS-VARIABLE: DOCS_DEPEND | ||
# @DEFAULT_UNSET | ||
# @PRE_INHERIT | ||
# @DESCRIPTION: | ||
# Sets additional dependencies to build docs. | ||
# For sphinx and mkdocs these dependencies should | ||
# be specified without [${PYTHON_USEDEP}], this | ||
# is added by the eclass. E.g. to depend on mkdocs-material: | ||
# | ||
# DOCS_DEPEND="dev-python/mkdocs-material" | ||
# | ||
# This eclass appends to this variable, so you can | ||
# call it later in your ebuild again if necessary. | ||
|
||
# @ECLASS-VARIABLE: DOCS_AUTODOC | ||
# @PRE_INHERIT | ||
# @DESCRIPTION: | ||
# Sets whether to use sphinx.ext.autodoc/mkautodoc | ||
# Defaults to 1 (True) for sphinx, and 0 (False) for mkdocs | ||
|
||
# @ECLASS-VARIABLE: DOCS_EXTRA_ARGS | ||
# @DESCRIPTION: | ||
# Extra arguments to parse to the DOCS_BUILDER | ||
|
||
# @ECLASS-VARIABLE: DOCS_OUTDIR | ||
# @DESCRIPTION: | ||
# Sets where the compiled files will be put. | ||
# There's no real reason to change this, but this | ||
# variable is useful if you want to overwrite the HTML_DOCS | ||
# added by this eclass. E.g.: | ||
# | ||
# HTML_DOCS=( "${yourdocs}" "${DOCS_OUTDIR}/." ) | ||
# | ||
# Defaults to ${DOCS_DIR}/_build/html | ||
|
||
# @ECLASS-VARIABLE: DOCS_CONFIG_NAME | ||
# @DESCRIPTION: | ||
# Name of the doc builder config file. | ||
# | ||
# Only relevant for doxygen, as it allows | ||
# config files with non-standard names | ||
# | ||
# Defaults to Doxyfile for doxygen | ||
|
||
if [[ ! ${_DOCS} ]]; then | ||
|
||
# For the python based DOCS_BUILDERS we need to inherit python-any-r1 | ||
case ${DOCS_BUILDER} in | ||
"sphinx"|"mkdocs") | ||
# We need the python_gen_any_dep function | ||
if [[ ! ${_PYTHON_R1} && ! ${_PYTHON_ANY_R1} ]]; then | ||
die "python-r1 or python-any-r1 needs to be inherited as well to use python based documentation builders" | ||
fi | ||
;; | ||
"doxygen") | ||
# do not need to inherit anything for doxygen | ||
;; | ||
"") | ||
die "DOCS_BUILDER unset, should be set to use ${ECLASS}" | ||
;; | ||
*) | ||
die "Unsupported DOCS_BUILDER=${DOCS_BUILDER} (unknown) for ${ECLASS}" | ||
;; | ||
esac | ||
|
||
# @FUNCTION: python_check_deps | ||
# @DESCRIPTION: | ||
# Check if the dependencies are valid | ||
python_check_deps() { | ||
debug-print-function ${FUNCNAME} | ||
use doc || return 0 | ||
|
||
local dep | ||
for dep in ${CHECK_DEPS[@]}; do | ||
has_version "${dep}[${PYTHON_USEDEP}]" || return 1 | ||
done | ||
} | ||
# Save this before we start manipulating it | ||
CHECK_DEPS=${DOCS_DEPEND} | ||
|
||
# @FUNCTION: python_append_dep | ||
# @DESCRIPTION: | ||
# Appends [\${PYTHON_USEDEP}] to all dependencies | ||
# for python based DOCS_BUILDERs such as mkdocs or | ||
# sphinx. | ||
python_append_deps() { | ||
debug-print-function ${FUNCNAME} | ||
|
||
local temp=() | ||
local dep | ||
for dep in ${DOCS_DEPEND[@]}; do | ||
temp+=(" ${dep}[\${PYTHON_USEDEP}]") | ||
done | ||
DOCS_DEPEND=${temp} | ||
} | ||
|
||
# @FUNCTION: sphinx_deps | ||
# @DESCRIPTION: | ||
# Sets dependencies for sphinx | ||
sphinx_deps() { | ||
debug-print-function ${FUNCNAME} | ||
|
||
: ${DOCS_AUTODOC:=1} | ||
|
||
if [[ ${DOCS_AUTODOC} == 0 ]]; then | ||
if [[ -n "${DOCS_DEPEND}" ]]; then | ||
die "${FUNCNAME}: do not set DOCS_AUTODOC to 0 if external plugins are used" | ||
else | ||
DOCS_DEPEND="dev-python/sphinx" | ||
fi | ||
elif [[ ${DOCS_AUTODOC} == 1 ]]; then | ||
DOCS_DEPEND="$(python_gen_any_dep " | ||
dev-python/sphinx[\${PYTHON_USEDEP}] | ||
${DOCS_DEPEND}")" | ||
else | ||
die "${FUNCNAME}: DOCS_AUTODOC should be set to 0 or 1" | ||
fi | ||
} | ||
|
||
# @FUNCTION: sphinx_compile | ||
# @DESCRIPTION: | ||
# Calls sphinx to build docs. | ||
# | ||
# If you overwrite src_compile or python_compile_all | ||
# do not call this function, call docs_compile instead | ||
sphinx_compile() { | ||
debug-print-function ${FUNCNAME} | ||
use doc || return | ||
|
||
local confpy=${DOCS_DIR}/conf.py | ||
[[ -f ${confpy} ]] || | ||
die "${FUNCNAME}: ${confpy} not found, DOCS_DIR=${DOCS_DIR} call wrong" | ||
|
||
if [[ ${DOCS_AUTODOC} == 0 ]]; then | ||
if grep -F -q 'sphinx.ext.autodoc' "${confpy}"; then | ||
die "${FUNCNAME}: autodoc disabled but sphinx.ext.autodoc found in ${confpy}" | ||
fi | ||
elif [[ ${DOCS_AUTODOC} == 1 ]]; then | ||
if ! grep -F -q 'sphinx.ext.autodoc' "${confpy}"; then | ||
die "${FUNCNAME}: sphinx.ext.autodoc not found in ${confpy}, set DOCS_AUTODOC=0" | ||
fi | ||
fi | ||
|
||
sed -i -e 's:^intersphinx_mapping:disabled_&:' \ | ||
"${DOCS_DIR}"/conf.py || die | ||
# not all packages include the Makefile in pypi tarball | ||
sphinx-build "${DOCS_EXTRA_ARGS}" -b html -d "${DOCS_DIR}"/_build/doctrees "${DOCS_DIR}" \ | ||
"${DOCS_OUTDIR}" || die "${FUNCNAME}: sphinx-build failed" | ||
} | ||
|
||
# @FUNCTION: mkdocs_deps | ||
# @DESCRIPTION: | ||
# Sets dependencies for mkdocs | ||
mkdocs_deps() { | ||
debug-print-function ${FUNCNAME} | ||
|
||
: ${DOCS_AUTODOC:=0} | ||
|
||
if [[ ${DOCS_AUTODOC} == 1 ]]; then | ||
DOCS_DEPEND="$(python_gen_any_dep " | ||
dev-python/mkdocs[\${PYTHON_USEDEP}] | ||
dev-python/mkautodoc[\${PYTHON_USEDEP}] | ||
${DOCS_DEPEND}")" | ||
elif [[ ${DOCS_AUTODOC} == 0 ]]; then | ||
DOCS_DEPEND="$(python_gen_any_dep " | ||
dev-python/mkdocs[\${PYTHON_USEDEP}] | ||
${DOCS_DEPEND}")" | ||
else | ||
die "${FUNCNAME}: DOCS_AUTODOC should be set to 0 or 1" | ||
fi | ||
} | ||
|
||
# @FUNCTION: mkdocs_compile | ||
# @DESCRIPTION: | ||
# Calls mkdocs to build docs. | ||
# | ||
# If you overwrite src_compile or python_compile_all | ||
# do not call this function, call docs_compile instead | ||
mkdocs_compile() { | ||
debug-print-function ${FUNCNAME} | ||
use doc || return | ||
|
||
local mkdocsyml=${DOCS_DIR}/mkdocs.yml | ||
[[ -f ${mkdocsyml} ]] || | ||
die "${FUNCNAME}: ${mkdocsyml} not found, DOCS_DIR=${DOCS_DIR} wrong" | ||
|
||
pushd "${DOCS_DIR}" || die | ||
mkdocs build "${DOCS_EXTRA_ARGS}" -d "${DOCS_OUTDIR}" || die "${FUNCNAME}: mkdocs build failed" | ||
popd || die | ||
|
||
# remove generated .gz variants | ||
# mkdocs currently has no option to disable this | ||
# and portage complains: "Colliding files found by ecompress" | ||
rm "${DOCS_OUTDIR}"/*.gz || die | ||
} | ||
|
||
# @FUNCTION: doxygen_deps | ||
# @DESCRIPTION: | ||
# Sets dependencies for doxygen | ||
doxygen_deps() { | ||
debug-print-function ${FUNCNAME} | ||
|
||
DOCS_DEPEND="app-doc/doxygen | ||
${DOCS_DEPEND}" | ||
} | ||
|
||
# @FUNCTION: doxygen_compile | ||
# @DESCRIPTION: | ||
# Calls doxygen to build docs. | ||
# | ||
# If you overwrite src_compile or python_compile_all | ||
# do not call this function, call docs_compile instead | ||
doxygen_compile() { | ||
debug-print-function ${FUNCNAME} | ||
use doc || return | ||
|
||
: ${DOCS_CONFIG_NAME:="Doxyfile"} | ||
|
||
local doxyfile=${DOCS_DIR}/${DOCS_CONFIG_NAME} | ||
[[ -f ${doxyfile} ]] || | ||
die "${FUNCNAME}: ${doxyfile} not found, DOCS_DIR=${DOCS_DIR} or DOCS_CONFIG_NAME=${DOCS_CONFIG_NAME} wrong" | ||
|
||
# doxygen wants the HTML_OUTPUT dir to already exist | ||
mkdir -p "${DOCS_OUTDIR}" || die | ||
|
||
pushd "${DOCS_DIR}" || die | ||
(cat "${doxyfile}" ; echo "HTML_OUTPUT=${DOCS_OUTDIR}") | doxygen "${DOCS_EXTRA_ARGS}" - || die "${FUNCNAME}: doxygen failed" | ||
popd || die | ||
} | ||
|
||
# @FUNCTION: docs_compile | ||
# @DESCRIPTION: | ||
# Calls DOCS_BUILDER and sets HTML_DOCS | ||
# | ||
# This function must be called in global scope. Take care not to | ||
# overwrite the variables set by it. Has support for distutils-r1 | ||
# eclass, but only if this eclass is inherited *after* | ||
# distutils-r1. If you need to extend src_compile() or | ||
# python_compile_all(), you can call the original implementation | ||
# as docs_compile. | ||
docs_compile() { | ||
debug-print-function ${FUNCNAME} | ||
use doc || return | ||
|
||
# Set a sensible default as DOCS_DIR | ||
: ${DOCS_DIR:="${S}"} | ||
|
||
# Where to put the compiled files? | ||
: ${DOCS_OUTDIR:="${DOCS_DIR}/_build/html"} | ||
|
||
${DOCS_BUILDER}_compile | ||
|
||
HTML_DOCS+=( "${DOCS_OUTDIR}/." ) | ||
|
||
# we need to ensure successful return in case we're called last, | ||
# otherwise Portage may wrongly assume sourcing failed | ||
return 0 | ||
} | ||
|
||
|
||
# This is where we setup the USE/(B)DEPEND variables | ||
# and call the doc builder specific setup functions | ||
IUSE+=" doc" | ||
|
||
# Call the correct setup function | ||
case ${DOCS_BUILDER} in | ||
"sphinx") | ||
python_append_deps | ||
sphinx_deps | ||
;; | ||
"mkdocs") | ||
python_append_deps | ||
mkdocs_deps | ||
;; | ||
"doxygen") | ||
doxygen_deps | ||
;; | ||
esac | ||
|
||
if [[ ${EAPI} == [7] ]]; then | ||
BDEPEND+=" doc? ( ${DOCS_DEPEND} )" | ||
else | ||
DEPEND+=" doc? ( ${DOCS_DEPEND} )" | ||
fi | ||
|
||
# If this is a python package using distutils-r1 | ||
# then put the compile function in the specific | ||
# python function, else docs_compile should be manually | ||
# added to src_compile | ||
if [[ ${_DISTUTILS_R1} && ( ${DOCS_BUILDER}="mkdocs" || ${DOCS_BUILDER}="sphinx" ) ]]; then | ||
python_compile_all() { docs_compile; } | ||
fi | ||
|
||
_DOCS=1 | ||
fi |