#!/usr/bin/env bash # Copyright (C) 2024-Ω Miquel Sabaté Solà # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ##### # Build the Linux Kernel and bundle it into a tarball that can then be used on # another machine. After you call this script it will: # 1. Call `defconfig`/`oldconfig` depending on whether the `.config` file # exists or not. # 2. Call `menuconfig` so the user can double check the configuration. # 3. Build the Kernel. # 4. Copy into a tarball the resulting image, modules, dtbs, and headers. Two # scripts are bundled in: install.sh and uninstall.sh. # # You can also pass some options: # 1. `--skip-config`: tell to skip the call to `defconfig` and/or # `menuconfig`. This is useful if you are just developing over the same # `.config` file again and again. # 2. `--skip-install`: don't generate the install/uninstall files. # 3. `-p/--profile`: the kind of machine you are building the kernel for. # 4. `-l/--local`: this is a local build, just generate install/uninstall scripts. # 5. `-h/--help`: show the help message. # # After that just send the resulting tarball to the machine where you want to # install this kernel. In there you just need to untar the given bundle and then # run the `install.sh` script from within the resulting directory. This will: # 1. Copy recursively all the files into their proper paths. # 2. Make an initramfs for the new image. # 3. Run your $EDITOR to update the boot loader configuration. # # *NOTE*: this script expects the `ARCH` environment variable to be set, and if # that doesn't match the current architecture, then it will expect to have # `CROSS_COMPILE` set as well. ##### set -e ## # Arguments that can be passed. while [[ $# -gt 0 ]]; do case $1 in --skip-config) SKIP_CONFIG="t" shift ;; --skip-install) NO_INSTALL="t" shift ;; -p | --profile) if [ -z "$2" ]; then echo "kbuild (error): the 'profile' option expects a value." exit 1 fi PROFILE="$2" shift 2 ;; -l | --local) IS_LOCAL=1 shift ;; -h | --help) SHOW_HELP=1 shift ;; -*) echo "kbuild (error): unknown option '$1'." exit 1 ;; *) echo "kbuild (warning): argument '$1' will be ignored." shift # past argument ;; esac done # Print the show message if needed. if [ -n "$SHOW_HELP" ]; then cat </dev/null ln -s usr/lib lib popd >/dev/null make modules_install INSTALL_MOD_PATH="$INSTALL_PATH" make dtbs_install INSTALL_DTBS_PATH="$INSTALL_PATH/boot/dtbs/$name" make headers_install INSTALL_HDR_PATH="$INSTALL_PATH/usr" unlink "$INSTALL_PATH/lib" make install INSTALL_PATH="$INSTALL_PATH/boot" &>/dev/null cp .config "$INSTALL_PATH/boot/config-$name" ## # Setup install.sh script. # Files that are going to be installed. Funnily enough, the pipeline will create # the "files.txt" first, so it will show on the `find` output. Hence the stupid # workaround you see of moving it in later. find "$INSTALL_PATH" -type f -printf "/%P\n" >files.txt mv files.txt "$INSTALL_PATH/files.txt" # Copy install/uninstall scripts. cp "$HOME/.config/kbuild/$PROFILE/install.sh" "$INSTALL_PATH/install.sh" sed -i "s/\$name/$name/g" "$INSTALL_PATH/install.sh" chmod +x "$INSTALL_PATH/install.sh" cp "$HOME/.config/kbuild/$PROFILE/uninstall.sh" "$INSTALL_PATH/uninstall.sh" sed -i "s/\$name/$name/g" "$INSTALL_PATH/uninstall.sh" chmod +x "$INSTALL_PATH/uninstall.sh" ## # Create tarball. tar czf "$INSTALL_PATH.tar.gz" "$INSTALL_PATH" rm -r "$INSTALL_PATH" echo "kbuild (info): your build is now ready at '$INSTALL_PATH.tar.gz'."