diff --git a/build.sh b/build.sh index d5ac642e..84c7e1c5 100755 --- a/build.sh +++ b/build.sh @@ -13,6 +13,8 @@ usage() { echo " wheel - Build the Python wheel." echo " ctest - Run tests (requires tests to be built)." echo " docstest - Run pytest markdown documentation tests." + echo " black - Run black over Python (matches CI)." + echo " clang-format - Run clang-format over src/ (matches CI)." echo "" echo "Options:" echo " -h, --help Display this help message and exit." @@ -220,7 +222,7 @@ _first_arg_val="$1" BUILD_TYPE="install" # Default build type if [[ -n "$_first_arg_val" ]]; then - if [[ "$_first_arg_val" == "install" || "$_first_arg_val" == "wheel" || "$_first_arg_val" == "ctest" || "$_first_arg_val" == "docstest" ]]; then + if [[ "$_first_arg_val" == "install" || "$_first_arg_val" == "wheel" || "$_first_arg_val" == "ctest" || "$_first_arg_val" == "docstest" || "$_first_arg_val" == "black" || "$_first_arg_val" == "clang-format" ]]; then BUILD_TYPE="$_first_arg_val" shift # Consume the build_type argument else @@ -348,7 +350,15 @@ if [ "$BUILD_TYPE" != "ctest" ] && [ "$BUILD_TYPE" != "docstest" ]; then fi # if the user specified 'wheel' as the build type, then we will build the wheel -if [ "$BUILD_TYPE" == "wheel" ]; then +if [ "$BUILD_TYPE" == "black" ]; then + echo "Running black (matches CI)" + ./src/scripts/run_black.sh + +elif [ "$BUILD_TYPE" == "clang-format" ]; then + echo "Running clang-format (matches CI clangFormatVersion=18, style=file)" + ./src/scripts/run_clang_format.sh + +elif [ "$BUILD_TYPE" == "wheel" ]; then echo "Build wheel" echo "pip wheel . --no-deps --wheel-dir dist/ $PIP_ARGS" run_with_sanitized_paths pip wheel . --no-deps --wheel-dir dist/ $PIP_ARGS @@ -438,6 +448,6 @@ elif [ "$BUILD_TYPE" == "docstest" ]; then else echo "Invalid build/run type: $BUILD_TYPE" - echo "Valid build/run types are: wheel, install, ctest, docstest" + echo "Valid build/run types are: wheel, install, ctest, docstest, black, clang-format" exit 1 fi diff --git a/src/scripts/run_black.sh b/src/scripts/run_black.sh new file mode 100755 index 00000000..8139e8bb --- /dev/null +++ b/src/scripts/run_black.sh @@ -0,0 +1,41 @@ +#!/bin/bash +# Copyright Contributors to the OpenVDB Project +# SPDX-License-Identifier: Apache-2.0 + +set -euo pipefail + +# CI uses psf/black@stable with: +# --check --diff --verbose --target-version=py311 --line-length=120 --extend-exclude='wip/' +# src: "./" +# version: "~= 24.0" +# See: .github/workflows/codestyle.yml + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)" + +MODE="${1:-format}" # "format" (default) or "check" + +if ! python -c "import black" >/dev/null 2>&1; then + echo "Error: black is not installed in this Python environment." + echo "Install with:" + echo " python -m pip install -U \"black~=24.0\"" + exit 127 +fi + +COMMON_ARGS=( + --target-version=py311 + --line-length=120 + --extend-exclude=wip/ +) + +pushd "${REPO_ROOT}" >/dev/null +if [[ "${MODE}" == "check" ]]; then + python -m black --check --diff --verbose "${COMMON_ARGS[@]}" ./ +elif [[ "${MODE}" == "format" ]]; then + python -m black "${COMMON_ARGS[@]}" ./ +else + echo "Error: unknown mode '${MODE}'. Expected 'format' or 'check'." + exit 2 +fi +popd >/dev/null + diff --git a/src/scripts/run_clang_format.sh b/src/scripts/run_clang_format.sh index 22e71646..bd6a17ad 100755 --- a/src/scripts/run_clang_format.sh +++ b/src/scripts/run_clang_format.sh @@ -1,30 +1,52 @@ +#!/bin/bash # Copyright Contributors to the OpenVDB Project # SPDX-License-Identifier: Apache-2.0 -#!/bin/bash - -format_files() { - find . -type f \( -name "*.cpp" -o -name "*.h" -o -name "*.hpp" -o -name "*.cu" -o -name "*.cuh" \) -exec clang-format -i {} + +set -euo pipefail + +# CI uses clang-format v18 with style=file on src/ for: +# h,cpp,cc,cu,cuh +# See: .github/workflows/codestyle.yml + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +SRC_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)" + +CLANG_FORMAT_BIN="${CLANG_FORMAT_BIN:-}" +if [[ -z "${CLANG_FORMAT_BIN}" ]]; then + if command -v clang-format-18 >/dev/null 2>&1; then + CLANG_FORMAT_BIN="clang-format-18" + elif command -v clang-format >/dev/null 2>&1; then + CLANG_FORMAT_BIN="clang-format" + else + echo "Error: clang-format not found in PATH." + echo "" + echo "CI uses clang-format v18. To match CI locally, either:" + echo " - run inside your conda env: conda run -n fvdb ./build.sh clang-format" + echo " - or install clang-format-18 and re-run." + exit 127 + fi +else + if ! command -v "${CLANG_FORMAT_BIN}" >/dev/null 2>&1; then + echo "Error: CLANG_FORMAT_BIN='${CLANG_FORMAT_BIN}' not found in PATH." + exit 127 + fi +fi + +echo "Using ${CLANG_FORMAT_BIN} ($(${CLANG_FORMAT_BIN} --version | head -n 1))" + +format_files_in_dir() { + local target_dir="$1" + pushd "${target_dir}" >/dev/null + # Use print0/xargs -0 to safely handle spaces. + find . -type f \( -name "*.cpp" -o -name "*.cc" -o -name "*.h" -o -name "*.hpp" -o -name "*.cu" -o -name "*.cuh" \) -print0 \ + | xargs -0 "${CLANG_FORMAT_BIN}" -i -style=file + popd >/dev/null } -pushd ../benchmarks -format_files -popd - -pushd ../dispatch -format_files -popd - -pushd ../fvdb -format_files -popd - -pushd ../python -format_files -popd - -pushd ../tests -format_files -popd +format_files_in_dir "${SRC_DIR}/benchmarks" +format_files_in_dir "${SRC_DIR}/dispatch" +format_files_in_dir "${SRC_DIR}/fvdb" +format_files_in_dir "${SRC_DIR}/python" +format_files_in_dir "${SRC_DIR}/tests"