Building Software API Docs (DocFX)

Home | Docs Hub | Back to Maintainers

This guide explains how to generate the WSS documentation hub while keeping code in external repositories.

The docs project lives under apiDocs/ and uses apiDocs/repos.manifest.json to map each linked repo to a documentation tool:

Prerequisites

Always needed for DocFX/API builds

Needed when rerendering standalone .Rmd guides

  • R / Rscript (required to regenerate standalone .Rmd guides such as this page and the hardware guide)
  • Pandoc (required by rmarkdown::render() when regenerating standalone .Rmd guides)
  • R packages: rmarkdown, knitr

Needed only when Python docs are enabled

  • Python + Sphinx (sphinx-build) for Python API repos
  • PowerShell (Windows) or Bash (macOS/Linux/Git Bash on Windows)

If DocFX isn’t installed, the build script will remind you to run docfx metadata and docfx build once you add it to PATH.

Tool setup by OS

Use the setup that matches your machine before running the build scripts.

Windows

  • Install the .NET SDK 7 or later.
  • Install DocFX and make sure docfx is on your PATH.
  • Install jq if you plan to run the Bash build.
  • Install Python 3.
  • Install R.
  • Install Pandoc.
  • Install Sphinx in the Python repo environment if you plan to build Python docs.
  • Run the docs build with PowerShell.

Typical commands:

dotnet tool install -g docfx
winget install RProject.R
winget install --id JohnMacFarlane.Pandoc -e
python -m pip install -U pip
python -m pip install sphinx

macOS

  • Install the .NET SDK 7 or later.
  • Install DocFX and make sure docfx is on your PATH.
  • Install jq if you plan to run the Bash build.
  • Install Python 3.
  • Install R.
  • Install Pandoc.
  • Install Sphinx in the Python repo environment if you plan to build Python docs.
  • Run the docs build with Bash.

Typical commands:

brew install --cask dotnet-sdk
brew install --cask r
brew install pandoc
brew install jq
dotnet tool install -g docfx
python3 -m pip install -U pip
python3 -m pip install sphinx
Rscript -e "install.packages(c('rmarkdown', 'knitr'), repos='https://cloud.r-project.org')"

If docfx is not found after installing it as a .NET global tool, add ~/.dotnet/tools to your shell PATH.

Linux

  • Install the .NET SDK 7 or later.
  • Install DocFX and make sure docfx is on your PATH.
  • Install jq.
  • Install Python 3 and pip.
  • Install R.
  • Install Pandoc.
  • Install Sphinx in the Python repo environment if you plan to build Python docs.
  • Run the docs build with Bash.

Typical commands:

sudo apt install -y r-base
sudo apt install -y pandoc
sudo apt install -y jq
dotnet tool install -g docfx
python3 -m pip install -U pip
python3 -m pip install sphinx
Rscript -e "install.packages(c('rmarkdown', 'knitr'), repos='https://cloud.r-project.org')"

Install the .NET SDK with your distribution’s package manager or Microsoft’s installer for your distro before running the commands above.

If docfx is not found after installing it as a .NET global tool, add ~/.dotnet/tools to your shell PATH.

If rmarkdown::render() reports that Pandoc is missing, install pandoc and retry the docs build.

If R package installation fails because the system library is not writable, install to a user library instead:

mkdir -p "$HOME/R/x86_64-pc-linux-gnu-library/4.3"
Rscript -e ".libPaths('$HOME/R/x86_64-pc-linux-gnu-library/4.3'); install.packages(c('rmarkdown', 'knitr'), repos='https://cloud.r-project.org')"

Configure linked repositories

Edit apiDocs/repos.manifest.json and add one entry per linked repo.

This repo’s default manifest is written to use environment variables for the linked repo roots (for example: "root": "${WSS_CORE_REPO_ROOT}"). The build scripts expand ${VARNAME} tokens at runtime.

Quick start:

  1. Set the required environment variables (paths to the linked repos).
  2. Run the build script with the manifest.

If you only want the main/core docs, add the main-only flag:

  • Bash: ./apiDocs/build-docs.sh --manifest ./apiDocs/repos.manifest.json --main
  • PowerShell: ./apiDocs/build-docs.ps1 -ManifestPath ./apiDocs/repos.manifest.json -Main

When --main or -Main is set, the build only includes the core manifest entry. In the default manifest, that core entry points at the root WSS_Core_Interface.sln, so main/core docs include the shared core plus any transport projects linked into that solution. Without that flag, the scripts build all enabled repositories.

If you want to skip Python docs, add the skip-Python flag:

  • Bash: ./apiDocs/build-docs.sh --manifest ./apiDocs/repos.manifest.json --skip-python
  • PowerShell: ./apiDocs/build-docs.ps1 -ManifestPath ./apiDocs/repos.manifest.json -SkipPython

When --skip-python or -SkipPython is set, the scripts skip Sphinx builds for kind: python manifest entries while still building the DocFX hub and any enabled C# API sections.

Python integration docs for the library are not currently supported in this local build workflow. For now, use --skip-python in Bash or -SkipPython in PowerShell.

