summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Racine <bass_dr@hotmail.com>2026-06-18 23:22:28 -0400
committerGitHub <noreply@github.com>2026-06-19 03:22:28 +0000
commitd912fd2c016bea51831da922f5f4fd31c14ccab3 (patch)
tree51584b5ba7e25476437ebaf1532485b2608e9180
parent4ea17f6933c931c4438abb0c625598ee046f7ba7 (diff)
docs: document clang-format 14 setup and add an opt-in pre-commit hook (#6741)
Recent distros and Homebrew ship only newer clang-format, so contributors can't easily get the version CI uses (14, matching the OoT/MM decomp). - docs/FORMATTING.md: how to get a 14.x binary (apt, AUR, muttleyxd static binaries, uvx/pipx wheel, brew) and how to run the formatter. - run-clang-format.sh: default to clang-format-14 but honor $CLANG_FORMAT so any matching binary works. Any 14.x produces byte-identical output here. - .pre-commit-config.yaml: opt-in hook to format staged C/C++ on commit. - README: link the new doc. The llvm@14 formula is available on Linux too, so filing it under a macOS-only heading was too narrow. * Support spaced paths in CLANG_FORMAT; document run-clang-format.ps1 eval the clang-format invocation so CLANG_FORMAT can carry arguments (uvx clang-format@14) or a quoted path with spaces without one breaking the other. The NUL-separated file list reaches xargs over the pipe, so filenames never pass through eval. Document the native Windows run-clang-format.ps1 path alongside the Git Bash/WSL route. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
-rw-r--r--.pre-commit-config.yaml10
-rw-r--r--README.md1
-rw-r--r--docs/FORMATTING.md69
-rwxr-xr-xrun-clang-format.sh11
4 files changed, 89 insertions, 2 deletions
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 000000000..634ba48ec
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,10 @@
+# Local clang-format hook: formats staged C/C++ in soh/ on commit, using a
+# pinned 14.x downloaded by pre-commit. Scope matches run-clang-format.sh / CI.
+# pre-commit install --install-hooks # enable (downloads clang-format up front)
+repos:
+ - repo: https://github.com/pre-commit/mirrors-clang-format
+ rev: v14.0.6
+ hooks:
+ - id: clang-format
+ files: '^soh/.*\.(c|cpp|h|hpp)$'
+ exclude: '^soh/assets/|^soh/(src|include)/.*\.(h|hpp)$'
diff --git a/README.md b/README.md
index 50982be53..3ac29e465 100644
--- a/README.md
+++ b/README.md
@@ -104,6 +104,7 @@ More detailed documentation can be found in the 'docs' directory, including the
* [Credits](docs/CREDITS.md)
* [Custom Music](docs/CUSTOM_MUSIC.md)
+* [Formatting](docs/FORMATTING.md)
* [Controller Mapping](docs/GAME_CONTROLLER_DB.md)
* [Modding](docs/MODDING.md)
* [Versioning](docs/VERSIONING.md)
diff --git a/docs/FORMATTING.md b/docs/FORMATTING.md
new file mode 100644
index 000000000..2208c3b3d
--- /dev/null
+++ b/docs/FORMATTING.md
@@ -0,0 +1,69 @@
+# Formatting
+
+Shipwright's C/C++ in `soh/` is formatted with **clang-format 14**, the version
+used by the OoT/MM decompilation that the vendored `soh/src/` tree comes from.
+clang-format's output is not stable across major versions, so the major version
+matters: any **14.x** produces identical output for this tree (verified across
+all formatted files), but clang-format 15+ will reformat differently and fail
+CI. Patch version (14.0.0 vs 14.0.6) does not matter.
+
+## Format the tree
+
+```bash
+./run-clang-format.sh
+```
+
+This formats every C/C++ file in `soh/` in place, skipping the decompiled
+headers (`soh/src`, `soh/include`) and autogenerated assets (`soh/assets`),
+matching what CI checks.
+
+The script calls `clang-format-14` by default. If your clang-format 14 is named
+or located differently, point `CLANG_FORMAT` at it:
+
+```bash
+CLANG_FORMAT=clang-format ./run-clang-format.sh # already 14.x
+CLANG_FORMAT=/path/to/clang-format ./run-clang-format.sh # static binary
+CLANG_FORMAT="uvx clang-format@14" ./run-clang-format.sh # uv wheel
+CLANG_FORMAT='"/path with spaces/cf"' ./run-clang-format.sh # quote a spaced path
+```
+
+`CLANG_FORMAT` is treated as a command line, so it can carry arguments (the `uvx`
+case) or a quoted path containing spaces.
+
+On Windows you have two options. Run `run-clang-format.ps1` from PowerShell: it
+downloads clang-format 14.0.6 itself (needs [7-Zip](https://www.7-zip.org/)
+installed) and formats the same fileset, so you don't have to install
+clang-format or pass `CLANG_FORMAT`. Or run `run-clang-format.sh` from Git Bash
+(ships with Git for Windows) or WSL, since it needs a Unix shell for
+`find`/`xargs`; get the binary from the `uvx` wheel or the Windows static binary
+below.
+
+## Getting clang-format 14
+
+Recent distros and Homebrew often ship only newer clang-format. Any of these
+gives you a 14.x binary:
+
+- **Debian/Ubuntu**: `sudo apt-get install clang-format-14` (where the package
+ still exists).
+- **Arch**: AUR [`clang-format-static-bin`](https://aur.archlinux.org/packages/clang-format-static-bin).
+- **Any Linux/macOS/Windows, no install**: download a static binary from
+ [muttleyxd/clang-tools-static-binaries](https://github.com/muttleyxd/clang-tools-static-binaries/releases/tag/master-796e77c)
+ (e.g. `clang-format-14_linux-amd64`), `chmod +x`, and point `CLANG_FORMAT` at it.
+- **Any OS via a Python wheel**: `uvx clang-format@14` (with
+ [uv](https://docs.astral.sh/uv/)), or `pipx install clang-format==14.0.6`.
+- **Homebrew (macOS or Linux)**: `brew install llvm@14` and use its
+ `clang-format`, or use one of the cross-platform options above.
+
+## Optional: format on commit
+
+The repo ships a [pre-commit](https://pre-commit.com/) config
+(`.pre-commit-config.yaml`) that auto-formats staged C/C++ with a pinned 14.x
+before each commit, so you never get caught by the CI check. With pre-commit
+[installed](https://pre-commit.com/#install), enable it once:
+
+```bash
+pre-commit install --install-hooks
+```
+
+`--install-hooks` downloads clang-format up front so your first commit isn't
+slowed by it.
diff --git a/run-clang-format.sh b/run-clang-format.sh
index 20129e63d..25158178b 100755
--- a/run-clang-format.sh
+++ b/run-clang-format.sh
@@ -1,3 +1,7 @@
+# Default to clang-format-14; override CLANG_FORMAT to use another 14.x binary
+# (distro pkg, muttleyxd static binary, uvx clang-format@14, ...). See docs/FORMATTING.md.
+CLANG_FORMAT="${CLANG_FORMAT:-clang-format-14}"
+
# this line does quite a bit, so let's break it down
#
# find soh
@@ -21,9 +25,12 @@
# -print0
# separate paths with NUL bytes, avoiding issues with spaces in paths
#
-# | xargs -0 clang-format-14 -i -verbose
+# | eval "xargs -0 $CLANG_FORMAT -i --verbose"
# use xargs to take each path we've found
# and pass it as an argument to clang-format
# verbose to print files being formatted and X out of Y status
+# eval so CLANG_FORMAT can carry arguments ("uvx clang-format@14")
+# or a quoted path with spaces; the NUL-separated file list reaches
+# xargs over the pipe, so it never passes through eval
-find soh -type f \( -name "*.c" -o -name "*.cpp" -o \( \( -name "*.h" -o -name "*.hpp" \) ! -path "soh/src/*" ! -path "soh/include/*" \) \) ! -path "soh/assets/*" -print0 | xargs -0 clang-format-14 -i --verbose
+find soh -type f \( -name "*.c" -o -name "*.cpp" -o \( \( -name "*.h" -o -name "*.hpp" \) ! -path "soh/src/*" ! -path "soh/include/*" \) \) ! -path "soh/assets/*" -print0 | eval "xargs -0 $CLANG_FORMAT -i --verbose"