From 08098351a9a3adc2c683527dce55eb3e0958339d Mon Sep 17 00:00:00 2001 From: raiden00pl Date: Mon, 27 Jul 2026 12:20:13 +0200 Subject: [PATCH] tools/nxstyle: add a script to check a whole tree at once nxstyle checks one file per invocation. nxstyle_sweep.sh runs it over the directories given, or the whole repository, and collects what it reports. Signed-off-by: raiden00pl Assisted-by: Claude Code --- .../components/tools/nxstyle_sweep.rst | 25 +++ tools/nxstyle_sweep.sh | 189 ++++++++++++++++++ 2 files changed, 214 insertions(+) create mode 100644 Documentation/components/tools/nxstyle_sweep.rst create mode 100755 tools/nxstyle_sweep.sh diff --git a/Documentation/components/tools/nxstyle_sweep.rst b/Documentation/components/tools/nxstyle_sweep.rst new file mode 100644 index 0000000000000..def0e72d5ab70 --- /dev/null +++ b/Documentation/components/tools/nxstyle_sweep.rst @@ -0,0 +1,25 @@ +==================== +``nxstyle_sweep.sh`` +==================== + +Run ``nxstyle`` over whole directories, or over the repository, and collect +what it reports. Usage: + +.. code:: console + + $ tools/nxstyle_sweep.sh [options] [ ...] + + -o Diagnostics (default: nxstyle-errors.txt) + -f Failing files, worst first (default: nxstyle-files.txt) + -l List failing files instead of writing the reports + -s Summarise the diagnostics by message + -b Use an existing nxstyle binary + -j Number of parallel checks + -a Check every file, not only those tracked by git + -h Show this help + +Options must precede the directories, which default to the whole repository +and are relative to its top. The exit status is non-zero if anything was +reported. + +See also ``nxstyle``. diff --git a/tools/nxstyle_sweep.sh b/tools/nxstyle_sweep.sh new file mode 100755 index 0000000000000..e61207e8eea60 --- /dev/null +++ b/tools/nxstyle_sweep.sh @@ -0,0 +1,189 @@ +#!/usr/bin/env bash +############################################################################ +# tools/nxstyle_sweep.sh +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +# Run nxstyle over the whole repository, or over a subdirectory, and collect +# what it reports. +# +# Usage: tools/nxstyle_sweep.sh [options] [ ...] +# +# -o Write the diagnostics to (default: nxstyle-errors.txt) +# -f Write the failing file names, with a count each and worst +# first, to (default: nxstyle-files.txt) +# -l List failing files on stdout instead of writing the reports +# -s Summarise the diagnostics by message on stdout +# -b Use an existing nxstyle binary rather than building one +# -j Run checks in parallel (default: number of CPUs) +# -a Check every file, not only those tracked by git +# -h Show this help +# +# With no directory given the whole repository is checked. Paths are taken +# relative to the top of the repository, as nxstyle verifies the path +# recorded in each file header. +# +# Examples: +# tools/nxstyle_sweep.sh +# tools/nxstyle_sweep.sh -s arch/arm/src/stm32h7 +# tools/nxstyle_sweep.sh -l drivers | head +# tools/nxstyle_sweep.sh -o /tmp/errors.txt arch drivers + +set -u + +tooldir=$(cd "$(dirname "$0")" && pwd) +topdir=$(cd "$tooldir/.." && pwd) + +outfile=nxstyle-errors.txt +filefile=nxstyle-files.txt +listonly=0 +summary=0 +nxstyle= +jobs=$( (nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 4) ) +allfiles=0 +tmpdir= + +usage() +{ + # Print the block of comments that follows the licence header + + awk '/^#####/ { sep++; next } + sep < 2 { next } + /^#/ { line = $0; sub(/^# ?/, "", line); + print line; started = 1; next } + started { exit }' "$0" + exit "${1:-1}" +} + +cleanup() +{ + if [ -n "$tmpdir" ]; then + rm -rf "$tmpdir" + fi +} + +while getopts ":o:f:b:j:lsah" opt; do + case $opt in + o) outfile=$OPTARG ;; + f) filefile=$OPTARG ;; + b) nxstyle=$OPTARG ;; + j) jobs=$OPTARG ;; + l) listonly=1 ;; + s) summary=1 ;; + a) allfiles=1 ;; + h) usage 0 ;; + *) usage ;; + esac +done +shift $((OPTIND - 1)) + +trap cleanup EXIT +tmpdir=$(mktemp -d) + +# Build nxstyle unless an existing binary was given + +if [ -z "$nxstyle" ]; then + nxstyle=$tmpdir/nxstyle + if ! ${CC:-cc} -O2 -o "$nxstyle" "$topdir/tools/nxstyle.c"; then + echo "ERROR: failed to build nxstyle" >&2 + exit 1 + fi +fi + +cd "$topdir" || exit 1 + +# Collect the files to check. Only the sources that nxstyle understands are +# of interest, and by default only those that are tracked by git. + +listing=$tmpdir/files +: > "$listing" + +if [ $# -eq 0 ]; then + set -- . +fi + +for dir in "$@"; do + if [ ! -d "$dir" ]; then + echo "ERROR: no such directory: $dir" >&2 + exit 1 + fi + + if [ "$allfiles" -eq 0 ] && git rev-parse --git-dir >/dev/null 2>&1; then + git ls-files -- "$dir/*.c" "$dir/*.h" >> "$listing" + else + find "$dir" -name '*.c' -o -name '*.h' >> "$listing" + fi +done + +sort -u "$listing" -o "$listing" +total=$(wc -l < "$listing") + +if [ "$total" -eq 0 ]; then + echo "No C sources found" >&2 + exit 1 +fi + +# Check each file, keeping the output of one file together. Writing to a +# file per source and concatenating afterwards avoids the interleaving that +# a shared pipe would produce. + +results=$tmpdir/results +mkdir -p "$results" +export nxstyle results + +# shellcheck disable=SC2016 +xargs -a "$listing" -P "$jobs" -n 1 sh -c ' + out=$("$nxstyle" "$1" 2>&1) + if [ -n "$out" ]; then + printf "%s\n" "$out" > "$results/$(printf "%s" "$1" | tr / _)" + fi + exit 0 +' sh + +collected=$tmpdir/all +cat "$results"/* 2>/dev/null | sed "s#^$topdir/##" | + sort -t: -k1,1 -k2,2n > "$collected" + +ndiag=$(wc -l < "$collected") +nfail=$(cut -d: -f1 "$collected" | sort -u | wc -l) + +if [ "$listonly" -eq 1 ]; then + cut -d: -f1 "$collected" | sort | uniq -c | sort -rn | + awk '{printf "%6d %s\n", $1, $2}' +else + cp "$collected" "$outfile" + cut -d: -f1 "$collected" | sort | uniq -c | sort -rn | + awk '{printf "%6d %s\n", $1, $2}' > "$filefile" + echo "$outfile: $ndiag diagnostics" + echo "$filefile: $nfail files" +fi + +if [ "$summary" -eq 1 ]; then + echo + echo "Diagnostics by message:" + sed 's/.*: \(error\|warning\|info\): //' "$collected" | + sort | uniq -c | sort -rn | awk '{$1=$1; printf "%6d ", $1; + $1=""; sub(/^ /, ""); print}' +fi + +echo +echo "Checked $total files, $nfail failed" + +[ "$ndiag" -eq 0 ]