If you want to skip standalone RMarkdown rerendering, add the skip-RMD flag:

  • Bash: ./apiDocs/build-docs.sh --manifest ./apiDocs/repos.manifest.json --skip-rmd
  • PowerShell: ./apiDocs/build-docs.ps1 -ManifestPath ./apiDocs/repos.manifest.json -SkipRmd

When --skip-rmd or -SkipRmd is set, the scripts skip regenerating the standalone .Rmd-based HTML guides while still building the DocFX hub and any enabled API sections.

Required environment variables

Set these to your local checkouts:

  • WSS_CORE_REPO_ROOT (C# core solution): /path/to/WSSCoreInterface
  • WSS_CSHARP_REPO_ROOT (C# integration): /path/to/HFI_WSS_Csharp_Implementation
  • WSS_UNITY_REPO_ROOT (Unity repo / Unity project root): /path/to/Project using HFI_WSS_Unity_Interface
  • WSS_UNITY_INTEGRATION_SRC (Unity integration submodule root inside the Unity project)
    • This must be the subfolder that contains the integration code you want documented.
    • Example: $WSS_UNITY_REPO_ROOT/Assets/SubModules/WSSInterfacingModule
  • WSS_PYTHON_REPO_ROOT (Python integration)
    • This must be the Python project root that contains a docs/ folder (with docs/conf.py).
    • Example: /path/to/WSS_Python_Wrapper/WSS_Py_Wrapper

Examples:

export WSS_CORE_REPO_ROOT="/path/to/WSSCoreInterface"
export WSS_CSHARP_REPO_ROOT="/path/to/HFI_WSS_Csharp_Implementation"
export WSS_UNITY_REPO_ROOT="/path/to/SimpleStimulationConsole"
export WSS_UNITY_INTEGRATION_SRC="$WSS_UNITY_REPO_ROOT/Assets/SubModules/WSSInterfacingModule"
export WSS_PYTHON_REPO_ROOT="/path/to/WSS_Python_Wrapper/WSS_Py_Wrapper"
$env:WSS_CORE_REPO_ROOT = 'C:\\path\\to\\WSSCoreInterface'
$env:WSS_CSHARP_REPO_ROOT = 'C:\\path\\to\\HFI_WSS_Csharp_Implementation'
$env:WSS_UNITY_REPO_ROOT = 'C:\\path\\to\\SimpleStimulationConsole'
$env:WSS_UNITY_INTEGRATION_SRC = "$env:WSS_UNITY_REPO_ROOT\\Assets\\SubModules\\WSSInterfacingModule"
$env:WSS_PYTHON_REPO_ROOT = 'C:\\path\\to\\WSS_Python_Wrapper\\WSS_Py_Wrapper'

For C# repos provide: - root: repo root path - csproj: path to a C# project file relative to root - or solution: path to a C# solution file relative to root - docfxDest: unique output section (example: api/core)

Use solution when one repository should publish all projects that belong to a shared root solution. This is the preferred setup for the WSS core repo so new transport projects are picked up automatically.

Optional (C#): entryUid

The hub auto-generates apiDocs/index.md links for each enabled C# repo. If you set entryUid, the index link will use xref:<entryUid> (a stable link to a namespace/type) instead of linking to a generated TOC file.

How to pick entryUid:

  1. Build once.
  2. Open apiDocs/api/<docfxDest>/toc.yml.
  3. Use the first namespace UID listed there.

Example:

  • If apiDocs/api/csharp/toc.yml starts with - uid: HFI.Wss, set entryUid to HFI.Wss.

For Python repos provide: - root: repo root path - sphinxSource: source docs folder (usually docs) - publishDir: destination under this docs repo (example: external/python-tools)

Selecting the correct Python root + sphinxSource

  • root must be the Python project root that contains the Sphinx docs/ folder.
  • sphinxSource should point to the directory that contains conf.py (usually docs).

Example (WSS_Python_Wrapper):

  • root: /home/lemf/Documents/GitHub/WSS_Python_Wrapper/WSS_Py_Wrapper
  • sphinxSource: docs (because docs/conf.py exists under that root)

Windows (PowerShell)

Build with manifest:

./apiDocs/build-docs.ps1 -ManifestPath ./apiDocs/repos.manifest.json

Build only the main/core docs:

./apiDocs/build-docs.ps1 -ManifestPath ./apiDocs/repos.manifest.json -Main

Serve locally after build:

./apiDocs/build-docs.ps1 -ManifestPath ./apiDocs/repos.manifest.json -Serve

After the command starts the local server, look for the localhost URL printed by DocFX in the terminal (for example, http://localhost:8080) and open it in your browser.

Execution policy

If scripts are blocked:

powershell -NoProfile -ExecutionPolicy Bypass -File ".\\apiDocs\\build-docs.ps1" -ManifestPath ".\\apiDocs\\repos.manifest.json"

macOS/Linux or Git Bash (Windows)

Build with manifest:

./apiDocs/build-docs.sh --manifest ./apiDocs/repos.manifest.json

Build only the main/core docs:

./apiDocs/build-docs.sh --manifest ./apiDocs/repos.manifest.json --main

Build the docs hub without Python and without rerendering standalone RMarkdown docs:

./apiDocs/build-docs.sh --manifest ./apiDocs/repos.manifest.json --skip-python --skip-rmd

Serve locally after build:

./apiDocs/build-docs.sh --manifest ./apiDocs/repos.manifest.json --serve

After the command starts the local server, look for the localhost URL printed by DocFX in the terminal (for example, http://localhost:8080) and open it in your browser.

Permission denied

If ./apiDocs/build-docs.sh returns Permission denied:

chmod +x ./apiDocs/build-docs.sh
./apiDocs/build-docs.sh --manifest ./apiDocs/repos.manifest.json

If execute permission cannot be changed (for example, restricted mount/ACL), run through Bash directly:

bash ./apiDocs/build-docs.sh --manifest ./apiDocs/repos.manifest.json

What the scripts do

  • Reads enabled entries from apiDocs/repos.manifest.json
  • If --main / -Main is set, keeps only the core entry and skips all optional external integrations
  • Renders the standalone RMarkdown guides before the DocFX build unless --skip-rmd / -SkipRmd is used:
    • hardwareDocs/wsshardware.rmd
    • howtoCompileAPIDocs/BuildSoftwareDocs.Rmd
    • simpleSerialPortDocs/SimpleSerial.Rmd
    • wssCommandsDocs/wsscommands.Rmd
  • Builds Python docs with Sphinx into apiDocs/external/<repo-id>
  • Generates a DocFX config file (apiDocs/docfx.generated.json) with one metadata section per C# repo
  • Regenerates apiDocs/index.md and apiDocs/toc.yml so all sections are accessible from the main page
  • Runs docfx metadata then docfx build

Adding more RMarkdown docs to the build

If you add another standalone .Rmd guide that should be regenerated as part of the docs build:

  1. Add the file path to the rmd_docs array in apiDocs/build-docs.sh.
  2. Add the same file path to the $rmdDocs array in apiDocs/build-docs.ps1.
  3. Keep the path repo-relative (for example: myDocs/MyGuide.Rmd).
  4. Re-run the docs build and confirm the corresponding .html output is regenerated.

Unity submodule repos (using a shim .csproj)

If a Unity repository contains a UI/app .csproj but the integration code you want to document is a submodule folder (not a standalone project), use the provided shim project:

  • apiDocs/shims/UnitySubmodule/UnitySubmodule.Docs.csproj

Add a C# repo entry pointing to the shim and pass the integration folder via MSBuild properties:

{
  "id": "unity-integration",
  "title": "API: Unity Integration (C#)",
  "kind": "csharp",
  "enabled": true,
  "root": "${WSS_UNITY_REPO_ROOT}",
  "csprojBase": "hub",
  "csproj": "apiDocs/shims/UnitySubmodule/UnitySubmodule.Docs.csproj",
  "docfxDest": "api/unity",
  "msbuildProperties": {
    "DocsSourceRoot": "${WSS_UNITY_INTEGRATION_SRC}",
    "DefineConstants": "UNITY_2021_3_OR_NEWER;UNITY_EDITOR"
  }
}

Where:

  • WSS_UNITY_REPO_ROOT points at the Unity app repo.
  • WSS_UNITY_INTEGRATION_SRC points at the submodule folder you want documented.
    • It must be the integration submodule root inside the Unity project (not the Unity repo root).

Output

  • The static site is generated under: apiDocs/ (for example: apiDocs/index.html)
  • Open apiDocs/index.html in a browser (or use -Serve in PowerShell)

Troubleshooting

  • DocFX not found
    • Install DocFX and ensure docfx is on PATH, then run:

      cd \"A:\\Documents\\GIT Projects\\WSS-documentation\\apiDocs\"
      docfx metadata && docfx build
  • Wrong repo path
    • Verify each root in repos.manifest.json exists.
  • Missing C# project path
    • Verify csproj is correct relative to root.
  • Missing Sphinx docs
    • Verify sphinxSource exists and Sphinx is installed.
  • Sphinx autodoc import errors
    • Ensure the Python repo’s docs dependencies are installed (common patterns: python -m pip install -e '.[docs]' or install docs/requirements.txt).
    • If conf.py modifies sys.path, confirm it points at the correct src/ directory.
  • Namespace/compile warnings
    • The docs build uses a small ApiProject; we suppress common nullability warnings that don’t affect documentation output.
  • Permissions
    • On Windows, run PowerShell as admin if you hit policy/permission issues.

Repository layout

  • apiDocs/ — DocFX project (docfx.json, templates, tools)
  • apiDocs/build-docs.ps1 — PowerShell build script (Windows)
  • apiDocs/build-docs.sh — Bash build script (macOS/Linux/Git Bash)
  • DocFX output is written into apiDocs/ (HTML files plus api/, conceptual/, styles/)

Navigation: