I HAVE JUST FINISHED DESIGNING “SATELLITE 004 REVISION 01”; ALTHOUGH SATELLITE IS NOT GOING TO BE RELEASED FOR ANOTHER 2 MONTHS, THE CURRENT DESIGN, AND IT WON’T GET ANY SLOWER THAN IT IS NOW… IS x119 FASTER THAN SATELLITE 003 REVISION 06.
THE REASON FOR IT IS THAT WE ARE COMPILING ALL OF THESE TINY C++ LIBRARIES, FIRST WE BUILD THE FUNCTION THAT RUNS FOR THAT satellite.something.something(), THEN WE BUILD THE MOST LIKELY ARGUMENTS TO BE INCLUDED… SO WHEN YOU CALL satellite.console.display(“some string”) IT RUNS LITERALLY AS FAST AS C++, AND SOME TIMINGS FOR IT RACING std::cout CAN BE –FASTER– THAN COMPILED C++ CODE, IT JUST KINDA GETS LUCKY IN THE TIMING AND IT COMES OUT FASTER;
I WAS KINDA STARTING TO NOT LIKE THE 003 06 INTERPRETER, AND AS I BEGAN TO ADD POLYMORPHIC CODE TO IT, I REALIZED I CAN JUST BUILD ALL OF THESE TINY C++ LIBRARIES THAT IT LOADS AHEAD OF TIME.. SO SATELLITE IS GOING TO BE SLIGHTLY SLOW FOR SOMETHING THAT’S LIKE THIS:
satellite.include(satellite)satellite.capsulesatellite.main(){satellite.console.display("welcome to my program")satellite.variable.numbersome_value=999999satellite.variable.numberanother_value=2344763satellite.console.display(some_value+another_value)satellite.return(satellite)}
I’M GOING TO BE COMPLETELY HONEST WITH YOU — IF YOU ARE THINKING ABOUT RUNNING SOME CODE THAT LOOKS LIKE THAT, YOU MIGHT AS WELL RUN IT IN PYTHON OR C++ — CODE LIKE THAT DOESN’T NEED TO LOAD 1,000 TINY C++ PROGRAMS, SATELLITE IS BEING BUILT FOR PROGRAMS THAT ARE BUILT OUT OF; 100,000 LINES, 20,000 LINE PROGRAMS, THINGS LIKE THAT.
YOU CAN TECHNICALLY USE IT FOR SMALL PROGRAMS, BUT WHY LOAD 1,000 TINY LIBRARIES TO ADD TWO NUMBERS TOGETHER?
ANYWAYS, FOR LIKE REALLY LARGE PROGRAMS, SATELLITE WILL RUN INCREDIBLY FAST.. THE EXACT SPEED IS GOING TO BE LIKE LITERALLY AS FAST, BUT FASTER, HERE IS WHY IT’S FASTER THAN COMPILED C++:
I'VE GOT AHOLD OF A GENERAL ARTIFICIAL INTELLIGENCE (LIKE A SUPER ONE) AND IT IS PROGRAMMING ALL OF THE TINY C++ LIBRARIES TO BE AS FAST AS THEY CAN POSSIBLY GO!!
SO IF YOU ARE GOING TO BUILD A PROGRAM THAT SAY, DOES JUST A _TON_ OF NORMAL OPERATIONS, YOUR CODE IS GOING TO RUN FASTER IF YOU USE SATELLITE THAN IF YOU WROTE IT YOURSELF, BECAUSE THE GENERAL ARTIFICIAL INTELLIGENCE KNOWS HOW TO WRITE BETTER C++ THAN YOU DO. WE ARE TAKING OUR TIME AND WRITING EACH TINY C++ LIBRARY TO BE AS FAST AS WE CAN MAKE IT, WE MIGHT STRIP “int main()” OUT OF EACH LIBRARY, I DON’T KNOW YET, I GUESS WE DON’T NEED TO TAKE IT THAT FAR, BUT THAT JUST GIVES YOU AN EXAMPLE OF THE LENGTHS THAT WE ARE GOING TO HERE…
SO FOR A LOT OF NORMAL COMPUTER CODE, SATELLITE WILL BE THE BEST SOLUTION FOR LOTS OF NORMAL COMPUTER CODE… NOW IF YOUR PROGRAMMING SOMETHING EXTREMELY COMPLICATED, LIKE SOMETHING WITH POINTERS, NAMESPACES, TEMPLATES, AND YOU UNDERSTAND ALL OF THAT STUFF, THEN C++ IS GOING TO BE THE BETTER OPTION.
THE ORIGINAL GOAL OF SATELLITE HAD JUST A SINGLE THING IN MIND: TO MAKE A PROGRAMMING LANGUAGE TO OVERCOME C++, SO THAT OUR SOCIETY DIDN’T HAVE TO USE C++; ALTHOUGH SATELLITE IS BUILT IN C++, WHICH MEANS IT WILL NEVER BECOME IRRELEVANT, IT IS BUILT TO CALL C++; SO IN OTHER WORDS, IT’S SUPPOSED TO BE USED INSTEAD OF C++, THAT IS LIKE, THE POINT OF THE ENTIRE PROJECT, BUT WHATEVER.
IT’S SO WE DON’T HAVE TO USE C++ ANYMORE, C++ STILL HAS LIKE EVERYTHING FROM 1994, AND YES IT STILL ALL WORKS, AND IT’S PROBABLY ONLY GOTTEN FASTER IF YOU STILL HAVE PROGRAMS FROM 1994, BUT IF YOUR ON A MACHINE THAT HAS A GUI AND ALMALINUX 10, WHY WOULD YOU CHOOSE C++ AS THE LANGUAGE TO USE? YOU HAVE A GUI, YOU HAVE THE MEMORY AVAILABLE, YOU HAVE THE PROCESSING POWER AVAILABLE, USE SOMETHING DESIGNED TO USE THESE THINGS, SOMETHING DESIGNED WITH ALL OF THESE THINGS IN MIND?
C++ CAN DO ANYTHING, IT CAN DO IT INCREDIBLY FAST, IT HAS ALL OF THE CONTROL, BUT IF YOU DON’T REALLY NEED THAT STUFF, AND YOUR JUST DOING SOME NORMAL STUFF, YOU DON’T NEED TO LOOK UP HOW TO WRITE A STD::CHRONO DURATION_CAST 6 TIMES TO WRITE A TIMER, YOU CAN JUST WRITE:
satellite.include(satellite)satellite.capsulesatellite.main(satellite.container.list<satellite.variable.string>arguments){satelllite.variable.timemy_timer=satellite.time.now()//wait,thatisn't a timer, but I know what i'llmakethesyntaxforatimer,satellite.variable.timemy_timer=satellite.time.timer()my_timer.start() my_timer.end()satellite.return(satellite)}
AND THAT WILL BE THE ENTIRE TIMER, WITH ALL OF THE HIGH RESOLUTION OF NANOSECONDS, IF YOU WANT THEM, YOU’LL BE ABLE TO DECLARE WHAT TYPE OF TIME YOU WANT, INPUTTING IT RIGHT INTO THE satellite.time.timer(“ms”) or “s” or “ns” or whatever, you can just do that. So here is an entire nanosecond timer in C++, with the time displayed:
satelllite.include(satellite)satellite.capsulesatellite.main(satellite.container.list<satellite.variable.string>arguments){satellite.variable.timemy_timer=satellite.time.timer("ns")my_timer.start() satellite.console.display("put the code you will run in between .start() and .end()")my_timer.end() satellite.console.display(my_timer)satellite.return(satellite)}
that’s all it’s going to take dude, no lies, and no bullshit it’s tiny compiled C++ libraries, so satellite can’t replace C++, it’s built using C++, it’s not going to run on someones watch, or inside of an MP3 Player, it’s made for large machines, but if you do have a large machine, perhaps with infinite amounts of memory and processing power, use all of that processing power, and use all of those threads, and use your graphics card (someday)!
We stupid people will be able to program graphical applications in satellite, things that are like little dots running around the screen, and someday I am using it for my artificial intelligence, QUAD AI, that is the literal reason why I have created it, but I built it to be able to take advantage of: large machines, that have like infinite resources, those resources can be maximized by satellite, it cannot program “large CERN particle colliders” but the tradeoff of not being able to do that stuff is in what it can actually do — do you have 32 – 64 gigabytes of memory? More? Then you can use satellite, but the tradeoff is that if you are trying to balance the tires on your car on a budget inside of a small chip that exists inside of a car, then no, your not going to be able to run satellite in that location, so I guess the moral of the story is that it doesn’t replace C++ when it’s intended goal is to replace C++, kind of a weird way to think about it?
I WROTE THIS TUTORIAL FOR MY MOM TO FOLLOW, SHE IS STILL LEARNING TO PROGRAM THE COMPUTER, SO I MADE THIS TUTORIAL EASY. SO THAT SHE COULD STILL FOLLOW IT BECAUSE SHE IS STILL LEARNING ABOUT PROGRAMMING, BUT THIS IS ALSO A PERFECT PLACE TO START FOR SOMEONE WHO IS A BEGINNER.
FIRST, TO RUN SATELLITE PROGRAMS, YOU NEED TO INSTALL SATELLITE. GO TO THE DOWNLOAD BUTTON AT THE TOP OF THIS WEBSITE, AND THEN CLICK DOWNLOAD. AFTER YOU DOWNLOAD THE APPLICATION, YOU NEED TO LOOK WHERE YOU SAVED IT AND EXTRACT THE FILES.
THEN YOU NEED TO OPEN A CONSOLE WINDOW IN THE SAME FOLDER AS THE EXTRACTED FILES. THIS IS BECAUSE WE WILL NEXT RUN THE INSTALL SCRIPT CALLED “install-satellite.sh” BY TYPING THIS IN TO THE CONSOLE:
./install-satellite.sh
TYPE THAT IN TO THE CONSOLE AFTER YOU HAVE CD’d TO THE SAME DIRECTORY THAT THE EXTRACTED FILES ARE IN. THESE FILES ARE IN A FOLDER THAT IS NEXT TO THE FILE THAT YOU DOWNLOADED. ALL THAT YOU HAVE TO DO IS OPEN A CONSOLE WINDOW INSIDE OF THAT FOLDER, AND TYPE IN “./install-satellite.sh” AND IT WILL INSTALL THE PROGRAM FOR YOU, THEN YOU NEED TO SET YOUR $PATH VARIABLE INSIDE OF YOUR “.bashrc” FILE.
THIS WILL ALLOW YOU TO ACCESS SATELLITE FROM ANY CONSOLE WINDOW, AND IT ALSO COMES WITH A PROGRAM CALLED “satl-term”, WHICH IS A TERMINAL DESIGNED ONLY FOR RUNNING SATELLITE PROGRAMS. YOU CAN ACCESS THE “satl-term” PROGRAM BY USING THE SAME $PATH VARIABLE THAT WE SET EARLIER, JUST ADD THIS COMMAND TO YOUR .bashrc FILE:
exportPATH="/~/.satl/bin:$PATH"
AFTER YOU HAVE TYPED THAT INTO YOUR .bashrc FILE, CLOSE ANY CONSOLE WINDOWS THAT YOU HAVE OPEN TO REFRESH YOUR VARIABLES AND OPEN THEM AGAIN, YOU WILL NOW HAVE ACCESS TO TWO SEPARATE PROGRAMS:
OPTIONALLY YOU CAN SET THE NAME “satellite” TO ALSO RUN SATELLITE PROGRAMS, THAT IS UP TO YOU, THE WORD “SATELLITE” MAY BE RESERVED BY REDHAT OR DEBIAN, BUT ESPECIALLY ON ENTERPRISE LINUX THE WORD “SATELLITE” IS RESERVED FOR THEIR PROGRAMS, BUT IF YOU DON’T USE REDHAT SATELLITE, THEN IT MIGHT NOT HURT ANYTHING.
NOW THAT WE HAVE INSTALLED THE INTERPRETER FOR SATELLITE PROGRAMS, WE CAN WRITE ONE! TYPE THESE LINES INTO A TEXT FILE AND CLICK SAVE AS, THEN TYPE IN A NAME FOR IT LIKE “hello_world.satl” OR SOMETHING SIMILAR, BUT ALSO REMEMBER WHERE YOU SAVED THE FILE, WE WILL NEED TO GO THERE TO RUN THE PROGRAM, WE WILL HAVE TO TYPE IN THE FULL ADDRESS OF THE PROGRAM TO RUN IT. SO FIRST THE SYNTAX THAT YOU NEED TO TYPE IN: (AND DON’T WORRY ABOUT THE COMMENTS FOR RIGHT NOW, THEY ARE JUST THERE TO TELL YOU ABOUT THE DIFFERENT LINES, AND YOU DON’T REALLY HAVE TO UNDERSTAND EVERY SINGLE ONE OF THEM.)
THE SCRIPT “install-satellite.sh” INCLUDES EVERYTHING THAT THE REAL INSTALLER INCLUDES, AND IT CHANGES YOUR FILES TO LOOK LIKE PIECES OF PAPER WITH SATELLITES ON THEM.
I AM STILL WORKING ON PROGRAMS THAT OFFER SYNTAX HIGHLIGHTING, I JUST DON’T HAVE THE TIME TO GET EVERYTHING WORKING FOR IT, GTK4 PROGRAMS ARE VERY COMPLICATED.
THIS PAGE DOESN’T OFFER SYNTAX HIGHLIGHTING FOR THE SATELLITE LANGUAGE BECAUSE I DON’T HAVE THE TIME TO PROGRAM SYNTAX HIGHLIGHTING FOR IT MYSELF.
This script works on enterprise linux, and it’s supposed to work on debian/ubuntu too. It grabs the latest kernel available, you just have to run it twice to install the kernel; First here’s the instructions:
Here is the complete build script for you to look at but I wouldn’t copy and paste it, just use the “Download” button and extract it. If you copy and paste it, some of the characters will not be copied and it might not work. You can compare the number of lines and file size of both though, if your worried about viruses!
#!/usr/bin/env bash## universal_linux_kernel_build.sh## Download, configure, build and install a mainline Linux kernel that works on# whatever graphics you actually have -- AMD, NVIDIA, Intel, a virtual machine,# or a headless server -- with the GPU compute and NPU ("AI") paths turned on.## It starts from your running distro's config so your existing hardware keeps# working, then enforces the options GPU compute needs and that hand-rolled# configs most often get wrong.## ./universal_linux_kernel_build.sh # detect, build only# INSTALL=1 ./universal_linux_kernel_build.sh # build, then install## GPU=auto detect from lspci (default)# GPU=all every vendor -- a kernel that boots on anything# GPU=amd,intel a comma-separated list: amd nvidia intel vm## KVER=6.12.9 ./universal_linux_kernel_build.sh # a specific release# SRC=~/src/linux ./universal_linux_kernel_build.sh # an existing tree# TOOLCHAIN=llvm LLVM_PREFIX=$HOME/opt/clang-current/bin/ ./universal_...sh## CLEAN=auto mrproper the tree only if the last attempt did not finish# CLEAN=always mrproper first, every time# CLEAN=never never clean; always build incrementally## CONFIG_BASE=auto keep the tree's .config if it has one, else the distro's# CONFIG_BASE=distro always reseed from /boot/config-$(uname -r)# CONFIG_BASE=defconfig start from the arch defconfig# CONFIG_BASE=<path> start from a config file you name# FRAME_WARN=8192 -Wframe-larger-than=; 0 disables the check entirely## Two files are written beside this script (override with STATE_FILE= / BUILD_LOG=):# kernel_build.ini what was done to each source tree, one [section] each# kernel_build.log full output of the last build (previous kept as .log.prev)## THE ONE THING THIS SCRIPT EXISTS TO GET RIGHT: GPU drivers are MODULES.# Built-in (=y) is the most common mistake in hand-rolled GPU kernel configs.# A built-in driver probes before the root filesystem is mounted, so all of its# firmware must already be in the initramfs -- but dracut and initramfs-tools# decide which firmware to include by looking at which MODULES are installed,# and a built-in driver is not a module. The result is a driver that cannot load# its firmware: no display, no /dev/kfd. As modules they also stay unloadable# and blacklistable, which the NVIDIA proprietary stack requires.## Licence: public domain / CC0. No warranty. It installs a kernel; read it first.set-euopipefail# --- integrity self-check -------------------------------------------------# This file must be pure ASCII. Copying a script out of a web page or a chat# window silently replaces ordinary spaces with U+00A0 (non-breaking space),# which bash treats as part of a command name -- you get "command not found"# on a line that looks perfectly correct.## NOTE: the body below is deliberately NOT indented. Leading whitespace is# exactly what gets converted, so an indented error handler is unable to report# the corruption it just detected -- it fails as "printf: command not found".if LC_ALL=Ctr-d'\11\12\40-\176'<"$0"|head-c1| LC_ALL=Cgrep-q.; thenprintf'ERROR: %s contains non-ASCII bytes.\n'"$0">&2printf'It was almost certainly corrupted by copy-paste from a web page.\n'>&2printf'Repair it with:\n'>&2printf" sed -i 's/%s/ /g' %s\n"'\xc2\xa0'"$0">&2printf'or, better, download the file directly instead of pasting it.\n'>&2exit1fi# --------------------------------------------------------------------------GPU="${GPU:-auto}"KVER="${KVER:-}"# empty = latest stableSRC="${SRC:-}"# empty = download a tarballWORK="${WORK:-$HOME/src}"LOCALVERSION="${LOCALVERSION:--gpu}"FRAME_WARN="${FRAME_WARN:-8192}"# -Wframe-larger-than=; 0 disables, 8192 is the Kconfig max# De-export it. This is OUR knob, but kbuild has a variable of the SAME NAME# and means something else by it: scripts/setlocalversion ends with# echo "${KERNELVERSION}${file_localversion}${config_localversion}${LOCALVERSION}${scm_version}"# so a LOCALVERSION that is in make's ENVIRONMENT is appended on top of the# CONFIG_LOCALVERSION this script sets below -- and the release comes out as# 7.2.0-gpu-gpu. It only bites when the value arrived from the environment# (an orchestrator, or `LOCALVERSION=-x ./this.sh`), because a plain assignment# does not export, but a value inherited from the environment stays exported# through re-assignment. The config setting below is the only path we want.export-nLOCALVERSION2>/dev/null||true# ------------------------------------------------------------- build bookkeeping# Two files live next to this script. kernel_build.ini records what was done to# each source tree so a later run can tell an interrupted or failed tree from a# finished one; kernel_build.log is the full output of the last build.## The .ini is keyed by SOURCE TREE, not by version -- one [section] per tree --# because a single machine easily ends up with several (a KVER= build in ~/src# beside an SRC=/KERNEL_SRC= tree elsewhere), and a state file that assumed one# tree would confidently report the wrong one. Delete it any time: a missing# entry simply reads as "previous attempt unknown".SELF_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"|| SELF_DIR="$PWD"STATE_FILE="${STATE_FILE:-$SELF_DIR/kernel_build.ini}"BUILD_LOG="${BUILD_LOG:-$SELF_DIR/kernel_build.log}"CLEAN="${CLEAN:-auto}"# auto: clean only an unfinished tree | always | never# Where the configuration comes from. "auto" keeps a .config the tree already# has and only seeds from the running distro when there is none, so re-running# no longer throws away work between runs. The enforcement below re-applies to# whatever base is chosen, and the verify block still refuses to install a# config that did not come out right, so keeping an existing one is safe.CONFIG_BASE="${CONFIG_BASE:-auto}"# auto | distro | defconfig | /path/to/config# Both are touched only AFTER this script has chdir'd into $WORK and then $SRC,# so a relative override would land somewhere the user did not mean. Resolve# them against the directory we were invoked from, once, while that is still cwd.case $STATE_FILE in /*) ;; *) STATE_FILE="$PWD/$STATE_FILE" ;; esaccase $BUILD_LOG in /*) ;; *) BUILD_LOG="$PWD/$BUILD_LOG" ;; esacJOBS="${JOBS:-$(nproc)}"INSTALL="${INSTALL:-0}"INSTALL_DEPS="${INSTALL_DEPS:-1}"TOOLCHAIN="${TOOLCHAIN:-gcc}"# gcc | llvmLLVM_PREFIX="${LLVM_PREFIX:-}"# e.g. $HOME/opt/clang-current/bin/ (TRAILING SLASH)KEEP_DEBUG_INFO="${KEEP_DEBUG_INFO:-0}"# 1 keeps DWARF+BTF (far bigger, far slower)say() { printf'\n\033[1m==> %s\033[0m\n'"$*"; }warn() { printf'\033[33mwarning:\033[0m %s\n'"$*">&2; }die() { printf'\n\033[31mERROR:\033[0m %s\n'"$*">&2; exit1; }# ---------------------------------------------------------------- state helpers# Loaded into an associative array and flushed whole, rather than edited in# place. Sections for OTHER trees are copied through verbatim, so two trees# never clobber each other, and a flush after every set means the record# survives a kill -9 mid-build -- which is exactly the case it exists to detect.declare-ASTATE=()STATE_OK=0STATE_STAGE=startupstate_init() {locald; d="$(dirname "$STATE_FILE")"if [ -d"$d" ] && [ -w"$d" ] && { [ !-e"$STATE_FILE" ] || [ -w"$STATE_FILE" ]; }; then STATE_OK=1elsewarn"cannot write $STATE_FILE -- continuing without build-state tracking. Set STATE_FILE=<path> to somewhere writable, or pass CLEAN=always/never to decide about cleaning explicitly."fi}state_load() { [ "$STATE_OK"=1 ] && [ -f"$STATE_FILE" ] ||return0locallinekvinm=0while IFS=read-rline; docase"$line"in"[$SRC]") inm=1; continue ;;\[*) inm=0; continue ;;''|'#'*) continue ;;esac [ "$inm"=1 ] ||continuecase"$line"in*=*) ;; *) continue ;; esac k=${line%%=*}; v=${line#*=} k=${k///}; k=${k//$'\t'/}; v=${v# }# An if, not `[ -n "$k" ] && ...`: a while-read returns the status of the# last command in its body, so a trailing blank key would make state_load# return 1 and `set -e` would kill the run silently at the call site.if [ -n"$k" ]; thenSTATE["$k"]="$v"; fidone<"$STATE_FILE"return0}state_flush() { [ "$STATE_OK"=1 ] ||return0localtmpk tmp="$(mktemp "${STATE_FILE}.XXXXXX" 2>/dev/null)"||return0 {printf'# universal_linux_kernel_build.sh -- build state, one [section] per source tree.\n'printf'# Written automatically; safe to delete.\n'# cat -s squeezes the blank line that the awk pass preserves and the# printf below re-emits; without it the file gains one blank per write. [ -f"$STATE_FILE" ] && awk-vsec="[$SRC]"'/^\[/ { keep = ($0 != sec) } keep'"$STATE_FILE"|cat-sprintf'\n[%s]\n'"$SRC"for k in"${!STATE[@]}"; doprintf'%s = %s\n'"$k""${STATE[$k]}"; done|sort } >"$tmp"2>/dev/null && mv-f"$tmp""$STATE_FILE"||rm-f"$tmp"}state_set() { [ "$STATE_OK"=1 ] ||return0; STATE["$1"]="$2"; state_flush; }# Records a failure without changing the exit status. `local rc=$?` must stay# the first statement or it captures the wrong command._state_on_exit() {local rc=$?if [ "$STATE_OK"=1 ] && [ "$rc"-ne0 ]; then STATE[status]=failed STATE[stage]="$STATE_STAGE" STATE[exit_code]="$rc" STATE[finished]="$(date-Is2>/dev/null ||date2>/dev/null ||true)"state_flushfireturn0}DNF_PKGS="gcc make flex bison bc openssl-devel elfutils-libelf-devel dwarves ncurses-devel rsync cpio perl python3 xz zstd git tar pciutils"APT_PKGS="build-essential flex bison bc libssl-dev libelf-dev dwarves libncurses-dev rsync cpio perl python3 xz-utils zstd git tar pciutils"# Best-effort, deliberately. A package manager exits non-zero for reasons that# have nothing to do with the packages asked for -- one third-party repo with an# unverifiable GPG key is enough, and dnf then refuses to load metadata and# exits 1 in the first ten seconds. Under `set -e` a bare install call would# take a multi-hour build down with it for a reason the user cannot see from the# error. So warn and carry on: the Preflight loop immediately below is the real# gate, and it names the tool that is actually missing.if [ "$INSTALL_DEPS"=1 ]; thensay"Installing build dependencies (sudo)"ifcommand-vdnf>/dev/null; thensudodnfinstall-y $DNF_PKGS \||warn"dnf could not install every dependency; continuing. If the build fails on a missing header, that is where to look. A single broken repo is the usual cause -- retry with sudo dnf install -y --disablerepo=<broken> $DNF_PKGS or set INSTALL_DEPS=0 if you know the packages are already present."elifcommand-vapt-get>/dev/null; then# Separate statements, not `update && install`: chained, a failed update# makes the whole list non-zero and set -e kills the script with nothing# printed. A stale index is not a reason to refuse to build.sudoapt-getupdate||warn"apt-get update failed; using the cached package lists"sudoapt-getinstall-y $APT_PKGS \||warn"apt-get could not install every dependency; continuing."elsewarn"no dnf/apt-get -- install kernel build deps yourself, then re-run with INSTALL_DEPS=0"fifisay"Preflight"for t in make gcc flex bison bc rsync cpio; docommand-v"$t">/dev/null||die"missing: $t"; done[ "$(id-u)"-ne0 ] ||die"do not run this whole script as root. The build runs as you; only the install steps use sudo."# ------------------------------------------------------------------ GPU detect## VM/legacy drivers are ALWAYS enabled. They are a few hundred KB of modules and# they are the difference between "this kernel boots on my machine" and "this# kernel boots anywhere" -- a VM, a server with an ASPEED BMC, a rescue boot on# unfamiliar hardware. There is no reason to leave them out.W_AMD=0; W_NV=0; W_INTEL=0ifcommand-vlspci>/dev/null; thenwhile IFS=read-rline; docase"$line"in*[Aa][Mm][Dd]*|*ATI*) W_AMD=1; printf' found: %s\n'"$line" ;;*NVIDIA*|*nVidia*) W_NV=1; printf' found: %s\n'"$line" ;;*Intel*) W_INTEL=1; printf' found: %s\n'"$line" ;;esacdone<<(lspci-nn2>/dev/null |grep-Ei 'vga|3d|display' ||true)ficase"$GPU"in auto)if [ "$W_AMD$W_NV$W_INTEL"="000" ]; thenwarn"no AMD/NVIDIA/Intel GPU detected (headless, VM, or unknown hardware). Enabling all vendors so the kernel boots anywhere. Use GPU= to narrow it." W_AMD=1; W_NV=1; W_INTEL=1fi ;; all) W_AMD=1; W_NV=1; W_INTEL=1 ;;*) W_AMD=0; W_NV=0; W_INTEL=0 IFS=','read-rawant<<<"$GPU"for v in"${want[@]}"; docase"${v///}"in amd) W_AMD=1 ;; nvidia|nv) W_NV=1 ;; intel) W_INTEL=1 ;; vm|none) ;;*) die "unknown GPU vendor '$v' (use: auto all amd nvidia intel vm)" ;;esac; done ;;esacprintf' enabling : %s%s%s%s\n'\"$([ "$W_AMD" =1 ] && echo 'AMD ')""$([ "$W_NV" =1 ] && echo 'NVIDIA ')"\"$([ "$W_INTEL" =1 ] && echo 'Intel ')"'VM/legacy(always)'MAKE_ARGS=(-j"$JOBS")if [ "$TOOLCHAIN"= llvm ]; then [ -n"$LLVM_PREFIX" ] && case"$LLVM_PREFIX"in*/) ;; *) die "LLVM_PREFIX must end in a slash -- kbuild treats it as a path prefix";; esac MAKE_ARGS+=(LLVM="${LLVM_PREFIX:-1}")# tools/lib/bpf can be compiled by gcc (non-PIC) while the host link runs# clang/ld.lld, which defaults to PIE. That mix fails building# tools/bpf/resolve_btfids with R_X86_64_32 relocation errors. MAKE_ARGS+=(HOSTLDFLAGS=-no-pie)printf' toolchain : clang (%s)\n'"${LLVM_PREFIX:-fromPATH}"elseprintf' toolchain : %s\n'"$(gcc--version|head-1)"fi# ---------------------------------------------------------------------- sourceif [ -z"$SRC" ]; thenif [ -z"$KVER" ]; then KVER=$(curl-fsSL https://www.kernel.org/finger_banner 2>/dev/null \|awk '/latest stable/{print $NF; exit}')||true [ -n"$KVER" ] ||die"could not determine the latest kernel version; set KVER="fi SRC="$WORK/linux-$KVER"if [ !-d"$SRC" ]; thenmkdir-p"$WORK"; cd"$WORK"say"Downloading linux-$KVER"curl-fL--progress-bar-O"https://cdn.kernel.org/pub/linux/kernel/v${KVER%%.*}.x/linux-$KVER.tar.xz"tarxf"linux-$KVER.tar.xz"fifi[ -f"$SRC/Makefile" ] ||die"no kernel source at $SRC"cd"$SRC"# Canonicalise now that we are standing in it, BEFORE it becomes a state key.# SRC is the [section] name, and a trailing slash from tab-completion, a# relative "." or a symlinked path would each key the same tree differently --# and a key that misses reads as "no previous attempt", which under CLEAN=auto# means mrproper on a tree that was perfectly good. pwd -P resolves all three.SRC="$(pwd-P)"printf' source : %s (%s)\n jobs : %s\n'"$SRC""$(make-s kernelversion)""$JOBS"# ------------------------------------------------------- previous build attemptstate_initstate_loadtrap_state_on_exitEXITsay"Previous build attempt"prev_status="${STATE[status]:-}"# -print -quit stops at the first hit: on a fully built tree this answers in# milliseconds, where counting all ~16000 objects would walk 4.6G of tree.objects="$(find . -name '*.o' -not-path './scripts/*' -print-quit2>/dev/null ||true)"if [ -n"$prev_status" ]; thenprintf' recorded : %s'"$prev_status" [ -n"${STATE[finished]:-}" ] && printf' (%s)'"${STATE[finished]}" [ "$prev_status"= failed ] && printf' at stage %s'"${STATE[stage]:-unknown}"printf'\n'elseprintf' recorded : nothing -- no entry for this tree in %s\n'"$STATE_FILE"fido_clean=0; clean_why=""case"$CLEAN"in never) clean_why="CLEAN=never" ;; always) do_clean=1; clean_why="CLEAN=always" ;; auto)if [ -z"$objects" ]; then clean_why="no object files present -- nothing to clean"elsecase"$prev_status"in built|installed) clean_why="the previous run finished ($prev_status); rebuilding incrementally is correct and far faster" ;; building) do_clean=1; clean_why="a previous run started and never recorded finishing -- interrupted or killed" ;; failed) do_clean=1; clean_why="the previous run failed at stage ${STATE[stage]:-unknown}" ;;"") do_clean=1; clean_why="objects are present but nothing recorded how they got there" ;;*) do_clean=1; clean_why="recorded status '$prev_status' is not a completed build" ;;esacfi ;;*) die "CLEAN must be auto, always or never (got '$CLEAN')" ;;esac# Back up BEFORE announcing or doing anything, and re-test afterwards. If the# configuration cannot be saved then cleaning would destroy it outright, and not# cleaning is always the safer of the two -- an incremental build on a suspect# tree is a slow problem, a deleted config is an unrecoverable one.if [ "$do_clean"=1 ]; then _bk=""if [ -f .config ]; then# The FIRST backup is the valuable one: by the second cleaning run# .config may no longer be the user's file, so overwriting a fixed name# would replace the only copy of their original. Keep the first,# timestamp the rest. --remove-destination because a plain `cp -a` onto# an existing symlink writes THROUGH it, clobbering its target. _bk=.config.before-clean [ -e"$_bk" ] && _bk=".config.before-clean.$(date +%Y%m%d-%H%M%S 2>/dev/null ||echo prev)"ifcp-a--remove-destination.config"$_bk"2>/dev/null; thenprintf' saved : .config -> %s\n'"$_bk"else do_clean=0; _bk="" clean_why="could not save .config, so cleaning would destroy it"warn"cannot back up $SRC/.config -- NOT cleaning this tree. Fix its permissions, or move it aside yourself, or pass CLEAN=never to stop being asked. Building incrementally instead."fififi# A SECOND test, not an else: $do_clean can have been cleared just above, and# the previous version of this block set it there and then cleaned anyway --# printing "not cleaning" immediately before deleting the file it could not save.if [ "$do_clean"=1 ]; thenprintf' cleaning : %s\n'"$clean_why"# mrproper, not clean: the failure this recovers from is a tree left# inconsistent, and `make clean` keeps include/config and the generated# headers that are the usual culprits. It deletes .config too, which is# incidental -- cleaning is about build PRODUCTS, not your configuration --# so that is restored immediately afterwards. STATE_STAGE=cleanmake-smrproperprintf' cleaned : %s\n'"$SRC"# Only for CONFIG_BASE=auto: the other modes are an explicit instruction# about where the config comes from, and restoring one would contradict it.if [ "$CONFIG_BASE"= auto ] && [ -n"$_bk" ] && [ -f"$_bk" ]; thencp-a--remove-destination"$_bk".config\ && printf' restored : .config kept across the clean (from %s)\n'"$_bk"fielseprintf' keeping : %s\n'"$clean_why"fistate_settree"$SRC"state_setversion"$(make-s kernelversion)"state_settoolchain"$TOOLCHAIN"state_setjobs"$JOBS"state_setlog"$BUILD_LOG"state_setstarted"$(date-Is2>/dev/null ||date2>/dev/null ||true)"state_setstatusconfiguringstate_setstage""state_setexit_code""state_setfinished""# or the previous run's finish time reads as this one'sSTATE_STAGE=configure# --------------------------------------------------------------------- configuresay"Configuring"# Copy the running distro's config in. Factored out because CONFIG_BASE=auto# calls it only as a fallback, where the old code called it unconditionally and# so destroyed a tuned .config on every single run.# Never write .config in place. A redirect truncates the target before the# first byte arrives, so a corrupt source or a killed run leaves a FRAGMENT --# and under CONFIG_BASE=auto the next run would adopt that fragment as its base,# with olddefconfig silently defaulting every symbol the fragment never reached.# Writing to a temp and renaming makes the swap atomic; rename also replaces a# .config SYMLINK rather than writing through it to whatever it points at.install_config() {local src="$1"tmp tmp=".config.seed.$$"case"$src"in*.gz) zcat "$src">"$tmp" ;;*) cp "$src""$tmp" ;;esac|| { rm-f"$tmp"; die"could not read the config at $src"; } [ -s"$tmp" ] || { rm-f"$tmp"; die"the config at $src is empty"; }mv-f"$tmp".config}seed_from_distro() {localcbase=""for c in"/boot/config-$(uname-r)" /proc/config.gz; do [ -r"$c" ] && { base="$c"; break; }doneif [ -n"$base" ]; thenprintf' base: %s\n'"$base"install_config"$base"elsewarn"no distro config found; starting from defconfig -- review before installing"makedefconfig>/dev/nullfi}case"$CONFIG_BASE"in auto)# Cheap sanity gate before adopting it: a truncated or empty file would# otherwise be taken as authoritative and quietly defaulted by# olddefconfig into a config nobody chose.if [ -s .config ] && grep-q'^CONFIG_[A-Z0-9_]*='.config2>/dev/null; thenprintf' base: the .config already in this tree -- kept, not replaced\n'printf' (CONFIG_BASE=distro to reseed from the running kernel)\n'else [ -e .config ] && warn"$SRC/.config is empty or has no CONFIG_ lines -- ignoring it and seeding from the running kernel instead. The old file is kept as .config.rejected if you want to look at it." [ -e .config ] && mv-f.config.config.rejectedseed_from_distrofi ;; distro)seed_from_distro ;; defconfig)printf' base: make defconfig\n'makedefconfig>/dev/null ;;*) [ -r"$CONFIG_BASE" ] ||die"CONFIG_BASE=$CONFIG_BASE is not a readable file. Expected: auto, distro, defconfig, or a path to a kernel config."printf' base: %s\n'"$CONFIG_BASE"install_config"$CONFIG_BASE" ;;esac# Bring whatever base was chosen up to date with THIS tree's Kconfig before the# enforcement below. A config from another kernel version is missing symbols# this one has; without this, scripts/config sets options against a stale symbol# table and the second olddefconfig quietly drops them again.makeolddefconfig>/dev/nullstate_setconfig_base"$CONFIG_BASE"cfg() { ./scripts/config"$@"; }# --- shared GPU-compute plumbing ---------------------------------------------# These are DEPENDENCIES, not preferences. HSA_AMD_SVM depends on DEVICE_PRIVATE# and HSA_AMD_P2P depends on PCI_P2PDMA; with those off, asking for them# silently does nothing and olddefconfig quietly drops them. The same machinery# backs NVIDIA UVM/GPUDirect and Intel's shared virtual memory.cfg--enableZONE_DEVICEcfg--enableDEVICE_PRIVATE# unaddressable device memory (HMM)cfg--enablePCI_P2PDMA# peer-to-peer DMA between GPUs over PCIecfg--enableHMM_MIRRORcfg--enableMMU_NOTIFIERcfg--enableDMA_SHARED_BUFFERcfg--enableDRM_ACCEL# the accel subsystem both NPUs live under# --- always: a console before any GPU driver, and the VM/BMC drivers ---------cfg--enableSYSFB_SIMPLEFBcfg--moduleDRM_SIMPLEDRM# EFI/VESA framebuffer -- your rescue consolecfg--moduleDRM_VIRTIO_GPU# QEMU/KVM, virt-manager, most Linux VMscfg--moduleDRM_VMWGFX# VMwarecfg--moduleDRM_QXL# SPICEcfg--moduleDRM_BOCHS# QEMU -vga stdcfg--moduleDRM_AST# ASPEED BMC -- almost every rack servercfg--moduleDRM_HYPERV# Hyper-V / WSL2cfg--moduleDRM_UDL# DisplayLink USB adaptersif [ "$W_AMD"=1 ]; then# --- AMD: display, ROCm compute, and the Ryzen AI NPU --------------------cfg--moduleDRM_AMDGPU# MODULE, not built-in -- see the headercfg--enableDRM_AMD_DC# modern display stack: atomic KMS, DP/HDMI audiocfg--enableDRM_AMDGPU_USERPTR# required by ROCm and by GL/Vulkan interopcfg--enableDRM_AMDGPU_SI# Southern Islands (older GCN)cfg--enableDRM_AMDGPU_CIK# Sea Islandscfg--enableHSA_AMD# KFD -- creates /dev/kfd, ROCm's entry pointcfg--enableHSA_AMD_SVM# shared virtual memory: HIP managed memorycfg--enableHSA_AMD_P2P# direct GPU-to-GPU transferscfg--enableAMD_IOMMU# DRM_ACCEL_AMDXDNA depends on itcfg--moduleDRM_ACCEL_AMDXDNA# "AMD AI Engine" NPU, Ryzen AI 300+fiif [ "$W_NV"=1 ]; then# --- NVIDIA --------------------------------------------------------------# nouveau is the in-tree open driver. Build it as a MODULE even if you intend# to use NVIDIA's proprietary or open-kernel modules: those require nouveau# to be absent at load time, and you can only blacklist a module.## NVIDIA's own modules are out-of-tree and built by DKMS against# /lib/modules/$KREL/build, which `make modules_install` creates. Nothing# else in the config is needed for them -- except that an unsigned# out-of-tree module must be loadable, hence MODULE_SIG_FORCE off below.## NOVA (the Rust GSP driver for Turing and later) is deliberately NOT# enabled: it depends on CONFIG_RUST and a matching rustc/bindgen, and is# still early. Enable RUST first, then NOVA_CORE and DRM_NOVA.cfg--moduleDRM_NOUVEAUfiif [ "$W_INTEL"=1 ]; then# --- Intel: graphics, compute, and the Meteor Lake+ NPU ------------------# i915 and xe overlap on Tiger Lake .. Meteor Lake. Building BOTH as modules# is correct and safe: only one binds a given device, chosen by the driver's# own device table and overridable with i915.force_probe / xe.force_probe.cfg--moduleDRM_I915# Gen2 .. Gen12: everything up to Alder/Raptor Lakecfg--moduleDRM_XE# Xe: Arc, Lunar Lake, Battlemage, newer iGPUscfg--moduleDRM_ACCEL_IVPU# "Intel NPU", Meteor Lake (14th gen) and newerfi# --- things that break a copied distro config --------------------------------# Distro configs point at signing keys and revocation lists shipped in their own# source package. Those files are not in the upstream tarball and the build dies# late with a confusing openssl error.cfg--set-strSYSTEM_TRUSTED_KEYS""cfg--set-strSYSTEM_REVOCATION_KEYS""# Same shape, one kernel release later: distro configs point EFI_SBAT_FILE at# kernel.sbat, which also lives only in their kernel SOURCE package. The rule# in arch/x86/boot/compressed/Makefile is a bare file dependency --# $(obj)/sbat.o: $(CONFIG_EFI_SBAT_FILE)# -- so a missing file is not a warning but a hard stop before a single object# of the boot stub links:# No rule to make target 'kernel.sbat', needed by '.../compressed/sbat.o'.# EFI_SBAT is `def_bool y if EFI_SBAT_FILE!=""`, so it cannot be switched off# directly; clearing the string is what turns it off. Nothing is lost -- SBAT# generations are Secure Boot revocation policy owned by whoever holds the# signing certificate, and upstream defines no components at all.cfg--set-strEFI_SBAT_FILE""cfg--disableEFI_SBATcfg--disableMODULE_SIG_FORCE# or no out-of-tree GPU module will load# Distro configs set CONFIG_WERROR=y, which is reasonable for the exact kernel# and exact compiler that distro tests -- and wrong for every other pairing.# This script deliberately feeds a distro config into a DIFFERENT kernel# version, and often with a different compiler; the new warnings that follow# are normal, and with WERROR they are all fatal, hours into the build.cfg--disableWERROR# The AMD display DML files (display_mode_vba_31 / _314 and friends) build ~2.4K# frames doing floating-point mode validation, so a distro config's 2048 warns on# every single build. Raised here so the setting survives -- .config is copied# fresh from /boot/config-$(uname -r) on every run, which silently reverts a# hand-edit. Note what this does NOT do: -Wframe-larger-than is a diagnostic# threshold, not an allocation. No function gets a byte more room, vmlinux is# unchanged, and the real bound is THREAD_SIZE (16K on x86_64, set by# THREAD_SIZE_ORDER in arch/x86/include/asm/page_64_types.h). It is consumed# once, globally, at scripts/Makefile.warn:25. FRAME_WARN=3072 keeps the check# useful while still covering the DML files; FRAME_WARN=0 turns it off entirely.cfg--set-valFRAME_WARN"$FRAME_WARN"if [ "$KEEP_DEBUG_INFO"!=1 ]; then# Full DWARF makes the build far slower and modules roughly 10x bigger. Set# KEEP_DEBUG_INFO=1 if you need BTF, bpftrace, or kernel debugging.cfg--disableDEBUG_INFO_BTFcfg--disableDEBUG_INFO_BTF_MODULES# The DWARF-version choice has to be cleared BEFORE selecting NONE, and the# order is not cosmetic. scripts/config edits in place, so enabling# DEBUG_INFO_NONE only rewrites the '# CONFIG_DEBUG_INFO_NONE is not set'# line where it already sits -- which in a distro config is the line ABOVE# CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y. Kconfig resolves a choice by# "the last one read wins" (confdata.c), so the DWARF entry won, selected# DEBUG_INFO, and full debug info stayed on for every module -- silently,# because nothing below checked for it.cfg--disableDEBUG_INFO_DWARF_TOOLCHAIN_DEFAULTcfg--disableDEBUG_INFO_DWARF4cfg--disableDEBUG_INFO_DWARF5cfg--enableDEBUG_INFO_NONEficfg--set-strLOCALVERSION"$LOCALVERSION"cfg--disableLOCALVERSION_AUTOmakeolddefconfig>/dev/null# --------------------------------------------------------------------- verifysay"Verifying the configuration"fail=0check() { got=$(grep-E "^(# )?CONFIG_$1[ =]" .config |head-1)if [ "$got"="CONFIG_$1=$2" ]; thenprintf' ok CONFIG_%-24s = %s\n'"$1""$2"elseprintf' FAIL CONFIG_%-24s want %s, got: %s\n'"$1""$2""${got:-<absent>}"; fail=1; fi}note() { # informational: hardware- or arch-gated, absence is not an error got=$(grep-E "^(# )?CONFIG_$1[ =]" .config |head-1)printf' -- CONFIG_%-24s %s\n'"$1""${got:-<absent>}"}checkDEVICE_PRIVATEycheckPCI_P2PDMAycheckDRM_SIMPLEDRMmcheckDRM_VIRTIO_GPUm# Verified, not assumed: this one failed silently for a long time, and the only# symptom was a build that took far longer and modules ten times the size.[ "$KEEP_DEBUG_INFO"=1 ] ||checkDEBUG_INFO_NONEyif [ "$W_AMD"=1 ]; thencheckDRM_AMDGPUm; checkDRM_AMD_DCy; checkDRM_AMDGPU_USERPTRycheckHSA_AMDy; checkHSA_AMD_SVMy; checkHSA_AMD_P2PynoteDRM_ACCEL_AMDXDNA# x86_64 + AMD_IOMMU onlyfi[ "$W_NV"=1 ] && checkDRM_NOUVEAUmif [ "$W_INTEL"=1 ]; thencheckDRM_I915mnoteDRM_XE# newer trees onlynoteDRM_ACCEL_IVPU# x86_64 onlyfi[ "$fail"-eq0 ] ||die"the config did not come out as intended -- do NOT install this kernel. Each FAIL is a dependency that is off, not a typo. Run 'make menuconfig' and search (/) for the symbol to see what it needs."KREL=$(make-s kernelrelease)printf' kernel release: %s\n'"$KREL"state_setrelease"$KREL"state_setmodules"/lib/modules/$KREL"# ------------------------------------------------------------------------ buildsay"Building -- this takes a while. Use tmux/screen over ssh."STATE_STAGE=buildstate_setstatusbuilding# The previous log is kept as .prev rather than appended to, so the file cannot# grow without bound across runs. pipefail (set at the top) is what makes the# tee honest: without it the pipeline would report tee's exit status and a# failed build would look like a successful one.if [ -f"$BUILD_LOG" ]; thenmv-f"$BUILD_LOG""$BUILD_LOG.prev"2>/dev/null||true; fiif { :>"$BUILD_LOG"; } 2>/dev/null; then# braces: else the error escapes fd2printf' logging to: %s\n'"$BUILD_LOG"make"${MAKE_ARGS[@]}"2>&1|tee"$BUILD_LOG"elsewarn"cannot write $BUILD_LOG -- building without a log. Set BUILD_LOG=<path>."make"${MAKE_ARGS[@]}"fistate_setstatusbuiltstate_setfinished"$(date-Is2>/dev/null ||date2>/dev/null ||true)"[ "$INSTALL"=1 ] || {say"Built, not installed."printf' Re-run with INSTALL=1, or install by hand:\n'printf' sudo make %s modules_install\n sudo make %s install\n'"${MAKE_ARGS[*]}""${MAKE_ARGS[*]}"exit0}# ---------------------------------------------------------------------- installifcommand-vdkms>/dev/null && dkmsstatus2>/dev/null|grep-q'^amdgpu'; thenwarn"amdgpu-dkms is installed. It exists to backport amdgpu to OLD enterprise kernels; the in-tree driver you just built is newer. It will try, and fail, to build against $KREL. To stop it without breaking your distro kernel, cap it: sudo sh -c 'echo BUILD_EXCLUSIVE_KERNEL_MAX=\"$(uname-r|cut-d--f1)\" >> /usr/src/amdgpu-*/dkms.conf'"fiifcommand-vdkms>/dev/null && dkmsstatus2>/dev/null|grep-q'^nvidia'; thenprintf' note: nvidia-dkms will rebuild for %s automatically once\n'"$KREL"printf' modules_install creates /lib/modules/%s/build.\n'"$KREL"printf' Remember to blacklist nouveau if you use the proprietary driver.\n'fisay"Installing modules and kernel (sudo)"STATE_STAGE=installstate_setstatusinstallingsudomake"${MAKE_ARGS[@]}"modules_installsudomake"${MAKE_ARGS[@]}"installstate_setstatusinstalledstate_setfinished"$(date-Is2>/dev/null ||date2>/dev/null ||true)"say"Post-install checks"img=""for i in"/boot/initramfs-$KREL.img""/boot/initrd.img-$KREL"; do [ -f"$i" ] && img="$i"; doneif [ -n"$img" ]; then lsi=""; command-vlsinitrd>/dev/null && lsi=lsinitrd [ -z"$lsi" ] && command-vlsinitramfs>/dev/null && lsi=lsinitramfsif [ -n"$lsi" ]; thenfor fw in amdgpu nvidia i915 xe; do [ "$fw"= amdgpu ] && [ "$W_AMD"!=1 ] && continue [ "$fw"= nvidia ] && [ "$W_NV"!=1 ] && continue { [ "$fw"= i915 ] || [ "$fw"= xe ]; } && [ "$W_INTEL"!=1 ] && continue n=$(sudo "$lsi" "$img" 2>/dev/null |grep-c "firmware/$fw" ||true) [ "${n:-0}"-gt0 ] && printf' ok %s %s firmware files in the initramfs\n'"$n""$fw"\||warn"no $fw firmware in $img -- install linux-firmware and regenerate the initramfs BEFORE rebooting, or that GPU will not come up."donefifi[ -e"/lib/modules/$KREL/build" ] \ && printf' ok /lib/modules/%s/build present -- DKMS and out-of-tree modules can build\n'"$KREL"\||warn"/lib/modules/$KREL/build is missing; DKMS modules cannot build against this kernel"# Driver presence check.## NOTE ON SPELLING: these are FILE names, and kernel module files keep their# hyphens -- virtio-gpu.ko, snd-hda-intel.ko, xen-blkfront.ko. Nearly 40% of# the modules in a typical kernel have a hyphen. It is the module's internal# NAME that uses underscores, which is what lsmod, modinfo -F name, /proc/modules# and /sys/module/ all display. Since this searches with find -name, the hyphen# is correct; "fixing" virtio-gpu to virtio_gpu here finds nothing.## A driver absent from /lib/modules is not necessarily a failure -- it may be# built in (=y), which is a perfectly good outcome and produces no .ko at all.# The old version of this loop printed nothing in that case, so a driver that# genuinely failed to build looked identical to one that succeeded as built-in.# Consult .config to tell those two apart.for entry in"amdgpu:DRM_AMDGPU""nouveau:DRM_NOUVEAU""i915:DRM_I915" \"xe:DRM_XE""simpledrm:DRM_SIMPLEDRM""virtio-gpu:DRM_VIRTIO_GPU"; do m="${entry%%:*}"; sym="${entry#*:}"iffind"/lib/modules/$KREL"-name"$m.ko*"2>/dev/null|head-1|grep-q.; thenprintf' ok %-12s installed as a module (%s.ko)\n'"$m""$m"elifgrep-q"^CONFIG_$sym=y".config2>/dev/null; thenprintf' ok %-12s built into the kernel image (CONFIG_%s=y)\n'"$m""$sym"elifgrep-q"^CONFIG_$sym=m".config2>/dev/null; thenwarn"$m: CONFIG_$sym=m was requested but no $m.ko was installed. That is a real failure -- check the modules_install step."elseprintf' -- %-12s not enabled in this config\n'"$m"fidonesay"Done. Keep your current kernel in the boot menu until $KREL is proven."
I HAVE JUST FINISHED DESIGNING “SATELLITE 004 REVISION 01”; ALTHOUGH SATELLITE IS NOT GOING TO BE RELEASED FOR ANOTHER 2 MONTHS, THE CURRENT DESIGN, AND IT WON’T GET ANY SLOWER THAN IT IS NOW… IS x119 FASTER THAN SATELLITE 003 REVISION 06.
THE REASON FOR IT IS THAT WE ARE COMPILING ALL OF THESE TINY C++ LIBRARIES, FIRST WE BUILD THE FUNCTION THAT RUNS FOR THAT satellite.something.something(), THEN WE BUILD THE MOST LIKELY ARGUMENTS TO BE INCLUDED… SO WHEN YOU CALL satellite.console.display(“some string”) IT RUNS LITERALLY AS FAST AS C++, AND SOME TIMINGS FOR IT RACING std::cout CAN BE –FASTER– THAN COMPILED C++ CODE, IT JUST KINDA GETS LUCKY IN THE TIMING AND IT COMES OUT FASTER;
I WAS KINDA STARTING TO NOT LIKE THE 003 06 INTERPRETER, AND AS I BEGAN TO ADD POLYMORPHIC CODE TO IT, I REALIZED I CAN JUST BUILD ALL OF THESE TINY C++ LIBRARIES THAT IT LOADS AHEAD OF TIME.. SO SATELLITE IS GOING TO BE SLIGHTLY SLOW FOR SOMETHING THAT’S LIKE THIS:
satellite.include(satellite)satellite.capsulesatellite.main(){satellite.console.display("welcome to my program")satellite.variable.numbersome_value=999999satellite.variable.numberanother_value=2344763satellite.console.display(some_value+another_value)satellite.return(satellite)}
I’M GOING TO BE COMPLETELY HONEST WITH YOU — IF YOU ARE THINKING ABOUT RUNNING SOME CODE THAT LOOKS LIKE THAT, YOU MIGHT AS WELL RUN IT IN PYTHON OR C++ — CODE LIKE THAT DOESN’T NEED TO LOAD 1,000 TINY C++ PROGRAMS, SATELLITE IS BEING BUILT FOR PROGRAMS THAT ARE BUILT OUT OF; 100,000 LINES, 20,000 LINE PROGRAMS, THINGS LIKE THAT.
YOU CAN TECHNICALLY USE IT FOR SMALL PROGRAMS, BUT WHY LOAD 1,000 TINY LIBRARIES TO ADD TWO NUMBERS TOGETHER?
ANYWAYS, FOR LIKE REALLY LARGE PROGRAMS, SATELLITE WILL RUN INCREDIBLY FAST.. THE EXACT SPEED IS GOING TO BE LIKE LITERALLY AS FAST, BUT FASTER, HERE IS WHY IT’S FASTER THAN COMPILED C++:
I'VE GOT AHOLD OF A GENERAL ARTIFICIAL INTELLIGENCE (LIKE A SUPER ONE) AND IT IS PROGRAMMING ALL OF THE TINY C++ LIBRARIES TO BE AS FAST AS THEY CAN POSSIBLY GO!!
SO IF YOU ARE GOING TO BUILD A PROGRAM THAT SAY, DOES JUST A _TON_ OF NORMAL OPERATIONS, YOUR CODE IS GOING TO RUN FASTER IF YOU USE SATELLITE THAN IF YOU WROTE IT YOURSELF, BECAUSE THE GENERAL ARTIFICIAL INTELLIGENCE KNOWS HOW TO WRITE BETTER C++ THAN YOU DO. WE ARE TAKING OUR TIME AND WRITING EACH TINY C++ LIBRARY TO BE AS FAST AS WE CAN MAKE IT, WE MIGHT STRIP “int main()” OUT OF EACH LIBRARY, I DON’T KNOW YET, I GUESS WE DON’T NEED TO TAKE IT THAT FAR, BUT THAT JUST GIVES YOU AN EXAMPLE OF THE LENGTHS THAT WE ARE GOING TO HERE…
SO FOR A LOT OF NORMAL COMPUTER CODE, SATELLITE WILL BE THE BEST SOLUTION FOR LOTS OF NORMAL COMPUTER CODE… NOW IF YOUR PROGRAMMING SOMETHING EXTREMELY COMPLICATED, LIKE SOMETHING WITH POINTERS, NAMESPACES, TEMPLATES, AND YOU UNDERSTAND ALL OF THAT STUFF, THEN C++ IS GOING TO BE THE BETTER OPTION.
THE ORIGINAL GOAL OF SATELLITE HAD JUST A SINGLE THING IN MIND: TO MAKE A PROGRAMMING LANGUAGE TO OVERCOME C++, SO THAT OUR SOCIETY DIDN’T HAVE TO USE C++; ALTHOUGH SATELLITE IS BUILT IN C++, WHICH MEANS IT WILL NEVER BECOME IRRELEVANT, IT IS BUILT TO CALL C++; SO IN OTHER WORDS, IT’S SUPPOSED TO BE USED INSTEAD OF C++, THAT IS LIKE, THE POINT OF THE ENTIRE PROJECT, BUT WHATEVER.
IT’S SO WE DON’T HAVE TO USE C++ ANYMORE, C++ STILL HAS LIKE EVERYTHING FROM 1994, AND YES IT STILL ALL WORKS, AND IT’S PROBABLY ONLY GOTTEN FASTER IF YOU STILL HAVE PROGRAMS FROM 1994, BUT IF YOUR ON A MACHINE THAT HAS A GUI AND ALMALINUX 10, WHY WOULD YOU CHOOSE C++ AS THE LANGUAGE TO USE? YOU HAVE A GUI, YOU HAVE THE MEMORY AVAILABLE, YOU HAVE THE PROCESSING POWER AVAILABLE, USE SOMETHING DESIGNED TO USE THESE THINGS, SOMETHING DESIGNED WITH ALL OF THESE THINGS IN MIND?
C++ CAN DO ANYTHING, IT CAN DO IT INCREDIBLY FAST, IT HAS ALL OF THE CONTROL, BUT IF YOU DON’T REALLY NEED THAT STUFF, AND YOUR JUST DOING SOME NORMAL STUFF, YOU DON’T NEED TO LOOK UP HOW TO WRITE A STD::CHRONO DURATION_CAST 6 TIMES TO WRITE A TIMER, YOU CAN JUST WRITE:
satellite.include(satellite)satellite.capsulesatellite.main(satellite.container.list<satellite.variable.string>arguments){satelllite.variable.timemy_timer=satellite.time.now()//wait,thatisn't a timer, but I know what i'llmakethesyntaxforatimer,satellite.variable.timemy_timer=satellite.time.timer()my_timer.start() my_timer.end()satellite.return(satellite)}
AND THAT WILL BE THE ENTIRE TIMER, WITH ALL OF THE HIGH RESOLUTION OF NANOSECONDS, IF YOU WANT THEM, YOU’LL BE ABLE TO DECLARE WHAT TYPE OF TIME YOU WANT, INPUTTING IT RIGHT INTO THE satellite.time.timer(“ms”) or “s” or “ns” or whatever, you can just do that. So here is an entire nanosecond timer in C++, with the time displayed:
satelllite.include(satellite)satellite.capsulesatellite.main(satellite.container.list<satellite.variable.string>arguments){satellite.variable.timemy_timer=satellite.time.timer("ns")my_timer.start() satellite.console.display("put the code you will run in between .start() and .end()")my_timer.end() satellite.console.display(my_timer)satellite.return(satellite)}
that’s all it’s going to take dude, no lies, and no bullshit it’s tiny compiled C++ libraries, so satellite can’t replace C++, it’s built using C++, it’s not going to run on someones watch, or inside of an MP3 Player, it’s made for large machines, but if you do have a large machine, perhaps with infinite amounts of memory and processing power, use all of that processing power, and use all of those threads, and use your graphics card (someday)!
We stupid people will be able to program graphical applications in satellite, things that are like little dots running around the screen, and someday I am using it for my artificial intelligence, QUAD AI, that is the literal reason why I have created it, but I built it to be able to take advantage of: large machines, that have like infinite resources, those resources can be maximized by satellite, it cannot program “large CERN particle colliders” but the tradeoff of not being able to do that stuff is in what it can actually do — do you have 32 – 64 gigabytes of memory? More? Then you can use satellite, but the tradeoff is that if you are trying to balance the tires on your car on a budget inside of a small chip that exists inside of a car, then no, your not going to be able to run satellite in that location, so I guess the moral of the story is that it doesn’t replace C++ when it’s intended goal is to replace C++, kind of a weird way to think about it?
I WROTE THIS TUTORIAL FOR MY MOM TO FOLLOW, SHE IS STILL LEARNING TO PROGRAM THE COMPUTER, SO I MADE THIS TUTORIAL EASY. SO THAT SHE COULD STILL FOLLOW IT BECAUSE SHE IS STILL LEARNING ABOUT PROGRAMMING, BUT THIS IS ALSO A PERFECT PLACE TO START FOR SOMEONE WHO IS A BEGINNER.
FIRST, TO RUN SATELLITE PROGRAMS, YOU NEED TO INSTALL SATELLITE. GO TO THE DOWNLOAD BUTTON AT THE TOP OF THIS WEBSITE, AND THEN CLICK DOWNLOAD. AFTER YOU DOWNLOAD THE APPLICATION, YOU NEED TO LOOK WHERE YOU SAVED IT AND EXTRACT THE FILES.
THEN YOU NEED TO OPEN A CONSOLE WINDOW IN THE SAME FOLDER AS THE EXTRACTED FILES. THIS IS BECAUSE WE WILL NEXT RUN THE INSTALL SCRIPT CALLED “install-satellite.sh” BY TYPING THIS IN TO THE CONSOLE:
./install-satellite.sh
TYPE THAT IN TO THE CONSOLE AFTER YOU HAVE CD’d TO THE SAME DIRECTORY THAT THE EXTRACTED FILES ARE IN. THESE FILES ARE IN A FOLDER THAT IS NEXT TO THE FILE THAT YOU DOWNLOADED. ALL THAT YOU HAVE TO DO IS OPEN A CONSOLE WINDOW INSIDE OF THAT FOLDER, AND TYPE IN “./install-satellite.sh” AND IT WILL INSTALL THE PROGRAM FOR YOU, THEN YOU NEED TO SET YOUR $PATH VARIABLE INSIDE OF YOUR “.bashrc” FILE.
THIS WILL ALLOW YOU TO ACCESS SATELLITE FROM ANY CONSOLE WINDOW, AND IT ALSO COMES WITH A PROGRAM CALLED “satl-term”, WHICH IS A TERMINAL DESIGNED ONLY FOR RUNNING SATELLITE PROGRAMS. YOU CAN ACCESS THE “satl-term” PROGRAM BY USING THE SAME $PATH VARIABLE THAT WE SET EARLIER, JUST ADD THIS COMMAND TO YOUR .bashrc FILE:
exportPATH="/~/.satl/bin:$PATH"
AFTER YOU HAVE TYPED THAT INTO YOUR .bashrc FILE, CLOSE ANY CONSOLE WINDOWS THAT YOU HAVE OPEN TO REFRESH YOUR VARIABLES AND OPEN THEM AGAIN, YOU WILL NOW HAVE ACCESS TO TWO SEPARATE PROGRAMS:
OPTIONALLY YOU CAN SET THE NAME “satellite” TO ALSO RUN SATELLITE PROGRAMS, THAT IS UP TO YOU, THE WORD “SATELLITE” MAY BE RESERVED BY REDHAT OR DEBIAN, BUT ESPECIALLY ON ENTERPRISE LINUX THE WORD “SATELLITE” IS RESERVED FOR THEIR PROGRAMS, BUT IF YOU DON’T USE REDHAT SATELLITE, THEN IT MIGHT NOT HURT ANYTHING.
NOW THAT WE HAVE INSTALLED THE INTERPRETER FOR SATELLITE PROGRAMS, WE CAN WRITE ONE! TYPE THESE LINES INTO A TEXT FILE AND CLICK SAVE AS, THEN TYPE IN A NAME FOR IT LIKE “hello_world.satl” OR SOMETHING SIMILAR, BUT ALSO REMEMBER WHERE YOU SAVED THE FILE, WE WILL NEED TO GO THERE TO RUN THE PROGRAM, WE WILL HAVE TO TYPE IN THE FULL ADDRESS OF THE PROGRAM TO RUN IT. SO FIRST THE SYNTAX THAT YOU NEED TO TYPE IN: (AND DON’T WORRY ABOUT THE COMMENTS FOR RIGHT NOW, THEY ARE JUST THERE TO TELL YOU ABOUT THE DIFFERENT LINES, AND YOU DON’T REALLY HAVE TO UNDERSTAND EVERY SINGLE ONE OF THEM.)
THE SCRIPT “install-satellite.sh” INCLUDES EVERYTHING THAT THE REAL INSTALLER INCLUDES, AND IT CHANGES YOUR FILES TO LOOK LIKE PIECES OF PAPER WITH SATELLITES ON THEM.
I AM STILL WORKING ON PROGRAMS THAT OFFER SYNTAX HIGHLIGHTING, I JUST DON’T HAVE THE TIME TO GET EVERYTHING WORKING FOR IT, GTK4 PROGRAMS ARE VERY COMPLICATED.
THIS PAGE DOESN’T OFFER SYNTAX HIGHLIGHTING FOR THE SATELLITE LANGUAGE BECAUSE I DON’T HAVE THE TIME TO PROGRAM SYNTAX HIGHLIGHTING FOR IT MYSELF.
This script works on enterprise linux, and it’s supposed to work on debian/ubuntu too. It grabs the latest kernel available, you just have to run it twice to install the kernel; First here’s the instructions:
Here is the complete build script for you to look at but I wouldn’t copy and paste it, just use the “Download” button and extract it. If you copy and paste it, some of the characters will not be copied and it might not work. You can compare the number of lines and file size of both though, if your worried about viruses!
#!/usr/bin/env bash## universal_linux_kernel_build.sh## Download, configure, build and install a mainline Linux kernel that works on# whatever graphics you actually have -- AMD, NVIDIA, Intel, a virtual machine,# or a headless server -- with the GPU compute and NPU ("AI") paths turned on.## It starts from your running distro's config so your existing hardware keeps# working, then enforces the options GPU compute needs and that hand-rolled# configs most often get wrong.## ./universal_linux_kernel_build.sh # detect, build only# INSTALL=1 ./universal_linux_kernel_build.sh # build, then install## GPU=auto detect from lspci (default)# GPU=all every vendor -- a kernel that boots on anything# GPU=amd,intel a comma-separated list: amd nvidia intel vm## KVER=6.12.9 ./universal_linux_kernel_build.sh # a specific release# SRC=~/src/linux ./universal_linux_kernel_build.sh # an existing tree# TOOLCHAIN=llvm LLVM_PREFIX=$HOME/opt/clang-current/bin/ ./universal_...sh## CLEAN=auto mrproper the tree only if the last attempt did not finish# CLEAN=always mrproper first, every time# CLEAN=never never clean; always build incrementally## CONFIG_BASE=auto keep the tree's .config if it has one, else the distro's# CONFIG_BASE=distro always reseed from /boot/config-$(uname -r)# CONFIG_BASE=defconfig start from the arch defconfig# CONFIG_BASE=<path> start from a config file you name# FRAME_WARN=8192 -Wframe-larger-than=; 0 disables the check entirely## Two files are written beside this script (override with STATE_FILE= / BUILD_LOG=):# kernel_build.ini what was done to each source tree, one [section] each# kernel_build.log full output of the last build (previous kept as .log.prev)## THE ONE THING THIS SCRIPT EXISTS TO GET RIGHT: GPU drivers are MODULES.# Built-in (=y) is the most common mistake in hand-rolled GPU kernel configs.# A built-in driver probes before the root filesystem is mounted, so all of its# firmware must already be in the initramfs -- but dracut and initramfs-tools# decide which firmware to include by looking at which MODULES are installed,# and a built-in driver is not a module. The result is a driver that cannot load# its firmware: no display, no /dev/kfd. As modules they also stay unloadable# and blacklistable, which the NVIDIA proprietary stack requires.## Licence: public domain / CC0. No warranty. It installs a kernel; read it first.set-euopipefail# --- integrity self-check -------------------------------------------------# This file must be pure ASCII. Copying a script out of a web page or a chat# window silently replaces ordinary spaces with U+00A0 (non-breaking space),# which bash treats as part of a command name -- you get "command not found"# on a line that looks perfectly correct.## NOTE: the body below is deliberately NOT indented. Leading whitespace is# exactly what gets converted, so an indented error handler is unable to report# the corruption it just detected -- it fails as "printf: command not found".if LC_ALL=Ctr-d'\11\12\40-\176'<"$0"|head-c1| LC_ALL=Cgrep-q.; thenprintf'ERROR: %s contains non-ASCII bytes.\n'"$0">&2printf'It was almost certainly corrupted by copy-paste from a web page.\n'>&2printf'Repair it with:\n'>&2printf" sed -i 's/%s/ /g' %s\n"'\xc2\xa0'"$0">&2printf'or, better, download the file directly instead of pasting it.\n'>&2exit1fi# --------------------------------------------------------------------------GPU="${GPU:-auto}"KVER="${KVER:-}"# empty = latest stableSRC="${SRC:-}"# empty = download a tarballWORK="${WORK:-$HOME/src}"LOCALVERSION="${LOCALVERSION:--gpu}"FRAME_WARN="${FRAME_WARN:-8192}"# -Wframe-larger-than=; 0 disables, 8192 is the Kconfig max# De-export it. This is OUR knob, but kbuild has a variable of the SAME NAME# and means something else by it: scripts/setlocalversion ends with# echo "${KERNELVERSION}${file_localversion}${config_localversion}${LOCALVERSION}${scm_version}"# so a LOCALVERSION that is in make's ENVIRONMENT is appended on top of the# CONFIG_LOCALVERSION this script sets below -- and the release comes out as# 7.2.0-gpu-gpu. It only bites when the value arrived from the environment# (an orchestrator, or `LOCALVERSION=-x ./this.sh`), because a plain assignment# does not export, but a value inherited from the environment stays exported# through re-assignment. The config setting below is the only path we want.export-nLOCALVERSION2>/dev/null||true# ------------------------------------------------------------- build bookkeeping# Two files live next to this script. kernel_build.ini records what was done to# each source tree so a later run can tell an interrupted or failed tree from a# finished one; kernel_build.log is the full output of the last build.## The .ini is keyed by SOURCE TREE, not by version -- one [section] per tree --# because a single machine easily ends up with several (a KVER= build in ~/src# beside an SRC=/KERNEL_SRC= tree elsewhere), and a state file that assumed one# tree would confidently report the wrong one. Delete it any time: a missing# entry simply reads as "previous attempt unknown".SELF_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"|| SELF_DIR="$PWD"STATE_FILE="${STATE_FILE:-$SELF_DIR/kernel_build.ini}"BUILD_LOG="${BUILD_LOG:-$SELF_DIR/kernel_build.log}"CLEAN="${CLEAN:-auto}"# auto: clean only an unfinished tree | always | never# Where the configuration comes from. "auto" keeps a .config the tree already# has and only seeds from the running distro when there is none, so re-running# no longer throws away work between runs. The enforcement below re-applies to# whatever base is chosen, and the verify block still refuses to install a# config that did not come out right, so keeping an existing one is safe.CONFIG_BASE="${CONFIG_BASE:-auto}"# auto | distro | defconfig | /path/to/config# Both are touched only AFTER this script has chdir'd into $WORK and then $SRC,# so a relative override would land somewhere the user did not mean. Resolve# them against the directory we were invoked from, once, while that is still cwd.case $STATE_FILE in /*) ;; *) STATE_FILE="$PWD/$STATE_FILE" ;; esaccase $BUILD_LOG in /*) ;; *) BUILD_LOG="$PWD/$BUILD_LOG" ;; esacJOBS="${JOBS:-$(nproc)}"INSTALL="${INSTALL:-0}"INSTALL_DEPS="${INSTALL_DEPS:-1}"TOOLCHAIN="${TOOLCHAIN:-gcc}"# gcc | llvmLLVM_PREFIX="${LLVM_PREFIX:-}"# e.g. $HOME/opt/clang-current/bin/ (TRAILING SLASH)KEEP_DEBUG_INFO="${KEEP_DEBUG_INFO:-0}"# 1 keeps DWARF+BTF (far bigger, far slower)say() { printf'\n\033[1m==> %s\033[0m\n'"$*"; }warn() { printf'\033[33mwarning:\033[0m %s\n'"$*">&2; }die() { printf'\n\033[31mERROR:\033[0m %s\n'"$*">&2; exit1; }# ---------------------------------------------------------------- state helpers# Loaded into an associative array and flushed whole, rather than edited in# place. Sections for OTHER trees are copied through verbatim, so two trees# never clobber each other, and a flush after every set means the record# survives a kill -9 mid-build -- which is exactly the case it exists to detect.declare-ASTATE=()STATE_OK=0STATE_STAGE=startupstate_init() {locald; d="$(dirname "$STATE_FILE")"if [ -d"$d" ] && [ -w"$d" ] && { [ !-e"$STATE_FILE" ] || [ -w"$STATE_FILE" ]; }; then STATE_OK=1elsewarn"cannot write $STATE_FILE -- continuing without build-state tracking. Set STATE_FILE=<path> to somewhere writable, or pass CLEAN=always/never to decide about cleaning explicitly."fi}state_load() { [ "$STATE_OK"=1 ] && [ -f"$STATE_FILE" ] ||return0locallinekvinm=0while IFS=read-rline; docase"$line"in"[$SRC]") inm=1; continue ;;\[*) inm=0; continue ;;''|'#'*) continue ;;esac [ "$inm"=1 ] ||continuecase"$line"in*=*) ;; *) continue ;; esac k=${line%%=*}; v=${line#*=} k=${k///}; k=${k//$'\t'/}; v=${v# }# An if, not `[ -n "$k" ] && ...`: a while-read returns the status of the# last command in its body, so a trailing blank key would make state_load# return 1 and `set -e` would kill the run silently at the call site.if [ -n"$k" ]; thenSTATE["$k"]="$v"; fidone<"$STATE_FILE"return0}state_flush() { [ "$STATE_OK"=1 ] ||return0localtmpk tmp="$(mktemp "${STATE_FILE}.XXXXXX" 2>/dev/null)"||return0 {printf'# universal_linux_kernel_build.sh -- build state, one [section] per source tree.\n'printf'# Written automatically; safe to delete.\n'# cat -s squeezes the blank line that the awk pass preserves and the# printf below re-emits; without it the file gains one blank per write. [ -f"$STATE_FILE" ] && awk-vsec="[$SRC]"'/^\[/ { keep = ($0 != sec) } keep'"$STATE_FILE"|cat-sprintf'\n[%s]\n'"$SRC"for k in"${!STATE[@]}"; doprintf'%s = %s\n'"$k""${STATE[$k]}"; done|sort } >"$tmp"2>/dev/null && mv-f"$tmp""$STATE_FILE"||rm-f"$tmp"}state_set() { [ "$STATE_OK"=1 ] ||return0; STATE["$1"]="$2"; state_flush; }# Records a failure without changing the exit status. `local rc=$?` must stay# the first statement or it captures the wrong command._state_on_exit() {local rc=$?if [ "$STATE_OK"=1 ] && [ "$rc"-ne0 ]; then STATE[status]=failed STATE[stage]="$STATE_STAGE" STATE[exit_code]="$rc" STATE[finished]="$(date-Is2>/dev/null ||date2>/dev/null ||true)"state_flushfireturn0}DNF_PKGS="gcc make flex bison bc openssl-devel elfutils-libelf-devel dwarves ncurses-devel rsync cpio perl python3 xz zstd git tar pciutils"APT_PKGS="build-essential flex bison bc libssl-dev libelf-dev dwarves libncurses-dev rsync cpio perl python3 xz-utils zstd git tar pciutils"# Best-effort, deliberately. A package manager exits non-zero for reasons that# have nothing to do with the packages asked for -- one third-party repo with an# unverifiable GPG key is enough, and dnf then refuses to load metadata and# exits 1 in the first ten seconds. Under `set -e` a bare install call would# take a multi-hour build down with it for a reason the user cannot see from the# error. So warn and carry on: the Preflight loop immediately below is the real# gate, and it names the tool that is actually missing.if [ "$INSTALL_DEPS"=1 ]; thensay"Installing build dependencies (sudo)"ifcommand-vdnf>/dev/null; thensudodnfinstall-y $DNF_PKGS \||warn"dnf could not install every dependency; continuing. If the build fails on a missing header, that is where to look. A single broken repo is the usual cause -- retry with sudo dnf install -y --disablerepo=<broken> $DNF_PKGS or set INSTALL_DEPS=0 if you know the packages are already present."elifcommand-vapt-get>/dev/null; then# Separate statements, not `update && install`: chained, a failed update# makes the whole list non-zero and set -e kills the script with nothing# printed. A stale index is not a reason to refuse to build.sudoapt-getupdate||warn"apt-get update failed; using the cached package lists"sudoapt-getinstall-y $APT_PKGS \||warn"apt-get could not install every dependency; continuing."elsewarn"no dnf/apt-get -- install kernel build deps yourself, then re-run with INSTALL_DEPS=0"fifisay"Preflight"for t in make gcc flex bison bc rsync cpio; docommand-v"$t">/dev/null||die"missing: $t"; done[ "$(id-u)"-ne0 ] ||die"do not run this whole script as root. The build runs as you; only the install steps use sudo."# ------------------------------------------------------------------ GPU detect## VM/legacy drivers are ALWAYS enabled. They are a few hundred KB of modules and# they are the difference between "this kernel boots on my machine" and "this# kernel boots anywhere" -- a VM, a server with an ASPEED BMC, a rescue boot on# unfamiliar hardware. There is no reason to leave them out.W_AMD=0; W_NV=0; W_INTEL=0ifcommand-vlspci>/dev/null; thenwhile IFS=read-rline; docase"$line"in*[Aa][Mm][Dd]*|*ATI*) W_AMD=1; printf' found: %s\n'"$line" ;;*NVIDIA*|*nVidia*) W_NV=1; printf' found: %s\n'"$line" ;;*Intel*) W_INTEL=1; printf' found: %s\n'"$line" ;;esacdone<<(lspci-nn2>/dev/null |grep-Ei 'vga|3d|display' ||true)ficase"$GPU"in auto)if [ "$W_AMD$W_NV$W_INTEL"="000" ]; thenwarn"no AMD/NVIDIA/Intel GPU detected (headless, VM, or unknown hardware). Enabling all vendors so the kernel boots anywhere. Use GPU= to narrow it." W_AMD=1; W_NV=1; W_INTEL=1fi ;; all) W_AMD=1; W_NV=1; W_INTEL=1 ;;*) W_AMD=0; W_NV=0; W_INTEL=0 IFS=','read-rawant<<<"$GPU"for v in"${want[@]}"; docase"${v///}"in amd) W_AMD=1 ;; nvidia|nv) W_NV=1 ;; intel) W_INTEL=1 ;; vm|none) ;;*) die "unknown GPU vendor '$v' (use: auto all amd nvidia intel vm)" ;;esac; done ;;esacprintf' enabling : %s%s%s%s\n'\"$([ "$W_AMD" =1 ] && echo 'AMD ')""$([ "$W_NV" =1 ] && echo 'NVIDIA ')"\"$([ "$W_INTEL" =1 ] && echo 'Intel ')"'VM/legacy(always)'MAKE_ARGS=(-j"$JOBS")if [ "$TOOLCHAIN"= llvm ]; then [ -n"$LLVM_PREFIX" ] && case"$LLVM_PREFIX"in*/) ;; *) die "LLVM_PREFIX must end in a slash -- kbuild treats it as a path prefix";; esac MAKE_ARGS+=(LLVM="${LLVM_PREFIX:-1}")# tools/lib/bpf can be compiled by gcc (non-PIC) while the host link runs# clang/ld.lld, which defaults to PIE. That mix fails building# tools/bpf/resolve_btfids with R_X86_64_32 relocation errors. MAKE_ARGS+=(HOSTLDFLAGS=-no-pie)printf' toolchain : clang (%s)\n'"${LLVM_PREFIX:-fromPATH}"elseprintf' toolchain : %s\n'"$(gcc--version|head-1)"fi# ---------------------------------------------------------------------- sourceif [ -z"$SRC" ]; thenif [ -z"$KVER" ]; then KVER=$(curl-fsSL https://www.kernel.org/finger_banner 2>/dev/null \|awk '/latest stable/{print $NF; exit}')||true [ -n"$KVER" ] ||die"could not determine the latest kernel version; set KVER="fi SRC="$WORK/linux-$KVER"if [ !-d"$SRC" ]; thenmkdir-p"$WORK"; cd"$WORK"say"Downloading linux-$KVER"curl-fL--progress-bar-O"https://cdn.kernel.org/pub/linux/kernel/v${KVER%%.*}.x/linux-$KVER.tar.xz"tarxf"linux-$KVER.tar.xz"fifi[ -f"$SRC/Makefile" ] ||die"no kernel source at $SRC"cd"$SRC"# Canonicalise now that we are standing in it, BEFORE it becomes a state key.# SRC is the [section] name, and a trailing slash from tab-completion, a# relative "." or a symlinked path would each key the same tree differently --# and a key that misses reads as "no previous attempt", which under CLEAN=auto# means mrproper on a tree that was perfectly good. pwd -P resolves all three.SRC="$(pwd-P)"printf' source : %s (%s)\n jobs : %s\n'"$SRC""$(make-s kernelversion)""$JOBS"# ------------------------------------------------------- previous build attemptstate_initstate_loadtrap_state_on_exitEXITsay"Previous build attempt"prev_status="${STATE[status]:-}"# -print -quit stops at the first hit: on a fully built tree this answers in# milliseconds, where counting all ~16000 objects would walk 4.6G of tree.objects="$(find . -name '*.o' -not-path './scripts/*' -print-quit2>/dev/null ||true)"if [ -n"$prev_status" ]; thenprintf' recorded : %s'"$prev_status" [ -n"${STATE[finished]:-}" ] && printf' (%s)'"${STATE[finished]}" [ "$prev_status"= failed ] && printf' at stage %s'"${STATE[stage]:-unknown}"printf'\n'elseprintf' recorded : nothing -- no entry for this tree in %s\n'"$STATE_FILE"fido_clean=0; clean_why=""case"$CLEAN"in never) clean_why="CLEAN=never" ;; always) do_clean=1; clean_why="CLEAN=always" ;; auto)if [ -z"$objects" ]; then clean_why="no object files present -- nothing to clean"elsecase"$prev_status"in built|installed) clean_why="the previous run finished ($prev_status); rebuilding incrementally is correct and far faster" ;; building) do_clean=1; clean_why="a previous run started and never recorded finishing -- interrupted or killed" ;; failed) do_clean=1; clean_why="the previous run failed at stage ${STATE[stage]:-unknown}" ;;"") do_clean=1; clean_why="objects are present but nothing recorded how they got there" ;;*) do_clean=1; clean_why="recorded status '$prev_status' is not a completed build" ;;esacfi ;;*) die "CLEAN must be auto, always or never (got '$CLEAN')" ;;esac# Back up BEFORE announcing or doing anything, and re-test afterwards. If the# configuration cannot be saved then cleaning would destroy it outright, and not# cleaning is always the safer of the two -- an incremental build on a suspect# tree is a slow problem, a deleted config is an unrecoverable one.if [ "$do_clean"=1 ]; then _bk=""if [ -f .config ]; then# The FIRST backup is the valuable one: by the second cleaning run# .config may no longer be the user's file, so overwriting a fixed name# would replace the only copy of their original. Keep the first,# timestamp the rest. --remove-destination because a plain `cp -a` onto# an existing symlink writes THROUGH it, clobbering its target. _bk=.config.before-clean [ -e"$_bk" ] && _bk=".config.before-clean.$(date +%Y%m%d-%H%M%S 2>/dev/null ||echo prev)"ifcp-a--remove-destination.config"$_bk"2>/dev/null; thenprintf' saved : .config -> %s\n'"$_bk"else do_clean=0; _bk="" clean_why="could not save .config, so cleaning would destroy it"warn"cannot back up $SRC/.config -- NOT cleaning this tree. Fix its permissions, or move it aside yourself, or pass CLEAN=never to stop being asked. Building incrementally instead."fififi# A SECOND test, not an else: $do_clean can have been cleared just above, and# the previous version of this block set it there and then cleaned anyway --# printing "not cleaning" immediately before deleting the file it could not save.if [ "$do_clean"=1 ]; thenprintf' cleaning : %s\n'"$clean_why"# mrproper, not clean: the failure this recovers from is a tree left# inconsistent, and `make clean` keeps include/config and the generated# headers that are the usual culprits. It deletes .config too, which is# incidental -- cleaning is about build PRODUCTS, not your configuration --# so that is restored immediately afterwards. STATE_STAGE=cleanmake-smrproperprintf' cleaned : %s\n'"$SRC"# Only for CONFIG_BASE=auto: the other modes are an explicit instruction# about where the config comes from, and restoring one would contradict it.if [ "$CONFIG_BASE"= auto ] && [ -n"$_bk" ] && [ -f"$_bk" ]; thencp-a--remove-destination"$_bk".config\ && printf' restored : .config kept across the clean (from %s)\n'"$_bk"fielseprintf' keeping : %s\n'"$clean_why"fistate_settree"$SRC"state_setversion"$(make-s kernelversion)"state_settoolchain"$TOOLCHAIN"state_setjobs"$JOBS"state_setlog"$BUILD_LOG"state_setstarted"$(date-Is2>/dev/null ||date2>/dev/null ||true)"state_setstatusconfiguringstate_setstage""state_setexit_code""state_setfinished""# or the previous run's finish time reads as this one'sSTATE_STAGE=configure# --------------------------------------------------------------------- configuresay"Configuring"# Copy the running distro's config in. Factored out because CONFIG_BASE=auto# calls it only as a fallback, where the old code called it unconditionally and# so destroyed a tuned .config on every single run.# Never write .config in place. A redirect truncates the target before the# first byte arrives, so a corrupt source or a killed run leaves a FRAGMENT --# and under CONFIG_BASE=auto the next run would adopt that fragment as its base,# with olddefconfig silently defaulting every symbol the fragment never reached.# Writing to a temp and renaming makes the swap atomic; rename also replaces a# .config SYMLINK rather than writing through it to whatever it points at.install_config() {local src="$1"tmp tmp=".config.seed.$$"case"$src"in*.gz) zcat "$src">"$tmp" ;;*) cp "$src""$tmp" ;;esac|| { rm-f"$tmp"; die"could not read the config at $src"; } [ -s"$tmp" ] || { rm-f"$tmp"; die"the config at $src is empty"; }mv-f"$tmp".config}seed_from_distro() {localcbase=""for c in"/boot/config-$(uname-r)" /proc/config.gz; do [ -r"$c" ] && { base="$c"; break; }doneif [ -n"$base" ]; thenprintf' base: %s\n'"$base"install_config"$base"elsewarn"no distro config found; starting from defconfig -- review before installing"makedefconfig>/dev/nullfi}case"$CONFIG_BASE"in auto)# Cheap sanity gate before adopting it: a truncated or empty file would# otherwise be taken as authoritative and quietly defaulted by# olddefconfig into a config nobody chose.if [ -s .config ] && grep-q'^CONFIG_[A-Z0-9_]*='.config2>/dev/null; thenprintf' base: the .config already in this tree -- kept, not replaced\n'printf' (CONFIG_BASE=distro to reseed from the running kernel)\n'else [ -e .config ] && warn"$SRC/.config is empty or has no CONFIG_ lines -- ignoring it and seeding from the running kernel instead. The old file is kept as .config.rejected if you want to look at it." [ -e .config ] && mv-f.config.config.rejectedseed_from_distrofi ;; distro)seed_from_distro ;; defconfig)printf' base: make defconfig\n'makedefconfig>/dev/null ;;*) [ -r"$CONFIG_BASE" ] ||die"CONFIG_BASE=$CONFIG_BASE is not a readable file. Expected: auto, distro, defconfig, or a path to a kernel config."printf' base: %s\n'"$CONFIG_BASE"install_config"$CONFIG_BASE" ;;esac# Bring whatever base was chosen up to date with THIS tree's Kconfig before the# enforcement below. A config from another kernel version is missing symbols# this one has; without this, scripts/config sets options against a stale symbol# table and the second olddefconfig quietly drops them again.makeolddefconfig>/dev/nullstate_setconfig_base"$CONFIG_BASE"cfg() { ./scripts/config"$@"; }# --- shared GPU-compute plumbing ---------------------------------------------# These are DEPENDENCIES, not preferences. HSA_AMD_SVM depends on DEVICE_PRIVATE# and HSA_AMD_P2P depends on PCI_P2PDMA; with those off, asking for them# silently does nothing and olddefconfig quietly drops them. The same machinery# backs NVIDIA UVM/GPUDirect and Intel's shared virtual memory.cfg--enableZONE_DEVICEcfg--enableDEVICE_PRIVATE# unaddressable device memory (HMM)cfg--enablePCI_P2PDMA# peer-to-peer DMA between GPUs over PCIecfg--enableHMM_MIRRORcfg--enableMMU_NOTIFIERcfg--enableDMA_SHARED_BUFFERcfg--enableDRM_ACCEL# the accel subsystem both NPUs live under# --- always: a console before any GPU driver, and the VM/BMC drivers ---------cfg--enableSYSFB_SIMPLEFBcfg--moduleDRM_SIMPLEDRM# EFI/VESA framebuffer -- your rescue consolecfg--moduleDRM_VIRTIO_GPU# QEMU/KVM, virt-manager, most Linux VMscfg--moduleDRM_VMWGFX# VMwarecfg--moduleDRM_QXL# SPICEcfg--moduleDRM_BOCHS# QEMU -vga stdcfg--moduleDRM_AST# ASPEED BMC -- almost every rack servercfg--moduleDRM_HYPERV# Hyper-V / WSL2cfg--moduleDRM_UDL# DisplayLink USB adaptersif [ "$W_AMD"=1 ]; then# --- AMD: display, ROCm compute, and the Ryzen AI NPU --------------------cfg--moduleDRM_AMDGPU# MODULE, not built-in -- see the headercfg--enableDRM_AMD_DC# modern display stack: atomic KMS, DP/HDMI audiocfg--enableDRM_AMDGPU_USERPTR# required by ROCm and by GL/Vulkan interopcfg--enableDRM_AMDGPU_SI# Southern Islands (older GCN)cfg--enableDRM_AMDGPU_CIK# Sea Islandscfg--enableHSA_AMD# KFD -- creates /dev/kfd, ROCm's entry pointcfg--enableHSA_AMD_SVM# shared virtual memory: HIP managed memorycfg--enableHSA_AMD_P2P# direct GPU-to-GPU transferscfg--enableAMD_IOMMU# DRM_ACCEL_AMDXDNA depends on itcfg--moduleDRM_ACCEL_AMDXDNA# "AMD AI Engine" NPU, Ryzen AI 300+fiif [ "$W_NV"=1 ]; then# --- NVIDIA --------------------------------------------------------------# nouveau is the in-tree open driver. Build it as a MODULE even if you intend# to use NVIDIA's proprietary or open-kernel modules: those require nouveau# to be absent at load time, and you can only blacklist a module.## NVIDIA's own modules are out-of-tree and built by DKMS against# /lib/modules/$KREL/build, which `make modules_install` creates. Nothing# else in the config is needed for them -- except that an unsigned# out-of-tree module must be loadable, hence MODULE_SIG_FORCE off below.## NOVA (the Rust GSP driver for Turing and later) is deliberately NOT# enabled: it depends on CONFIG_RUST and a matching rustc/bindgen, and is# still early. Enable RUST first, then NOVA_CORE and DRM_NOVA.cfg--moduleDRM_NOUVEAUfiif [ "$W_INTEL"=1 ]; then# --- Intel: graphics, compute, and the Meteor Lake+ NPU ------------------# i915 and xe overlap on Tiger Lake .. Meteor Lake. Building BOTH as modules# is correct and safe: only one binds a given device, chosen by the driver's# own device table and overridable with i915.force_probe / xe.force_probe.cfg--moduleDRM_I915# Gen2 .. Gen12: everything up to Alder/Raptor Lakecfg--moduleDRM_XE# Xe: Arc, Lunar Lake, Battlemage, newer iGPUscfg--moduleDRM_ACCEL_IVPU# "Intel NPU", Meteor Lake (14th gen) and newerfi# --- things that break a copied distro config --------------------------------# Distro configs point at signing keys and revocation lists shipped in their own# source package. Those files are not in the upstream tarball and the build dies# late with a confusing openssl error.cfg--set-strSYSTEM_TRUSTED_KEYS""cfg--set-strSYSTEM_REVOCATION_KEYS""# Same shape, one kernel release later: distro configs point EFI_SBAT_FILE at# kernel.sbat, which also lives only in their kernel SOURCE package. The rule# in arch/x86/boot/compressed/Makefile is a bare file dependency --# $(obj)/sbat.o: $(CONFIG_EFI_SBAT_FILE)# -- so a missing file is not a warning but a hard stop before a single object# of the boot stub links:# No rule to make target 'kernel.sbat', needed by '.../compressed/sbat.o'.# EFI_SBAT is `def_bool y if EFI_SBAT_FILE!=""`, so it cannot be switched off# directly; clearing the string is what turns it off. Nothing is lost -- SBAT# generations are Secure Boot revocation policy owned by whoever holds the# signing certificate, and upstream defines no components at all.cfg--set-strEFI_SBAT_FILE""cfg--disableEFI_SBATcfg--disableMODULE_SIG_FORCE# or no out-of-tree GPU module will load# Distro configs set CONFIG_WERROR=y, which is reasonable for the exact kernel# and exact compiler that distro tests -- and wrong for every other pairing.# This script deliberately feeds a distro config into a DIFFERENT kernel# version, and often with a different compiler; the new warnings that follow# are normal, and with WERROR they are all fatal, hours into the build.cfg--disableWERROR# The AMD display DML files (display_mode_vba_31 / _314 and friends) build ~2.4K# frames doing floating-point mode validation, so a distro config's 2048 warns on# every single build. Raised here so the setting survives -- .config is copied# fresh from /boot/config-$(uname -r) on every run, which silently reverts a# hand-edit. Note what this does NOT do: -Wframe-larger-than is a diagnostic# threshold, not an allocation. No function gets a byte more room, vmlinux is# unchanged, and the real bound is THREAD_SIZE (16K on x86_64, set by# THREAD_SIZE_ORDER in arch/x86/include/asm/page_64_types.h). It is consumed# once, globally, at scripts/Makefile.warn:25. FRAME_WARN=3072 keeps the check# useful while still covering the DML files; FRAME_WARN=0 turns it off entirely.cfg--set-valFRAME_WARN"$FRAME_WARN"if [ "$KEEP_DEBUG_INFO"!=1 ]; then# Full DWARF makes the build far slower and modules roughly 10x bigger. Set# KEEP_DEBUG_INFO=1 if you need BTF, bpftrace, or kernel debugging.cfg--disableDEBUG_INFO_BTFcfg--disableDEBUG_INFO_BTF_MODULES# The DWARF-version choice has to be cleared BEFORE selecting NONE, and the# order is not cosmetic. scripts/config edits in place, so enabling# DEBUG_INFO_NONE only rewrites the '# CONFIG_DEBUG_INFO_NONE is not set'# line where it already sits -- which in a distro config is the line ABOVE# CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y. Kconfig resolves a choice by# "the last one read wins" (confdata.c), so the DWARF entry won, selected# DEBUG_INFO, and full debug info stayed on for every module -- silently,# because nothing below checked for it.cfg--disableDEBUG_INFO_DWARF_TOOLCHAIN_DEFAULTcfg--disableDEBUG_INFO_DWARF4cfg--disableDEBUG_INFO_DWARF5cfg--enableDEBUG_INFO_NONEficfg--set-strLOCALVERSION"$LOCALVERSION"cfg--disableLOCALVERSION_AUTOmakeolddefconfig>/dev/null# --------------------------------------------------------------------- verifysay"Verifying the configuration"fail=0check() { got=$(grep-E "^(# )?CONFIG_$1[ =]" .config |head-1)if [ "$got"="CONFIG_$1=$2" ]; thenprintf' ok CONFIG_%-24s = %s\n'"$1""$2"elseprintf' FAIL CONFIG_%-24s want %s, got: %s\n'"$1""$2""${got:-<absent>}"; fail=1; fi}note() { # informational: hardware- or arch-gated, absence is not an error got=$(grep-E "^(# )?CONFIG_$1[ =]" .config |head-1)printf' -- CONFIG_%-24s %s\n'"$1""${got:-<absent>}"}checkDEVICE_PRIVATEycheckPCI_P2PDMAycheckDRM_SIMPLEDRMmcheckDRM_VIRTIO_GPUm# Verified, not assumed: this one failed silently for a long time, and the only# symptom was a build that took far longer and modules ten times the size.[ "$KEEP_DEBUG_INFO"=1 ] ||checkDEBUG_INFO_NONEyif [ "$W_AMD"=1 ]; thencheckDRM_AMDGPUm; checkDRM_AMD_DCy; checkDRM_AMDGPU_USERPTRycheckHSA_AMDy; checkHSA_AMD_SVMy; checkHSA_AMD_P2PynoteDRM_ACCEL_AMDXDNA# x86_64 + AMD_IOMMU onlyfi[ "$W_NV"=1 ] && checkDRM_NOUVEAUmif [ "$W_INTEL"=1 ]; thencheckDRM_I915mnoteDRM_XE# newer trees onlynoteDRM_ACCEL_IVPU# x86_64 onlyfi[ "$fail"-eq0 ] ||die"the config did not come out as intended -- do NOT install this kernel. Each FAIL is a dependency that is off, not a typo. Run 'make menuconfig' and search (/) for the symbol to see what it needs."KREL=$(make-s kernelrelease)printf' kernel release: %s\n'"$KREL"state_setrelease"$KREL"state_setmodules"/lib/modules/$KREL"# ------------------------------------------------------------------------ buildsay"Building -- this takes a while. Use tmux/screen over ssh."STATE_STAGE=buildstate_setstatusbuilding# The previous log is kept as .prev rather than appended to, so the file cannot# grow without bound across runs. pipefail (set at the top) is what makes the# tee honest: without it the pipeline would report tee's exit status and a# failed build would look like a successful one.if [ -f"$BUILD_LOG" ]; thenmv-f"$BUILD_LOG""$BUILD_LOG.prev"2>/dev/null||true; fiif { :>"$BUILD_LOG"; } 2>/dev/null; then# braces: else the error escapes fd2printf' logging to: %s\n'"$BUILD_LOG"make"${MAKE_ARGS[@]}"2>&1|tee"$BUILD_LOG"elsewarn"cannot write $BUILD_LOG -- building without a log. Set BUILD_LOG=<path>."make"${MAKE_ARGS[@]}"fistate_setstatusbuiltstate_setfinished"$(date-Is2>/dev/null ||date2>/dev/null ||true)"[ "$INSTALL"=1 ] || {say"Built, not installed."printf' Re-run with INSTALL=1, or install by hand:\n'printf' sudo make %s modules_install\n sudo make %s install\n'"${MAKE_ARGS[*]}""${MAKE_ARGS[*]}"exit0}# ---------------------------------------------------------------------- installifcommand-vdkms>/dev/null && dkmsstatus2>/dev/null|grep-q'^amdgpu'; thenwarn"amdgpu-dkms is installed. It exists to backport amdgpu to OLD enterprise kernels; the in-tree driver you just built is newer. It will try, and fail, to build against $KREL. To stop it without breaking your distro kernel, cap it: sudo sh -c 'echo BUILD_EXCLUSIVE_KERNEL_MAX=\"$(uname-r|cut-d--f1)\" >> /usr/src/amdgpu-*/dkms.conf'"fiifcommand-vdkms>/dev/null && dkmsstatus2>/dev/null|grep-q'^nvidia'; thenprintf' note: nvidia-dkms will rebuild for %s automatically once\n'"$KREL"printf' modules_install creates /lib/modules/%s/build.\n'"$KREL"printf' Remember to blacklist nouveau if you use the proprietary driver.\n'fisay"Installing modules and kernel (sudo)"STATE_STAGE=installstate_setstatusinstallingsudomake"${MAKE_ARGS[@]}"modules_installsudomake"${MAKE_ARGS[@]}"installstate_setstatusinstalledstate_setfinished"$(date-Is2>/dev/null ||date2>/dev/null ||true)"say"Post-install checks"img=""for i in"/boot/initramfs-$KREL.img""/boot/initrd.img-$KREL"; do [ -f"$i" ] && img="$i"; doneif [ -n"$img" ]; then lsi=""; command-vlsinitrd>/dev/null && lsi=lsinitrd [ -z"$lsi" ] && command-vlsinitramfs>/dev/null && lsi=lsinitramfsif [ -n"$lsi" ]; thenfor fw in amdgpu nvidia i915 xe; do [ "$fw"= amdgpu ] && [ "$W_AMD"!=1 ] && continue [ "$fw"= nvidia ] && [ "$W_NV"!=1 ] && continue { [ "$fw"= i915 ] || [ "$fw"= xe ]; } && [ "$W_INTEL"!=1 ] && continue n=$(sudo "$lsi" "$img" 2>/dev/null |grep-c "firmware/$fw" ||true) [ "${n:-0}"-gt0 ] && printf' ok %s %s firmware files in the initramfs\n'"$n""$fw"\||warn"no $fw firmware in $img -- install linux-firmware and regenerate the initramfs BEFORE rebooting, or that GPU will not come up."donefifi[ -e"/lib/modules/$KREL/build" ] \ && printf' ok /lib/modules/%s/build present -- DKMS and out-of-tree modules can build\n'"$KREL"\||warn"/lib/modules/$KREL/build is missing; DKMS modules cannot build against this kernel"# Driver presence check.## NOTE ON SPELLING: these are FILE names, and kernel module files keep their# hyphens -- virtio-gpu.ko, snd-hda-intel.ko, xen-blkfront.ko. Nearly 40% of# the modules in a typical kernel have a hyphen. It is the module's internal# NAME that uses underscores, which is what lsmod, modinfo -F name, /proc/modules# and /sys/module/ all display. Since this searches with find -name, the hyphen# is correct; "fixing" virtio-gpu to virtio_gpu here finds nothing.## A driver absent from /lib/modules is not necessarily a failure -- it may be# built in (=y), which is a perfectly good outcome and produces no .ko at all.# The old version of this loop printed nothing in that case, so a driver that# genuinely failed to build looked identical to one that succeeded as built-in.# Consult .config to tell those two apart.for entry in"amdgpu:DRM_AMDGPU""nouveau:DRM_NOUVEAU""i915:DRM_I915" \"xe:DRM_XE""simpledrm:DRM_SIMPLEDRM""virtio-gpu:DRM_VIRTIO_GPU"; do m="${entry%%:*}"; sym="${entry#*:}"iffind"/lib/modules/$KREL"-name"$m.ko*"2>/dev/null|head-1|grep-q.; thenprintf' ok %-12s installed as a module (%s.ko)\n'"$m""$m"elifgrep-q"^CONFIG_$sym=y".config2>/dev/null; thenprintf' ok %-12s built into the kernel image (CONFIG_%s=y)\n'"$m""$sym"elifgrep-q"^CONFIG_$sym=m".config2>/dev/null; thenwarn"$m: CONFIG_$sym=m was requested but no $m.ko was installed. That is a real failure -- check the modules_install step."elseprintf' -- %-12s not enabled in this config\n'"$m"fidonesay"Done. Keep your current kernel in the boot menu until $KREL is proven."