name: Build OS

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

jobs:
  buildcompiler:
    name: Build Cross-Compiler & Toolchain
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
      with:
        submodules: recursive

    - name: Cache cross Folder
      id: cache-cross
      uses: actions/cache@v4
      with:
        path: tools/cross
        key: ${{ runner.os }}-cross-${{ hashFiles('tools/Makefile') }}

    - name: Update System
      if: steps.cache-cross.outputs.cache-hit != 'true'
      run: sudo apt update

    - name: Install GCC Dependencies
      if: steps.cache-cross.outputs.cache-hit != 'true'
      run: sudo apt --no-install-recommends -y install build-essential bison flex libgmp3-dev libmpc-dev libmpfr-dev texinfo libzstd-dev libisl-dev m4 automake gettext gperf dejagnu guile-3.0 guile-3.0-dev expect tcl autogen tex-common sphinx-common git ssh diffutils patch autoconf2.69 libtool wget dpkg

    - name: Check autoconf
      if: steps.cache-cross.outputs.cache-hit != 'true'
      run: |
        if [ "$(autoconf --version | head -n 1 | awk '{print $NF}')" != "2.69" ]; then
          echo "Autoconf version is not 2.69, performing additional steps..."
          wget https://launchpad.net/ubuntu/+archive/primary/+files/autoconf_2.69-11.1_all.deb
          sudo dpkg --force-all -i ./autoconf_2.69-11.1_all.deb
        fi

    - name: Check automake
      if: steps.cache-cross.outputs.cache-hit != 'true'
      run: |
        if [ "$(automake --version | head -n 1 | awk '{print $NF}')" != "1.15.1" ]; then
          echo "Automake version is not 1.15.1, performing additional steps..."
          wget https://ftp.gnu.org/gnu/automake/automake-1.15.1.tar.gz
          tar -xzf automake-1.15.1.tar.gz
          cd automake-1.15.1
          ./configure
          make
          sudo make install
        fi

    - name: Clone All
      if: steps.cache-cross.outputs.cache-hit != 'true'
      run: make --quiet -C tools __clone_all_no_qemu

    - name: Compile Binutils
      if: steps.cache-cross.outputs.cache-hit != 'true'
      run: make --quiet -C tools do_binutils

    - name: Compile GCC
      if: steps.cache-cross.outputs.cache-hit != 'true'
      run: make --quiet -C tools do_gcc

    - name: Clean Up
      if: steps.cache-cross.outputs.cache-hit != 'true'
      run: |
        cd tools
        rm -rf binutils-gdb gcc

  analyze:
    name: Analyze (${{ matrix.language }})
    runs-on: ubuntu-latest
    needs: [buildcompiler]
    permissions:
      security-events: write
      packages: read
      actions: read
      contents: read

    defaults:
      run:
        shell: bash

    strategy:
      fail-fast: false
      matrix:
        include:
        - language: c-cpp
          build-mode: manual

    steps:
    - name: Checkout repository
      uses: actions/checkout@v4

    - name: Check for cache
      id: check-cache
      run: |
        if [ -z "${{ runner.os }}-cross-${{ hashFiles('tools/Makefile') }}" ]; then
          echo "No cache found, cancelling job."
          exit 1
        fi

    - name: Initialize CodeQL
      uses: github/codeql-action/init@v3
      with:
        languages: ${{ matrix.language }}
        build-mode: ${{ matrix.build-mode }}

    - if: matrix.build-mode == 'manual'
      shell: bash
      run: |
        echo 'If you are using a "manual" build mode for one or more of the' \
          'languages you are analyzing, replace this with the commands to build' \
          'your code, for example:'
        echo '  make bootstrap'
        echo '  make release'
        exit 0

    - name: Install Packages
      run: |
        sudo apt update
        sudo apt --no-install-recommends -y install rustc xorriso mtools genisoimage ovmf nasm doxygen make gcc-mingw-w64-x86-64 gcc-mingw-w64-i686 mingw-w64 build-essential bison flex libgmp3-dev libmpc-dev libmpfr-dev texinfo
        make --quiet -C tools do_limine
        make --quiet prepare

    - name: Cache cross
      id: cache-cross
      uses: actions/cache@v4
      with:
        path: tools/cross
        key: ${{ runner.os }}-cross-${{ hashFiles('tools/Makefile') }}

    - name: Build OS
      run: |
        make build_userspace
        make build_drivers
        make build_kernel
        make build_userspace

    - name: Perform CodeQL Analysis
      uses: github/codeql-action/analyze@v3
      with:
        category: "/language:${{matrix.language}}"

  deploydoc:
    name: Deploy Documentation to GitHub Pages
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          submodules: recursive

      - name: Update System
        run: sudo apt update

      - name: Install Doxygen
        run: sudo apt --no-install-recommends -y install doxygen make

      - name: Generate Documentation
        run: make doxygen

      - name: Copy GitHub Pages Website
        run: cp -r tools/website/* doxygen-doc/

      - name: Deploy documentation
        uses: JamesIves/github-pages-deploy-action@v4
        with:
          folder: doxygen-doc

  compile_amd64:
    name: Build amd64
    runs-on: ubuntu-latest
    needs: [buildcompiler]
    steps:
    - uses: actions/checkout@v4
      with:
        submodules: recursive

    - name: Update & Install Required Packages
      run: |
        sudo apt update
        sudo apt --no-install-recommends -y install rustc xorriso mtools genisoimage ovmf nasm doxygen make meson gcc-10 g++-10 gcc-mingw-w64-x86-64 gcc-mingw-w64-i686 mingw-w64
        make --quiet -C tools do_limine
        make --quiet prepare

    - name: Cache cross Folder
      id: cache-cross
      uses: actions/cache@v4
      with:
        path: tools/cross
        key: ${{ runner.os }}-cross-${{ hashFiles('tools/Makefile') }}

    - name: Configure config.mk
      run: sed -i 's/.*OSARCH = .*/OSARCH = amd64/' ./config.mk && cat config.mk | grep OSARCH

    - name: Compile Debug and Release ISO
      run: |
        make build
        mv Fennix.iso Fennix-debug.iso
        make clean
        sed -i 's/.*DEBUG = .*/DEBUG = 0/' ./config.mk && cat config.mk | grep DEBUG
        make build
        mv Fennix.iso Fennix-release.iso

    - name: Upload Artifact (Fennix-debug.iso)
      uses: actions/upload-artifact@v4
      with:
        name: Fennix-amd64-debug
        path: Fennix-debug.iso

    - name: Upload Artifact (Fennix-release.iso)
      uses: actions/upload-artifact@v4
      with:
        name: Fennix-amd64-release
        path: Fennix-release.iso

  compile_i386:
    name: Build i386
    runs-on: ubuntu-latest
    needs: [buildcompiler]
    steps:
    - uses: actions/checkout@v4
      with:
        submodules: recursive

    - name: Update & Install Required Packages
      run: |
        sudo apt update
        sudo apt --no-install-recommends -y install rustc xorriso mtools genisoimage ovmf nasm doxygen make meson gcc-10 g++-10 gcc-mingw-w64-x86-64 gcc-mingw-w64-i686 mingw-w64
        make --quiet -C tools do_limine
        make --quiet prepare

    - name: Cache cross Folder
      id: cache-cross
      uses: actions/cache@v4
      with:
        path: tools/cross
        key: ${{ runner.os }}-cross-${{ hashFiles('tools/Makefile') }}

    - name: Configure config.mk
      run: sed -i 's/.*OSARCH = .*/OSARCH = i386/' ./config.mk && cat config.mk | grep OSARCH

    - name: Compile Debug and Release ISO
      run: |
        make build
        mv Fennix.iso Fennix-debug.iso
        make clean
        sed -i 's/.*DEBUG = .*/DEBUG = 0/' ./config.mk && cat config.mk | grep DEBUG
        make build
        mv Fennix.iso Fennix-release.iso

    - name: Upload Artifact (Fennix-debug.iso)
      uses: actions/upload-artifact@v4
      with:
        name: Fennix-i386-debug
        path: Fennix-debug.iso

    - name: Upload Artifact (Fennix-release.iso)
      uses: actions/upload-artifact@v4
      with:
        name: Fennix-i386-release
        path: Fennix-release.iso

  compile_aarch64:
    name: Build aarch64
    runs-on: ubuntu-latest
    needs: [buildcompiler]
    steps:
    - uses: actions/checkout@v4
      with:
        submodules: recursive

    - name: Update & Install Required Packages
      run: |
        sudo apt update
        sudo apt --no-install-recommends -y install rustc xorriso mtools genisoimage ovmf nasm doxygen make meson gcc-10 g++-10 gcc-mingw-w64-x86-64 gcc-mingw-w64-i686 mingw-w64
        make --quiet -C tools do_limine
        make --quiet prepare

    - name: Cache cross Folder
      id: cache-cross
      uses: actions/cache@v4
      with:
        path: tools/cross
        key: ${{ runner.os }}-cross-${{ hashFiles('tools/Makefile') }}

    - name: Configure config.mk
      run: sed -i 's/.*OSARCH = .*/OSARCH = aarch64/' ./config.mk && cat config.mk | grep OSARCH

    - name: Compile Debug and Release ISO
      run: |
        make build
        mv Fennix.iso Fennix-debug.iso
        make clean
        sed -i 's/.*DEBUG = .*/DEBUG = 0/' ./config.mk && cat config.mk | grep DEBUG
        make build
        mv Fennix.iso Fennix-release.iso

    - name: Upload Artifact (Fennix-debug.iso)
      uses: actions/upload-artifact@v4
      with:
        name: Fennix-aarch64-debug
        path: Fennix-debug.iso

    - name: Upload Artifact (Fennix-release.iso)
      uses: actions/upload-artifact@v4
      with:
        name: Fennix-aarch64-release
        path: Fennix-release.iso

  compile_arm:
    name: Build arm
    runs-on: ubuntu-latest
    needs: [buildcompiler]
    steps:
    - uses: actions/checkout@v4
      with:
        submodules: recursive

    - name: Update & Install Required Packages
      run: |
        sudo apt update
        sudo apt --no-install-recommends -y install rustc xorriso mtools genisoimage ovmf nasm doxygen make meson gcc-10 g++-10 gcc-mingw-w64-x86-64 gcc-mingw-w64-i686 mingw-w64
        make --quiet -C tools do_limine
        make --quiet prepare

    - name: Cache cross Folder
      id: cache-cross
      uses: actions/cache@v4
      with:
        path: tools/cross
        key: ${{ runner.os }}-cross-${{ hashFiles('tools/Makefile') }}

    - name: Configure config.mk
      run: sed -i 's/.*OSARCH = .*/OSARCH = arm/' ./config.mk && cat config.mk | grep OSARCH

    - name: Compile Debug and Release ISO
      run: |
        make build
        mv Fennix.iso Fennix-debug.iso
        make clean
        sed -i 's/.*DEBUG = .*/DEBUG = 0/' ./config.mk && cat config.mk | grep DEBUG
        make build
        mv Fennix.iso Fennix-release.iso

    - name: Upload Artifact (Fennix-debug.iso)
      uses: actions/upload-artifact@v4
      with:
        name: Fennix-arm-debug
        path: Fennix-debug.iso

    - name: Upload Artifact (Fennix-release.iso)
      uses: actions/upload-artifact@v4
      with:
        name: Fennix-arm-release
        path: Fennix-release.iso
