compile kernel from kernel.org
#!/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
Category:
Kernel