Build a monodoc Source from Man Pages with mdoc assemble
You will turn an XML list of man pages into the .tree and .zip files that monodoc can browse, then connect them with a matching .source file. Allow about fifteen minutes for a small source. The examples use mdoc 5.7.4.9 from package monodoc-base 6.8.0.105+dfsg-3.6ubuntu2, installed here as /usr/bin/mdoc.
The route
Jump straight to the step you need, or tick off Done means at the end.
Assembly is normally an unprivileged build step. Copying the finished files into monodoc's system source directory is a separate operation and usually needs elevated privileges. This guide does not modify that directory until the final step.
1. Check the installed command
Confirm the executable, package version and destination directory before preparing any files:
$ command -v mdoc
/usr/bin/mdoc
$ mdoc --version
mdoc 5.7.4.9
$ dpkg-query -W -f='${Package} ${Version}\n' monodoc-base
monodoc-base 6.8.0.105+dfsg-3.6ubuntu2
$ pkg-config monodoc --variable=sourcesdir
/usr/lib/monodoc/sources
Versions and paths vary by distribution. Keep the output from your own machine as the authority for the command you are about to run.
2. Describe the man pages in XML
The man provider expects an XML file with a manpages root and one manpage element per page. The name becomes the visible lookup name. The page value points to the file that contains the page; it must exist or that page is omitted.
Create a working directory and a file named manpages.xml:
<?xml version="1.0"?>
<manpages>
<manpage name="mdoc-assemble(1)" page="/usr/share/man/man1/mdoc-assemble.1.gz" />
</manpages>
Add more manpage elements for a larger source. Use exact paths and names, including the section suffix. A missing path is easy to mistake for a successful build because mdoc assemble can still exit successfully while leaving that page out.
Checkpoint: verify the referenced file before assembling:
$ test -r /usr/share/man/man1/mdoc-assemble.1.gz && echo readable
readable
3. Assemble the man-page archive
Choose an output prefix without a file extension. The command creates PREFIX.tree and PREFIX.zip; it does not create the .source file for you.
$ mkdir -p build
$ mdoc assemble --format=man --out=build/mono-man manpages.xml
$ printf '%s\n' "$?"
0
$ ls -l build/mono-man.tree build/mono-man.zip
-rw-r--r-- 1 user user ... build/mono-man.tree
-rw-r--r-- 1 user user ... build/mono-man.zip
The exact sizes and timestamps are host-specific. A zero exit status and both expected files are the useful checkpoint. The tree is a monodoc index, not a text file to edit. The archive contains the rendered page data:
$ unzip -l build/mono-man.zip
Archive: build/mono-man.zip
Length Date Time Name
--------- ---------- ----- ----
... ... ... mdoc-assemble(1)
--------- -------
... 1 file
4. Understand the format and output traps
--format=man is required for this XML input. If you omit it, the documented default is ecma, which is for Mono ECMA XML rather than this man-page list. Other providers have different input contracts: simple recursively adds supported files and directories, while error expects an error-provider configuration file. Do not switch formats to silence an input error.
The format option can be interleaved with paths. It applies to the paths that follow it until another format option appears:
$ mdoc assemble --out=build/mixed \
--format=man manpages.xml \
--format=simple ./extra-docs
Keep the option beside the paths it controls. A common distraction trap is putting a directory before --format=simple and assuming the later option changes how that earlier directory was read.
5. Write the matching source file
monodoc needs a .source file alongside the generated files. Its provider must match the assembly format, and its basefile must match the output prefix without .tree or .zip. The path is the parent node in the monodoc tree.
<?xml version="1.0"?>
<monodoc>
<node label="Local man pages" name="local-man" parent="Various" />
<source provider="man" basefile="mono-man" path="local-man" />
</monodoc>
Here, mono-man matches build/mono-man.tree and build/mono-man.zip. The node is optional, but it gives the source a deliberate place in the tree. The parent name must exist in monodoc's own tree, or the entry is inserted under Various. Check the installed monodoc.xml when choosing a different parent rather than guessing a label.
Save this as build/mono-man.source. Before installing, check that all three names use the same prefix:
$ ls -l build/mono-man.source build/mono-man.tree build/mono-man.zip
-rw-r--r-- 1 user user ... build/mono-man.source
-rw-r--r-- 1 user user ... build/mono-man.tree
-rw-r--r-- 1 user user ... build/mono-man.zip
6. Install the source files carefully
Installation changes the system-wide monodoc source set. Stop here if you are only preparing an archive, or if you do not have a rollback plan. First inspect the destination and make a backup if any of the three target names already exist:
$ source_dir=$(pkg-config monodoc --variable=sourcesdir)
$ printf '%s\n' "$source_dir"
/usr/lib/monodoc/sources
$ sudo test -e "$source_dir/mono-man.source" && echo 'target exists'
$ sudo cp --preserve=all "$source_dir/mono-man.source" /tmp/mono-man.source.backup
The backup command is only needed when the target exists. Replace /tmp/mono-man with a protected, known location if another administrator manages temporary files on your host. Do not overwrite an existing source blindly: a matching prefix may belong to another package.
Copy the three files as one deliberate operation:
$ sudo cp --preserve=all \
build/mono-man.source build/mono-man.tree build/mono-man.zip \
"$source_dir"
Elevated privileges are used only for this system-directory write. If the copy fails, the build directory is unchanged. To undo a replacement, restore the backup to the exact target name, then reopen monodoc. If this was a new source, remove only the three files you created after checking their names; do not use a broad wildcard in a shared directory.
7. Diagnose an empty or missing entry
If the source opens but the page is absent, check the page path in the input XML and rebuild. The path must point to an existing readable man page. If the build reports an invalid format, use one of the documented values such as man, simple or ecma; the format name is not a free-form provider label.
If monodoc shows the entry under Various, the parent value was not found in its tree. That is a placement issue, not a failed archive. If it cannot open the source, compare the provider, basefile and filenames character by character. A source with basefile="other-name" will not find mono-man.tree.
Done means
- The installed
mdocversion and monodoc source directory were checked. - The man-page XML names readable files and uses
--format=man. - The build produced matching
.treeand.zipfiles. - The
.sourceprovider and basefile match those outputs. - System installation was performed only after checking for an existing target and recording recovery steps.