--- /dev/null
+<!--
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+SPDX-License-Identifier: MPL-2.0
+
+This Source Code Form is subject to the terms of the Mozilla Public
+License, v. 2.0. If a copy of the MPL was not distributed with this
+file, you can obtain one at https://mozilla.org/MPL/2.0/.
+
+See the COPYRIGHT file distributed with this work for additional
+information regarding copyright ownership.
+-->
+# Building the Manpage
+
+## Building from the tarball
+
+When building BIND from the tarball, there will be pre-generated `.in` manpage templates.
+For every page relevant to the build (`man_srcset`), meson will generate the manpage and install it using `install_man`.
+
+Sphinx can also be used like in git tree builds described below but the pages generated with sphinx will not be installed if templated ones are available.
+
+## Building from the git tree
+
+Sphinx is required when building the manpages from the git tree.
+If `sphinx-build` didn't exist when creating the build directory, build targets for the manpage will not exist.
+Use the command `meson configure --clearcache` to force the next build to probe for sphinx again.
+
+The source set `manrst_srcset` is used only to determine when a rebuild is necessary from meson's perspective and doesn't actually pass the source files.
+Sphinx works by handling entire directories and so meson needs to use `depend_files` for the task.
+
+To find which optional manpages need to be built or not, we pass the build directory to sphinx using the environment variable `BIND_BUILD_ROOT`.
+Sphinx will then inspect the meson-generated `intro-targets.json` file to see which optional build components are enabled.
+
+If an optional component like LMDB is disabled in the build directory, its corresponding manpage needs to be removed.
+From meson's perspective, the entire folder is the output and doesn't concern itself with the insides specifically.
+This is done by checking which optional targets are not built but have the page entry in the output folder.
+
+If the `BIND_BUILD_ROOT` is not specified, sphinx will build every page.
+This is used when creating a release tarball.
+Meson will use the script `util/meson-dist-package.sh` to create the templates when runnnig the `dist` command.
+If sphinx is not available in the build directory, this step will be skipped and so the tarballs must be created on a system with `sphinx-build`.
# information regarding copyright ownership.
############################################################################
+import json
+import os
import sys
from pathlib import Path
),
("dnssec-signzone", "dnssec-signzone", "DNSSEC zone signing tool", author, 1),
("dnssec-verify", "dnssec-verify", "DNSSEC zone verification tool", author, 1),
- (
- "dnstap-read",
- "dnstap-read",
- "print dnstap data in human-readable form",
- author,
- 1,
- ),
(
"filter-aaaa",
"filter-aaaa",
author,
1,
),
- (
- "named-nzd2nzf",
- "named-nzd2nzf",
- "convert an NZD database to NZF text format",
- author,
- 1,
- ),
(
"named-rrchecker",
"named-rrchecker",
("tsig-keygen", "tsig-keygen", "TSIG key generation tool", author, 8),
]
+bind_optional_pages = {
+ "dnstap-read": (
+ "dnstap-read",
+ "dnstap-read",
+ "print dnstap data in human-readable form",
+ author,
+ 1,
+ ),
+ "named-nzd2nzf": (
+ "named-nzd2nzf",
+ "named-nzd2nzf",
+ "convert an NZD database to NZF text format",
+ author,
+ 1,
+ ),
+}
+
+bind_build_root = os.getenv("BIND_BUILD_ROOT")
+if bind_build_root is None:
+ man_pages.extend(bind_optional_pages.values())
+else:
+ bind_build_path = Path(bind_build_root).resolve()
+ with open(
+ bind_build_path / "meson-info" / "intro-targets.json", encoding="utf-8"
+ ) as f:
+ for target in json.load(f):
+ if target["name"] in bind_optional_pages:
+ page = bind_optional_pages.pop(target["name"])
+ man_pages.append(page)
+
+ # Delete artifacts if an optional binary is no longer built.
+ # This happens when the build directory is reconfigured to exclude
+ # dnstap etc.
+ #
+ # Meson can't handle this because:
+ # - "man.p" is under our control
+ # - Meson just expects an entire folder as an output, this is just how sphinx works.
+ for unused in bind_optional_pages.values():
+ doctree = bind_build_path / "man.p" / f"{unused[0]}.doctree"
+ if doctree.exists():
+ doctree.unlink()
+
+ page = bind_build_path / "man" / f"man{unused[4]}" / f"{unused[0]}.{unused[4]}"
+ if page.exists():
+ page.unlink()
+
+
#
# The rst_epilog will be completely overwritten from meson
# the definition here is provided for when manpages are generated
custom_target(
'man',
+ build_always_stale: true,
depend_files: manrst_srcconf.sources(),
depends: doc_misc_targets,
install: man_srcconf.sources().length() == 0,
exit 1
fi
-export BIND_BUILD_ROOT=${MESON_BUILD_ROOT}
-export BIND_SOURCE_ROOT=${MESON_SOURCE_ROOT}
-
generate_man_pages() {
export MESON_PROJECT_VERSION=$1