xo-umbrella2/xo-cmake/bin/xo-gen-clang-format.in
Roland Conybeare 2626ef518e build: ++ reconfigure --capture-subsystem-edges [SDLC]
writes to xo-camke/etc/xo/subsystem-edges;
rejects if build directory doesn't enable all the
dependency-unlocking feature flags.
2026-08-08 17:59:52 -04:00

86 lines
3.4 KiB
Bash

#!/usr/bin/env bash
#
# xo-gen-clang-format - generate a .clang-format from an xo subsystem-edges file
#
# Emits (to stdout) a .clang-format whose IncludeCategories encode the xo
# include-ordering policy:
#
# 0 self (the translation unit's own header; matched automatically)
# 1 self-subsystem (same-repo, "quoted" includes)
# 2+ other xo (one category per subsystem, DESCENDING topological order)
# electives (third-party packages: catch2, pybind11, replxx, ...)
# C++ stdlib (<vector>, <iostream>, ...)
# platform (<time.h>, <sys/mman.h>, ...)
#
# The xo block is derived from EDGES_FILE (tsort format, "dep self" pairs, the
# same file xo_emit_dependency_edges() writes). Reversed tsort order puts
# higher-level subsystems first, matching the "descending topo" policy.
#
# Usage:
# xo-gen-clang-format [EDGES_FILE] > .clang-format
#
# EDGES_FILE defaults to the snapshot installed alongside xo-cmake, so this is
# runnable outside a build tree (e.g. to regenerate .clang-format from
# xo-cmake/etc/xo/subsystem-edges).
set -euo pipefail
# baked at configure time, like xo-deps' INSTALLED_EDGES_FILE
INSTALLED_EDGES_FILE=@CMAKE_INSTALL_FULL_DATADIR@/etc/xo/subsystem-edges
edges_file="${1:-$INSTALLED_EDGES_FILE}"
if [[ ! -r "$edges_file" ]]; then
echo "xo-gen-clang-format: cannot read edges file: $edges_file" >&2
exit 1
fi
# tsort yields dependencies-first (bottom-up); reverse (tac) for descending topo
# order, so higher-level subsystems get earlier categories.
order=$(tsort "$edges_file" | tac)
emit_xo_categories() {
local prio=100
local repo prefix
for repo in $order; do
prefix="${repo#xo-}" # xo-indentlog -> indentlog (=> <xo/indentlog/...>)
printf " - { Regex: '^<xo/%s/',%*sPriority: %d }\n" \
"$prefix" $(( 18 - ${#prefix} > 1 ? 18 - ${#prefix} : 1 )) "" "$prio"
prio=$((prio + 1))
done
}
cat <<'HEADER'
# GENERATED by xo-gen-clang-format. DO NOT EDIT.
#
# Regenerate from the committed snapshot:
# xo-gen-clang-format > .clang-format
# or from a build tree's edge list:
# xo-gen-clang-format path/to/build/subsystem-edges > .clang-format
#
# Only include ordering (+ preprocessor-directive indentation) is specified
# here; other formatting is left to defaults.
Language: Cpp
SortIncludes: CaseSensitive
# Merge (not Regroup): order includes by the categories below in one block,
# without forcing a blank line between every category (per-subsystem categories
# would otherwise scatter blank lines through the xo block).
IncludeBlocks: Merge
IncludeIsMainRegex: '(\.test|_test|_utest)?$'
# Preprocessor-guarded includes: indent one space per nesting level after '#',
# so #ifdef X / # include ... / #endif is preserved (not flattened to #include).
# NB this ENFORCES that indentation on nested #-directives, not just preserves it.
IndentPPDirectives: AfterHash
PPIndentWidth: 1
IncludeCategories:
- { Regex: '^"', Priority: 1 } # self-subsystem (same-repo, quoted)
HEADER
emit_xo_categories
cat <<'TAIL'
- { Regex: '^<xo/', Priority: 500 } # any other xo (fallback / not in graph)
- { Regex: '^<(catch2|pybind11|replxx|Eigen|nlohmann|websocketpp|boost|json)', Priority: 600 } # electives
- { Regex: '^<[A-Za-z0-9_]+>', Priority: 700 } # C++ standard library (angle, no dot/slash)
- { Regex: '^<.*\.h>', Priority: 800 } # platform / C headers
TAIL