cm: mx4_ctx reshape prev[0]>>3 + prev[1]>>4 (drop bp, widen prev[0]) … #663
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| branches: [main] | |
| env: | |
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true | |
| jobs: | |
| build-linux: | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| compiler: [gcc, clang] | |
| build_type: [Release, Debug] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install dependencies | |
| run: sudo apt-get update && sudo apt-get install -y cmake build-essential libomp-dev | |
| - name: Configure | |
| run: cmake -S . -B build -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_C_COMPILER=${{ matrix.compiler }} | |
| - name: Build | |
| run: cmake --build build --config ${{ matrix.build_type }} -j$(nproc) | |
| - name: Run tests | |
| run: cd build && ctest --output-on-failure --timeout 300 | |
| build-macos: | |
| runs-on: macos-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Configure | |
| run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Release | |
| - name: Build | |
| run: cmake --build build --config Release -j$(sysctl -n hw.ncpu) | |
| - name: Run tests | |
| run: cd build && ctest --output-on-failure --timeout 300 | |
| build-windows: | |
| runs-on: windows-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Configure | |
| run: cmake -S . -B build | |
| - name: Build | |
| run: cmake --build build --config Release | |
| - name: Run tests | |
| run: cd build && ctest -C Release --output-on-failure --timeout 300 | |
| roundtrip-test: | |
| runs-on: ubuntu-latest | |
| needs: build-linux | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Build | |
| run: | | |
| cmake -S . -B build -DCMAKE_BUILD_TYPE=Release | |
| cmake --build build -j$(nproc) | |
| - name: Download Canterbury Corpus | |
| run: | | |
| mkdir -p /tmp/cantrbry | |
| cd /tmp/cantrbry | |
| wget -q https://corpus.canterbury.ac.nz/resources/cantrbry.tar.gz | |
| tar xzf cantrbry.tar.gz 2>/dev/null || true | |
| - name: Roundtrip test (all levels) | |
| run: | | |
| for f in /tmp/cantrbry/*; do | |
| [ -f "$f" ] || continue | |
| name=$(basename "$f") | |
| for level in 1 3 6 9 12 20 26; do | |
| ./build/bin/mcx compress -l $level "$f" -o "/tmp/${name}.mcx" | |
| ./build/bin/mcx decompress "/tmp/${name}.mcx" -o "/tmp/${name}.dec" | |
| if diff "$f" "/tmp/${name}.dec" > /dev/null 2>&1; then | |
| echo "OK: $name L$level" | |
| else | |
| echo "FAIL: $name L$level" | |
| exit 1 | |
| fi | |
| rm -f "/tmp/${name}.mcx" "/tmp/${name}.dec" | |
| done | |
| done | |
| coverage: | |
| runs-on: ubuntu-latest | |
| needs: build-linux | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install dependencies | |
| run: sudo apt-get update && sudo apt-get install -y cmake build-essential libomp-dev lcov | |
| - name: Configure with coverage | |
| run: | | |
| cmake -S . -B build \ | |
| -DCMAKE_BUILD_TYPE=Debug \ | |
| -DCMAKE_C_COMPILER=gcc \ | |
| -DMCX_CODE_COVERAGE=ON \ | |
| -DMCX_BUILD_BENCHMARKS=OFF | |
| - name: Build | |
| run: cmake --build build -j$(nproc) | |
| - name: Run tests | |
| run: cd build && ctest --output-on-failure --timeout 300 | |
| - name: Generate coverage report | |
| run: | | |
| lcov --capture --directory build --output-file coverage.info \ | |
| --rc branch_coverage=1 --ignore-errors unused | |
| # Remove external/test/system files from report | |
| lcov --remove coverage.info \ | |
| '/usr/*' \ | |
| '*/tests/*' \ | |
| '*/external/*' \ | |
| --output-file coverage.info \ | |
| --rc branch_coverage=1 --ignore-errors unused | |
| lcov --list coverage.info --rc branch_coverage=1 --ignore-errors unused | |
| - name: Upload coverage to Codecov | |
| if: ${{ !cancelled() }} | |
| uses: codecov/codecov-action@v4 | |
| with: | |
| files: coverage.info | |
| flags: unittests | |
| fail_ci_if_error: false | |
| env: | |
| CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} | |
| - name: Upload coverage artifact | |
| if: ${{ !cancelled() }} | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: lcov-report | |
| path: coverage.info | |
| retention-days: 30 | |
| pkg-config-test: | |
| runs-on: ubuntu-latest | |
| needs: build-linux | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Build and install | |
| run: | | |
| cmake -S . -B build -DCMAKE_BUILD_TYPE=Release | |
| cmake --build build -j$(nproc) | |
| sudo cmake --install build --prefix /usr/local | |
| - name: Test pkg-config discovery | |
| run: | | |
| pkg-config --exists maxcomp | |
| echo "CFLAGS: $(pkg-config --cflags maxcomp)" | |
| echo "LIBS: $(pkg-config --libs maxcomp)" | |
| - name: Build minimal program via pkg-config | |
| run: | | |
| cat > /tmp/test_pkgconfig.c << 'EOF' | |
| #include <maxcomp/maxcomp.h> | |
| #include <stdio.h> | |
| #include <string.h> | |
| int main(void) { | |
| const char* data = "Hello MaxCompression pkg-config test!"; | |
| size_t src_size = strlen(data); | |
| size_t cap = mcx_compress_bound(src_size); | |
| unsigned char comp[1024], decomp[1024]; | |
| size_t comp_size = mcx_compress(comp, cap, data, src_size, 3); | |
| if (mcx_is_error(comp_size)) { fprintf(stderr, "compress failed\n"); return 1; } | |
| size_t dec_size = mcx_decompress(decomp, sizeof(decomp), comp, comp_size); | |
| if (mcx_is_error(dec_size)) { fprintf(stderr, "decompress failed\n"); return 1; } | |
| if (dec_size != src_size || memcmp(data, decomp, src_size) != 0) { | |
| fprintf(stderr, "roundtrip mismatch\n"); return 1; | |
| } | |
| printf("pkg-config integration OK: %s v%s\n", "maxcomp", mcx_version_string()); | |
| return 0; | |
| } | |
| EOF | |
| gcc /tmp/test_pkgconfig.c -o /tmp/test_pkgconfig \ | |
| $(pkg-config --cflags --libs maxcomp) -lm | |
| LD_LIBRARY_PATH=/usr/local/lib /tmp/test_pkgconfig | |
| # TODO: Add find_package(MaxCompression) test once CMake config export is implemented | |
| python-bindings: | |
| runs-on: ubuntu-latest | |
| needs: build-linux | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.11" | |
| - name: Build shared library | |
| run: | | |
| cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON | |
| cmake --build build -j$(nproc) | |
| - name: Test Python bindings | |
| run: | | |
| cp build/lib/libmaxcomp.so bindings/python/ 2>/dev/null || cp build/bin/libmaxcomp.so bindings/python/ | |
| cd bindings/python | |
| python3 -c " | |
| import maxcomp | |
| data = b'Hello World! ' * 1000 | |
| compressed = maxcomp.compress(data, level=6) | |
| restored = maxcomp.decompress(compressed) | |
| assert restored == data, 'Roundtrip failed' | |
| ratio = len(data) / len(compressed) | |
| print(f'Python bindings OK: {len(data)} -> {len(compressed)} ({ratio:.1f}x)') | |
| print(f'Version: {maxcomp.version()}') | |
| print(f'Bound(1MB): {maxcomp.compress_bound(1048576)}') | |
| " | |
| valgrind: | |
| runs-on: ubuntu-latest | |
| needs: build-linux | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install dependencies | |
| run: sudo apt-get update && sudo apt-get install -y cmake build-essential libomp-dev valgrind | |
| - name: Build (Debug, without OpenMP for cleaner valgrind output) | |
| run: | | |
| cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug \ | |
| -DCMAKE_C_FLAGS="-g -O1" | |
| cmake --build build -j$(nproc) | |
| - name: Run tests under valgrind memcheck | |
| run: | | |
| cd build | |
| ctest --output-on-failure --timeout 600 \ | |
| --overwrite MemoryCheckCommand=/usr/bin/valgrind \ | |
| --overwrite "MemoryCheckCommandOptions=--leak-check=full --error-exitcode=1 --track-origins=yes --suppressions=${{ github.workspace }}/valgrind.supp" \ | |
| -T MemCheck || true | |
| # Show memcheck results | |
| cat Testing/Temporary/MemoryChecker.*.log 2>/dev/null || true | |
| - name: Valgrind roundtrip on sample data | |
| run: | | |
| echo "The quick brown fox jumps over the lazy dog. Pack my box with five dozen liquor jugs." > /tmp/vg_test.txt | |
| for level in 1 3 6 9 12; do | |
| echo "=== Level $level ===" | |
| valgrind --leak-check=full --error-exitcode=1 --track-origins=yes --suppressions=${{ github.workspace }}/valgrind.supp \ | |
| ./build/bin/mcx compress -l $level -q /tmp/vg_test.txt -o /tmp/vg_test.mcx -f | |
| valgrind --leak-check=full --error-exitcode=1 --track-origins=yes --suppressions=${{ github.workspace }}/valgrind.supp \ | |
| ./build/bin/mcx decompress -q /tmp/vg_test.mcx -o /tmp/vg_test.dec -f | |
| diff /tmp/vg_test.txt /tmp/vg_test.dec | |
| echo "Level $level: OK (no leaks)" | |
| rm -f /tmp/vg_test.mcx /tmp/vg_test.dec | |
| done | |
| rm -f /tmp/vg_test.txt | |
| doxygen: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install Doxygen | |
| run: sudo apt-get update && sudo apt-get install -y doxygen | |
| - name: Generate API docs | |
| run: doxygen Doxyfile | |
| - name: Check for undocumented public functions | |
| run: | | |
| # Extract public function declarations from header | |
| grep -oP 'MCXAPI\s+\S+\s+\K(mcx_\w+)' include/maxcomp/maxcomp.h | sort > /tmp/public_funcs.txt | |
| echo "Public functions:" | |
| cat /tmp/public_funcs.txt | |
| # Check Doxygen warnings for undocumented members | |
| if doxygen Doxyfile 2>&1 | grep -i "not documented"; then | |
| echo "WARNING: Some public symbols are undocumented" | |
| else | |
| echo "All public symbols documented" | |
| fi | |
| - name: Upload docs artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: api-docs | |
| path: docs/api/html | |
| retention-days: 30 |