| build: | build: | ||||
| runs-on: ${{ matrix.os }}-${{ matrix.osver }} | runs-on: ${{ matrix.os }}-${{ matrix.osver }} | ||||
| name: "${{ matrix.os }} ${{ matrix.arch }}: ${{ matrix.compiler }} + ${{ matrix.sanitizer }}" | |||||
| name: "${{ matrix.os }} ${{ matrix.arch }}: ${{ matrix.compiler }} + ${{ matrix.config }}" | |||||
| strategy: | strategy: | ||||
| fail-fast: false | fail-fast: false | ||||
| matrix: | matrix: | ||||
| os: [ubuntu, macos] | os: [ubuntu, macos] | ||||
| arch: [amd64, i386, aarch64, arm, riscv64] | arch: [amd64, i386, aarch64, arm, riscv64] | ||||
| sanitizer: [no, address, leak, memory, thread, undefined, valgrind] | |||||
| config: [debug, release, release-dyn, asan, lsan, msan, tsan, ubsan, valgrind] | |||||
| compiler: [gcc, clang] | compiler: [gcc, clang] | ||||
| include: | include: | ||||
| runenv: 'LD_LIBRARY_PATH=/usr/riscv64-linux-gnu/lib:$LD_LIBRARY_PATH' | runenv: 'LD_LIBRARY_PATH=/usr/riscv64-linux-gnu/lib:$LD_LIBRARY_PATH' | ||||
| cross: yes | cross: yes | ||||
| - sanitizer: "address" | |||||
| sanitizer_cflags: "-fsanitize=address" | |||||
| sanitize_env: "ASAN_OPTIONS=detect_leaks=0" | |||||
| - config: "asan" | |||||
| config_cflags: "-fsanitize=address" | |||||
| config_env: "ASAN_OPTIONS=detect_leaks=0" | |||||
| - sanitizer: "leak" | |||||
| sanitizer_cflags: "-fsanitize=leak" | |||||
| sanitize_env: "LSAN_OPTIONS=fast_unwind_on_malloc=0" | |||||
| - config: "lsan" | |||||
| config_cflags: "-fsanitize=leak" | |||||
| config_env: "LSAN_OPTIONS=fast_unwind_on_malloc=0" | |||||
| - sanitizer: "memory" | |||||
| - config: "msan" | |||||
| configenv: "CC=clang CXX=clang++" | configenv: "CC=clang CXX=clang++" | ||||
| sanitizer_cflags: "-fsanitize=memory -fsanitize-memory-track-origins=2" | |||||
| config: "-DUSE_LIBPCAUDIO:BOOL=OFF -DUSE_LIBSONIC:BOOL=OFF" | |||||
| sanitize_env: "MSAN_OPTIONS=exitcode=42" | |||||
| config_cflags: "-fsanitize=memory -fsanitize-memory-track-origins=2" | |||||
| settings: "-DUSE_LIBPCAUDIO:BOOL=OFF -DUSE_LIBSONIC:BOOL=OFF" | |||||
| config_env: "MSAN_OPTIONS=exitcode=42" | |||||
| - sanitizer: "thread" | |||||
| sanitizer_cflags: "-fsanitize=thread" | |||||
| - config: "tsan" | |||||
| config_cflags: "-fsanitize=thread" | |||||
| - sanitizer: "undefined" | |||||
| sanitizer_cflags: "-fsanitize=undefined" | |||||
| sanitize_env: "UBSAN_OPTIONS=halt_on_error=1" | |||||
| - config: "ubsan" | |||||
| config_cflags: "-fsanitize=undefined" | |||||
| config_env: "UBSAN_OPTIONS=halt_on_error=1" | |||||
| - sanitizer: "valgrind" | |||||
| sanitize_env: 'VALGRIND="valgrind --track-origins=yes --leak-check=full --error-exitcode=1"' | |||||
| - config: "valgrind" | |||||
| config_env: 'VALGRIND="valgrind --track-origins=yes --leak-check=full --error-exitcode=1"' | |||||
| - config: "release" | |||||
| settings: "-DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo" | |||||
| - config: "release-dyn" | |||||
| settings: "-DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo -DBUILD_SHARED_LIBS:BOOL=ON" | |||||
| exclude: | exclude: | ||||
| - os: macos | - os: macos | ||||
| arch: riscv64 | arch: riscv64 | ||||
| - os: macos | - os: macos | ||||
| sanitizer: valgrind # Not supported on macOS | |||||
| config: valgrind # Not supported on macOS | |||||
| - compiler: gcc | - compiler: gcc | ||||
| sanitizer: memory # Not supported by GCC | |||||
| config: msan # Not supported by GCC | |||||
| - os: macos | - os: macos | ||||
| compiler: clang | compiler: clang | ||||
| sanitizer: leak # Not supported by Apple Clang | |||||
| config: lsan # Not supported by Apple Clang | |||||
| - os: macos | - os: macos | ||||
| compiler: clang | compiler: clang | ||||
| sanitizer: memory # Not supported by Apple Clang | |||||
| config: msan # Not supported by Apple Clang | |||||
| - os: macos | - os: macos | ||||
| compiler: gcc | compiler: gcc | ||||
| sanitizer: thread # Failing on CI, should be supported? | |||||
| config: tsan # Failing on CI, should be supported? | |||||
| # Valgrind is unavailable for cross-builds | # Valgrind is unavailable for cross-builds | ||||
| - arch: aarch64 | - arch: aarch64 | ||||
| sanitizer: valgrind | |||||
| config: valgrind | |||||
| - arch: arm | - arch: arm | ||||
| sanitizer: valgrind | |||||
| config: valgrind | |||||
| - arch: riscv64 | - arch: riscv64 | ||||
| sanitizer: valgrind | |||||
| config: valgrind | |||||
| # Leak sanitizer is unavailable for cross-builds | # Leak sanitizer is unavailable for cross-builds | ||||
| - arch: i386 | - arch: i386 | ||||
| sanitizer: leak | |||||
| config: lsan | |||||
| - arch: aarch64 | - arch: aarch64 | ||||
| sanitizer: leak | |||||
| config: lsan | |||||
| - arch: arm | - arch: arm | ||||
| sanitizer: leak | |||||
| config: lsan | |||||
| - arch: riscv64 | - arch: riscv64 | ||||
| sanitizer: leak | |||||
| config: lsan | |||||
| # Thread sanitizer is partially unavailable | # Thread sanitizer is partially unavailable | ||||
| - arch: i386 | - arch: i386 | ||||
| sanitizer: thread | |||||
| config: tsan | |||||
| - arch: arm | - arch: arm | ||||
| sanitizer: thread | |||||
| config: tsan | |||||
| - arch: riscv64 | - arch: riscv64 | ||||
| sanitizer: thread | |||||
| config: tsan | |||||
| - arch: aarch64 | - arch: aarch64 | ||||
| compiler: clang | compiler: clang | ||||
| sanitizer: thread | |||||
| config: tsan | |||||
| # Undefined sanitizer is partially unavailable | # Undefined sanitizer is partially unavailable | ||||
| - arch: riscv64 | - arch: riscv64 | ||||
| sanitizer: undefined | |||||
| config: ubsan | |||||
| - arch: arm | - arch: arm | ||||
| compiler: clang | compiler: clang | ||||
| sanitizer: undefined | |||||
| config: ubsan | |||||
| - arch: aarch64 | - arch: aarch64 | ||||
| compiler: clang | compiler: clang | ||||
| sanitizer: undefined | |||||
| config: ubsan | |||||
| # Memory sanitizer is partially unavailable | # Memory sanitizer is partially unavailable | ||||
| - arch: i386 | - arch: i386 | ||||
| sanitizer: memory | |||||
| config: msan | |||||
| - arch: riscv64 | - arch: riscv64 | ||||
| sanitizer: memory | |||||
| config: msan | |||||
| - arch: arm | - arch: arm | ||||
| sanitizer: memory | |||||
| config: msan | |||||
| - arch: aarch64 | - arch: aarch64 | ||||
| sanitizer: memory | |||||
| config: msan | |||||
| # Address sanitizer is partially unavailable | # Address sanitizer is partially unavailable | ||||
| - arch: riscv64 | - arch: riscv64 | ||||
| sanitizer: address | |||||
| config: asan | |||||
| - arch: arm | - arch: arm | ||||
| compiler: clang | compiler: clang | ||||
| sanitizer: address | |||||
| config: asan | |||||
| - arch: aarch64 | - arch: aarch64 | ||||
| compiler: clang | compiler: clang | ||||
| sanitizer: address | |||||
| config: asan | |||||
| # Disable Thread sanitizer that runs for over 2h on aarch64 | # Disable Thread sanitizer that runs for over 2h on aarch64 | ||||
| - arch: aarch64 | - arch: aarch64 | ||||
| sanitizer: thread | |||||
| config: tsan | |||||
| steps: | steps: | ||||
| [ 'x${{ matrix.compiler }}' = 'xclang' ] && export CC="clang --target=${{ matrix.ccarch }}-${{ matrix.sys }}" | [ 'x${{ matrix.compiler }}' = 'xclang' ] && export CC="clang --target=${{ matrix.ccarch }}-${{ matrix.sys }}" | ||||
| [ 'x${{ matrix.compiler }}' = 'xclang' ] && export CXX="clang++ --target=${{ matrix.ccarch }}-${{ matrix.sys }}" | [ 'x${{ matrix.compiler }}' = 'xclang' ] && export CXX="clang++ --target=${{ matrix.ccarch }}-${{ matrix.sys }}" | ||||
| [ 'x${{ matrix.cross }}' = 'xyes' ] && export LD="${{ matrix.ccarch }}-${{ matrix.sys }}-ld" | [ 'x${{ matrix.cross }}' = 'xyes' ] && export LD="${{ matrix.ccarch }}-${{ matrix.sys }}-ld" | ||||
| export CFLAGS="-g -Og -fno-omit-frame-pointer ${{ matrix.compiler_flags }} ${{ matrix.sanitizer_cflags }} ${{ matrix.archcflags }}" | |||||
| export CXXFLAGS="-g -Og -fno-omit-frame-pointer ${{ matrix.compiler_flags }} ${{ matrix.sanitizer_cflags }} ${{ matrix.archcflags }}" | |||||
| cmake -Bbuild ${{ matrix.config }} -DCMAKE_SYSTEM_PROCESSOR=${{ matrix.arch }} -DUSE_ASYNC:BOOL=OFF | |||||
| export CFLAGS="-g -Og -fno-omit-frame-pointer ${{ matrix.compiler_flags }} ${{ matrix.config_cflags }} ${{ matrix.archcflags }}" | |||||
| export CXXFLAGS="-g -Og -fno-omit-frame-pointer ${{ matrix.compiler_flags }} ${{ matrix.config_cflags }} ${{ matrix.archcflags }}" | |||||
| cmake -Bbuild ${{ matrix.settings }} -DCMAKE_SYSTEM_PROCESSOR=${{ matrix.arch }} -DUSE_ASYNC:BOOL=OFF | |||||
| - name: config-failed-upload | - name: config-failed-upload | ||||
| if: ${{ failure() }} | if: ${{ failure() }} | ||||
| uses: actions/upload-artifact@v3 | uses: actions/upload-artifact@v3 | ||||
| with: | with: | ||||
| name: cmake-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.compiler }}-${{ matrix.sanitizer }}-builddir | |||||
| name: cmake-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.compiler }}-${{ matrix.config }}-builddir | |||||
| path: build | path: build | ||||
| # Build and test | # Build and test | ||||
| - name: make-binary | - name: make-binary | ||||
| run: cmake --build build --target espeak-ng | run: cmake --build build --target espeak-ng | ||||
| - name: make-data | - name: make-data | ||||
| run: ${{ matrix.sanitize_env }} ${{ matrix.runenv }} cmake --build build --target data | |||||
| run: ${{ matrix.config_env }} ${{ matrix.runenv }} cmake --build build --target data | |||||
| - name: test | - name: test | ||||
| run: | | run: | | ||||
| ${{ matrix.sanitize_env }} ${{ matrix.runenv }} cmake --build build --target tests | |||||
| ${{ matrix.sanitize_env }} ${{ matrix.runenv }} ctest --test-dir build -Ttest -j1 --output-on-failure | |||||
| ${{ matrix.config_env }} ${{ matrix.runenv }} cmake --build build --target tests | |||||
| ${{ matrix.config_env }} ${{ matrix.runenv }} ctest --test-dir build -Ttest -j1 --output-on-failure |