name: Build+Upload MCXCL and Octave/MATLAB mex
on:
  push:
    branches:
      - master
    tags:
      - '*'
  pull_request:
    branches:
      - master

jobs:
  build_all:
    name: Build All
    strategy:
      matrix:
        os: [ubuntu-22.04, ubuntu-24.04, macos-15-intel, macos-14, windows-2022]
    runs-on: ${{ matrix.os }}
    defaults:
      run:
        shell: bash
    steps:
      - name: Checkout repo
        uses: actions/checkout@v3
        with:
          submodules: 'recursive'
      - name: Install dependencies (Linux only, except 24.04)
        if: ${{ runner.os == 'Linux' && matrix.os != 'ubuntu-24.04' }}
        run: sudo apt-get update && sudo apt-get install -y ocl-icd-libopencl1 opencl-headers ocl-icd-opencl-dev liboctave-dev upx-ucl
      - name: Install dependencies (Linux, 24.04 only)
        if: ${{ matrix.os == 'ubuntu-24.04' }}
        run: sudo apt-get update && sudo apt-get install -y ocl-icd-libopencl1 opencl-headers ocl-icd-opencl-dev octave-dev upx-ucl
      - name: Install dependencies (MacOS only)
        if: ${{ runner.os == 'macOS' && matrix.os != 'macos-14' }}
        run: |
          curl -L -o Octave-9.2-Intel.dmg --insecure https://github.com/octave-app/octave-app/releases/download/v9.2/Octave-9.2-Intel.dmg
          xattr -c Octave-*.dmg
          sudo hdiutil attach Octave-9.2-Intel.dmg
          sudo cp -a /Volumes/Octave\ 9.2/Octave-9.2.app /Applications
          sudo hdiutil detach /Volumes/Octave\ 9.2
          rm -rf Octave-9.2-Intel.dmg
          echo "/Applications/Octave-9.2.app/Contents/Resources/usr/Cellar/octave-octapp@9.2.0/9.2.0/bin" >> $GITHUB_PATH
      - name: Install dependencies (MacOS only)
        if: ${{ runner.os == 'macOS' }}
        run: |
          brew install octave
          brew install gcc@12
          #brew install upx
      - name: Install dependencies (Windows only)
        if: ${{ runner.os == 'Windows' }}
        run: |
          #choco install octave.portable --version=9.2.0
          echo 'C:\ProgramData\chocolatey\lib\octave.portable\tools\octave\mingw64\bin' >> $GITHUB_PATH
          curl --retry 3 -kL https://ftpmirror.gnu.org/octave/windows/octave-9.2.0-w64.7z --output octave_9.2.7z
          7z x octave_9.2.7z -ooctave -y
          rm -rf octave_9.2.7z
          echo "$PWD/octave/octave-9.2.0-w64/mingw64/bin" >> $GITHUB_PATH
          choco install upx
          choco install mingw --version=8.1.0
          echo 'C:\ProgramData\Chocolatey\lib\mingw\tools\install\mingw64\bin\' >> $GITHUB_PATH
          echo 'MW_MINGW64_LOC=/c/ProgramData/Chocolatey/lib/mingw/tools/install/mingw64' >> $GITHUB_ENV
      - name: Install OpenCL.dll and static libraries (Windows only)
        if: ${{ runner.os == 'Windows' }}
        run: |
          vcpkg --triplet=x64-windows install opencl
          cp 'c:\vcpkg\packages\opencl_x64-windows\bin\OpenCL.dll' 'c:\Windows\System32'
      - name: Set up MATLAB (non-MacOS14)
        if: ${{ runner.os != 'macOS' }}
        uses: matlab-actions/setup-matlab@v1
        with:
          release: R2022a
      - name: Set up MATLAB (MacOS-14)
        if: ${{ runner.os == 'macOS' }}
        uses: matlab-actions/setup-matlab@v2
        with:
          release: R2023b
      - name: Update RCS keywords
        run: |
          printf '\n[filter "rcs-keywords"]\n\tclean  = .git_filters/rcs-keywords.clean\n\tsmudge = .git_filters/rcs-keywords.smudge %f\n' >> .git/config
          rm -rf src/*.c
          git checkout src/*.c
      - name: Build mcxlabcl for Octave
        run: |
          cd src
          which gcc
          gcc -v
          mkoctfile --version
          mkoctfile -p OCTLIBDIR
          if [[ "$RUNNER_OS" == "Linux" ]]; then
            make oct MEXLINKOPT="-static-libgcc -static-libstdc++ -Wl,-Bstatic -lc -lm -lstdc++ -pthread -Wl,-Bdynamic" EXTRALIB="-v -s"
            ldd ../mcxlabcl/mcxcl.mex
          elif [[ "$RUNNER_OS" == "macOS" ]]; then
            make oct CC=gcc-12 CXX=g++-12 LDFLAGS='-static-libgcc -static-libstdc++' EXTRALIB='-v'
            otool -L ../mcxlabcl/mcxcl.mex
          else
            PATH="$PWD/../octave/octave-9.2.0-w64/mingw64/bin":$PATH
            make oct CC=gcc CXX=g++ LIBOPENCL='/c/Windows/System32/OpenCL.dll --verbose' MEXLINKOPT='-static-libgcc -static-libstdc++ -Wl,-Bstatic -lm -Wl,-Bdynamic -v'
            objdump -p ../mcxlabcl/mcxcl.mex | grep "DLL Name:"
            make clean
          fi
          octave-cli --eval "fprintf(1,['OCTAVE_ARCH=' regexprep(computer('arch'), 'darwin[0-9.]+-', 'darwin-')])"
          octave-cli --eval "fprintf(1,['OCTAVE_ARCH=' regexprep(computer('arch'), 'darwin[0-9.]+-', 'darwin-')])" >> $GITHUB_ENV
      - name: Build mcxlabcl for MATLAB
        run: |
          cd src
          if [[ "$RUNNER_OS" == "Windows" ]]; then
            make mex CC=gcc CXX=g++ LDFLAGS="-static libzmat.a" EXTRALIB="-Lc:/ProgramData/chocolatey/lib/mingw/tools/install/mingw64/x86_64-w64-mingw32/lib -v"
            objdump -p ../mcxlabcl/mcxcl.mexw* | grep "DLL Name:"
          elif [[ "$RUNNER_OS" == "macOS" ]]; then
            which mex
            make mex CC=gcc-12 CXX=g++-12 MEXLINKOPT="-static-libstdc++"
            otool -L ../mcxlabcl/mcxcl.mex*
          else
            make mex MEXLINKOPT="-static-libgcc -static-libstdc++ -Wl,-Bstatic -lstdc++ -lpthread -Wl,-Bdynamic" EXTRALIB="-v"
            ldd ../mcxlabcl/mcxcl.mex*
          fi
      - name: Build binary
        run: |
          cd src
          make clean
          if [[ "$RUNNER_OS" == "Linux" ]]; then
            make static USERARFLAGS="-Wl,-Bstatic -lm -Wl,-Bdynamic"
            ldd ../bin/mcxcl
          elif [[ "$RUNNER_OS" == "macOS" ]]; then
            make CC=gcc-12 CXX=g++-12
            otool -L ../bin/mcxcl
          else
            make CC=gcc CXX=g++ USERARFLAGS="-Lc:/ProgramData/chocolatey/lib/mingw/tools/install/mingw64/x86_64-w64-mingw32/lib -Lc:/ghcup/ghc/9.0.2/mingw/lib -Lc:/ghcup/ghc/9.0.2/mingw/x86_64-w64-mingw32/lib libzmat.a"
            objdump -p ../bin/mcxcl.exe | grep "DLL Name:"
          fi
      - name: Create package folder
        run: |
          mkdir packages
          mkdir -p mcxlabcl/octave/${{ env.OCTAVE_ARCH }}
      - name: Create release tag
        run: perl -e "print 'RELEASE_TAG='. lc('${{ runner.os }}-${{ runner.arch }}-github-latest')" >> $GITHUB_ENV
      - name: Zip mcxlabcl
        run: |
          if [[ "$RUNNER_OS" != "macOS" ]]; then
            upx -9 mcxlabcl/mcxcl.mex* || true
          fi
          mv mcxlabcl/mcxcl.mex mcxlabcl/octave/${{ env.OCTAVE_ARCH }}
          if [[ "$RUNNER_OS" == "Windows" ]]; then
            cp "$PWD/octave/octave-9.2.0-w64/mingw64/bin/libwinpthread-1.dll" mcxlabcl/octave/${{ env.OCTAVE_ARCH }}
            rm -rf "$PWD/octave/"
            upx -9 mcxlabcl/octave/${{ env.OCTAVE_ARCH }}/* || true
            7z a -tzip packages/mcxlabcl-${{ env.RELEASE_TAG }}.zip mcxlabcl
          else
            zip -FSr --symlink packages/mcxlabcl-${{ env.RELEASE_TAG }}.zip mcxlabcl
          fi
      - name: Upload mcxlabcl package
        if: ${{ matrix.os == 'ubuntu-22.04' || matrix.os == 'macos-15-intel' || matrix.os == 'macos-14' || matrix.os == 'windows-2022' }}
        uses: actions/upload-artifact@v4
        with:
          name: all-mcxlabcl-packages-${{ env.RELEASE_TAG }}
          path: packages/mcxlabcl-${{ env.RELEASE_TAG }}.zip
      - name: Prepare mcxcl package
        run: |
          rm -rf .git mcxlabcl src .git_filters .gitattributes .github .travis.yml deploy
      - name: Zip mcxcl
        run: |
          cd .. && pwd
          if [[ "$RUNNER_OS" != "macOS" ]]; then
            upx -9 mcxcl/bin/*
          fi
          if [[ "$RUNNER_OS" == "Windows" ]]; then
            7z a -tzip mcxcl/packages/mcxcl-${{ env.RELEASE_TAG }}.zip mcxcl -xr!mcxcl/packages
          else
            zip -FSr --symlink mcxcl/packages/mcxcl-${{ env.RELEASE_TAG }}.zip mcxcl -x 'mcxcl/packages*'
          fi
      - name: Upload mcxcl package
        if: ${{ matrix.os == 'ubuntu-22.04' || matrix.os == 'macos-15-intel' || matrix.os == 'macos-14' || matrix.os == 'windows-2022' }}
        uses: actions/upload-artifact@v4
        with:
          name: all-mcxcl-packages-${{ env.RELEASE_TAG }}
          path: packages/mcxcl-${{ env.RELEASE_TAG }}.zip

  upload_package:
    name: Upload Packages
    needs: build_all
    runs-on: ubuntu-22.04
    if: ${{ github.repository_owner == 'fangq' && github.event_name != 'pull_request'}}
    steps:
      - name: Download mcxcl
        uses: actions/download-artifact@v4
        with:
          pattern: all-mcx*-packages-*
          merge-multiple: true
          path: packages
      - name: Create all-in-one mcxlabcl package
        run: |
          cd packages
          unzip -n 'mcxlabcl*.zip'
          tree .
          zip -FSr --symlink mcxlabcl-allinone-github-latest.zip mcxlabcl
          rm -rf mcxlabcl
      - name: Display structure of downloaded files
        run: ls -R packages
      - name: Copy package to server
        if: ${{ github.repository_owner == 'fangq' && github.event_name != 'pull_request'}}
        uses: wlixcc/SFTP-Deploy-Action@v1.2.4
        with:
          server: ${{ secrets.MCX_SERVER }}
          username: ${{ secrets.MCX_SERVER_USER }}
          ssh_private_key: ${{ secrets.MCX_SERVER_SSH_KEY }}
          local_path: "packages/*"
          remote_path: ${{ secrets.MCX_CI_PATH }}
