diff --git a/Makefile b/Makefile index 3361146..bcc05ba 100644 --- a/Makefile +++ b/Makefile @@ -155,17 +155,17 @@ $(COMPILE_OPTIONS): $(STAGE3) $(PORTAGE_DIR) configs/make.conf.$(ARCH) configs/l done touch $(COMPILE_OPTIONS) -$(KERNEL): $(COMPILE_OPTIONS) $(KERNEL_CONFIG) scripts/kernel.sh +$(KERNEL): $(COMPILE_OPTIONS) $(KERNEL_CONFIG) scripts/build-kernel ifneq ($(EXTERNAL_KERNEL),YES) @scripts/echo Configuring kernel cp $(KERNEL_CONFIG) $(CHROOT)/root/kernel.config - cp scripts/kernel.sh $(CHROOT)/root/kernel.sh + cp scripts/build-kernel $(CHROOT)/root/build-kernel $(inroot) --setenv=KERNEL=$(KERNEL_PKG) \ --setenv=EMERGE="$(EMERGE)" \ --setenv=USEPKG="$(USEPKG)" \ --setenv=MAKEOPTS="$(MAKEOPTS)" \ - /bin/sh /root/kernel.sh - rm -f $(CHROOT)/root/kernel.sh + /root/build-kernel + rm -f $(CHROOT)/root/build-kernel endif touch $(KERNEL) diff --git a/scripts/build-kernel b/scripts/build-kernel new file mode 100755 index 0000000..db4f017 --- /dev/null +++ b/scripts/build-kernel @@ -0,0 +1,124 @@ +#!/usr/bin/env python +"""Build the latest kernel but only if need be""" +import os +import shutil +import subprocess + +EMERGE = os.environ['EMERGE'].split() +USEPKG = os.environ['USEPKG'].split() + + +def get_latest_available_kernel(): + kernel = os.environ['KERNEL'] + package_name = 'sys-kernel/{}'.format(kernel) + popen = subprocess.Popen( + ['portageq', 'best_visible', '/', package_name], + stdout=subprocess.PIPE, + ) + cpv = popen.stdout.read().decode().strip() + + return cpv.rpartition('-')[2] + + +def get_current_kernel(): + """what kernel does /boot/vmlinuz point to""" + vmlinuz = '/boot/vmlinuz' + + if not os.path.islink(vmlinuz): + return None + + filename = os.path.basename(os.path.realpath(vmlinuz)) + assert filename.startswith('vmlinuz') + part_after_vmlinuz = filename[8:] + + # may have "-gentoo" or whatever in the name + version = part_after_vmlinuz.rpartition('-')[0] + + return version + + +def install_kernel_package(): + kernel = os.environ['KERNEL'] + package_name = 'sys-kernel/{}'.format(kernel) + cmd = EMERGE + USEPKG + ['--oneshot', '--noreplace', package_name] + + subprocess.check_call(cmd) + + +def copy_kernel_config(): + filename = '/root/kernel.config' + + shutil.copy(filename, '/usr/src/linux/.config') + + +def build_kernel(): + makeopts = os.environ.get('MAKEOPTS', '') + + subprocess.check_call([ + 'make', '-C', '/usr/src/linux', 'MAKEOPTS=' + makeopts, 'oldconfig' + ]) + subprocess.check_call([ + 'make', '-C', '/usr/src/linux', 'MAKEOPTS=' + makeopts + ]) + + +def remove_old_kernels(): + kernel_files = ['vmlinuz-', 'System.map-', 'config-'] + + for filename in os.listdir('/boot'): + for kernel_file in kernel_files: + if filename.startswith(kernel_file): + path = os.path.join('/boot', filename) + os.unlink(path) + + if os.path.exists('/boot/vmlinuz'): + os.unlink('/boot/vmlinuz') + + shutil.rmtree('/lib/modules', ignore_errors=True) + + +def install_kernel(): + makeopts = os.environ.get('MAKEOPTS', '') + + subprocess.check_call([ + 'make', '-C', '/usr/src/linux', 'MAKEOPTS=' + makeopts, 'install', + 'modules_install' + ]) + + # create the symlink. /sbin/installkernel claims this is not used on + # "modern" distributions and doesn't create it (unless it already + # exists). I still do this however. + for filename in os.listdir('/boot'): + if filename.startswith('vmlinuz-'): + os.symlink(filename, '/boot/vmlinuz') + break + else: + raise Exception('Could not find installed kernel') + + +def uninstall_kernel_package(): + subprocess.check_call([ + 'make', '-C', '/usr/src/linux', 'distclean' + ]) + + subprocess.check_call(EMERGE + USEPKG + ['--depclean', '--with-bdeps=n']) + + +def main(): + latest_kernel = get_latest_available_kernel() + current_kernel = get_current_kernel() + + if current_kernel == latest_kernel: + return + + install_kernel_package() + copy_kernel_config() + build_kernel() + remove_old_kernels() + install_kernel() + + uninstall_kernel_package() + + +main() + diff --git a/scripts/kernel.sh b/scripts/kernel.sh deleted file mode 100755 index af8e998..0000000 --- a/scripts/kernel.sh +++ /dev/null @@ -1,31 +0,0 @@ -set -ev - -# (possibly) build the kernel - -current_kernel=$(emerge -qp ${KERNEL}|awk '{print $4}'|cut -d/ -f2|sed s/"${KERNEL}-//;s/-r[1-9]\+$//") -echo $current_kernel - -# If there is already a kernel in /boot and emerging the kernel only -# re-installs the same kernel, we can skip this -if [ -n "$current_kernel" ] && [ -e /boot/vmlinuz ] && \ - readlink /boot/vmlinuz | grep $current_kernel > /dev/null -then - exit -fi - -${EMERGE} ${USEPKG} --oneshot --newuse --noreplace sys-kernel/${KERNEL} -cp /root/kernel.config /usr/src/linux/.config -gcc-config 1 -cd /usr/src/linux -make ${MAKEOPTS} oldconfig -make ${MAKEOPTS} -rm -rf /lib/modules/* -make ${MAKEOPTS} modules_install -rm -f /boot/vmlinuz* -make ${MAKEOPTS} install -cp -a /usr/src/linux/.config /root/kernel.config -make ${MAKEOPTS} mrproper -cd /boot -k=`/bin/ls -1 vmlinuz-*` -ln -nsf $k vmlinuz -${EMERGE} --depclean