#!/bin/bash
export LANG=en_US.UTF-8

# compile.sh
# depends : libncurses5 libncurses5-dev debhelper libssl-dev libelf-dev libdw-dev flex bison fakeroot build-essential
# v1 2024-04-28 compile
# v2 2024-09-24 wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-x.y.z.tar.xz
# v3 2024-12-09 parse ChangeLog : awk only commmit, author, date and title from kernel.org ChangeLog
# v3.1 2024-12-10 parse version argument to get major version
# v3.2 2025-12-07 add -localversion argument to set LOCALVERSION
# v3.3 2025-12-19 add move previous files to debs directory

## TODO

## /TODO

# Check dependencies
DEPENDENCIES=(
    'libncurses5'
    'libncurses5-dev'
    'debhelper'
    'libssl-dev'
    'libelf-dev'
    'libdw-dev'
    'flex'
    'bison'
    'fakeroot'
    'build-essential'
)

for i in "${DEPENDENCIES[@]}"; do
    dpkg -s $i > /dev/null 2>&1;
       if [ $? == 1 ]; then
          echo >&2 "'$i' package is required, but not available. Aborting.";
          exit 1;
       fi
done

# Check if the number of arguments provided is zero
if [ $# -eq 0 ]; then
    echo "Usage: $0  [-localversion ]"
    exit 1
fi

# Capture the first argument
arg=$1

# Define a regular expression to match the Kernel version format x.y(.z)
regex='^[0-9]+\.[0-9]+(\.[0-9]+)?$'

# Validate the argument against the regular expression
if ! [[ "$arg" =~ $regex ]]; then
    # Output an error message if the argument does not match the expected format
    echo -e "Error: Invalid Kernel version format.\nPlease provide a Kernel version in the 'x.y(.z)' format." >&2
    exit 1
fi

# Extract the part before the first dot
version="$arg"
major_version="${version%%.*}"
# Check if the extracted part is a digit(s)
if [[ "$major_version" =~ ^[0-9]+$ ]]; then
  echo "The Kernel major version is: $major_version"
else
  echo "The part before the first dot is not a digit(s)."
  exit 1
fi

# Parse optional -localversion option
CUSTOM_LOCALVERSION=""
while [[ $# -gt 0 ]]; do
  case "$1" in
    -localversion)
      shift
      if [[ -n "$1" && "$1" =~ ^[0-9]{8}$ ]]; then
        CUSTOM_LOCALVERSION="$1"
      else
        echo "Please specify localversion in YYYYMMDD format." >&2
        exit 1
      fi
      ;;
    *)
      ;;
  esac
  shift
done

# Move previous files to debs directory
# Enable nullglob so that unmatched patterns are removed from the loop
shopt -s nullglob
# Create the target directory if it doesn't exist
mkdir -p debs
# List of patterns to match
patterns=(
  "linux-headers-*.deb"
  "linux-image-*.deb"
  "ChangeLog-*"
  "parsed-ChangeLog-*"
)
# Loop over each pattern, then over each file that matches it
for pattern in "${patterns[@]}"; do
  for file in $pattern; do
    if [[ -e "$file" ]]; then
      mv "$file" debs/
      echo "Moved: $file -> debs/"
    fi
  done
done
# Disable nullglob – this restores the default pattern‑expansion behaviour
shopt -u nullglob

dir=linux-"$arg"
tarball=linux-"$arg".tar.xz
changelog=ChangeLog-$arg

## https://cdn.kernel.org/pub/linux/kernel/v6.x/ChangeLog-6.12.4
# Check if directory already exists
if [ -f "$changelog" ]; then
    echo "File $changelog exists."
else
    # Check if ChangeLog file exists, if not download it
    if [ ! -f "$changelog" ]; then
        echo -e "File $changelog does not exist,\ndownloading $changelog from https://kernel.org/"
        wget --continue --limit-rate=10000k "https://cdn.kernel.org/pub/linux/kernel/v$major_version.x/$changelog"
        if [ $? -ne 0 ]; then
            echo "Download failed. Exiting."
            exit 1
        fi
    fi
fi

## parse kernel.org ChangeLog
# Start processing
echo "Start parsing $changelog ..."
# Use awk to process the file
awk '
/^commit / {
    commit = $0
    next
}
/^Author: / {
    author = $0
    next
}
/^Date: / {
    date = $0
    next
}
/^    / {
    if (commit != "" && author != "" && date != "") {
        print commit
        print author
        print date
        print $0
        print ""
        commit = ""
        author = ""
        date = ""
    }
}
' "$changelog" > parsed-$changelog
# End processing
echo "Finished parsing $changelog ..."

# Cleanup existing files except filenames that match $arg, the current script ($0) and specific files
for file in *; do
    if [[ ! ("$file" =~ (^.*)$arg(.*) || "$file" == $0 || "$file" == "debs" || "$file" == "compile-linux-20231107.txt" || "$file" == "compile.sh" || "$file" =~ (^compile_v([0-9]\.[0-9])\.sh) || "$file" == "parse-ChangeLog.sh") ]]; then
        echo "Deleting $file"
        rm -rf "$file"
    fi
done

# Check if directory already exists
if [ -d "$dir" ]; then
    echo "Directory $dir exists."
else
    # Check if archive file exists, if not download it
    if [ ! -f "$tarball" ]; then
        echo -e "File $tarball does not exist,\ndownloading $tarball from https://kernel.org/"
        wget --continue --limit-rate=10000k "https://cdn.kernel.org/pub/linux/kernel/v$major_version.x/$tarball"
        if [ $? -ne 0 ]; then
            echo "Download failed. Exiting."
            exit 1
        fi
    fi

    # Extract the archive
    echo -e "Directory $dir does not exist,\nextracting archive $tarball ..."
    if ! tar xf "$tarball"; then
        echo "Failed to extract $tarball. Exiting."
        exit 1
    fi
fi

# Change directory to the extracted directory
if ! cd "$dir"; then
    echo "Failed to change directory to $dir"
    exit 1
fi
pwd

# Uncomment the following lines if you want to configure and build the kernel
#cp /boot/config-6.13.6-20250308 .config && yes "" | make oldconfig
cp /boot/config-`uname -r` .config && yes "" | make oldconfig
#make menuconfig
##Kernel hacking > Compile-time checks and compiler options > DEBUG_INFO 
##(X) Disable debug information = set CONFIG_DEBUG_INFO_NONE=y
#fakeroot make bindeb-pkg -j$(nproc) LOCALVERSION=-20251029 KDEB_PKGVERSION=1+i
# Use CUSTOM_LOCALVERSION if supplied with --version argument
if [[ -n "$CUSTOM_LOCALVERSION" ]]; then
  fakeroot make bindeb-pkg -j$(nproc) LOCALVERSION=-${CUSTOM_LOCALVERSION} KDEB_PKGVERSION=1+i
#echo ${CUSTOM_LOCALVERSION}
else
  fakeroot make bindeb-pkg -j$(nproc) LOCALVERSION=-$(date +%Y%m%d) KDEB_PKGVERSION=1+i
#echo $(date +%Y%m%d)
fi
# Beep to notify the user
beep
Then save this as compile-kernel.sh, chmod +x compile-kernel.sh and launch with :

./compile.sh 6.18.19
or :

./compile.sh 6.18.19 -localversion 20260319