#!/bin/bash set -eo pipefail # Set language to C.UTF-8 (for easier debugging) export "LANG=C.UTF-8" export "LC_MESSAGES=${LANG}" # Variables export "BUILDTOOL_ISSUETRACKER=https://git.staropensource.de/StarOpenSource/server-kernel/issues" ## Cloning (update these if you fork this project) export "BUILDTOOL_REPOSITORY=https://git.staropensource.de/StarOpenSource/server-kernel.git" export "BUILDTOOL_CLONEDIR=server-kernel" ## Base packages to install, packages will be added by questions export "BUILDTOOL_PACKAGES=base-devel git rustup" ## Building command line stuff export "BUILDTOOL_BUILDCMDLINE=nice -20 env MAKEFLAGS=-j$(nproc)" ## OOOOoooo colors! (not true color tho) export "BUILDTOOL_COLOR_SPECIAL=\e[0;35m" export "BUILDTOOL_COLOR_DIAG=\e[0;36m" export "BUILDTOOL_COLOR_WARN=\e[0;33m" export "BUILDTOOL_COLOR_ERROR=\e[0;31m" export "BUILDTOOL_COLOR_RESET=\e[0m" # Logging ## Empty function empty() { echo "" } ## Special function special() { echo -e "${BUILDTOOL_COLOR_SPECIAL}${*}${BUILDTOOL_COLOR_RESET}" } ## Diagnostic (header) function diagh() { if [ -z "${BUILDTOOL_DEBUG}" ]; then return; fi echo -e "${BUILDTOOL_COLOR_DIAG}[DIAG] ${*}${BUILDTOOL_COLOR_RESET}" } ## Diagnostic (extension) function diage() { if [ -z "${BUILDTOOL_DEBUG}" ]; then return; fi echo -e "${BUILDTOOL_COLOR_DIAG} ${*}${BUILDTOOL_COLOR_RESET}" } ## Informational (header) function infoh() { echo -e "${BUILDTOOL_COLOR_RESET}[INFO] ${*}" } ## Informational (extension) function infoe() { echo -e "${BUILDTOOL_COLOR_RESET} ${*}" } ## Warning (header) function warnh() { echo -e "${BUILDTOOL_COLOR_WARN}[WARN] ${*}${BUILDTOOL_COLOR_RESET}" } ## Warning (extension) function warne() { echo -e "${BUILDTOOL_COLOR_WARN} ${*}${BUILDTOOL_COLOR_RESET}" } ## Error (header) function errorh() { echo -e "${BUILDTOOL_COLOR_ERROR}[ERR!] ${*}${BUILDTOOL_COLOR_RESET}" } ## Error (extension) function errore() { echo -e "${BUILDTOOL_COLOR_ERROR} ${*}${BUILDTOOL_COLOR_RESET}" } # Banner special " based on jstm-kernel-optimized _ made by staropensource _ " special " ___ ___ _ ____ _____ _ __ | | _____ _ __ _ __ ___| |" special "/ __|/ _ \ '__\ \ / / _ \ '__|____| |/ / _ \ '__| '_ \ / _ \ |" special "\__ \ __/ | \ V / __/ | |_____| < __/ | | | | | __/ |" special "|___/\___|_| \_/ \___|_| |_|\_\___|_| |_| |_|\___|_|" empty # Print environment configuration if [ -n "${BUILDTOOL_DEBUG}" ]; then warnh "\$BUILDTOOL_DEBUG is set, debug mode is enabled" fi if [ -n "${BUILDTOOL_LOCALDIR}" ]; then warnh "\$BUILDTOOL_LOCALDIR is set, will build kernel package from current working directory" fi # Checks ## Check for Arch Linux ( # shellcheck disable=SC1091 source "/etc/os-release" if [ "${NAME}" != "Arch Linux" ] || [ "${PRETTY_NAME}" != "Arch Linux" ] || [ "${ID}" != "arch" ]; then if [ -z "${BUILDTOOL_COMPILE_NONARCH}" ]; then errorh "Not running on Arch Linux" errore "This kernel can only compile on Arch Linux" errore "If you are sure that you want to compile this kernel on other distributions" errore "set the \$BUILDTOOL_COMPILE_NONARCH environment variable to \"true\"" exit 1 else warnh "\$BUILDTOOL_COMPILE_NONARCH is set, allowing compiling on a non-arch distribution" fi fi ) ## Check for root if [ "${UID}" == "0" ]; then errorh "Can't build kernel as root" errore "Please create a new user for building the kernel" exit 1 fi ## Check for sudo if ! which sudo &> /dev/null; then errorh "Could not find sudo in \$PATH" errore "Please ensure that you have sudo installed" exit 1 fi # Questions ## Ask if mold should replace ld/lld function ask_mold() { read -rp "$(infoh "Do you want to use mold as your linker (much faster) [Y/n]? ")" BUILDTOOL_MOLD case "${BUILDTOOL_MOLD}" in "y"|"Y"|"") export "BUILDTOOL_PACKAGES=${BUILDTOOL_PACKAGES} mold" export "BUILDTOOL_BUILDCMDLINE=${BUILDTOOL_BUILDCMDLINE} LDFLAGS=-fuse-ld=mold RUSTFLAGS=\"-C link-arg=-fuse-ld=mold\"" ;; "n"|"N") ;; *) errorh "Invalid answer. Please answer with Y or N" ask_mold esac } ## Ask if the governor should be adjusted function ask_cpupower() { read -rp "$(infoh "Do you want to adjust the cpu governor (improves build performance) [Y/n]? ")" BUILDTOOL_CPUPOWER case "${BUILDTOOL_CPUPOWER}" in "y"|"Y"|"") export "BUILDTOOL_PACKAGES=${BUILDTOOL_PACKAGES} cpupower" ;; "n"|"N") ;; *) errorh "Invalid answer. Please answer with Y or N" ask_cpupower esac } ## Ask for building in tmpfs function ask_tmpfs() { if [ -n "${BUILDTOOL_LOCALDIR}" ]; then warnh "Skipped ask_tmpfs, building in local directory instead (\$BUILDTOOL_LOCALDIR is set)" export "BUILDTOOL_CLONEDIR=$(pwd)" return fi read -rp "$(infoh "Do you want to build in a tmpfs (improves build performance, protects your disk from wearing out faster, ~32 GiB memory required) [Y/n]? ")" BUILDTOOL_TMPFS case "${BUILDTOOL_TMPFS}" in "y"|"Y"|"") export "BUILDTOOL_CLONEDIR=/tmp/${BUILDTOOL_CLONEDIR}" ;; "n"|"N") export "BUILDTOOL_CLONEDIR=$(pwd)/${BUILDTOOL_CLONEDIR}" ;; *) errorh "Invalid answer. Please answer with Y or N" ask_tmpfs esac } ## Ask for kernel config modification using xconfig function ask_xconfig() { read -rp "$(infoh "Do you want to configure the kernel using xconfig before build [y/N]? ")" BUILDTOOL_XCONFIG case "${BUILDTOOL_XCONFIG}" in "y"|"Y") export "BUILDTOOL_PKGBUILD_XCONFIG=_makexconfig=SET" ;; "n"|"N"|"") export "BUILDTOOL_PKGBUILD_XCONFIG=_makexconfig=" ;; *) errorh "Invalid answer. Please answer with Y or N" ask_xconfig esac } ## Ask for kernel config modification using xconfig function ask_nconfig() { read -rp "$(infoh "Do you want to configure the kernel using nconfig before build [y/N]? ")" BUILDTOOL_NCONFIG case "${BUILDTOOL_NCONFIG}" in "y"|"Y") export "BUILDTOOL_PKGBUILD_NCONFIG=_makenconfig=SET" ;; "n"|"N"|"") export "BUILDTOOL_PKGBUILD_NCONFIG=_makenconfig=" ;; *) errorh "Invalid answer. Please answer with Y or N" ask_nconfig esac } ## Ask if the final kernel configuration should be copied function ask_cpfinalconfig() { read -rp "$(infoh "Do you want to copy the final kernel configuration before build [y/N]? ")" BUILDTOOL_CPFINALCONFIG case "${BUILDTOOL_CPFINALCONFIG}" in "y"|"Y") export "BUILDTOOL_PKGBUILD_CPFINALCONFIG=_copyfinalconfig=SET" ;; "n"|"N"|"") export "BUILDTOOL_PKGBUILD_CPFINALCONFIG=_copyfinalconfig=" ;; *) errorh "Invalid answer. Please answer with Y or N" ask_cpfinalconfig esac } ## Ask if only active modules should be compiled into the kernel function ask_modprobeddb() { read -rp "$(infoh "Do you want to only build active kernel modules (modprobed-db must be installed, read \"https://wiki.archlinux.org/index.php/Modprobed-db\" first) [y/N]? ")" BUILDTOOL_MODPROBEDDB case "${BUILDTOOL_MODPROBEDDB}" in "y"|"Y") if ! which modprobed-db &> /dev/null; then errorh "Could not find modprobed-db in \$PATH." errore "Please ensure that you have modprobed-db installed." ask_modprobeddb return 1 fi export "BUILDTOOL_PACKAGES=${BUILDTOOL_PACKAGES} modprobed-db" export "BUILDTOOL_PKGBUILD_MODPROBEDDB=_localmodcfg=SET" ;; "n"|"N"|"") export "BUILDTOOL_PKGBUILD_MODPROBEDDB=_localmodcfg=" ;; *) errorh "Invalid answer. Please answer with Y or N" ask_modprobeddb esac } ## Ask for sub architecture function ask_subarchitecture() { infoh "Displaying sub architecture list" infoe " 1. AMD Opteron/Athlon64/Hammer/K8 (MK8)" infoe " 2. AMD Opteron/Athlon64/Hammer/K8 with SSE3 (MK8SSE3)" infoe " 3. AMD 61xx/7x50/PhenomX3/X4/II/K10 (MK10)" infoe " 4. AMD Barcelona (MBARCELONA)" infoe " 5. AMD Bobcat (MBOBCAT)" infoe " 6. AMD Jaguar (MJAGUAR)" infoe " 7. AMD Bulldozer (MBULLDOZER)" infoe " 8. AMD Piledriver (MPILEDRIVER)" infoe " 9. AMD Steamroller (MSTEAMROLLER)" infoe "10. AMD Excavator (MEXCAVATOR)" infoe "11. AMD Zen (MZEN)" infoe "12. AMD Zen 2 (MZEN2)" infoe "13. AMD Zen 3 (MZEN3)" infoe "14. AMD Zen 4 (MZEN4)" infoe "15. Intel P4 / older Netburst based Xeon (MPSC)" infoe "16. Intel Core 2 (MCORE2)" infoe "17. Intel Atom (MATOM)" infoe "18. Intel Nehalem (MNEHALEM)" infoe "19. Intel Westmere (MWESTMERE)" infoe "20. Intel Silvermont (MSILVERMONT)" infoe "21. Intel Goldmont (MGOLDMONT)" infoe "22. Intel Goldmont Plus (MGOLDMONTPLUS)" infoe "23. Intel Sandy Bridge (MSANDYBRIDGE)" infoe "24. Intel Ivy Bridge (MIVYBRIDGE)" infoe "25. Intel Haswell (MHASWELL)" infoe "26. Intel Broadwell (MBROADWELL)" infoe "27. Intel Skylake (MSKYLAKE)" infoe "28. Intel Skylake X (MSKYLAKEX)" infoe "29. Intel Cannon Lake (MCANNONLAKE)" infoe "30. Intel Ice Lake (MICELAKE)" infoe "31. Intel Cascade Lake (MCASCADELAKE)" infoe "32. Intel Cooper Lake (MCOOPERLAKE)" infoe "33. Intel Tiger Lake (MTIGERLAKE)" infoe "34. Intel Sapphire Rapids (MSAPPHIRERAPIDS)" infoe "35. Intel Rocket Lake (MROCKETLAKE)" infoe "36. Intel Alder Lake (MALDERLAKE)" infoe "37. Intel Raptor Lake (MRAPTORLAKE)" infoe "38. Intel Meteor Lake (MMETEORLAKE)" infoe "39. Intel Emerald Rapids (MEMERALDRAPIDS)" infoe "40. Generic-x86-64 (GENERIC_CPU)" infoe "41. Generic-x86-64-v2 (GENERIC_CPU2)" infoe "42. Generic-x86-64-v3 (GENERIC_CPU3)" infoe "43. Generic-x86-64-v4 (GENERIC_CPU4)" infoe "44. Intel-Native optimizations autodetected by the compiler (MNATIVE_INTEL)" infoe "45. AMD-Native optimizations autodetected by the compiler (MNATIVE_AMD)" read -rp ":: Which sub architecture do you want to build Linux for (see above, enter 40 if unsure) [40]? " BUILDTOOL_SUBARCHITECTURE case "${BUILDTOOL_SUBARCHITECTURE}" in "") export "BUILDTOOL_PKGBUILD_SUBARCHITECTURE=_subarch=40" ;; *[!0-9]*) errorh "Invalid subarchitecture" ask_subarchitecture return 1 ;; *) if [ ! "${BUILDTOOL_SUBARCHITECTURE}" -gt 0 ] || [ ! "${BUILDTOOL_SUBARCHITECTURE}" -lt 46 ]; then errorh "Invalid subarchitecture" ask_subarchitecture else export "BUILDTOOL_PKGBUILD_SUBARCHITECTURE=_subarch=${BUILDTOOL_SUBARCHITECTURE}" fi ;; esac } ## Ask for kernel debug mode function ask_debug() { read -rp "$(infoh "Do you want to enable kernel debug mode [y/N/i(gnore)]? ")" BUILDTOOL_KERNELDEBUG case "${BUILDTOOL_KERNELDEBUG}" in "y"|"Y") export "BUILDTOOL_PKGBUILD_DEBUG=_debug=y" ;; "n"|"N"|"") export "BUILDTOOL_PKGBUILD_DEBUG=_debug=n" ;; "i"|"I") export "BUILDTOOL_PKGBUILD_DEBUG=_debug=" ;; *) errorh "Invalid answer. Please answer with Y, N or I" ask_debug esac } ## Ask for clone directory conflict resolution (includes check) function ask_clonedir_conflictresolution() { if [ -n "${BUILDTOOL_LOCALDIR}" ]; then warnh "Skipped conflict resolution (\$BUILDTOOL_LOCALDIR is set)" export "BUILDTOOL_CLONEDIR_CONFLICT=r" if [ -a "${BUILDTOOL_CLONEDIR}/src" ]; then diagh "src/ directory present, appending \"--noextract\"" export "BUILDTOOL_MAKEPKG_REUSE= --noextract" fi if [ -a "${BUILDTOOL_CLONEDIR}/pkg" ]; then diagh "pkg/ directory present, appending \"--force\"" export "BUILDTOOL_MAKEPKG_REUSE=${BUILDTOOL_MAKEPKG_REUSE} --force" fi return fi if [ ! -d "${BUILDTOOL_CLONEDIR}" ] && [ ! -L "${BUILDTOOL_CLONEDIR}" ]; then return elif [ -a "${BUILDTOOL_CLONEDIR}" ] && [ ! -d "${BUILDTOOL_CLONEDIR}" ] && [ ! -L "${BUILDTOOL_CLONEDIR}" ]; then warnh "Something that isn't a directory or symlink exists at location \"${BUILDTOOL_CLONEDIR}\"" fi read -rp "$(infoh "Warning: \"${BUILDTOOL_CLONEDIR}\" already exists. What should be done to resolve the conflict [A(bort)/r(ecompile)/f(resh)]? ")" BUILDTOOL_CLONEDIR_CONFLICT case "${BUILDTOOL_CLONEDIR_CONFLICT}" in "a"|"A"|"") errorh "Conflict resolution failed" exit 1 ;; "r"|"R") if [ -a "${BUILDTOOL_CLONEDIR}/src" ]; then diagh "src/ directory present, appending \"--noextract\"" export "BUILDTOOL_MAKEPKG_REUSE= --noextract" elif [ -a "${BUILDTOOL_CLONEDIR}/pkg" ]; then diagh "pkg/ directory present, appending \"--force\"" export "BUILDTOOL_MAKEPKG_REUSE=${BUILDTOOL_MAKEPKG_REUSE} --force" fi ;; "f"|"F") infoh "Removing existing \$BUILDTOOL_CLONEDIR directory" rm -rf "${BUILDTOOL_CLONEDIR}" ;; *) errorh "Invalid answer. Please answer with Y, N or I" ask_debug esac } ask_mold ask_cpupower ask_tmpfs ask_xconfig ask_nconfig ask_cpfinalconfig ask_modprobeddb ask_subarchitecture ask_debug ask_clonedir_conflictresolution # Pre-building ## Install dependencies infoh "Installing dependencies" # shellcheck disable=SC2086 if ! sudo pacman -Syu --asdeps --needed ${BUILDTOOL_PACKAGES}; then errorh "Installing dependencies failed: pacman returned with non-zero exit code" exit 1 fi if ! rustup default nightly; then errorh "Installing dependencies failed: rustup returned with non-zero exit code" exit 1 fi ## Adjust cpu governor case "${BUILDTOOL_CPUPOWER}" in "y"|"Y"|"") infoh "Adjusting cpu governor" if ! sudo cpupower frequency-set -g performance; then errorh "Adjusting cpu governor failed: cpupower returned with non-zero exit code" return 1 fi ;; "n"|"N") ;; *) errorh "Internal inconsistency detected: Value of \$BUILDTOOL_CPUPOWER is not a valid boolean answer" exit 2 ;; esac # Clone repository if [ "${BUILDTOOL_CLONEDIR_CONFLICT}" == "r" ] || [ "${BUILDTOOL_CLONEDIR_CONFLICT}" == "R" ]; then warnh "Skipping cloning process" else infoh "Cloning repository" git clone "${BUILDTOOL_REPOSITORY}" "${BUILDTOOL_CLONEDIR}" fi cd "${BUILDTOOL_CLONEDIR}" # Print debug information if [ -n "${BUILDTOOL_DEBUG}" ]; then diagh "Printing debug information" diage "Environment variables:" env|grep "BUILDTOOL_"|sort diagh "More debug information:" diage "Build cmdline=${BUILDTOOL_BUILDCMDLINE} ${BUILDTOOL_PKGBUILD_XCONFIG} ${BUILDTOOL_PKGBUILD_NCONFIG} ${BUILDTOOL_PKGBUILD_CPFINALCONFIG} ${BUILDTOOL_PKGBUILD_MODPROBEDDB} ${BUILDTOOL_PKGBUILD_SUBARCHITECTURE} ${BUILDTOOL_PKGBUILD_DEBUG} makepkg --syncdeps -p PKGBUILD.buildtool" diage "Cwd=$(pwd)" fi # Build package infoh "Building package" # shellcheck disable=SC2086 if ! ${BUILDTOOL_BUILDCMDLINE} "${BUILDTOOL_PKGBUILD_XCONFIG}" "${BUILDTOOL_PKGBUILD_NCONFIG}" "${BUILDTOOL_PKGBUILD_CPFINALCONFIG}" "${BUILDTOOL_PKGBUILD_MODPROBEDDB}" "${BUILDTOOL_PKGBUILD_SUBARCHITECTURE}" "${BUILDTOOL_PKGBUILD_DEBUG}" makepkg --syncdeps${BUILDTOOL_MAKEPKG_REUSE} -p PKGBUILD.buildtool; then errorh "Failed package compilation: makepkg returned with non-zero exit code" errore "Please report this at \"${BUILDTOOL_ISSUETRACKER}\"" exit 1 fi # Finish message infoh "Finished kernel compilation successfully" infoe "You can now install your kernel and kernel headers."