diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..f81b860 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,100 @@ +name: CI Build Tests + +on: + push: + pull_request: + release: + types: [published] + schedule: + - cron: '30 3 * * 0' + +jobs: + build: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + # ── Linux gcc-11 ────────────────────────────────────────── + - { os: ubuntu-latest, cc: gcc-11, cxx: g++-11, name: gcc-11, config: portable, cmake_flags: "-DFORCE_PORTABLE=ON" } + - { os: ubuntu-latest, cc: gcc-11, cxx: g++-11, name: gcc-11, config: native, cmake_flags: "" } + + # ── Linux gcc-12 ────────────────────────────────────────── + - { os: ubuntu-latest, cc: gcc-12, cxx: g++-12, name: gcc-12, config: portable, cmake_flags: "-DFORCE_PORTABLE=ON" } + - { os: ubuntu-latest, cc: gcc-12, cxx: g++-12, name: gcc-12, config: native, cmake_flags: "" } + + # ── Linux clang-14 ──────────────────────────────────────── + - { os: ubuntu-latest, cc: clang-14, cxx: clang++-14, name: clang-14, config: portable, cmake_flags: "-DFORCE_PORTABLE=ON" } + - { os: ubuntu-latest, cc: clang-14, cxx: clang++-14, name: clang-14, config: native, cmake_flags: "" } + + # ── Linux clang-15 ──────────────────────────────────────── + - { os: ubuntu-latest, cc: clang-15, cxx: clang++-15, name: clang-15, config: portable, cmake_flags: "-DFORCE_PORTABLE=ON" } + - { os: ubuntu-latest, cc: clang-15, cxx: clang++-15, name: clang-15, config: native, cmake_flags: "" } + + # ── Linux ARM64 gcc (via ubuntu-24.04-arm) ────────────────── + - { os: ubuntu-24.04-arm, cc: gcc, cxx: g++, name: gcc, config: portable, cmake_flags: "-DFORCE_PORTABLE=ON" } + - { os: ubuntu-24.04-arm, cc: gcc, cxx: g++, name: gcc, config: arm64, cmake_flags: "" } + + # ── Linux ARM64 clang (via ubuntu-24.04-arm) ──────────────── + - { os: ubuntu-24.04-arm, cc: clang, cxx: clang++, name: clang, config: portable, cmake_flags: "-DFORCE_PORTABLE=ON" } + - { os: ubuntu-24.04-arm, cc: clang, cxx: clang++, name: clang, config: arm64, cmake_flags: "" } + + # ── macOS Homebrew clang (ARM64 — no x86 SIMD configs) ─── + - { os: macos-latest, cc: /opt/homebrew/opt/llvm/bin/clang, cxx: /opt/homebrew/opt/llvm/bin/clang++, name: clang, config: portable, cmake_flags: "-DFORCE_PORTABLE=ON" } + - { os: macos-latest, cc: /opt/homebrew/opt/llvm/bin/clang, cxx: /opt/homebrew/opt/llvm/bin/clang++, name: clang, config: arm64, cmake_flags: "" } + + # ── macOS AppleClang (ARM64 — no x86 SIMD configs) ─────── + - { os: macos-latest, name: AppleClang, config: portable, cmake_flags: "-DFORCE_PORTABLE=ON" } + - { os: macos-latest, name: AppleClang, config: arm64, cmake_flags: "" } + + # ── Windows MSVC ────────────────────────────────────────── + - { os: windows-latest, name: msvc, config: portable, cmake_flags: "-DFORCE_PORTABLE=ON" } + - { os: windows-latest, name: msvc, config: native, cmake_flags: "" } + + # ── Windows MinGW GCC ───────────────────────────────────── + - { os: windows-latest, name: mingw-gcc, config: portable, cmake_flags: "-G \"MinGW Makefiles\" -DCMAKE_CXX_COMPILER=g++ -DFORCE_PORTABLE=ON" } + - { os: windows-latest, name: mingw-gcc, config: native, cmake_flags: "-G \"MinGW Makefiles\" -DCMAKE_CXX_COMPILER=g++" } + + name: ${{ matrix.os }} / ${{ matrix.name }} / ${{ matrix.config }} + steps: + - uses: actions/checkout@v4 + + - name: Install Compiler (Linux) + if: startsWith(matrix.os, 'ubuntu') + run: | + sudo apt-get update + sudo apt-get install -y ${{ matrix.cc }} + if [[ "${{ matrix.cxx }}" != *"clang"* ]]; then sudo apt-get install -y ${{ matrix.cxx }}; fi + + - name: Install LLVM (macOS) + if: matrix.os == 'macos-latest' && matrix.name == 'clang' + run: brew install llvm || brew upgrade llvm + + - name: Configure + env: + CC: ${{ matrix.cc }} + CXX: ${{ matrix.cxx }} + run: cmake -S . -B build -DBUILD_TESTS=ON -DBUILD_BENCHMARKS=ON ${{ matrix.cmake_flags }} + + - name: Build + run: cmake --build build --config Release -j + + - name: Resolve executable paths + id: exe + shell: bash + run: | + if [ "${{ matrix.os }}" = "windows-latest" ] && [ "${{ matrix.name }}" = "msvc" ]; then + echo "tests=./build/Release/tinyaes_tests.exe" >> "$GITHUB_OUTPUT" + echo "bench=./build/Release/tinyaes_benchmarks.exe" >> "$GITHUB_OUTPUT" + else + echo "tests=./build/tinyaes_tests" >> "$GITHUB_OUTPUT" + echo "bench=./build/tinyaes_benchmarks" >> "$GITHUB_OUTPUT" + fi + + - name: Tests + shell: bash + run: ${{ steps.exe.outputs.tests }} + + - name: Benchmark + shell: bash + run: ${{ steps.exe.outputs.bench }} diff --git a/README.md b/README.md index 0b5abdf..c1f1728 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # tinyaes +[![CI Build Tests](https://github.com/gibme-c/tinyaes/actions/workflows/ci.yml/badge.svg)](https://github.com/gibme-c/tinyaes/actions/workflows/ci.yml) + A zero-dependency C++17 [AES](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard) encryption library supporting AES-128, AES-192, and AES-256 in ECB, CBC, CTR, and GCM modes, with SIMD-accelerated backends and runtime CPU dispatch. AES (Advanced Encryption Standard) is the most widely deployed symmetric cipher, used in TLS, disk encryption, VPNs, and virtually every modern security protocol. This library provides the complete set of block cipher modes you need for real applications -- from raw ECB blocks to authenticated encryption with GCM -- with both a C API and a modern C++ API. On x86_64, AES-NI and VAES hardware instructions are selected at runtime; on ARM64, the Crypto Extensions backend is used. A portable T-table implementation is always available as a fallback.