Skip to content

Multi-Group Projects: Library + Tests

Most C/C++ projects have at least two source areas: the library code and the tests that exercise it. mkdocs-cdoc lets you document both in a single site with separate navigation sections, cross-references working across groups, and per-group overview pages.

Typical project layout

my-project/
  include/
    mylib.h
  src/
    core.c
    utils.c
    io.c
  tests/
    test_core.c
    test_utils.c
    test_io.c
  docs/
    index.md
    lib-intro.md
    tests-intro.md
  mkdocs.yml

Configuration

site_name: My Project

plugins:
  - search
  - cdoc:
      project_name: My Project
      version_file: version.h
      clang_args: ["-Iinclude"]

      custom_index_pages:
        - docs/api-overview.md

      sources:
        - root: src
          nav_title: Library API
          output_dir: api/lib
          extensions: [".c", ".h"]
          custom_index_pages:
            - docs/lib-intro.md

        - root: include
          nav_title: Public Headers
          output_dir: api/headers
          extensions: [".h"]

        - root: tests
          nav_title: Tests
          output_dir: api/tests
          extensions: [".c"]
          custom_index_pages:
            - docs/tests-intro.md

      convert_rst: true
      auto_xref: true

What gets generated

The navigation sidebar will show:

My Project
  API Reference          ← top-level overview linking all groups
    Library API
      Overview           ← file table + A–Z symbol index
      core.c             ← functions, structs from this file
      utils.c
      io.c
    Public Headers
      Overview
      mylib.h
    Tests
      Overview
      test_core.c
      test_utils.c
      test_io.c

Cross-references between groups

References work across all groups. A test file can link to a library function:

/**
 * Test the initialization path.
 *
 * Verifies that :func:`mylib_init` returns 0 on success
 * and populates the :struct:`mylib_context` correctly.
 */
void test_init(void) { ... }

The links resolve to the correct pages in the Library API section, regardless of which group the reference appears in.

Similarly, hand-written pages in docs/ can reference any symbol:

The library provides `mylib_init()` for setup and `mylib_cleanup()`
for teardown. See the full API in the Library API section.

With auto_xref: true, backticked symbols become links automatically.

Custom overview content

The custom_index_pages option embeds your hand-written content at the top of each group's overview page — before the source file table and symbol index. This is the place for introductions, architecture overviews, or getting-started guides:

docs/lib-intro.md:

## About the Library

The core library provides device management, I/O helpers, and a
configuration framework. Start with `mylib_init()` to create a
context, then use the module-specific APIs.

### Key modules

- `core.c` — initialization, context management, lifecycle
- `utils.c` — string helpers, memory pools, logging
- `io.c` — file I/O, buffered readers, async operations

docs/tests-intro.md:

## Test Suite

Each test file corresponds to a library module. Tests use
standard assertions and are designed to run independently.

Adding structured test metadata

If your tests use structured doc comments, you can enable test mode for richer documentation with metadata tables, subtest listings, and "By …" index pages:

sources:
  - root: tests
    nav_title: Tests
    output_dir: api/tests
    extensions: [".c"]
    igt:
      group_by: [category, feature]

This requires TEST: / SUBTEST: blocks in your doc comments:

/**
 * TEST: test_core
 * Category: Core
 * Feature: Initialization
 * Description: Tests for the core initialization path.
 *
 * SUBTEST: init-basic
 * Description: Basic init and cleanup cycle.
 *
 * SUBTEST: init-double
 * Description: Verify double-init is handled gracefully.
 */

See Enabling Test Mode for the full reference on test metadata options.

Separating public and private APIs

A common pattern is to document public headers separately from implementation files:

sources:
  - root: include
    nav_title: Public API
    output_dir: api/public
    extensions: [".h"]

  - root: src
    nav_title: Implementation
    output_dir: api/internal
    extensions: [".c"]
    exclude: ["**/test_*"]

This gives users a clean "Public API" section with just the headers, while keeping the full implementation details accessible in a separate section.

To add links back to your repository from each symbol:

plugins:
  - cdoc:
      show_source_link: true
      source_uri: "https://github.com/you/my-project/blob/main/{filename}#L{line}"

Each function, struct, and enum heading will get a [source] link pointing to the exact file and line in your repo.