From 45436aa6841131ecc43af7ffb152b49415100f0d Mon Sep 17 00:00:00 2001 From: sentomk Date: Sat, 20 Sep 2025 17:40:42 +0800 Subject: [PATCH 01/17] ci: add GitHub Actions workflows (C++17/20/23 matrix) --- .github/workflows/ci-full.yml | 0 .github/workflows/ci-pr.yml | 0 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 .github/workflows/ci-full.yml create mode 100644 .github/workflows/ci-pr.yml diff --git a/.github/workflows/ci-full.yml b/.github/workflows/ci-full.yml new file mode 100644 index 00000000..e69de29b diff --git a/.github/workflows/ci-pr.yml b/.github/workflows/ci-pr.yml new file mode 100644 index 00000000..e69de29b From fb849f2a54bfe287fae57951206094dbd6b20081 Mon Sep 17 00:00:00 2001 From: sentomk Date: Sat, 20 Sep 2025 17:43:04 +0800 Subject: [PATCH 02/17] ci(workflow): update --- .github/workflows/ci-full.yml | 168 ++++++++++++++++++++++++++++++++++ .github/workflows/ci-pr.yml | 129 ++++++++++++++++++++++++++ 2 files changed, 297 insertions(+) diff --git a/.github/workflows/ci-full.yml b/.github/workflows/ci-full.yml index e69de29b..90d4d417 100644 --- a/.github/workflows/ci-full.yml +++ b/.github/workflows/ci-full.yml @@ -0,0 +1,168 @@ +name: CI - Full (C++17/20/23 matrix) + +on: + push: + branches: + - main + workflow_dispatch: + schedule: + - cron: '0 3 * * 1' # weekly (UTC) + +jobs: + build-matrix: + name: Build & Test (${{ matrix.os }} / ${{ matrix.compiler }} / c++${{ matrix.cpp_std }}) + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + # same include list as ci-pr.yml (copy/paste) + - os: ubuntu-latest + compiler: gcc + cpp_std: 17 + - os: ubuntu-latest + compiler: gcc + cpp_std: 20 + - os: ubuntu-latest + compiler: gcc + cpp_std: 23 + - os: ubuntu-latest + compiler: clang + cpp_std: 17 + - os: ubuntu-latest + compiler: clang + cpp_std: 20 + - os: ubuntu-latest + compiler: clang + cpp_std: 23 + - os: macos-latest + compiler: clang + cpp_std: 17 + - os: macos-latest + compiler: clang + cpp_std: 20 + - os: macos-latest + compiler: clang + cpp_std: 23 + - os: windows-latest + compiler: msvc + cpp_std: 17 + - os: windows-latest + compiler: msvc + cpp_std: 20 + - os: windows-latest + compiler: msvc + cpp_std: 23 + + steps: + - uses: actions/checkout@v4 + + - name: Cache build dir + uses: actions/cache@v4 + with: + path: build + key: full-${{ runner.os }}-cmake-${{ matrix.compiler }}-std${{ matrix.cpp_std }}-${{ hashFiles('**/CMakeLists.txt') }} + restore-keys: | + full-${{ runner.os }}-cmake-${{ matrix.compiler }}-std${{ matrix.cpp_std }}- + + - name: Prepare (Linux/macOS) + if: runner.os != 'Windows' + run: | + sudo apt-get update -y || true + sudo apt-get install -y ninja-build ccache || true + + - name: Configure + if: runner.os != 'Windows' + env: + CC: ${{ matrix.compiler == 'clang' && 'clang' || 'gcc' }} + CXX: ${{ matrix.compiler == 'clang' && 'clang++' || 'g++' }} + run: | + cmake -S . -B build \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_CXX_STANDARD=${{ matrix.cpp_std }} \ + -DCMAKE_CXX_STANDARD_REQUIRED=ON \ + -DBUILD_TESTS=ON \ + -DBUILD_BENCHMARKS=ON + - name: Configure (Windows) + if: runner.os == 'Windows' + run: | + powershell -Command "cmake -S . -B build -G 'Visual Studio 17 2022' -A x64 -DCMAKE_CXX_STANDARD=${{ matrix.cpp_std }} -DBUILD_TESTS=ON -DBUILD_BENCHMARKS=ON" + + - name: Build + if: runner.os != 'Windows' + run: cmake --build build --parallel + - name: Build (Windows) + if: runner.os == 'Windows' + run: powershell -Command "cmake --build build --config Release --parallel" + + - name: Run tests + if: runner.os != 'Windows' + run: | + if [ -f build/CTestTestfile.cmake ]; then + pushd build + ctest --output-on-failure --parallel || (cat Testing/Temporary/LastTest.log || true; exit 1) + popd + else + echo "No tests." + fi + shell: bash + + - name: Run tests (Windows) + if: runner.os == 'Windows' + run: | + if (Test-Path build/CTestTestfile.cmake) { + Push-Location build + ctest --config Release --output-on-failure --parallel + Pop-Location + } else { + Write-Host "No tests configured." + } + shell: pwsh + + - name: Upload build artifact (success) + if: success() + uses: actions/upload-artifact@v4 + with: + name: build-${{ matrix.os }}-${{ matrix.compiler }}-std${{ matrix.cpp_std }} + path: build + + clang-format-check: + name: clang-format check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install clang-format + run: sudo apt-get update -y && sudo apt-get install -y clang-format + - name: Check formatting + run: | + files=$(git ls-files '*.hpp' '*.h' '*.cpp' '*.c' | xargs) + if [ -z "$files" ]; then echo "No source files"; exit 0; fi + bad=0 + for f in $files; do + if ! clang-format -style=file "$f" | diff -u "$f" - >/dev/null; then + echo "Not formatted: $f" + bad=1 + fi + done + if [ $bad -ne 0 ]; then + echo "Run clang-format -i on reported files." + exit 2 + fi + + clang-tidy-scan: + name: clang-tidy (quick) + runs-on: ubuntu-latest + needs: build-matrix + steps: + - uses: actions/checkout@v4 + - name: Install clang-tidy + run: sudo apt-get update -y && sudo apt-get install -y clang-tidy + - name: Configure compile_commands.json + run: cmake -S . -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_CXX_STANDARD=23 -DBUILD_TESTS=OFF + - name: Run clang-tidy on headers (limited) + run: | + if [ -f build/compile_commands.json ]; then + find include -name '*.hpp' -or -name '*.h' | head -n 50 | xargs -r clang-tidy -p build || true + else + echo "No compile_commands.json; skipping" + fi diff --git a/.github/workflows/ci-pr.yml b/.github/workflows/ci-pr.yml index e69de29b..07d7409a 100644 --- a/.github/workflows/ci-pr.yml +++ b/.github/workflows/ci-pr.yml @@ -0,0 +1,129 @@ +name: CI - PR (C++17/20/23 matrix) + +on: + pull_request: + push: + branches: + - main + +jobs: + build: + name: Build & Test (${{ matrix.os }} / ${{ matrix.compiler }} / c++${{ matrix.cpp_std }}) + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + # Linux - gcc / clang + - os: ubuntu-latest + compiler: gcc + cpp_std: 17 + - os: ubuntu-latest + compiler: gcc + cpp_std: 20 + - os: ubuntu-latest + compiler: gcc + cpp_std: 23 + - os: ubuntu-latest + compiler: clang + cpp_std: 17 + - os: ubuntu-latest + compiler: clang + cpp_std: 20 + - os: ubuntu-latest + compiler: clang + cpp_std: 23 + + # macOS - clang + - os: macos-latest + compiler: clang + cpp_std: 17 + - os: macos-latest + compiler: clang + cpp_std: 20 + - os: macos-latest + compiler: clang + cpp_std: 23 + + # Windows - MSVC (Visual Studio) + - os: windows-latest + compiler: msvc + cpp_std: 17 + - os: windows-latest + compiler: msvc + cpp_std: 20 + - os: windows-latest + compiler: msvc + cpp_std: 23 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup cache (build) + uses: actions/cache@v4 + with: + path: build + key: ${{ runner.os }}-cmake-${{ matrix.compiler }}-std${{ matrix.cpp_std }}-${{ hashFiles('**/CMakeLists.txt') }} + restore-keys: | + ${{ runner.os }}-cmake-${{ matrix.compiler }}-std${{ matrix.cpp_std }}- + + - name: Prepare toolchain (Linux/macOS) + if: runner.os != 'Windows' + run: | + sudo apt-get update -y || true + # basic helpers; on macOS these cmds are no-ops + sudo apt-get install -y ninja-build ccache || true + + - name: Configure & build (Linux/macOS) + if: runner.os != 'Windows' + env: + CC: ${{ matrix.compiler == 'clang' && 'clang' || 'gcc' }} + CXX: ${{ matrix.compiler == 'clang' && 'clang++' || 'g++' }} + run: | + mkdir -p build + cmake -S . -B build \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_CXX_STANDARD=${{ matrix.cpp_std }} \ + -DCMAKE_CXX_STANDARD_REQUIRED=ON \ + -DBUILD_TESTS=ON + cmake --build build --parallel + shell: bash + + - name: Configure & build (Windows - MSVC) + if: runner.os == 'Windows' + run: | + powershell -Command "cmake -S . -B build -G 'Visual Studio 17 2022' -A x64 -DCMAKE_CXX_STANDARD=${{ matrix.cpp_std }} -DBUILD_TESTS=ON" + powershell -Command "cmake --build build --config Release --parallel" + shell: pwsh + + - name: Run tests (if any) - Linux/macOS + if: runner.os != 'Windows' + run: | + if [ -f build/CTestTestfile.cmake ]; then + pushd build + ctest --output-on-failure --parallel || (cat Testing/Temporary/LastTest.log || true; exit 1) + popd + else + echo "No tests configured." + fi + shell: bash + + - name: Run tests (if any) - Windows + if: runner.os == 'Windows' + run: | + if (Test-Path build/CTestTestfile.cmake) { + Push-Location build + ctest --config Release --output-on-failure --parallel + Pop-Location + } else { + Write-Host "No tests configured." + } + shell: pwsh + + - name: Upload build artifact on failure + if: failure() + uses: actions/upload-artifact@v4 + with: + name: build-${{ matrix.os }}-${{ matrix.compiler }}-std${{ matrix.cpp_std }} + path: build || . From a90440b59f35f25f6992d3bb4c39d9299a2d0e47 Mon Sep 17 00:00:00 2001 From: sentomk Date: Sat, 20 Sep 2025 17:48:15 +0800 Subject: [PATCH 03/17] ci(workflow): update ci-full --- .github/workflows/ci-full.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci-full.yml b/.github/workflows/ci-full.yml index 90d4d417..52554b90 100644 --- a/.github/workflows/ci-full.yml +++ b/.github/workflows/ci-full.yml @@ -4,6 +4,8 @@ on: push: branches: - main + - ci/workflows + workflow_dispatch: schedule: - cron: '0 3 * * 1' # weekly (UTC) From 776c9f622bb6454dec408c11c33884119968c954 Mon Sep 17 00:00:00 2001 From: sentomk Date: Sat, 20 Sep 2025 17:40:42 +0800 Subject: [PATCH 04/17] ci: add GitHub Actions workflows (C++17/20/23 matrix) --- .github/workflows/ci-full.yml | 0 .github/workflows/ci-pr.yml | 0 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 .github/workflows/ci-full.yml create mode 100644 .github/workflows/ci-pr.yml diff --git a/.github/workflows/ci-full.yml b/.github/workflows/ci-full.yml new file mode 100644 index 00000000..e69de29b diff --git a/.github/workflows/ci-pr.yml b/.github/workflows/ci-pr.yml new file mode 100644 index 00000000..e69de29b From 86362b41c2f72e1450a88444b1359ea218448c10 Mon Sep 17 00:00:00 2001 From: sentomk Date: Sat, 20 Sep 2025 17:43:04 +0800 Subject: [PATCH 05/17] ci(workflow): update --- .github/workflows/ci-full.yml | 168 ++++++++++++++++++++++++++++++++++ .github/workflows/ci-pr.yml | 129 ++++++++++++++++++++++++++ 2 files changed, 297 insertions(+) diff --git a/.github/workflows/ci-full.yml b/.github/workflows/ci-full.yml index e69de29b..90d4d417 100644 --- a/.github/workflows/ci-full.yml +++ b/.github/workflows/ci-full.yml @@ -0,0 +1,168 @@ +name: CI - Full (C++17/20/23 matrix) + +on: + push: + branches: + - main + workflow_dispatch: + schedule: + - cron: '0 3 * * 1' # weekly (UTC) + +jobs: + build-matrix: + name: Build & Test (${{ matrix.os }} / ${{ matrix.compiler }} / c++${{ matrix.cpp_std }}) + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + # same include list as ci-pr.yml (copy/paste) + - os: ubuntu-latest + compiler: gcc + cpp_std: 17 + - os: ubuntu-latest + compiler: gcc + cpp_std: 20 + - os: ubuntu-latest + compiler: gcc + cpp_std: 23 + - os: ubuntu-latest + compiler: clang + cpp_std: 17 + - os: ubuntu-latest + compiler: clang + cpp_std: 20 + - os: ubuntu-latest + compiler: clang + cpp_std: 23 + - os: macos-latest + compiler: clang + cpp_std: 17 + - os: macos-latest + compiler: clang + cpp_std: 20 + - os: macos-latest + compiler: clang + cpp_std: 23 + - os: windows-latest + compiler: msvc + cpp_std: 17 + - os: windows-latest + compiler: msvc + cpp_std: 20 + - os: windows-latest + compiler: msvc + cpp_std: 23 + + steps: + - uses: actions/checkout@v4 + + - name: Cache build dir + uses: actions/cache@v4 + with: + path: build + key: full-${{ runner.os }}-cmake-${{ matrix.compiler }}-std${{ matrix.cpp_std }}-${{ hashFiles('**/CMakeLists.txt') }} + restore-keys: | + full-${{ runner.os }}-cmake-${{ matrix.compiler }}-std${{ matrix.cpp_std }}- + + - name: Prepare (Linux/macOS) + if: runner.os != 'Windows' + run: | + sudo apt-get update -y || true + sudo apt-get install -y ninja-build ccache || true + + - name: Configure + if: runner.os != 'Windows' + env: + CC: ${{ matrix.compiler == 'clang' && 'clang' || 'gcc' }} + CXX: ${{ matrix.compiler == 'clang' && 'clang++' || 'g++' }} + run: | + cmake -S . -B build \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_CXX_STANDARD=${{ matrix.cpp_std }} \ + -DCMAKE_CXX_STANDARD_REQUIRED=ON \ + -DBUILD_TESTS=ON \ + -DBUILD_BENCHMARKS=ON + - name: Configure (Windows) + if: runner.os == 'Windows' + run: | + powershell -Command "cmake -S . -B build -G 'Visual Studio 17 2022' -A x64 -DCMAKE_CXX_STANDARD=${{ matrix.cpp_std }} -DBUILD_TESTS=ON -DBUILD_BENCHMARKS=ON" + + - name: Build + if: runner.os != 'Windows' + run: cmake --build build --parallel + - name: Build (Windows) + if: runner.os == 'Windows' + run: powershell -Command "cmake --build build --config Release --parallel" + + - name: Run tests + if: runner.os != 'Windows' + run: | + if [ -f build/CTestTestfile.cmake ]; then + pushd build + ctest --output-on-failure --parallel || (cat Testing/Temporary/LastTest.log || true; exit 1) + popd + else + echo "No tests." + fi + shell: bash + + - name: Run tests (Windows) + if: runner.os == 'Windows' + run: | + if (Test-Path build/CTestTestfile.cmake) { + Push-Location build + ctest --config Release --output-on-failure --parallel + Pop-Location + } else { + Write-Host "No tests configured." + } + shell: pwsh + + - name: Upload build artifact (success) + if: success() + uses: actions/upload-artifact@v4 + with: + name: build-${{ matrix.os }}-${{ matrix.compiler }}-std${{ matrix.cpp_std }} + path: build + + clang-format-check: + name: clang-format check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install clang-format + run: sudo apt-get update -y && sudo apt-get install -y clang-format + - name: Check formatting + run: | + files=$(git ls-files '*.hpp' '*.h' '*.cpp' '*.c' | xargs) + if [ -z "$files" ]; then echo "No source files"; exit 0; fi + bad=0 + for f in $files; do + if ! clang-format -style=file "$f" | diff -u "$f" - >/dev/null; then + echo "Not formatted: $f" + bad=1 + fi + done + if [ $bad -ne 0 ]; then + echo "Run clang-format -i on reported files." + exit 2 + fi + + clang-tidy-scan: + name: clang-tidy (quick) + runs-on: ubuntu-latest + needs: build-matrix + steps: + - uses: actions/checkout@v4 + - name: Install clang-tidy + run: sudo apt-get update -y && sudo apt-get install -y clang-tidy + - name: Configure compile_commands.json + run: cmake -S . -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_CXX_STANDARD=23 -DBUILD_TESTS=OFF + - name: Run clang-tidy on headers (limited) + run: | + if [ -f build/compile_commands.json ]; then + find include -name '*.hpp' -or -name '*.h' | head -n 50 | xargs -r clang-tidy -p build || true + else + echo "No compile_commands.json; skipping" + fi diff --git a/.github/workflows/ci-pr.yml b/.github/workflows/ci-pr.yml index e69de29b..07d7409a 100644 --- a/.github/workflows/ci-pr.yml +++ b/.github/workflows/ci-pr.yml @@ -0,0 +1,129 @@ +name: CI - PR (C++17/20/23 matrix) + +on: + pull_request: + push: + branches: + - main + +jobs: + build: + name: Build & Test (${{ matrix.os }} / ${{ matrix.compiler }} / c++${{ matrix.cpp_std }}) + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + # Linux - gcc / clang + - os: ubuntu-latest + compiler: gcc + cpp_std: 17 + - os: ubuntu-latest + compiler: gcc + cpp_std: 20 + - os: ubuntu-latest + compiler: gcc + cpp_std: 23 + - os: ubuntu-latest + compiler: clang + cpp_std: 17 + - os: ubuntu-latest + compiler: clang + cpp_std: 20 + - os: ubuntu-latest + compiler: clang + cpp_std: 23 + + # macOS - clang + - os: macos-latest + compiler: clang + cpp_std: 17 + - os: macos-latest + compiler: clang + cpp_std: 20 + - os: macos-latest + compiler: clang + cpp_std: 23 + + # Windows - MSVC (Visual Studio) + - os: windows-latest + compiler: msvc + cpp_std: 17 + - os: windows-latest + compiler: msvc + cpp_std: 20 + - os: windows-latest + compiler: msvc + cpp_std: 23 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup cache (build) + uses: actions/cache@v4 + with: + path: build + key: ${{ runner.os }}-cmake-${{ matrix.compiler }}-std${{ matrix.cpp_std }}-${{ hashFiles('**/CMakeLists.txt') }} + restore-keys: | + ${{ runner.os }}-cmake-${{ matrix.compiler }}-std${{ matrix.cpp_std }}- + + - name: Prepare toolchain (Linux/macOS) + if: runner.os != 'Windows' + run: | + sudo apt-get update -y || true + # basic helpers; on macOS these cmds are no-ops + sudo apt-get install -y ninja-build ccache || true + + - name: Configure & build (Linux/macOS) + if: runner.os != 'Windows' + env: + CC: ${{ matrix.compiler == 'clang' && 'clang' || 'gcc' }} + CXX: ${{ matrix.compiler == 'clang' && 'clang++' || 'g++' }} + run: | + mkdir -p build + cmake -S . -B build \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_CXX_STANDARD=${{ matrix.cpp_std }} \ + -DCMAKE_CXX_STANDARD_REQUIRED=ON \ + -DBUILD_TESTS=ON + cmake --build build --parallel + shell: bash + + - name: Configure & build (Windows - MSVC) + if: runner.os == 'Windows' + run: | + powershell -Command "cmake -S . -B build -G 'Visual Studio 17 2022' -A x64 -DCMAKE_CXX_STANDARD=${{ matrix.cpp_std }} -DBUILD_TESTS=ON" + powershell -Command "cmake --build build --config Release --parallel" + shell: pwsh + + - name: Run tests (if any) - Linux/macOS + if: runner.os != 'Windows' + run: | + if [ -f build/CTestTestfile.cmake ]; then + pushd build + ctest --output-on-failure --parallel || (cat Testing/Temporary/LastTest.log || true; exit 1) + popd + else + echo "No tests configured." + fi + shell: bash + + - name: Run tests (if any) - Windows + if: runner.os == 'Windows' + run: | + if (Test-Path build/CTestTestfile.cmake) { + Push-Location build + ctest --config Release --output-on-failure --parallel + Pop-Location + } else { + Write-Host "No tests configured." + } + shell: pwsh + + - name: Upload build artifact on failure + if: failure() + uses: actions/upload-artifact@v4 + with: + name: build-${{ matrix.os }}-${{ matrix.compiler }}-std${{ matrix.cpp_std }} + path: build || . From 43135a0d29816a6b54e6963875a918c081d0b1b0 Mon Sep 17 00:00:00 2001 From: sentomk Date: Sat, 20 Sep 2025 17:48:15 +0800 Subject: [PATCH 06/17] ci(workflow): update ci-full --- .github/workflows/ci-full.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci-full.yml b/.github/workflows/ci-full.yml index 90d4d417..52554b90 100644 --- a/.github/workflows/ci-full.yml +++ b/.github/workflows/ci-full.yml @@ -4,6 +4,8 @@ on: push: branches: - main + - ci/workflows + workflow_dispatch: schedule: - cron: '0 3 * * 1' # weekly (UTC) From 7cfbeca66df1569d3e2a5045c0289ea92495bdec Mon Sep 17 00:00:00 2001 From: sentomk Date: Sat, 20 Sep 2025 18:12:57 +0800 Subject: [PATCH 07/17] update .gitignore --- .gitignore | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 83 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 56eaf55f..51d0dcbc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,86 @@ -* +# === build artifacts === +# generic build dirs +/build/ +**/build/ +cmake-build-*/ +out/ +bin/ -!.gitignore -!.clang-format -!CMakeLists.txt -!README.md +# object / temporary files +*.o +*.obj +*.lo +*.la + +# libraries / executables +*.so +*.a +*.lib +*.dll +*.exe + +# === CMake / IDE === +CMakeFiles/ +CMakeCache.txt +cmake_install.cmake +install_manifest.txt + +# IDEs / editors +.vscode/ +.idea/ +*.sublime-project +*.sublime-workspace + +# === OS === +.DS_Store +Thumbs.db + +# === tooling caches === +# ccache +.ccache/ +.cache/ +# pip / python envs +venv/ +.env +__pycache__/ + +# === CI runtime results and logs (do NOT commit) === +# local CI results produced by scripts / workflows +ci/results/ +ci/*.log +*.log +*.xml + +# test & coverage outputs +coverage/ +coverage.info +*.gcda +*.gcno +*.gcov + +# sanitizer outputs +*.san +asan.log + +# packaging / temp +*.tar.gz +*.zip +*.tar +*.egg-info + +# node / npm (if repo has front-end/tools) +node_modules/ + +# secrets / user config (safety) +secrets.yml +*.key +*.pem + +# Keep repo files that should still be tracked (explicit allows) +!/.gitignore +!/.clang-format +!/CMakeLists.txt +!/README.md !include !src @@ -15,4 +92,4 @@ !src/** !tests/** !benchmarks/** -!cmake/** \ No newline at end of file +!cmake/** From bbce03cf55dc74a4e13b53c4cc08d73a519c82db Mon Sep 17 00:00:00 2001 From: Yingfan Guo <115908952+sentomk@users.noreply.github.com> Date: Sun, 21 Sep 2025 00:30:47 +0800 Subject: [PATCH 08/17] Update ci-full.yml --- .github/workflows/ci-full.yml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci-full.yml b/.github/workflows/ci-full.yml index 52554b90..7b99fff4 100644 --- a/.github/workflows/ci-full.yml +++ b/.github/workflows/ci-full.yml @@ -97,17 +97,17 @@ jobs: if: runner.os == 'Windows' run: powershell -Command "cmake --build build --config Release --parallel" - - name: Run tests - if: runner.os != 'Windows' + - name: Run tests (Windows) + if: runner.os == 'Windows' run: | - if [ -f build/CTestTestfile.cmake ]; then - pushd build - ctest --output-on-failure --parallel || (cat Testing/Temporary/LastTest.log || true; exit 1) - popd - else - echo "No tests." - fi - shell: bash + if (Test-Path build/CTestTestfile.cmake) { + Push-Location build + ctest -C Release --output-on-failure --parallel + Pop-Location + } else { + Write-Host "No tests configured." + } + shell: pwsh - name: Run tests (Windows) if: runner.os == 'Windows' From 497e37b99269535dfb19f65b754e0b349ffa9cd1 Mon Sep 17 00:00:00 2001 From: Yingfan Guo <115908952+sentomk@users.noreply.github.com> Date: Sun, 21 Sep 2025 00:34:18 +0800 Subject: [PATCH 09/17] Update ci-full.yml --- .github/workflows/ci-full.yml | 141 +++++++++++++++++++++++++--------- 1 file changed, 103 insertions(+), 38 deletions(-) diff --git a/.github/workflows/ci-full.yml b/.github/workflows/ci-full.yml index 7b99fff4..77ae5dba 100644 --- a/.github/workflows/ci-full.yml +++ b/.github/workflows/ci-full.yml @@ -5,7 +5,6 @@ on: branches: - main - ci/workflows - workflow_dispatch: schedule: - cron: '0 3 * * 1' # weekly (UTC) @@ -18,7 +17,7 @@ jobs: fail-fast: false matrix: include: - # same include list as ci-pr.yml (copy/paste) + # Ubuntu - gcc/clang - os: ubuntu-latest compiler: gcc cpp_std: 17 @@ -37,6 +36,7 @@ jobs: - os: ubuntu-latest compiler: clang cpp_std: 23 + # macOS - clang (AppleClang) - os: macos-latest compiler: clang cpp_std: 17 @@ -46,6 +46,7 @@ jobs: - os: macos-latest compiler: clang cpp_std: 23 + # Windows - MSVC - os: windows-latest compiler: msvc cpp_std: 17 @@ -58,87 +59,141 @@ jobs: steps: - uses: actions/checkout@v4 + with: + submodules: recursive + fetch-depth: 0 - name: Cache build dir uses: actions/cache@v4 with: path: build - key: full-${{ runner.os }}-cmake-${{ matrix.compiler }}-std${{ matrix.cpp_std }}-${{ hashFiles('**/CMakeLists.txt') }} + key: full-${{ runner.os }}-cmake-${{ matrix.compiler }}-std${{ matrix.cpp_std }}-${{ hashFiles('**/CMakeLists.txt', '**/*.cmake') }} restore-keys: | full-${{ runner.os }}-cmake-${{ matrix.compiler }}-std${{ matrix.cpp_std }}- - - name: Prepare (Linux/macOS) - if: runner.os != 'Windows' + # ----------------------------- + # Dependencies per platform + # ----------------------------- + - name: Prepare (Ubuntu) + if: runner.os == 'Linux' + run: | + sudo apt-get update -y + sudo apt-get install -y ninja-build ccache + # clang/gcc 通常已预装;如需特定版本可在这里安装 + + - name: Prepare (macOS) + if: runner.os == 'macOS' run: | - sudo apt-get update -y || true - sudo apt-get install -y ninja-build ccache || true + brew update + brew install ninja || true - - name: Configure + # ----------------------------- + # Configure + # ----------------------------- + - name: Configure (Linux/macOS, Ninja single-config) if: runner.os != 'Windows' - env: - CC: ${{ matrix.compiler == 'clang' && 'clang' || 'gcc' }} - CXX: ${{ matrix.compiler == 'clang' && 'clang++' || 'g++' }} + shell: bash run: | - cmake -S . -B build \ + set -euxo pipefail + if [ "${{ matrix.compiler }}" = "clang" ]; then + export CC=clang + export CXX=clang++ + else + export CC=gcc + export CXX=g++ + fi + cmake -S . -B build -G Ninja \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_CXX_STANDARD=${{ matrix.cpp_std }} \ -DCMAKE_CXX_STANDARD_REQUIRED=ON \ + -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ -DBUILD_TESTS=ON \ -DBUILD_BENCHMARKS=ON - - name: Configure (Windows) + + - name: Configure (Windows, Visual Studio multi-config) if: runner.os == 'Windows' - run: | - powershell -Command "cmake -S . -B build -G 'Visual Studio 17 2022' -A x64 -DCMAKE_CXX_STANDARD=${{ matrix.cpp_std }} -DBUILD_TESTS=ON -DBUILD_BENCHMARKS=ON" + shell: pwsh + run: > + cmake -S . -B build + -G "Visual Studio 17 2022" + -A x64 + -DCMAKE_CXX_STANDARD=${{ matrix.cpp_std }} + -DCMAKE_EXPORT_COMPILE_COMMANDS=ON + -DBUILD_TESTS=ON + -DBUILD_BENCHMARKS=ON - - name: Build + # ----------------------------- + # Build + # ----------------------------- + - name: Build (Linux/macOS) if: runner.os != 'Windows' run: cmake --build build --parallel + - name: Build (Windows) if: runner.os == 'Windows' - run: powershell -Command "cmake --build build --config Release --parallel" + shell: pwsh + run: cmake --build build --config Release --parallel - - name: Run tests (Windows) - if: runner.os == 'Windows' + # ----------------------------- + # Test + # ----------------------------- + - name: Run tests (Linux/macOS) + if: runner.os != 'Windows' + shell: bash run: | - if (Test-Path build/CTestTestfile.cmake) { - Push-Location build - ctest -C Release --output-on-failure --parallel - Pop-Location - } else { - Write-Host "No tests configured." - } - shell: pwsh + set -euxo pipefail + if [ -f build/CTestTestfile.cmake ]; then + pushd build + ctest --output-on-failure --parallel + popd + else + echo "No tests configured." + fi - name: Run tests (Windows) if: runner.os == 'Windows' + shell: pwsh run: | if (Test-Path build/CTestTestfile.cmake) { Push-Location build - ctest --config Release --output-on-failure --parallel + # 注意:ctest 在多配置生成器下应使用 -C,而不是 --config + ctest -C Release --output-on-failure --parallel Pop-Location } else { Write-Host "No tests configured." } - shell: pwsh - - name: Upload build artifact (success) - if: success() + # ----------------------------- + # Artifacts + # ----------------------------- + - name: Upload build artifact (always) + if: always() uses: actions/upload-artifact@v4 with: name: build-${{ matrix.os }}-${{ matrix.compiler }}-std${{ matrix.cpp_std }} path: build + # ----------------------------------------- + # clang-format style check + # ----------------------------------------- clang-format-check: name: clang-format check runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install clang-format - run: sudo apt-get update -y && sudo apt-get install -y clang-format + run: | + sudo apt-get update -y + sudo apt-get install -y clang-format - name: Check formatting + shell: bash run: | - files=$(git ls-files '*.hpp' '*.h' '*.cpp' '*.c' | xargs) - if [ -z "$files" ]; then echo "No source files"; exit 0; fi + set -euxo pipefail + files="$(git ls-files '*.hpp' '*.h' '*.cpp' '*.c' | xargs || true)" + if [ -z "$files" ]; then + echo "No source files" + exit 0 + fi bad=0 for f in $files; do if ! clang-format -style=file "$f" | diff -u "$f" - >/dev/null; then @@ -151,6 +206,9 @@ jobs: exit 2 fi + # ----------------------------------------- + # clang-tidy (quick scan on part of headers) + # ----------------------------------------- clang-tidy-scan: name: clang-tidy (quick) runs-on: ubuntu-latest @@ -158,13 +216,20 @@ jobs: steps: - uses: actions/checkout@v4 - name: Install clang-tidy - run: sudo apt-get update -y && sudo apt-get install -y clang-tidy - - name: Configure compile_commands.json - run: cmake -S . -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_CXX_STANDARD=23 -DBUILD_TESTS=OFF + run: | + sudo apt-get update -y + sudo apt-get install -y clang-tidy + - name: Configure compile_commands.json (Ninja) + run: | + cmake -S . -B build -G Ninja \ + -DCMAKE_CXX_STANDARD=23 \ + -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ + -DBUILD_TESTS=OFF \ + -DBUILD_BENCHMARKS=OFF - name: Run clang-tidy on headers (limited) run: | if [ -f build/compile_commands.json ]; then - find include -name '*.hpp' -or -name '*.h' | head -n 50 | xargs -r clang-tidy -p build || true + find include -type f \( -name '*.hpp' -o -name '*.h' \) | head -n 50 | xargs -r clang-tidy -p build || true else echo "No compile_commands.json; skipping" fi From 3fedcdcb645625d541af92231b598758aa586e0f Mon Sep 17 00:00:00 2001 From: Yingfan Guo <115908952+sentomk@users.noreply.github.com> Date: Sun, 21 Sep 2025 00:52:37 +0800 Subject: [PATCH 10/17] Update ci-full.yml --- .github/workflows/ci-full.yml | 84 ++++++++++++++++++++++------------- 1 file changed, 53 insertions(+), 31 deletions(-) diff --git a/.github/workflows/ci-full.yml b/.github/workflows/ci-full.yml index 77ae5dba..fcfbb4ec 100644 --- a/.github/workflows/ci-full.yml +++ b/.github/workflows/ci-full.yml @@ -17,45 +17,57 @@ jobs: fail-fast: false matrix: include: - # Ubuntu - gcc/clang + # Ubuntu - gcc/clang (Ninja) - os: ubuntu-latest compiler: gcc cpp_std: 17 + generator: ninja - os: ubuntu-latest compiler: gcc cpp_std: 20 + generator: ninja - os: ubuntu-latest compiler: gcc cpp_std: 23 + generator: ninja - os: ubuntu-latest compiler: clang cpp_std: 17 + generator: ninja - os: ubuntu-latest compiler: clang cpp_std: 20 + generator: ninja - os: ubuntu-latest compiler: clang cpp_std: 23 - # macOS - clang (AppleClang) + generator: ninja + # macOS - AppleClang (Ninja) - os: macos-latest compiler: clang cpp_std: 17 + generator: ninja - os: macos-latest compiler: clang cpp_std: 20 + generator: ninja - os: macos-latest compiler: clang cpp_std: 23 - # Windows - MSVC + generator: ninja + # Windows - MSVC (VS 2022) - os: windows-latest compiler: msvc cpp_std: 17 + generator: vs17 - os: windows-latest compiler: msvc cpp_std: 20 + generator: vs17 - os: windows-latest compiler: msvc cpp_std: 23 + generator: vs17 steps: - uses: actions/checkout@v4 @@ -63,23 +75,21 @@ jobs: submodules: recursive fetch-depth: 0 - - name: Cache build dir + # 建议:不要缓存整个 build 目录;如果你坚持缓存,至少把 generator 放进 key + - name: Cache build dir (optional) uses: actions/cache@v4 with: path: build - key: full-${{ runner.os }}-cmake-${{ matrix.compiler }}-std${{ matrix.cpp_std }}-${{ hashFiles('**/CMakeLists.txt', '**/*.cmake') }} + key: full-${{ runner.os }}-cmake-${{ matrix.compiler }}-std${{ matrix.cpp_std }}-gen-${{ matrix.generator }}-${{ hashFiles('**/CMakeLists.txt', '**/*.cmake') }} restore-keys: | - full-${{ runner.os }}-cmake-${{ matrix.compiler }}-std${{ matrix.cpp_std }}- + full-${{ runner.os }}-cmake-${{ matrix.compiler }}-std${{ matrix.cpp_std }}-gen-${{ matrix.generator }}- - # ----------------------------- - # Dependencies per platform - # ----------------------------- + # ---- Dependencies per platform ---- - name: Prepare (Ubuntu) if: runner.os == 'Linux' run: | sudo apt-get update -y sudo apt-get install -y ninja-build ccache - # clang/gcc 通常已预装;如需特定版本可在这里安装 - name: Prepare (macOS) if: runner.os == 'macOS' @@ -87,10 +97,33 @@ jobs: brew update brew install ninja || true - # ----------------------------- - # Configure - # ----------------------------- - - name: Configure (Linux/macOS, Ninja single-config) + # ---- Clean stale build dir if generator mismatched ---- + - name: Ensure clean build dir for Ninja (Linux/macOS) + if: runner.os != 'Windows' + shell: bash + run: | + set -euxo pipefail + if [ -f build/CMakeCache.txt ]; then + if ! grep -q 'CMAKE_GENERATOR:INTERNAL=Ninja' build/CMakeCache.txt; then + rm -rf build + fi + fi + mkdir -p build + + - name: Ensure clean build dir for VS (Windows) + if: runner.os == 'Windows' + shell: pwsh + run: | + if (Test-Path build/CMakeCache.txt) { + $gen = Select-String -Path build/CMakeCache.txt -Pattern 'CMAKE_GENERATOR:INTERNAL=(.*)' | ForEach-Object { $_.Matches[0].Groups[1].Value } + if ($gen -notlike 'Visual Studio*') { + Remove-Item -Recurse -Force build + } + } + New-Item -ItemType Directory -Force -Path build | Out-Null + + # ---- Configure ---- + - name: Configure (Linux/macOS, Ninja) if: runner.os != 'Windows' shell: bash run: | @@ -110,7 +143,7 @@ jobs: -DBUILD_TESTS=ON \ -DBUILD_BENCHMARKS=ON - - name: Configure (Windows, Visual Studio multi-config) + - name: Configure (Windows, VS 2022) if: runner.os == 'Windows' shell: pwsh run: > @@ -122,9 +155,7 @@ jobs: -DBUILD_TESTS=ON -DBUILD_BENCHMARKS=ON - # ----------------------------- - # Build - # ----------------------------- + # ---- Build ---- - name: Build (Linux/macOS) if: runner.os != 'Windows' run: cmake --build build --parallel @@ -134,9 +165,7 @@ jobs: shell: pwsh run: cmake --build build --config Release --parallel - # ----------------------------- - # Test - # ----------------------------- + # ---- Test ---- - name: Run tests (Linux/macOS) if: runner.os != 'Windows' shell: bash @@ -156,16 +185,13 @@ jobs: run: | if (Test-Path build/CTestTestfile.cmake) { Push-Location build - # 注意:ctest 在多配置生成器下应使用 -C,而不是 --config ctest -C Release --output-on-failure --parallel Pop-Location } else { Write-Host "No tests configured." } - # ----------------------------- - # Artifacts - # ----------------------------- + # ---- Artifacts ---- - name: Upload build artifact (always) if: always() uses: actions/upload-artifact@v4 @@ -173,9 +199,7 @@ jobs: name: build-${{ matrix.os }}-${{ matrix.compiler }}-std${{ matrix.cpp_std }} path: build - # ----------------------------------------- - # clang-format style check - # ----------------------------------------- + # ---- clang-format ---- clang-format-check: name: clang-format check runs-on: ubuntu-latest @@ -206,9 +230,7 @@ jobs: exit 2 fi - # ----------------------------------------- - # clang-tidy (quick scan on part of headers) - # ----------------------------------------- + # ---- clang-tidy (quick) ---- clang-tidy-scan: name: clang-tidy (quick) runs-on: ubuntu-latest From e1cb69b9144427f5587aae5ada468c1b9292a704 Mon Sep 17 00:00:00 2001 From: Yingfan Guo <115908952+sentomk@users.noreply.github.com> Date: Sun, 21 Sep 2025 01:05:18 +0800 Subject: [PATCH 11/17] Update ci-full.yml --- .github/workflows/ci-full.yml | 153 ++++++++-------------------------- 1 file changed, 33 insertions(+), 120 deletions(-) diff --git a/.github/workflows/ci-full.yml b/.github/workflows/ci-full.yml index fcfbb4ec..52554b90 100644 --- a/.github/workflows/ci-full.yml +++ b/.github/workflows/ci-full.yml @@ -5,6 +5,7 @@ on: branches: - main - ci/workflows + workflow_dispatch: schedule: - cron: '0 3 * * 1' # weekly (UTC) @@ -17,207 +18,127 @@ jobs: fail-fast: false matrix: include: - # Ubuntu - gcc/clang (Ninja) + # same include list as ci-pr.yml (copy/paste) - os: ubuntu-latest compiler: gcc cpp_std: 17 - generator: ninja - os: ubuntu-latest compiler: gcc cpp_std: 20 - generator: ninja - os: ubuntu-latest compiler: gcc cpp_std: 23 - generator: ninja - os: ubuntu-latest compiler: clang cpp_std: 17 - generator: ninja - os: ubuntu-latest compiler: clang cpp_std: 20 - generator: ninja - os: ubuntu-latest compiler: clang cpp_std: 23 - generator: ninja - # macOS - AppleClang (Ninja) - os: macos-latest compiler: clang cpp_std: 17 - generator: ninja - os: macos-latest compiler: clang cpp_std: 20 - generator: ninja - os: macos-latest compiler: clang cpp_std: 23 - generator: ninja - # Windows - MSVC (VS 2022) - os: windows-latest compiler: msvc cpp_std: 17 - generator: vs17 - os: windows-latest compiler: msvc cpp_std: 20 - generator: vs17 - os: windows-latest compiler: msvc cpp_std: 23 - generator: vs17 steps: - uses: actions/checkout@v4 - with: - submodules: recursive - fetch-depth: 0 - # 建议:不要缓存整个 build 目录;如果你坚持缓存,至少把 generator 放进 key - - name: Cache build dir (optional) + - name: Cache build dir uses: actions/cache@v4 with: path: build - key: full-${{ runner.os }}-cmake-${{ matrix.compiler }}-std${{ matrix.cpp_std }}-gen-${{ matrix.generator }}-${{ hashFiles('**/CMakeLists.txt', '**/*.cmake') }} + key: full-${{ runner.os }}-cmake-${{ matrix.compiler }}-std${{ matrix.cpp_std }}-${{ hashFiles('**/CMakeLists.txt') }} restore-keys: | - full-${{ runner.os }}-cmake-${{ matrix.compiler }}-std${{ matrix.cpp_std }}-gen-${{ matrix.generator }}- - - # ---- Dependencies per platform ---- - - name: Prepare (Ubuntu) - if: runner.os == 'Linux' - run: | - sudo apt-get update -y - sudo apt-get install -y ninja-build ccache + full-${{ runner.os }}-cmake-${{ matrix.compiler }}-std${{ matrix.cpp_std }}- - - name: Prepare (macOS) - if: runner.os == 'macOS' - run: | - brew update - brew install ninja || true - - # ---- Clean stale build dir if generator mismatched ---- - - name: Ensure clean build dir for Ninja (Linux/macOS) + - name: Prepare (Linux/macOS) if: runner.os != 'Windows' - shell: bash - run: | - set -euxo pipefail - if [ -f build/CMakeCache.txt ]; then - if ! grep -q 'CMAKE_GENERATOR:INTERNAL=Ninja' build/CMakeCache.txt; then - rm -rf build - fi - fi - mkdir -p build - - - name: Ensure clean build dir for VS (Windows) - if: runner.os == 'Windows' - shell: pwsh run: | - if (Test-Path build/CMakeCache.txt) { - $gen = Select-String -Path build/CMakeCache.txt -Pattern 'CMAKE_GENERATOR:INTERNAL=(.*)' | ForEach-Object { $_.Matches[0].Groups[1].Value } - if ($gen -notlike 'Visual Studio*') { - Remove-Item -Recurse -Force build - } - } - New-Item -ItemType Directory -Force -Path build | Out-Null + sudo apt-get update -y || true + sudo apt-get install -y ninja-build ccache || true - # ---- Configure ---- - - name: Configure (Linux/macOS, Ninja) + - name: Configure if: runner.os != 'Windows' - shell: bash + env: + CC: ${{ matrix.compiler == 'clang' && 'clang' || 'gcc' }} + CXX: ${{ matrix.compiler == 'clang' && 'clang++' || 'g++' }} run: | - set -euxo pipefail - if [ "${{ matrix.compiler }}" = "clang" ]; then - export CC=clang - export CXX=clang++ - else - export CC=gcc - export CXX=g++ - fi - cmake -S . -B build -G Ninja \ + cmake -S . -B build \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_CXX_STANDARD=${{ matrix.cpp_std }} \ -DCMAKE_CXX_STANDARD_REQUIRED=ON \ - -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ -DBUILD_TESTS=ON \ -DBUILD_BENCHMARKS=ON - - - name: Configure (Windows, VS 2022) + - name: Configure (Windows) if: runner.os == 'Windows' - shell: pwsh - run: > - cmake -S . -B build - -G "Visual Studio 17 2022" - -A x64 - -DCMAKE_CXX_STANDARD=${{ matrix.cpp_std }} - -DCMAKE_EXPORT_COMPILE_COMMANDS=ON - -DBUILD_TESTS=ON - -DBUILD_BENCHMARKS=ON + run: | + powershell -Command "cmake -S . -B build -G 'Visual Studio 17 2022' -A x64 -DCMAKE_CXX_STANDARD=${{ matrix.cpp_std }} -DBUILD_TESTS=ON -DBUILD_BENCHMARKS=ON" - # ---- Build ---- - - name: Build (Linux/macOS) + - name: Build if: runner.os != 'Windows' run: cmake --build build --parallel - - name: Build (Windows) if: runner.os == 'Windows' - shell: pwsh - run: cmake --build build --config Release --parallel + run: powershell -Command "cmake --build build --config Release --parallel" - # ---- Test ---- - - name: Run tests (Linux/macOS) + - name: Run tests if: runner.os != 'Windows' - shell: bash run: | - set -euxo pipefail if [ -f build/CTestTestfile.cmake ]; then pushd build - ctest --output-on-failure --parallel + ctest --output-on-failure --parallel || (cat Testing/Temporary/LastTest.log || true; exit 1) popd else - echo "No tests configured." + echo "No tests." fi + shell: bash - name: Run tests (Windows) if: runner.os == 'Windows' - shell: pwsh run: | if (Test-Path build/CTestTestfile.cmake) { Push-Location build - ctest -C Release --output-on-failure --parallel + ctest --config Release --output-on-failure --parallel Pop-Location } else { Write-Host "No tests configured." } + shell: pwsh - # ---- Artifacts ---- - - name: Upload build artifact (always) - if: always() + - name: Upload build artifact (success) + if: success() uses: actions/upload-artifact@v4 with: name: build-${{ matrix.os }}-${{ matrix.compiler }}-std${{ matrix.cpp_std }} path: build - # ---- clang-format ---- clang-format-check: name: clang-format check runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install clang-format - run: | - sudo apt-get update -y - sudo apt-get install -y clang-format + run: sudo apt-get update -y && sudo apt-get install -y clang-format - name: Check formatting - shell: bash run: | - set -euxo pipefail - files="$(git ls-files '*.hpp' '*.h' '*.cpp' '*.c' | xargs || true)" - if [ -z "$files" ]; then - echo "No source files" - exit 0 - fi + files=$(git ls-files '*.hpp' '*.h' '*.cpp' '*.c' | xargs) + if [ -z "$files" ]; then echo "No source files"; exit 0; fi bad=0 for f in $files; do if ! clang-format -style=file "$f" | diff -u "$f" - >/dev/null; then @@ -230,7 +151,6 @@ jobs: exit 2 fi - # ---- clang-tidy (quick) ---- clang-tidy-scan: name: clang-tidy (quick) runs-on: ubuntu-latest @@ -238,20 +158,13 @@ jobs: steps: - uses: actions/checkout@v4 - name: Install clang-tidy - run: | - sudo apt-get update -y - sudo apt-get install -y clang-tidy - - name: Configure compile_commands.json (Ninja) - run: | - cmake -S . -B build -G Ninja \ - -DCMAKE_CXX_STANDARD=23 \ - -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ - -DBUILD_TESTS=OFF \ - -DBUILD_BENCHMARKS=OFF + run: sudo apt-get update -y && sudo apt-get install -y clang-tidy + - name: Configure compile_commands.json + run: cmake -S . -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_CXX_STANDARD=23 -DBUILD_TESTS=OFF - name: Run clang-tidy on headers (limited) run: | if [ -f build/compile_commands.json ]; then - find include -type f \( -name '*.hpp' -o -name '*.h' \) | head -n 50 | xargs -r clang-tidy -p build || true + find include -name '*.hpp' -or -name '*.h' | head -n 50 | xargs -r clang-tidy -p build || true else echo "No compile_commands.json; skipping" fi From a7b2dbcb7f97d42e0b197e196a81e404882d3daa Mon Sep 17 00:00:00 2001 From: Yingfan Guo <115908952+sentomk@users.noreply.github.com> Date: Sun, 21 Sep 2025 02:03:39 +0800 Subject: [PATCH 12/17] Update ci-full.yml --- .github/workflows/ci-full.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-full.yml b/.github/workflows/ci-full.yml index 52554b90..77dc5db8 100644 --- a/.github/workflows/ci-full.yml +++ b/.github/workflows/ci-full.yml @@ -114,7 +114,7 @@ jobs: run: | if (Test-Path build/CTestTestfile.cmake) { Push-Location build - ctest --config Release --output-on-failure --parallel + ctest --output-on-failure --parallel Pop-Location } else { Write-Host "No tests configured." From 3d278cd441ee6a1bee9940dfa6a8fb59014afc85 Mon Sep 17 00:00:00 2001 From: Yingfan Guo <115908952+sentomk@users.noreply.github.com> Date: Sun, 21 Sep 2025 02:25:09 +0800 Subject: [PATCH 13/17] Update ci-full.yml --- .github/workflows/ci-full.yml | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-full.yml b/.github/workflows/ci-full.yml index 77dc5db8..d8b4ecd5 100644 --- a/.github/workflows/ci-full.yml +++ b/.github/workflows/ci-full.yml @@ -108,18 +108,28 @@ jobs: echo "No tests." fi shell: bash - + - name: Run tests (Windows) if: runner.os == 'Windows' + shell: pwsh run: | if (Test-Path build/CTestTestfile.cmake) { Push-Location build - ctest --output-on-failure --parallel + $gen = "" + if (Test-Path CMakeCache.txt) { + $m = Select-String -Path CMakeCache.txt -Pattern '^CMAKE_GENERATOR:INTERNAL=(.*)' -ErrorAction SilentlyContinue + if ($m) { $gen = $m.Matches[0].Groups[1].Value } + } + if ($gen -like "Visual Studio*") { + ctest -C Release --output-on-failure --parallel + } else { + ctest --output-on-failure --parallel + } Pop-Location } else { Write-Host "No tests configured." } - shell: pwsh + - name: Upload build artifact (success) if: success() From 0db2473dfd27d67084368b89e84eab35cdf42554 Mon Sep 17 00:00:00 2001 From: sentomk Date: Sun, 21 Sep 2025 02:31:21 +0800 Subject: [PATCH 14/17] create ci.yml --- .github/workflows/ci.yml | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..dac5c68a --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,29 @@ +name: Gate CI (runs on PRs into B) + +on: + pull_request_target: + branches: [ 'ci/workflows' ] + types: [ opened, synchronize, reopened ] + +permissions: + contents: read + +jobs: + build-test: + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: read + actions: read + steps: + - name: Checkout PR HEAD safely + uses: actions/checkout@v4 + with: + repository: ${{ github.event.pull_request.head.repo.full_name }} + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 0 + + - run: | + cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTS=ON + cmake --build build --parallel + ctest --test-dir build --output-on-failure --parallel From 228b872f8c090fc6587c66a96dea5194206126c9 Mon Sep 17 00:00:00 2001 From: sentomk Date: Sun, 21 Sep 2025 02:42:09 +0800 Subject: [PATCH 15/17] update --- .github/workflows/ci-pr.yml | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-pr.yml b/.github/workflows/ci-pr.yml index 07d7409a..1588922e 100644 --- a/.github/workflows/ci-pr.yml +++ b/.github/workflows/ci-pr.yml @@ -111,15 +111,24 @@ jobs: - name: Run tests (if any) - Windows if: runner.os == 'Windows' + shell: pwsh run: | if (Test-Path build/CTestTestfile.cmake) { Push-Location build - ctest --config Release --output-on-failure --parallel - Pop-Location + try { + ctest -C Release --output-on-failure --parallel + } catch { + if (Test-Path "Testing/Temporary/LastTest.log") { + Write-Host "==== LastTest.log ====" + Get-Content "Testing/Temporary/LastTest.log" + } + throw + } finally { + Pop-Location + } } else { Write-Host "No tests configured." } - shell: pwsh - name: Upload build artifact on failure if: failure() From 9f4d5b6f6138dc0be968d78da40a1c28497ec7d3 Mon Sep 17 00:00:00 2001 From: Yingfan Guo <115908952+sentomk@users.noreply.github.com> Date: Sun, 21 Sep 2025 02:55:32 +0800 Subject: [PATCH 16/17] create pull request from dev/fix to ci branch (#5) * fix(core): pass tuple to match_builder::create, not to V constructor * fix(core): make friend match declaration identical to patternia.hpp to avoid noexcept mismatch (clang) * fix(core): remove noexcept from friend declaration of ptn::match to avoid exception-spec mismatch (clang) * fix(core) * fix(core): replace the function-style cast with direct initialization using parentheses (MSVC) * fix(core): replace the function-style cast with direct initialization using parentheses (MSVC) * fix(core): resolved error C2440: '' * fix(core): resolved error C2440: '' * fix(core): resolved error C2440: '' * fix(core): resolved error C2440: '' * fix(msvc): use brace-init in match_builder to avoid initializer-list ambiguity * fix(msvc): use brace-init in match_builder to avoid initializer-list ambiguity --- include/ptn/core/match_builder.hpp | 42 +++++++++++++++++++----------- include/ptn/patternia.hpp | 6 ++--- 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/include/ptn/core/match_builder.hpp b/include/ptn/core/match_builder.hpp index 3f7807e6..20d497f5 100644 --- a/include/ptn/core/match_builder.hpp +++ b/include/ptn/core/match_builder.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #if PTN_USE_CONCEPTS #include @@ -17,9 +18,9 @@ namespace ptn { /* free match function forward declaration */ - template + template constexpr auto - match(U &&) noexcept(std::is_nothrow_constructible_v, U &&>); + match(T &&) noexcept(std::is_nothrow_constructible_v, T &&>); } // namespace ptn namespace ptn::detail { @@ -89,35 +90,45 @@ namespace ptn::core { class match_builder { TV value_; std::tuple cases_; - using ctor_tag_t = ctor_tag; - - template - friend constexpr auto ::ptn::match(U &&) noexcept( - std::is_nothrow_constructible_v, U &&>); - + using ctor_tag_t = ptn::core::ctor_tag; /* make all specializations of match_builder mutual friends */ template friend class match_builder; - template + template #if PTN_USE_CONCEPTS - requires std::constructible_from, Tuple> + requires std::constructible_from && + std::constructible_from, Tuple> #endif - explicit constexpr match_builder(TV &&v, Tuple &&cs, ctor_tag_t) - : value_(std::forward(v)), cases_(std::forward(cs)) { + explicit constexpr match_builder(TV2 &&v, Tuple &&cs, ctor_tag_t) + : value_(std::forward(v)), cases_(std::forward(cs)) { } public: - // with + // Correctly place template & requires for create + template +#if PTN_USE_CONCEPTS + requires std::constructible_from, Tuple> +#endif + static constexpr auto create(VArg &&v, Tuple &&cs) + -> match_builder, Cases...> { + using result_t = match_builder, Cases...>; + return result_t( + std::forward(v), std::forward(cs), ctor_tag{}); + } + + // with (lvalue) template constexpr auto with(Pattern p, Handler h) & { using pair_t = std::pair; auto new_cases = std::tuple_cat( cases_, std::make_tuple(pair_t{std::move(p), std::move(h)})); + // use brace-init to construct the returned match_builder return match_builder( value_, std::move(new_cases), ctor_tag_t{}); } + // with (rvalue) template constexpr auto with(Pattern p, Handler h) && { using pair_t = std::pair; @@ -138,7 +149,8 @@ namespace ptn::core { decltype(ptn::detail::run_handler( std::declval &>(), std::declval()))>; R out{}; - bool done = false; + bool done = false; + auto try_one = [&](auto &c) { if (done) return; @@ -199,4 +211,4 @@ namespace ptn::core { return std::move(*this).with(std::move(e.pattern), std::move(e.handler)); } }; -} // namespace ptn::core \ No newline at end of file +} // namespace ptn::core diff --git a/include/ptn/patternia.hpp b/include/ptn/patternia.hpp index b46d4823..d83090b7 100644 --- a/include/ptn/patternia.hpp +++ b/include/ptn/patternia.hpp @@ -18,8 +18,8 @@ namespace ptn { constexpr auto match(T &&value) noexcept( std::is_nothrow_constructible_v, T &&>) { using V = std::decay_t; - return core::match_builder( - V(std::forward(value)), std::tuple<>{}, core::ctor_tag{}); + return core::match_builder::create( + V(std::forward(value)), std::tuple<>{}); } }; // namespace ptn @@ -31,7 +31,7 @@ namespace ptn { #if PTN_ENABLE_RELATIONAL_PATTERN // clang-format off -# include +#include // clang-format on #endif From 5ef29249ed12d25ea4d77be71f1555a318d389ff Mon Sep 17 00:00:00 2001 From: sentomk Date: Sun, 21 Sep 2025 16:03:20 +0800 Subject: [PATCH 17/17] format: resolve the formatting check failure --- include/ptn/patterns/relational.hpp | 90 ++++++++++++++--------------- include/ptn/patterns/value.hpp | 43 +++++++------- tests/tests_value_pattern.cpp | 2 +- 3 files changed, 67 insertions(+), 68 deletions(-) diff --git a/include/ptn/patterns/relational.hpp b/include/ptn/patterns/relational.hpp index 22cf0629..8cc0648d 100644 --- a/include/ptn/patterns/relational.hpp +++ b/include/ptn/patterns/relational.hpp @@ -6,11 +6,11 @@ namespace ptn::patterns { /* enhance this alias later to support string_view */ - template + template using rel_store_t = std::decay_t; // x < v - template > + template > struct lt_pattern { rel_store_t v; #if defined(__cpp_no_unique_address) && __cpp_no_unique_address >= 201803L @@ -19,15 +19,15 @@ namespace ptn::patterns { Cmp cmp{}; #endif - template + template constexpr bool operator()(X const &x) const - noexcept(noexcept(std::declval()(x, v))) { + noexcept(noexcept(std::declval()(x, v))) { return cmp(x, v); } }; // x <= v <=> !(v < x) - template > + template > struct le_pattern { rel_store_t v; #if defined(__cpp_no_unique_address) && __cpp_no_unique_address >= 201803L @@ -35,15 +35,15 @@ namespace ptn::patterns { #else Cmp cmp{}; #endif - template + template constexpr bool operator()(X const &x) const - noexcept(noexcept(std::declval()(v, x))) { + noexcept(noexcept(std::declval()(v, x))) { return !cmp(v, x); } }; // x > v <=> (v < x) - template > + template > struct gt_pattern { rel_store_t v; #if defined(__cpp_no_unique_address) && __cpp_no_unique_address >= 201803L @@ -52,15 +52,15 @@ namespace ptn::patterns { Cmp cmp{}; #endif - template + template constexpr bool operator()(X const &x) const - noexcept(noexcept(std::declval()(v, x))) { + noexcept(noexcept(std::declval()(v, x))) { return cmp(v, x); } }; // x >= v <=> !(x < v) - template > + template > struct ge_pattern { rel_store_t v; #if defined(__cpp_no_unique_address) && __cpp_no_unique_address >= 201803L @@ -68,15 +68,15 @@ namespace ptn::patterns { #else Cmp cmp{}; #endif - template + template constexpr bool operator()(X const &x) const - noexcept(noexcept(std::declval()(x, v))) { + noexcept(noexcept(std::declval()(x, v))) { return !cmp(x, v); } }; // x == v - template > + template > struct eq_pattern { rel_store_t v; #if defined(__cpp_no_unique_address) && __cpp_no_unique_address >= 201803L @@ -84,15 +84,15 @@ namespace ptn::patterns { #else Cmp cmp{}; #endif - template + template constexpr bool operator()(X const &x) const - noexcept(noexcept(std::declval()(x, v))) { + noexcept(noexcept(std::declval()(x, v))) { return cmp(x, v); } }; // x != v - template > + template > struct ne_pattern { rel_store_t v; #if defined(__cpp_no_unique_address) && __cpp_no_unique_address >= 201803L @@ -100,42 +100,42 @@ namespace ptn::patterns { #else Cmp cmp{}; #endif - template + template constexpr bool operator()(X const &x) const - noexcept(noexcept(std::declval()(x, v))) { + noexcept(noexcept(std::declval()(x, v))) { return cmp(x, v); } }; /* Factories */ - template + template constexpr auto lt(V &&v) { - return lt_pattern >{rel_store_t(std::forward(v))}; + return lt_pattern>{rel_store_t(std::forward(v))}; } - template + template constexpr auto le(V &&v) { - return le_pattern >{rel_store_t(std::forward(v))}; + return le_pattern>{rel_store_t(std::forward(v))}; } - template + template constexpr auto gt(V &&v) { - return gt_pattern >{rel_store_t(std::forward(v))}; + return gt_pattern>{rel_store_t(std::forward(v))}; } - template + template constexpr auto ge(V &&v) { - return ge_pattern >{rel_store_t(std::forward(v))}; + return ge_pattern>{rel_store_t(std::forward(v))}; } - template + template constexpr auto eq(V &&v) { - return eq_pattern >{rel_store_t(std::forward(v))}; + return eq_pattern>{rel_store_t(std::forward(v))}; } - template + template constexpr auto ne(V &&v) { - return ne_pattern >{rel_store_t(std::forward(v))}; + return ne_pattern>{rel_store_t(std::forward(v))}; } /* @@ -143,36 +143,36 @@ namespace ptn::patterns { closed==true -> [lo, hi] : !(x < lo) && !(hi < x) closed==false -> (lo, hi) : (lo < x) && (x < hi) */ - template > + template > struct between_pattern { rel_store_t lo; rel_store_t hi; - bool closed{}; + bool closed{}; #if defined(__cpp_no_unique_address) && __cpp_no_unique_address >= 201803L [[no_unique_address]] Cmp cmp{}; #else Cmp cmp{}; #endif - template + template constexpr bool operator()(X const &x) const noexcept( - noexcept(std::declval()(x, lo)) && - noexcept(std::declval()(hi, x)) && - noexcept(std::declval()(lo, x)) && - noexcept(std::declval()(x, hi))) { + noexcept(std::declval()(x, lo)) && + noexcept(std::declval()(hi, x)) && + noexcept(std::declval()(lo, x)) && + noexcept(std::declval()(x, hi))) { if (closed) { return !cmp(x, lo) && !cmp(hi, x); - } else { + } + else { return cmp(lo, x) && cmp(x, hi); } } }; - template + template constexpr auto between(L &&lo, R &&hi, bool closed = true) { - return between_pattern, rel_store_t >{ - rel_store_t(std::forward(lo)), - rel_store_t(std::forward(hi)), - closed - }; + return between_pattern, rel_store_t>{ + rel_store_t(std::forward(lo)), + rel_store_t(std::forward(hi)), + closed}; } } // namespace ptn::patterns diff --git a/include/ptn/patterns/value.hpp b/include/ptn/patterns/value.hpp index da2d2ea1..a4c6f8de 100644 --- a/include/ptn/patterns/value.hpp +++ b/include/ptn/patterns/value.hpp @@ -7,15 +7,15 @@ #include "ptn/config.hpp" namespace ptn::patterns { - template + template /* if is c-style string/array or others */ using value_store_t = std::conditional_t< - std::is_array_v > || - std::is_same_v, const char *>, - std::string_view, - std::decay_t >; + std::is_array_v> || + std::is_same_v, const char *>, + std::string_view, + std::decay_t>; - template > + template > struct value_pattern { using store_t = value_store_t; @@ -28,16 +28,16 @@ namespace ptn::patterns { #endif /* allow matching end x to be compared heterogeneously with stored v */ - template + template constexpr bool operator()(X const &x) const - noexcept(noexcept(std::declval()(x, v))) { + noexcept(noexcept(std::declval()(x, v))) { return cmp(x, v); } }; /* factory: automatic selection of the storage type based on the entry * parameter */ - template + template constexpr auto value(V &&v) { using store_t = value_store_t; return value_pattern{store_t(std::forward(v))}; @@ -63,20 +63,20 @@ namespace ptn::patterns { /* transparent comparison */ #if PTN_USE_CONCEPTS - template + template requires( - std::is_convertible_v && - std::is_convertible_v - ) + std::is_convertible_v && + std::is_convertible_v) constexpr bool operator()(A const &a, B const &b) const noexcept { return (*this)(std::string_view(a), std::string_view(b)); } -# else - template && - std::is_convertible_v - > > +#else + template < + typename A, + typename B, + typename = std::enable_if_t< + std::is_convertible_v && + std::is_convertible_v>> constexpr bool operator()(A const &a, B const &b) const noexcept { return (*this)(std::string_view(a), std::string_view(b)); } @@ -84,11 +84,10 @@ namespace ptn::patterns { }; /* convenience factory: case-insensitive value model */ - template + template constexpr auto ci_value(V &&v) { using store_t = value_store_t; return value_pattern{ - store_t(std::forward(v)), iequal_ascii{} - }; + store_t(std::forward(v)), iequal_ascii{}}; } } // namespace ptn::patterns diff --git a/tests/tests_value_pattern.cpp b/tests/tests_value_pattern.cpp index 3e2896a4..3ace0efc 100644 --- a/tests/tests_value_pattern.cpp +++ b/tests/tests_value_pattern.cpp @@ -81,7 +81,7 @@ TEST(ValuePattern, StringTypes_CaseInsensitive_Mixed) { struct approx_equal { double eps{1e-6}; bool operator()(double x, double y) const { - return std::fabs(x - y) <= eps; + return std::fabs(x - y) <= eps; } };