После уста­новки новых исход­ных тек­стов ядра и уда­ле­ния ста­рых через «portage» в «Gentoo GNU/Linux» в дирек­то­рии «/usr/src» оста­ется «мусор» после сборки ста­рого ядра. При­хо­дится его уда­лять вруч­ную, что про­сто надо­ело. Я решил бороться с этим явле­нием, выпол­няя сборку ядра отдельно от исход­ных тек­стов. В резуль­тате, при уда­ле­нии ста­рых исход­ных тек­стов ядра через «portage», в «/usr/src» больше не оста­ется ничего лишнего.

Так же мне захо­те­лось иметь бинар­ный пакет с отком­пи­ли­ро­ван­ным ядром, чтобы не выпол­нять ком­пи­ля­цию ядра на дру­гом ком­пью­тере, где это неудобно делать. Напри­мер на нетбуке.

Весь этот про­цесс я попро­бо­вал мак­си­мально упро­стить с помо­щью неболь­шого набора скриптов.

Эта заметка явля­ется допол­не­нием преды­ду­щей боль­шой ста­тьи про уста­новку «Gentoo GNU/Linux» из бинар­ных паке­тов.

Сна­чала надо опре­де­литься, в какой дирек­то­рии будут созда­ваться вре­мен­ные файлы при сборке ядра. Поскольку у меня вся работа с пакет­ным мене­дже­ром пере­не­сена в «/var/portage», то пусть и ядро будет соби­раться там же в «/var/portage/kernel». Созда­дим эту дирек­то­рию.
# mkdir -p /var/portage/kernel

Здесь будут нахо­диться файлы, созда­ю­щи­еся во время сборки ядра. Они будут раз­ло­жены по отдель­ным дирек­то­риям. Напри­мер, для пакета «sys-kernel/gentoo-sources-2.6.36-r1» будет необ­хо­дима дирек­то­рия «/var/portage/kernel/kernel-2.6.36-gentoo-r1». В нее в даль­ней­шем нужно будет ско­пи­ро­вать файл «.config» от ста­рого ядра.

Для того, чтобы не созда­вать вруч­ную при уста­новке све­жих исход­ных тек­стов ядра новую дирек­то­рию в «/var/portage/kernel», воз­ло­жим это на плечи пакет­ного мене­джера. Для этого созда­дим дирек­то­рию «/etc/portage/env/sys-kernel».
# mkdir -p /etc/portage/env/sys-kernel

Если выпол­ня­ется уста­новка, напри­мер, пакета «gentoo-sources», созда­дим файл «gentoo-sources» в «/etc/portage/env/sys-kernel» сле­ду­ю­щего содер­жа­ния.
/etc/portage/env/sys-kernel/gentoo-sourcespost_src_unpack() {
    # Remove "-rXX" from EXTRAVERSION
    sed -i -e 's/\(^EXTRAVERSION = .*\)-r.*$/\1/' "${S}/Makefile"
}

post_pkg_postinst() {

    # Specify a directory for temporary kernel files.
    KBUILD_DIR="/var/portage/kernel"

    [ "${PR}" != "r0" ] && PR="-${PR}" || PR=""
    KBUILD_OUTPUT="${KBUILD_DIR}/kernel-${PV}-${PN/-sources/}${PR}"
    [ ! -d "${KBUILD_OUTPUT}" ] && mkdir -p "${KBUILD_OUTPUT}"

    # If you want to copy the current kernel configuration, uncomment the following line.
    # [ -f /proc/config.gz ] && [ ! -f "${KBUILD_OUTPUT}/.config" ] && gzip -cd /proc/config.gz >"${KBUILD_OUTPUT}/.config"
}

Изме­ните в нем зна­че­ние пере­мен­ной «KBUILD_DIR», если это необ­хо­димо. Так же можно рас­ком­мен­ти­ро­вать пред­по­след­нюю строку скрипта, если сборка ведется не в «chroot», а для этого же самого ком­пью­тера и в теку­щем запу­щен­ном ядре была вклю­чена опция «CONFIG_IKCONFIG_PROC». Тогда теку­щая кон­фи­гу­ра­ция ядра будет ско­пи­ро­вана во вновь создан­ную директорию.

Сле­дует доба­вить в файл «/etc/portage/bashrc» про­верку на имя уста­нав­ли­ва­е­мого пакета. И если это имя закан­чи­ва­ется на «…modules» или «…addons», то гло­бально уста­нав­ли­вать пере­мен­ную «KBUILD_OUTPUT». Как и ранее, можно заме­нить «/var/portage/kernel» на что-либо свое.
/etc/portage/bashrcif [[ ${PN} =~ (modules|addons)$ ]]; then
    export KBUILD_OUTPUT="/var/portage/kernel/kernel-$(readlink /usr/src/linux|sed -e 's/^linux-//')"
