Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
59e5e7d
chore: drop uv.lock
ubmarco Sep 29, 2026
464cdb1
docs: highlight the JSON blocks with comments as json
ubmarco Sep 29, 2026
cbef21a
docs: give every page a place in the navigation
ubmarco Sep 29, 2026
d610d5b
feat(needs): declare the fields the imported needs carry
ubmarco Sep 29, 2026
d84d052
chore(ubc): ignore tabs in the generated source listings
ubmarco Sep 29, 2026
d5f4fb1
fix(brightness_controller): implement SWDD_BC-203 in the automatic br…
ubmarco Sep 29, 2026
db9e968
docs(agents): a condition that cannot be evaluated warns
ubmarco Sep 29, 2026
6825977
docs(variants): trace code to the design, per variant
ubmarco Sep 29, 2026
dd8216e
refactor: define implementation needs as one-line comments
ubmarco Sep 29, 2026
218247e
docs(variants): name the component directory in src-trace
ubmarco Sep 29, 2026
e0bebae
fix(csv): put the requirement images into the needs' content
ubmarco Sep 29, 2026
f439624
feat: select a variant with generated files instead of a link
ubmarco Sep 29, 2026
5c4c6e8
feat: import the test results as needs in both readers
ubmarco Sep 29, 2026
d3df1b3
feat: hand codelinks the selected build's compile database
ubmarco Sep 29, 2026
3b630bd
docs: give every generated page a place in the navigation
ubmarco Sep 29, 2026
5076fdc
docs: describe the generated selection
ubmarco Sep 29, 2026
40a8046
ci: gate the documentation on both readers, strictly
ubmarco Sep 29, 2026
8cd0dbe
build: pin the spl-core commit that the generated selection needs
ubmarco Sep 29, 2026
3303b5a
feat: check the configuration whenever Sphinx reads it
ubmarco Sep 29, 2026
b4f38a4
test: check the generated selection instead of the link
ubmarco Sep 29, 2026
bfb7ab1
fix(csv): let ubc show the images of the imported requirements
ubmarco Sep 29, 2026
6550277
test: run the documentation gate in a linked worktree too
ubmarco Sep 29, 2026
536f633
fix: show only its own component in a component report
ubmarco Sep 29, 2026
9b3c644
ci: gate the per-component reports as well
ubmarco Sep 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 15 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,19 @@ jobs:
echo "marker=$marker" >> "$GITHUB_OUTPUT"

documentation:
name: Documentation (no compiler)
name: Documentation
runs-on: ubuntu-24.04
timeout-minutes: 15
timeout-minutes: 30
needs: determine-gate

# The documentation is derivable from the sources alone: KConfig is pure
# Python and the documents are text. Only CMake's top-level project()
# call needs a C toolchain, and nothing here goes through it. So this
# gate installs a Python and the locked dependencies, and nothing else --
# no poks, no scoop, no cross-compiler. It is the fastest signal in the
# workflow and it covers every variant, where the build jobs cover the
# variants they build.
# The documentation of every variant and kit, in both readers, in strict
# mode, with their needs compared (test/test_docs_gate.py). Nothing is
# compiled, but each cell is CONFIGURED: codelinks takes a variant's
# #ifdef branches from its build's compile database, which only CMake
# writes, and CMake's top-level project() call wants a C/C++ toolchain.
# The runner's gcc, g++, cmake and ninja are enough -- no poks, no scoop,
# no cross-compiler. It covers every variant, where the build jobs cover
# the variants they build.
steps:
- name: Checkout Code
uses: actions/checkout@v6
Expand All @@ -71,6 +72,11 @@ jobs:
poetry config virtualenvs.in-project true
poetry install --no-root

# cmake and gcc are part of the runner image; Ninja is the generator
# the builds use.
- name: Install Ninja
run: sudo apt-get install -y --no-install-recommends ninja-build

