Files
modulus/README.md
T
khodowany b9d30fb975
publish / publish (push) Successful in 11m40s
Clangd
2026-09-11 00:01:55 -05:00

6.9 KiB

Modulus

Modulus is the shared C++23 foundation library and build tooling used by the khodo Product Vamp repositories. It provides small runtime utilities, Conan profiles, CMake package integration, editor configuration generation, typed LSP compile-database setup, and bridge targets for the external libraries needed by Product Vamp.

The core modulus::modulus target requires only Boost.JSON. Optional bridges are loaded when requested:

find_package(modulus CONFIG REQUIRED COMPONENTS openssl)
target_link_libraries(app PRIVATE modulus::modulus modulus::openssl)

Available components are boost_json, openssl, sqlite, raylib, and miniaudio. Existing package discovery can also be followed by modulus_require_openssl() (or the corresponding bridge helper). Source builds opt in with MODULUS_WITH_OPENSSL, MODULUS_WITH_SQLITE, MODULUS_WITH_RAYLIB, and MODULUS_WITH_MINIAUDIO.

Conan consumers must enable the matching modulus/*:with_openssl, with_sqlite, with_raylib, or with_miniaudio option to add that dependency to the graph. Applications combining several bridge consumers should set the union of these options on their direct Modulus requirement. All four options default to false.

Build

Use the checked-in tools directly inside CI or a compatible build environment:

MODULUS_DIRECT=1 ./tools/configure.py --target x86_64_gcc12_release
./tools/build.py --target x86_64_gcc12_release
./tools/test.py --target x86_64_gcc12_release

Outside that environment, downstream repos use python3 modulus.py <command> to fetch the public modulus/latest package from the khodo Conan registry and export the tool wrappers into build/build_tools/.

build automatically configures a target when CMake metadata is missing. Run configure explicitly when you want to force a reconfigure or refresh dependencies.

Refresh clangd compile databases with:

./tools/lsp.py

Product repos can add typed extra CMake compile databases under tooling.lsp.compile_databases; this is intended for cases like Product Vamp's Pico firmware tree.

Editor Configuration

modulus.json is the source for generated .clangd, .clang-format, and pyrightconfig.json files. Configure, LSP refresh, and tooling export regenerate them only when their content changes. Keep these generated files ignored; customize tooling.editor instead:

{
  "tooling": {
    "editor": {
      "clangd": [
        {"CompileFlags": {"CompilationDatabase": "build/native"}},
        {"If": {"PathMatch": "src/firmware/.*"}, "CompileFlags": {"CompilationDatabase": "build/firmware"}}
      ],
      "clang_format": {"DisableFormat": true},
      "pyright": {"include": ["tools", "conanfile.py"]}
    }
  }
}

Each supplied entry replaces that file's entire configuration. Omitted entries use Modulus defaults: the default target's build directory for clangd, -Wall/-Wextra, disabled clang-tidy and formatting, and Python paths for the bootstrap, recipe, and exported tools. Entries use the editors' own configuration keys. LLVM files use JSON-compatible YAML, with separate documents for clangd fragments.

The authored cmake/ directory belongs in Git. CMakeFiles/, compiler caches, and generated sources belong in build directories. Modulus rejects project/source-root output directories before clearing configure or LSP caches. Conan may still use its own isolated build folders. Existing build caches are retained; they are not source files.

Container Clangd

All managed repos use clangd 19 in their build image. configure and lsp rebuild images whose Dockerfile fingerprint has changed and prepare container headers on the host. lsp also refreshes extra databases, such as Pico firmware. Run these commands on the host before starting your editor. Direct/container-only builds do not prepare a host header cache.

Neovim 0.11+ with exrc enabled loads the generated, ignored .nvim.lua after you review and trust it. The shared Lua helper finishes LazyVim's LSP setup before changing clangd's command and project routing; completion capabilities, keybindings, and attach handlers are preserved. Non-Modulus projects keep their existing server. Content-stable generation avoids repeated trust prompts. An existing hand-authored .nvim.lua is never overwritten; it can call dofile(root .. "/build/build_tools/nvim/modulus.lua").setup(root) (use /tools/nvim/ in Modulus itself). Set tooling.editor.nvim.enabled to false to opt out.

Other editors can launch python3 modulus.py clangd in a consumer repo, or python3 tools/clangd.py in Modulus. This is a stdio-only transport: no TTY, downloads, builds, credential environment forwarding, Docker socket, or host-server fallback. Startup fails on stderr if the image, database, or header cache needs preparation. Workspace paths stay identical in the container; sources are read-only and build/ is writable. The container exits on EOF/shutdown and is removed on launcher termination.

Server settings are separate from .clangd's parsing/diagnostic settings:

{
  "tooling": {
    "lsp": {
      "clangd": {
        "executable": "/usr/bin/clangd-19",
        "arguments": ["--background-index", "--completion-style=detailed", "--header-insertion=never"],
        "query_drivers": ["/usr/bin/gcc-12", "/usr/bin/g++-12", "/usr/bin/aarch64-linux-gnu-gcc", "/usr/bin/aarch64-linux-gnu-g++"],
        "header_roots": []
      }
    }
  }
}

Omitted settings use these defaults; supplied lists replace defaults. Compiler paths must be explicit, trusted absolute paths, not wildcards. Add embedded compiler paths and SDK header roots in product config. --query-driver and --path-mappings are managed by the launcher, not the argument list. The default image uses Debian's clangd layout; custom images must provide /usr/lib/llvm-<major>/lib/clang/<major>/include for built-in headers.

Header-only snapshots are shared by immutable image ID and header settings under $XDG_CACHE_HOME/modulus/clangd (default ~/.cache/modulus/clangd). Preparation is locked and atomic. Symlinks are dereferenced in the container, and extracted files are read-only. clangd maps definition locations to these local files; Neovim additionally opens them unmodifiable. Old image caches can be removed when no editor uses them; run lsp to recreate a removed cache. Toolchains themselves are not copied to the host.

Package

Create Conan packages with:

./tools/package.py --all

Publishing requires credentials only for the upload step:

CONAN_USER=<user> \
CONAN_TOKEN=<token> \
MODULUS_CONAN_UPLOAD=1 \
MODULUS_ALLOW_PACKAGE_REPLACE=1 \
./tools/package.py --all --replace

The default public Conan remote is:

https://git.thyme-labs.com/api/packages/khodo/conan

Generic application artifacts default to:

https://git.thyme-labs.com/api/packages/khodo/generic

Configure/build/test do not require package credentials for public packages.

License

Modulus is released under the MIT License.