fi

Если этого не сде­лать, то допол­ни­тель­ные модули ядра уста­нав­ли­ваться не будут!

Поме­стим ниже­при­ве­ден­ные четыре скрипта в «/var/portage/kernel».

/var/portage/kernel/makekernel.sh#!/bin/bash
#
# Make kernel and modules
# Install into portage
# Build binary package
#

source $(dirname $(readlink -f $0))/lib.sh
prepare

TMPDIR=$(mktemp -u -d -p /tmp/ krn.XXXXXX)
PREFIX="$(echo "${KERNELLINK}"|cut -d '-' -f2)"
PN="${PREFIX}-kernel"
PNFW="kernel-firmware"
PV=$(echo "${KERNELLINK}"|cut -d '-' -f1)
PR=$(echo "${KERNELLINK}"|cut -d '-' -f3)
[ -n "${PR}" ] && PR="-${PR}"
PVR="${PV}${PR}"
PF="${PN}-${PVR}"
PFFW="${PNFW}-${PVR}"

INSTALL="${TMPDIR}/sys-kernel/${PN}/files"
INSTALLFW="${TMPDIR}/sys-kernel/${PNFW}/files/lib"

eval $(portageq envvar -v PKGDIR)

if [ -z "${PKGDIR}" ]; then
    eerror "Variable 'PKGDIR' not set in '/etc/make.conf'"
    exit 1
fi

cd "${KERNEL}"
einfo "Preparing kernel and modules..."
if make bzImage modules; then
    einfo "Install modules..."
    INSTALL_MOD_PATH="${INSTALL}" make modules_install
else
    eerror "Kernel compilation error!"
    exit 1
fi

if [ -d "${INSTALL}/lib/modules" ]; then
    einfo "Prepare environment..."

    mkdir -p "${INSTALLFW}"

    if [ -d "${INSTALL}/lib/firmware" ]; then
        mv -f "${INSTALL}/lib/firmware" "${INSTALLFW}"
        FWDEP=">=sys-kernel/kernel-firmware-${PVR}"
    else
        ewarn "Firmware not found."
        FWDEP=""
    fi

    mkdir -p "${INSTALL}/boot"

    cp "${KBUILD_OUTPUT}/System.map" "${INSTALL}/boot/System.map-${PV}-${PREFIX}"
    cp "${KBUILD_OUTPUT}/arch/i386/boot/bzImage" "${INSTALL}/boot/kernel-${PV}-${PREFIX}"
    rm -f "${INSTALL}/lib/modules/${PV}-${PREFIX}/build"
    rm -f "${INSTALL}/lib/modules/${PV}-${PREFIX}/source"

    cat > "${TMPDIR}/sys-kernel/${PN}/${PF}.ebuild" << EOF
# Copyright 1999-2010 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2

inherit mount-boot

EAPI="2"

DESCRIPTION="Binary ${PVR} kernel and modules"
HOMEPAGE="http://mrcat.ru"
SRC_URI=""

LICENSE="GPL-2"
SLOT="${PV}"
KEYWORDS="~amd64 ~x86"
IUSE=""

RDEPEND="virtual/dev-manager ${FWDEP}"

pkg_setup() {
    ewarn 'All modules from "/lib/modules/${PV}-${PREFIX}" removed'
    ewarn 'Please, run "module-rebuild rebuild" after installation'
    rm -rf /lib/modules/${PV}-${PREFIX}
}

src_install() {
        insinto /
        doins -r "\${FILESDIR}/boot"
        doins -r "\${FILESDIR}/lib"
}

pkg_prerm() {
    mount-boot_mount_boot_partition
}
EOF
    cat > "${TMPDIR}/sys-kernel/${PNFW}/${PFFW}.ebuild" << EOF
# Copyright 1999-2010 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2

EAPI="2"

DESCRIPTION="Binary ${PVR} kernel firmware"
HOMEPAGE="http://mrcat.ru"
SRC_URI=""

LICENSE="GPL-2"
SLOT="0"
KEYWORDS="~amd64 ~x86"
IUSE=""

RDEPEND="!sys-kernel/linux-firmware"