# `ubc` is the second reader. Without it the parity tests skip, and
# a guarantee that only holds on a developer machine is not a
# guarantee -- so the gate installs it and CI_REQUIRE_UBC turns a
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
# Windows without Developer Mode, a copy) of the configured variant's build
# output directory. Generated output, never committed.
/generated
# The document rules tools/variant_data.py generates (see ubproject.toml).
/ubproject.variants.toml

# Output directory of test results
/test/output
Expand Down
4 changes: 2 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@
// the edit is the only guard rail that also applies to an assistant.
"files.readonlyInclude": {
"build/**": true,
"generated/**": true
"generated/**": true,
"ubproject.variants.toml": true
},
"cmake.buildDirectory": "${workspaceFolder}/build/${variant:variant}/${buildKit}/${buildType}",
"cmake.copyCompileCommands": "${workspaceFolder}/build/compile_commands.json",
"cmake.configureSettings": {
"BUILD_KIT": "${buildKit}",
"CMAKE_MESSAGE_LOG_LEVEL": "STATUS",
Expand Down
202 changes: 121 additions & 81 deletions AGENTS.md

Large diffs are not rendered by default.

81 changes: 61 additions & 20 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,12 @@ include("${SPL_CORE_DIR}/spl.cmake")
# Variant data: one generation step, everything downstream declarative.
#
# tools/variant_data.py writes build/variants/<Variant>/<kit>/<target>.json for
# every variant, plus build/autoconf.json as the "current" pointer and a
# `generated` symlink to this build directory. It is invoked here so that
# configuring in the IDE keeps the pointer in step with whatever CMake Tools
# selected -- the same role cmake.copyCompileCommands plays for the compilation
# database.
# the variant (and one per component report), the document rules
# ubproject.variants.toml, and the selection of this build: build/selection.toml
# for the IDE and a bare run, and <build>/selection/... for every documentation
# run spl-core starts here. Configuring a build is selecting it, so configuring in
# the IDE keeps the selection in step with whatever CMake Tools selected. A test
# kit build shows its reports, a prod kit build its design documentation.
#
# It is deliberately a standalone script and not CMake code. KConfig is pure
# Python, while the top-level project() call above demands a C toolchain before
Expand All @@ -74,11 +75,16 @@ set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS
${_SPLED_VARIANT_DATA_SCRIPT}
${CMAKE_SOURCE_DIR}/variants/${VARIANT}/parts.cmake
)
if(BUILD_KIT STREQUAL test)
set(_spled_selected_target reports)
else()
set(_spled_selected_target docs)
endif()
execute_process(
COMMAND "${_VENV_PYTHON}" ${_SPLED_VARIANT_DATA_SCRIPT}
--variant ${VARIANT}
--kit ${BUILD_KIT}
--target docs
--target ${_spled_selected_target}
--current
--build-dir ${CMAKE_BINARY_DIR}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
Expand All @@ -94,27 +100,31 @@ endif()
# it has to be set before parts.cmake adds the components, which is where
# spl-core computes the paths it writes for Sphinx.
#
# The variant data file for each build shape. spl-core hands it to sphinx-build
# as `-D needs_variant_data_file=`, so a reports build evaluates its fences
# against the reports cell. `build/autoconf.json`, the pointer ubCode and a bare
# sphinx-build read, always holds the docs cell, so the IDE sees the report
# fences as a clean false.
set(SPL_VARIANT_DATA_FILE_DOCS ${CMAKE_SOURCE_DIR}/build/variants/${VARIANT}/${BUILD_KIT}/docs.json)
set(SPL_VARIANT_DATA_FILE_REPORTS ${CMAKE_SOURCE_DIR}/build/variants/${VARIANT}/${BUILD_KIT}/reports.json)
# Every documentation run spl-core starts names its own selection file, which
# tools/variant_data.py has just written for this build: the variant data file of
# its shape (and component), and the mount of this build directory. conf.py reads
# it, and ubc takes the same file with `-c "$(cat <file>)"`. No run depends on
# which build was configured last, so the reports of two builds can be built side
# by side.
set(SPL_SPHINX_OPTIONS -D spl_selection=${CMAKE_BINARY_DIR}/selection/@SHAPE@.toml)
set(SPL_SPHINX_COMPONENT_OPTIONS -D spl_selection=${CMAKE_BINARY_DIR}/selection/@COMPONENT_PATH@/@SHAPE@.toml)

# Sphinx reaches this build directory through `generated`, the link
# tools/variant_data.py has just pointed at it. The generated report pages are
# therefore named `generated/...` whatever the variant, kit or build type, and
# the report sections name them directly instead of globbing `/build/**`.
# spl-core writes each coverage report next to its page under that name, and
# stops a documentation build whose link has since been re-pointed at another
# build directory.
# The selection mounts this build directory at `generated`, so every page
# spl-core generates is named `generated/...` whatever the variant, kit or build
# type, and the report sections name them directly instead of globbing
# `/build/**`. spl-core writes each coverage report next to its page under that
# name. `generated` does not exist on disk: it is a mount, not a link.
set(SPL_SPHINX_BINARY_DIR ${CMAKE_SOURCE_DIR}/generated)

# No document is rendered through Jinja, so the source listings clanguru
# generates need no `{% raw %}` armour.
set(SPL_SOURCE_DOCS_JINJA_RAW_TAGS OFF)

# Test results as needs.json that every reader imports, instead of
# sphinx-test-reports' test-report directive, which only Sphinx knows. The
# results page also carries the `results` links of the test specifications.
set(SPL_TEST_RESULTS_AS_NEEDS ON)

# The object_deps_report extension is currently Windows-only: its index.cmake
# hardcodes the runner as "object_deps_report.exe", which does not exist on
# Linux/macOS (the console script is "object_deps_report"). Guard the include to
Expand All @@ -135,3 +145,34 @@ endif()

# Include variant specific parts/components definitions
include(${PROJECT_SOURCE_DIR}/variants/${VARIANT}/parts.cmake)

# codelinks reads the selected build's compile database from a fixed path,
# build/compile_commands.json, to take each variant's #ifdef branches.
# tools/compile_commands.py copies it there without `-save-temps`, which libclang
# rejects, and only for the selected build. CMake writes the database at the end
# of configuring, so this runs with every build; after a configure alone, build
# just this target.
add_custom_target(spled_codelinks_compile_commands ALL
COMMAND "${_VENV_PYTHON}" ${CMAKE_SOURCE_DIR}/tools/compile_commands.py --build-dir ${CMAKE_BINARY_DIR}
COMMENT "Handing codelinks the compile database of this build"
VERBATIM
)

# Every documentation run reads the database, so it waits for the copy. spl-core
# creates those targets at the end of configuring, in a deferred call of its own,
# so this one is deferred as well and runs after it.
function(_spled_documentation_runs_need_the_database)
foreach(_target IN ITEMS docs reports)
if(TARGET ${_target})
add_dependencies(${_target} spled_codelinks_compile_commands)
endif()
endforeach()
foreach(_component IN LISTS COMPONENT_NAMES)
foreach(_suffix IN ITEMS _docs _report)
if(TARGET ${_component}${_suffix})
add_dependencies(${_component}${_suffix} spled_codelinks_compile_commands)
endif()
endforeach()
endforeach()
endfunction()
cmake_language(DEFER CALL _spled_documentation_runs_need_the_database)
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ For the full testing strategy, marker definitions, and the gate assignment matri
## Variants and their documentation

What a variant contains, and what its documentation shows, is decided by data, not by templates.
Selecting a variant generates everything the readers need, so nothing is maintained per component:
adding one is adding it to a variant's `parts.cmake` and writing its documentation.
[VARIANTS.md](VARIANTS.md) walks through it by use case: switching the variant ubCode shows,
previewing any variant, comparing two variants, trying a change without touching the product, and
writing documentation that depends on the variant.
Expand Down
Loading