# Some convenient links:
# - https://github.com/actions/virtual-environments/blob/master/images/win/Windows2019-Readme.md
#

name: CI-windows

on: [push,pull_request]

defaults:
  run:
    shell: cmd
    
jobs:

  build:
    strategy:
      matrix:
        os: [windows-2019, windows-2022]
        arch: [x64, x86]
        qt_ver: ['', 5.15.2, 6.2.4, 6.3.0]
      fail-fast: false

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

    env:
      # see https://www.pcre.org/original/changelog.txt
      PCRE_VERSION: 8.45

    steps:
      - uses: actions/checkout@v2
        if: matrix.arch == 'x64' || matrix.qt_ver == ''

      - name: Set up Python 3.10
        if: matrix.qt_ver == ''
        uses: actions/setup-python@v2
        with:
          python-version: '3.10'

      - name: Set up Visual Studio environment
        uses: ilammy/msvc-dev-cmd@v1
        with:
          arch: ${{ matrix.arch }}

      - name: Cache PCRE
        id: cache-pcre
        uses: actions/cache@v2
        if: matrix.arch == 'x64' || matrix.qt_ver == ''
        with:
          path: pcre-${{ env.PCRE_VERSION }}.zip
          key: pcre-${{ env.PCRE_VERSION }}

      - name: Download PCRE
        if: (matrix.arch == 'x64' || matrix.qt_ver == '') && steps.cache-pcre.outputs.cache-hit != 'true'
        run: |
          curl -fsSL https://github.com/pfultz2/pcre/archive/refs/tags/%PCRE_VERSION%.zip -o pcre-%PCRE_VERSION%.zip || exit /b !errorlevel!

      - name: Install PCRE
        if: matrix.arch == 'x64' || matrix.qt_ver == ''
        run: |
          7z x pcre-%PCRE_VERSION%.zip || exit /b !errorlevel!
          cd pcre-%PCRE_VERSION% || exit /b !errorlevel!
          cmake . -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=Release -DPCRE_BUILD_PCRECPP=Off -DPCRE_BUILD_TESTS=Off -DPCRE_BUILD_PCREGREP=Off || exit /b !errorlevel!
          nmake || exit /b !errorlevel!
          copy pcre.h ..\externals || exit /b !errorlevel!
          if "${{ matrix.arch }}" == "x86" (
            copy pcre.lib ..\externals\pcre.lib || exit /b !errorlevel!
          ) else (
            copy pcre.lib ..\externals\pcre64.lib || exit /b !errorlevel!
          )
        env:
          CL: /MP

      - name: Cache Qt ${{ matrix.qt_ver }}
        if: matrix.qt_ver != '' && matrix.arch == 'x64'
        id: cache-qt
        uses: actions/cache@v1  # not v2!
        with:
          path: ../Qt
          key: Windows-QtCache-${{ matrix.qt_ver }}-qtcharts

      # no 32-bit Qt available
      - name: Install Qt ${{ matrix.qt_ver }}
        if: matrix.qt_ver != '' && matrix.arch == 'x64'
        uses: jurplel/install-qt-action@v3
        with:
          aqtversion: '==2.0.6'
          version: ${{ matrix.qt_ver }}
          modules: 'qtcharts'
          cached: ${{ steps.cache-qt.outputs.cache-hit }}

      - name: Install missing Python packages
        if: matrix.qt_ver == ''
        run: |
          python -m pip install pip --upgrade || exit /b !errorlevel!
          python -m pip install pytest || exit /b !errorlevel!
          python -m pip install pytest-custom_exit_code || exit /b !errorlevel!

      - name: Build GUI release (qmake)
        if: startsWith(matrix.qt_ver, '5') && matrix.arch == 'x64'
        run: |
          cd gui || exit /b !errorlevel!
          qmake HAVE_QCHART=yes || exit /b !errorlevel!
          nmake release || exit /b !errorlevel!
        env:
          CL: /MP
      
      - name: Deploy GUI
        if: startsWith(matrix.qt_ver, '5') && matrix.arch == 'x64'
        run: |
          windeployqt Build\gui || exit /b !errorlevel!
          del Build\gui\cppcheck-gui.ilk || exit /b !errorlevel!
          del Build\gui\cppcheck-gui.pdb || exit /b !errorlevel!

      - name: Build GUI release (CMake)
        if: startsWith(matrix.qt_ver, '6') && matrix.arch == 'x64'
        run: |
          md build || exit /b !errorlevel!
          cd build || exit /b !errorlevel!
          cmake -DBUILD_GUI=On -DWITH_QCHART=On -DUSE_QT6=On .. || exit /b !errorlevel!
          cmake --build . --target cppcheck-gui || exit /b !errorlevel!

      # TODO: deploy with Qt6

      - name: Run CMake
        if: false && matrix.qt_ver == ''
        run: |
          set ARCH=${{ matrix.arch }}
          if "${{ matrix.arch }}" == "x86" (
            set ARCH=Win32
          )
          md build || exit /b !errorlevel!
          cd build || exit /b !errorlevel!
          cmake -DBUILD_TESTS=On .. || exit /b !errorlevel!

      - name: Build CLI debug configuration using MSBuild
        if: matrix.qt_ver == ''
        run: |
          set ARCH=${{ matrix.arch }}
          if "${{ matrix.arch }}" == "x86" (
            set ARCH=Win32
          )
          :: cmake --build build --target check --config Debug || exit /b !errorlevel!
          msbuild -m cppcheck.sln /p:Configuration=Debug-PCRE;Platform=%ARCH% -maxcpucount || exit /b !errorlevel!

      - name: Run Debug test
        if: matrix.qt_ver == ''
        run: .\bin\debug\testrunner.exe || exit /b !errorlevel!

      - name: Build CLI release configuration using MSBuild
        if: matrix.qt_ver == ''
        run: |
          set ARCH=${{ matrix.arch }}
          if "${{ matrix.arch }}" == "x86" (
            set ARCH=Win32
          )
          :: cmake --build build --target check --config Release || exit /b !errorlevel!
          msbuild -m cppcheck.sln /p:Configuration=Release-PCRE;Platform=%ARCH% -maxcpucount || exit /b !errorlevel!

      - name: Run Release test
        if: matrix.qt_ver == ''
        run: .\bin\testrunner.exe || exit /b !errorlevel!

      - name: Run test/cli
        if: matrix.qt_ver == ''
        run: |
          :: since FILESDIR is not set copy the binary to the root so the addons are found
          :: copy .\build\bin\Release\cppcheck.exe .\cppcheck.exe || exit /b !errorlevel!
          copy .\bin\cppcheck.exe .\cppcheck.exe || exit /b !errorlevel!
          copy .\bin\cppcheck-core.dll .\cppcheck-core.dll || exit /b !errorlevel!
          cd test/cli || exit /b !errorlevel!
          :: python -m pytest --suppress-no-test-exit-code test-clang-import.py || exit /b !errorlevel!
          python -m pytest test-helloworld.py || exit /b !errorlevel!
          python -m pytest test-inline-suppress.py || exit /b !errorlevel!
          python -m pytest test-more-projects.py || exit /b !errorlevel!
          python -m pytest test-proj2.py || exit /b !errorlevel!
          python -m pytest test-suppress-syntaxError.py || exit /b !errorlevel!

      - name: Test addons
        if: matrix.qt_ver == ''
        run: |
          .\cppcheck --addon=threadsafety addons\test\threadsafety || exit /b !errorlevel!
          .\cppcheck --addon=threadsafety --std=c++03 addons\test\threadsafety || exit /b !errorlevel!
          .\cppcheck --addon=misra --inline-suppr --enable=information --error-exitcode=1 addons\test\misra\misra-ctu-*-test.c || exit /b !errorlevel!
          cd addons\test
          rem We'll force C89 standard to enable an additional verification for
          rem rules 5.4 and 5.5 which have standard-dependent options.
          ..\..\cppcheck --dump -DDUMMY --suppress=uninitvar --inline-suppr misra\misra-test.c --std=c89 --platform=unix64 || exit /b !errorlevel!
          python3 ..\misra.py -verify misra\misra-test.c.dump || exit /b !errorlevel!
          rem TODO: do we need to verify something here?
          ..\..\cppcheck --dump -DDUMMY --suppress=uninitvar --suppress=uninitStructMember --std=c89 misra\misra-test.h || exit /b !errorlevel!
          ..\..\cppcheck --dump misra\misra-test.cpp || exit /b !errorlevel!
          python3 ..\misra.py -verify misra\misra-test.cpp.dump || exit /b !errorlevel!
          python3 ..\misra.py --rule-texts=misra\misra2012_rules_dummy_ascii.txt -verify misra\misra-test.cpp.dump || exit /b !errorlevel!
          python3 ..\misra.py --rule-texts=misra\misra2012_rules_dummy_utf8.txt -verify misra\misra-test.cpp.dump || exit /b !errorlevel!
          python3 ..\misra.py --rule-texts=misra\misra2012_rules_dummy_windows1250.txt -verify misra\misra-test.cpp.dump || exit /b !errorlevel!
          ..\..\cppcheck --addon=misra --platform=avr8 --error-exitcode=1 misra\misra-test-avr8.c || exit /b !errorlevel!
          ..\..\cppcheck --dump misc-test.cpp || exit /b !errorlevel!
          python3 ..\misc.py -verify misc-test.cpp.dump || exit /b !errorlevel!
          ..\..\cppcheck --dump naming_test.c || exit /b !errorlevel!
          rem TODO: fix this - does not fail on Linux
          rem python3 ..\naming.py --var='[a-z].*' --function='[a-z].*' naming_test.c.dump || exit /b !errorlevel!
          ..\..\cppcheck --dump naming_test.cpp || exit /b !errorlevel!
          python3 ..\naming.py --var='[a-z].*' --function='[a-z].*' naming_test.cpp.dump || exit /b !errorlevel!
          ..\..\cppcheck --dump namingng_test.c || exit /b !errorlevel!
          python3 ..\namingng.py --configfile ..\naming.json --verify namingng_test.c.dump || exit /b !errorlevel!