name: Build FreeDV (Linux)

on:
  push:
    branches-ignore:
    - 'dr-render-manual'

concurrency:
  group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }}
  cancel-in-progress: true
    
env:
  # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
  BUILD_TYPE: Debug

jobs:
  build:
    strategy:
      fail-fast: true
      matrix:
        os: [ubuntu-24.04, ubuntu-22.04]

    runs-on: ${{ matrix.os }}

    steps:
    - uses: actions/checkout@v4

    - name: Install LLVM/Clang >=20.0 (Required for RTSan)
      if: ${{ matrix.os == 'ubuntu-24.04' }}
      uses: MorganCaron/latest-clang-action@master

    - name: Install rtkit for RT threading
      shell: bash
      run: |
           sudo apt-get update
           sudo apt-get upgrade -y
           sudo apt-get install dbus-x11 rtkit libdbus-1-dev polkitd
           sudo sed -i 's/no/yes/g' /usr/share/polkit-1/actions/org.freedesktop.RealtimeKit1.policy 
           sudo systemctl restart polkit

    - name: Install common packages
      shell: bash
      run: |
           sudo apt-get install libpulse-dev libspeexdsp-dev libsamplerate0-dev sox git portaudio19-dev libhamlib-dev libasound2-dev libao-dev libgsm1-dev libsndfile-dev xvfb pipewire pulseaudio-utils pipewire-pulse wireplumber metacity at-spi2-core octave octave-signal

    - name: Install version-specific packages
      if: ${{ matrix.os == 'ubuntu-22.04' }}
      shell: bash
      run: |
           sudo apt-get install libwxgtk3.0-gtk3-dev

    - name: Install version-specific packages
      if: ${{ matrix.os == 'ubuntu-24.04' }}
      shell: bash
      run: |
           sudo apt-get install codespell libwxgtk3.2-dev
            
    - name: Spellcheck codebase
      if: ${{ matrix.os == 'ubuntu-24.04' }}
      shell: bash
      run: codespell --ignore-words-list=caf,radae,rade,inout,nin,ontop,parm,tthe,ue `find src -name '*.c*' -o -name '*.h' | grep -v 3rdparty`

    - name: Install Python required modules
      shell: bash
      working-directory: ${{github.workspace}}
      run: |
          python3 -m venv rade-venv
          . ./rade-venv/bin/activate
          pip3 install torch torchaudio --index-url https://download.pytorch.org/whl/cpu
          pip3 install matplotlib

    - name: Build freedv-gui using PortAudio
      shell: bash
      working-directory: ${{github.workspace}}
      run: |
          . ./rade-venv/bin/activate
          UT_ENABLE=1 USE_NATIVE_AUDIO=0 ./build_linux.sh 

    - name: Build freedv-gui using PulseAudio
      shell: bash
      working-directory: ${{github.workspace}}
      run: |
          . ./rade-venv/bin/activate
          BUILD_TYPE=RelWithDebInfo UT_ENABLE=1 ./build_linux.sh 

    - name: Execute unit tests
      shell: bash
      if: ${{ matrix.os == 'ubuntu-24.04' }}
      working-directory: ${{github.workspace}}/build_linux
      run: |
          sudo systemctl enable rtkit-daemon
          sudo systemctl start rtkit-daemon
          Xvfb :99 -screen 0 1024x768x16 &
          sleep 5
          export DISPLAY=:99.0
          export XDG_RUNTIME_DIR=/run/user/$(id -u)
          mkdir -p $XDG_RUNTIME_DIR
          chmod 700 $XDG_RUNTIME_DIR
          eval "$(dbus-launch --sh-syntax --exit-with-x11)"
          pipewire &
          pipewire-pulse &
          wireplumber &
          metacity --sm-disable --replace &
          sleep 5
          ln -s ${{github.workspace}}/build_linux/rade_src/model19_check3 model19_check3
          . ../rade-venv/bin/activate
          PYTHONPATH=${{github.workspace}}/build_linux/rade_src:$PYTHONPATH ctest -V
      
    - name: Instrument AddressSanitizer
      shell: bash
      if: ${{ matrix.os == 'ubuntu-24.04' }}
      working-directory: ${{github.workspace}}
      run: |
          . ./rade-venv/bin/activate
          BUILD_TYPE=RelWithDebInfo WITH_ASAN=1 UT_ENABLE=1 ./build_linux.sh 

    - name: Check for memory leaks
      shell: bash
      if: ${{ matrix.os == 'ubuntu-24.04' }}
      working-directory: ${{github.workspace}}/build_linux
      run: |
          export DISPLAY=:99.0
          export XDG_RUNTIME_DIR=/run/user/$(id -u)
          . ../rade-venv/bin/activate
          ASAN_OPTIONS=suppressions=${{github.workspace}}/test/asan_suppressions.txt LSAN_OPTIONS=suppressions=${{github.workspace}}/test/lsan_suppressions.txt PYTHONPATH=${{github.workspace}}/build_linux/rade_src:$PYTHONPATH ctest -V -R "fullduplex_(RADE|700D)|rade_reporting_clean"

    - name: Instrument RealtimeSanitizer
      shell: bash
      if: ${{ matrix.os == 'ubuntu-24.04' }}
      working-directory: ${{github.workspace}}
      run: |
          . ./rade-venv/bin/activate
          BUILD_TYPE=RelWithDebInfo WITH_RTSAN=1 UT_ENABLE=1 CC=clang CXX=clang++ ./build_linux.sh 
          
    - name: Check for RT-unsafe function calls
      shell: bash
      if: ${{ matrix.os == 'ubuntu-24.04' }}
      working-directory: ${{github.workspace}}/build_linux
      run: |
          export DISPLAY=:99.0
          export XDG_RUNTIME_DIR=/run/user/$(id -u)
          . ../rade-venv/bin/activate
          PYTHONPATH=${{github.workspace}}/build_linux/rade_src:$PYTHONPATH ctest -V -R "fullduplex_(RADE|700D)|rade_reporting_clean"