src_install() {
        insinto /
        doins -r "\${FILESDIR}/lib"
}
EOF
    if [ -n "${FWDEP}" ]; then
        einfo "Building kernel firmware..."
        ebuild "${TMPDIR}/sys-kernel/${PNFW}/${PFFW}.ebuild" digest package
        einfo "Install kernel firmware..."
        [ -f "${PKGDIR}/sys-kernel/${PFFW}.tbz2" ] && emerge -1K "=sys-kernel/${PFFW}" || eerror "Kernel firmware not installed"
    fi
    einfo "Building binary kernel..."
    ebuild "${TMPDIR}/sys-kernel/${PN}/${PF}.ebuild" digest package
    einfo "Install binary kernel..."
    [ -f "${PKGDIR}/sys-kernel/${PF}.tbz2" ] && emerge -K "=sys-kernel/${PF}" || eerror "Kernel not installed"
    rm -rf "${TMPDIR}"
else
    eerror "Kernel compilation error!"
    exit 1
fi

/var/portage/kernel/makemenuconfig.sh#!/bin/bash
#
# Run 'make menuconfig'
#

source $(dirname $(readlink -f $0))/lib.sh
prepare

cd "${KERNEL}"
make menuconfig

/var/portage/kernel/makeoldconfig.sh#!/bin/bash
#
# Run 'make oldconfig'
#

source $(dirname $(readlink -f $0))/lib.sh
prepare

cd "${KERNEL}"
make oldconfig

/var/portage/kernel/lib.sh#!/bin/bash

# Specify a directory for temporary kernel files.
KBUILD_DIR="/var/portage/kernel"

prepare () {
    source "/usr/lib/portage/bin/isolated-functions.sh"

    if [ ! -L "/usr/src/linux" ]; then
        eerror "'/usr/src/linux' not a symlink"
        exit 1
    fi

    KERNELLINK=$(readlink /usr/src/linux|sed -e 's/^linux-//')
    KERNEL="/usr/src/linux-${KERNELLINK}"
    export KBUILD_OUTPUT="${KBUILD_DIR}/kernel-${KERNELLINK}"

    if [ -d "${KBUILD_OUTPUT}" ]; then
        if [ ! -f "${KBUILD_OUTPUT}/.config" ]; then
            eerror "Kernel confiruration '${KBUILD_OUTPUT}/.config' not found"
            exit 1
        fi
    else
        eerror "Kernel binary directory '${KBUILD_OUTPUT}' not exist"
        exit 1
    fi
}

Все файлы одним архи­вом можно загру­зить тут.

В файле «lib.sh» можно изме­нить зна­че­ние пере­мен­ной «KBUILD_DIR», если это необходимо.

Сде­лаем скрипты испол­ня­е­мыми.
# chmod 755 /var/portage/kernel/makekernel.sh
# chmod 755 /var/portage/kernel/makemenuconfig.sh
# chmod 755 /var/portage/kernel/makeoldconfig.sh

Поря­док работы со всем этим хозяй­ством сле­ду­ю­щий. Допу­стим, необ­хо­димо уста­но­вить све­жее ядро «sys-kernel/gentoo-sources-2.6.36-r1». После уста­новки должна появится дирек­то­рия «/var/portage/kernel/kernel-2.6.36-gentoo-r1» и, если было задано, с фай­лом «.config» от теку­щего рабо­та­ю­щего ядра. Иначе ско­пи­руйте файл «.config» в «/var/portage/kernel/kernel-2.6.36-gentoo-r1» вруч­ную от преды­ду­щего ядра.

Далее с помо­щью «eselect kernel» или вруч­ную меняем ссылку «/usr/src/linux» на дирек­то­рию с новыми исход­ными тек­стами ядра. После этого выпол­няем скрипт «makeoldconfig.sh». При этом фор­ми­ру­ется кон­фи­гу­ра­ция для нового ядра. Потом, если необ­хо­димо, выпол­няем «makemenuconfig.sh» для кор­рек­ти­ровки кон­фи­гу­ра­ции. И в заклю­че­ние - «makekernel.sh», в резуль­тате работы кото­рого будет собрано новое ядро, создан и уста­нов­лен бинар­ный пакет «sys-kernel/gentoo-kernel-2.6.31-r1» с новым ядром.

Я не стал учи­ты­вать номер реви­зии при уста­новке бинар­ного пакета с ядром. Думаю так будет проще при обнов­ле­нии той же самой вер­сии ядра, только дру­гой реви­зии. Напри­мер, модули ядра вер­сии «2.6.36-r1» будут уста­нав­ли­ваться в «/lib/modules/2.6.36-gentoo».

Дан­ный набор скрип­тов помог мне упро­стить про­цесс обнов­ле­ния ядра в «Gentoo GNU/Linux». Наде­юсь что помо­жет и вам, если вы соби­ра­ете ядро вручную.