summaryrefslogblamecommitdiff
path: root/eclass/linux-build.eclass
blob: 38188702b606f4c4a7097877778efd887df33cb6 (plain) (tree)
1
2
3
4
5
6
7
                                       
                                                                  
      


                             
                                         




                                    
          









                                                                      




                                                                           












                                                     



                                  
                          
                      





















                                                                  




























                                                                                                          

























                                                                                                                    




                                           





                                                 
                                  

               















                                                                                       

                                                    
                                                                

         

                                                                
 




                                                                                                                  
 

                                                                 
 


                                                                          

                                                                                                         
















                                                                                                                         



                                                                                          

          





                                                                                                
 













                                                                                                                           











                                                                                                 
                                                                                 








                                                                                                              
                                                      

















                                                                                                                           
                                                    















                                                                                                          
                                           
                                   



                                                






                                                                        



                           

                                           

                                                    
                                                                             


















                                                                                 





































                                                                                       


















                                                                                     







                                                                 




                                                       
                                                           

          


















                                                                   
# Copyright 1999-2015 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Id$

# @ECLASS: linux-build.eclass
# @MAINTAINER:
# Bertrand Jacquin <bertrand@jacquin.bzh>
# @BLURB: Eclass for building kernel
# @DESCRIPTION:
# Build kernel properly

case "${EAPI:-0}" in
	5)
		;;
	*)	die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}"
		;;
esac

ETYPE="sources"

inherit savedconfig kernel-2
detect_version

EXPORT_FUNCTIONS pkg_setup src_prepare src_compile src_install pkg_postinst

: ${LINUX_BUILD_MOD_SIG_DAYS:=3650}
: ${LINUX_BUILD_MOD_SIG_KEY_ALG:=rsa}
: ${LINUX_BUILD_MOD_SIG_KEY_SIZE:=4096}

SLOT="${PV%.*}"

DESCRIPTION="Kernel stable sources and build"
HOMEPAGE="http://www.kernel.org"
SRC_URI="${KERNEL_URI} ${GENPATCHES_URI} ${ARCH_URI}"

SRCDIR="${WORKDIR}/linux-${KV_FULL}"
BUILDDIR="${WORKDIR}/build"

KV_EXTRA="${EXTRAVERSION}"
S="${SRCDIR}"

IUSE="build source"
REQUIRED_USE="symlink? ( source )"

DEPEND="sys-devel/bc
	sys-apps/diffutils
	sys-apps/kmod"
RDEPEND=""

# @FUNCTION: _linux-build_configval
# @INTERNAL
# @DESCRIPTION:
# Request a CONFIG value from .config file
# Return true if set, and define CONFIG_<key>
# Return false if not set
_linux-build_configval() {
	local _v="CONFIG_$1"

	# Export only the needed config value
	# when not already define
	declare -p "${_v}" > /dev/null 2>&1 \
		|| . <(sed -n "/^${_v}=/ p" "${BUILDDIR}/.config")

	case "${!_v}" in
		"") declare "$_v=n" ; export "${_v}" ; return 1 ;;
		*)                    export "${_v}" ; return 0 ;;
	esac
}

_linux-build_pkg_setup-build-config() {
	local _v

	if ! use savedconfig ; then
		return 0
	fi

	if [[ -z "${REPLACING_VERSIONS}" ]] ; then
		return 0
	fi

	for _v in "${PF}" "${P}" "${PN}" ; do
		if [[ -e "${PORTAGE_CONFIGROOT}/etc/portage/savedconfig/${CATEGORY}/${_v}" ]] ; then
			return 0
		fi
	done

	for _v in ${REPLACING_VERSIONS} ; do
		einfo "Restoring previous install configuration"
		if [[ -e "${PORTAGE_CONFIGROOT}/etc/portage/savedconfig/${CATEGORY}/${PN}-${_v}" ]] ; then
			einfo "From ${PORTAGE_CONFIGROOT}/etc/portage/savedconfig/${CATEGORY}/${PN}-${_v}"
			cp "${PORTAGE_CONFIGROOT}/etc/portage/savedconfig/${CATEGORY}/${PN}-${_v}" \
				"${PORTAGE_CONFIGROOT}/etc/portage/savedconfig/${CATEGORY}/${PF}"
			eend 0
		fi
	done
}

_linux-build_pkg_setup-build-x509() {
	local _v

	for _v in "${PF}" "${P}" "${PN}" ; do
		einfo "Checking existence of ${PORTAGE_CONFIGROOT%/}/etc/ssl/private/${_v}.{crt,key}"

		if [[ -e "${PORTAGE_CONFIGROOT}/etc/ssl/private/${_v}.crt" &&
			  -e "${PORTAGE_CONFIGROOT}/etc/ssl/private/${_v}.key" ]] ; then

			mkdir -p "${T}/etc/ssl/private"
			cp --preserve=mode,ownership \
				"${PORTAGE_CONFIGROOT}/etc/ssl/private/${_v}.crt" "${T}/etc/ssl/private/${PF}.crt" \
				|| die "Failed to copy ${PORTAGE_CONFIGROOT%/}/etc/ssl/private/${_v}.crt"
			cp --preserve=mode,ownership \
				"${PORTAGE_CONFIGROOT}/etc/ssl/private/${_v}.key" "${T}/etc/ssl/private/${PF}.key" \
				|| die "Failed to copy ${PORTAGE_CONFIGROOT%/}/etc/ssl/private/${_v}.key"

			export _LINUX_BUILD_MOD_SIG_X509_PFX="${_v}"
			eend 0

			break
		fi

		eend 1
	done
}

_linux-build_pkg_setup-build() {
	_linux-build_pkg_setup-build-config
	_linux-build_pkg_setup-build-x509
}

linux-build_pkg_setup() {
	kernel-2_pkg_setup

	use build && _linux-build_pkg_setup-build
}

_linux-build_src_prepare_build() {
	local i

	mkdir "${BUILDDIR}"

	restore_config "${BUILDDIR}/.config"
	if [[ ! -e "${BUILDDIR}/.config" ]] ; then
		ewarn "Generate .config using 'defconfig'"
		emake defconfig "${myopt[@]}"
	fi

	mkdir "${WORKDIR}/boot"

	if _linux-build_configval CMDLINE_BOOL && _linux-build_configval CMDLINE ; then
		einfo "Creating kernel.arg"
		einfo "  CONFIG_CMDLINE='${CONFIG_CMDLINE}'"
		echo "${CONFIG_CMDLINE}" > "${WORKDIR}/boot/kernel.arg"
	fi

	local -a BOOTLOADERS=(
		sys-boot/grub:0 /boot/grub/grub.conf
		sys-boot/syslinux:0 /boot/extlinux/extlinux.conf
	)

	KV_INSTALLED="$(best_version ${CATEGORY}/${PN}:${SLOT})"
	KV_INSTALLED="${KV_INSTALLED/#${CATEGORY}\/${PN}-}"

	if [[ -n "${KV_INSTALLED}" ]] ; then
		for (( i = 0 ; i < ${#BOOTLOADERS[@]} ; i+=2 )) ; do
			if ! has_version "${BOOTLOADERS[i]}" || [[ ! -e "${EPREFIX}/${BOOTLOADERS[i+1]}" ]] ; then
				continue
			fi

			BOOTLOADER_DIR="${BOOTLOADERS[i+1]%/*}"
			BOOTLOADER_FILE="${BOOTLOADERS[i+1]##*/}"

			mkdir -p "${WORKDIR}/bootloader/${BOOTLOADER_DIR}"

			# Handle collision protect
			for (( j = 0 ; j < 9999 ; j++ )) ; do
				printf -v BOOTLOADER_PROTECTED_FILE "._cfg%04d_${BOOTLOADER_FILE}" "${j}"
				if [[ ! -e "${EPREFIX}/${BOOTLOADER_DIR}/${BOOTLOADER_PROTECTED_FILE}" ]] ; then
					break
				fi
			done

			einfo "Generating ${BOOTLOADER_DIR}/${BOOTLOADER_FILE}"
			sed -e "s@${KV_INSTALLED}${KV_EXTRA}@${KV_FULL}@g" \
				"${EPREFIX}/${BOOTLOADER_DIR}/${BOOTLOADER_FILE}" \
				> "${WORKDIR}/bootloader/${BOOTLOADER_DIR}/${BOOTLOADER_PROTECTED_FILE}"

			if diff -q \
				"${EPREFIX}/${BOOTLOADER_DIR}/${BOOTLOADER_FILE}" \
				"${WORKDIR}/bootloader/${BOOTLOADER_DIR}/${BOOTLOADER_PROTECTED_FILE}" > /dev/null ; then

				rm "${WORKDIR}/bootloader/${BOOTLOADER_DIR}/${BOOTLOADER_PROTECTED_FILE}"
			fi

			_CONFIG_PROTECT+=( "${BOOTLOADER_DIR}/${BOOTLOADER_FILE}" )
		done

		echo "CONFIG_PROTECT='${_CONFIG_PROTECT[@]}'" > "${WORKDIR}/env.d_42-${P}"
	fi

	_linux-build_configval MODULES || ewarn "CONFIG_MODULES is not set"
	_linux-build_configval UEVENT_HELPER_PATH \
		&& ewarn "CONFIG_UEVENT_HELPER_PATH should be empty"

	_linux-build_configval FHANDLE || ewarn "CONFIG_FHANDLE is needed for >=sys-fs/udev-210"
	_linux-build_configval NET     || ewarn "CONFIG_NET is needed for >=sys-fs/udev-210"

	if _linux-build_configval MODULE_COMPRESS ; then
		if _linux-build_configval MODULE_COMPRESS_GZIP ; then
			if ! has_version "app-arch/gzip" ; then
				die "app-arch/gzip is required for CONFIG_MODULE_COMPRESS_GZIP"
			fi
		elif _linux-build_configval MODULE_COMPRESS_XZ ; then
			if ! has_version "app-arch/xz-utils" ; then
				die "app-arch/xz-utils is required for CONFIG_MODULE_COMPRESS_XZ"
			fi
		else
			die "CONFIG_MODULE_COMPRESS needs one of ( CONFIG_MODULE_COMPRESS_GZIP CONFIG_MODULE_COMPRESS_XZ )"
		fi
	fi

	if _linux-build_configval MODULE_SIG ; then
		if ! has_version "dev-libs/openssl" ; then
			die "dev-libs/openssl is required for CONFIG_MODULE_SIG"
		fi

		if ! _linux-build_configval MODULE_SIG_HASH ; then
			die "CONFIG_MODULE_SIG_HASH must be defined when using CONFIG_MODULE_SIG"
		fi

		if [[ -e "${T}/etc/ssl/private/${PF}.crt" &&
			  -e "${T}/etc/ssl/private/${PF}.key" ]] ; then

			einfo "Use the following x509 pair for CONFIG_MODULE_SIG"
			einfo "  ${PORTAGE_CONFIGROOT%/}/etc/ssl/private/${_LINUX_BUILD_MOD_SIG_X509_PFX}.crt"
			einfo "  ${PORTAGE_CONFIGROOT%/}/etc/ssl/private/${_LINUX_BUILD_MOD_SIG_X509_PFX}.key"

			touch "${BUILDDIR}/x509.genkey"
			cp --preserve=mode,ownership \
				"${T}/etc/ssl/private/${PF}.crt" "${BUILDDIR}/signing_key.x509"
			cp --preserve=mode,ownership \
				"${T}/etc/ssl/private/${PF}.key" "${BUILDDIR}/signing_key.priv"
		else
			einfo "Generating x509 config"
			cat > "${BUILDDIR}/x509.genkey" <<-EOF
				[ req ]
				prompt = no
				distinguished_name = ${PF}_subj
				x509_extensions    = ${PF}_exts

				[ ${PF}_subj ]
				O            = as29
				CN           = ${KBUILD_BUILD_HOST:-${HOSTNAME}}
				emailAddress = ${KBUILD_BUILD_USER:-${PORTAGE_USERNAME}}@${KBUILD_BUILD_HOST:-${HOSTNAME}}"

				[ ${PF}_exts ]
				basicConstraints=critical,CA:FALSE
				keyUsage=digitalSignature
				subjectKeyIdentifier=hash
				authorityKeyIdentifier=keyid
			EOF

			einfo "Generating x509 pair"
			openssl req -x509 -nodes -batch \
				-days "${LINUX_BUILD_MOD_SIG_DAYS}" \
				-newkey "${LINUX_BUILD_MOD_SIG_KEY_ALG}:${LINUX_BUILD_MOD_SIG_KEY_SIZE}" \
				"-${CONFIG_MODULE_SIG_HASH}" \
				-outform DER \
				-config "${BUILDDIR}/x509.genkey" \
				-out    "${BUILDDIR}/signing_key.x509" \
				-keyout "${BUILDDIR}/signing_key.priv" \
				|| die "openssl req fail"
		fi

		openssl x509 -inform DER -noout \
			-in "${BUILDDIR}/signing_key.x509" \
			-subject
	fi

	einfo "Checking configuration file"
	if kernel_is -le 3 5 ; then
		emake oldnoconfig "${myopt[@]}"
	else
		emake olddefconfig "${myopt[@]}"
	fi

	if diff -Nu0 "${BUILDDIR}/.config.old" "${BUILDDIR}/.config" \
		| egrep -q '^(\-|\+)CONFIG_' ; then
		eerror "You configuration is not up to date"
		diff -Nu "${BUILDDIR}/.config.old" "${BUILDDIR}/.config"
		die "Bad configuration"
	fi
}

linux-build_src_prepare() {
	bopt=(
		-C "${SRCDIR}"
		KBUILD_OUTPUT="${BUILDDIR}"
		KCONFIG_CONFIG="${BUILDDIR}/.config"

		KBUILD_BUILD_USER="${KBUILD_BUILD_USER:-${PORTAGE_USERNAME}}"
	)

	copt=(
		CC="$(tc-getCC)" HOSTCC="${CBUILD}-gcc" CROSS_COMPILE="${CHOST}-"
		ARCH="$(tc-arch-kernel)" SUBARCH="$(tc-arch-kernel)"
	)

	vopt=(
		EXTRAVERSION="${KV_EXTRA}"
		LOCALVERSION= CONFIG_LOCALVERSION=
		V=1
	)

	myopt=( "${bopt[@]}" "${copt[@]}" "${vopt[@]}" )

	use build && _linux-build_src_prepare_build
}

_linux-build_src_compile_build() {
	einfo "Building kernel"
	emake bzImage "${myopt[@]}"

	if _linux-build_configval MODULES ; then
		einfo "Building modules"
		emake modules "${myopt[@]}"
	fi
}

linux-build_src_compile() {
	use build && _linux-build_src_compile_build
}

_linux-build_src_install_sources() {
	kernel-2_src_install
}

_linux-build_src_install_build() {
	einfo "Installing kernel"
	emake install "${myopt[@]}" \
		INSTALL_PATH="${WORKDIR}/boot"

	insinto "/boot/${KV_FULL}"

	newins "${WORKDIR}/boot/config-${KV_FULL}"     kernel.cfg
	newins "${WORKDIR}/boot/vmlinuz-${KV_FULL}"    kernel.img
	newins "${WORKDIR}/boot/System.map-${KV_FULL}" System.map

	if _linux-build_configval CMDLINE_BOOL && _linux-build_configval CMDLINE ; then
		doins "${WORKDIR}/boot/kernel.arg"
	fi

	if _linux-build_configval MODULES ; then
		einfo "Installing modules"
		emake modules_install "${myopt[@]}" \
			INSTALL_MOD_PATH="${WORKDIR}" \
			INSTALL_MOD_STRIP="${PORTAGE_STRIP_FLAGS}"

		einfo "Generating modules.dep"
		depmod -ae -F "${BUILDDIR}/System.map" -b "${WORKDIR}" "${KV_FULL}" \
			|| die "depmod failed"

		rm "${WORKDIR}/lib/modules/${KV_FULL}/build"
		rm "${WORKDIR}/lib/modules/${KV_FULL}/source"

		insinto /lib
		doins -r "${WORKDIR}/lib/modules"

		# No need to make firmware_install, make modules_install does
		if [[ -e "${WORKDIR}/lib/firmware" ]] ; then
			einfo "Installing firmwares"

			insinto /lib
			doins -r "${WORKDIR}/lib/firmware"
		fi
	fi

	if _linux-build_configval MODULE_SIG ; then
		insinto /etc/ssl/private
		newins "${BUILDDIR}/signing_key.x509" "${PF}.crt"
		newins "${BUILDDIR}/signing_key.priv" "${PF}.key"

		fperms 0400 "/etc/ssl/private/${PF}.key"
	fi

	if [[ -d "${WORKDIR}/bootloader/boot" ]] ; then
		insinto /boot
		doins -r "${WORKDIR}"/bootloader/boot/*

		insinto /etc/env.d
		newins "${WORKDIR}/env.d_42-${P}" "42-${P}"
	fi

	use savedconfig && save_config "${BUILDDIR}/.config"
}

linux-build_src_install() {
	use build  && _linux-build_src_install_build
	use source && _linux-build_src_install_sources
}

linux-build_pkg_postinst() {
	kernel-2_pkg_postinst

	# Bypass kernel-2_pkg_postinst madness
	if ! use symlink && [[ -L "${EROOT}usr/src/linux" ]] ; then
		rm "${EROOT}usr/src/linux"
	fi

	einfo "You may need to:"
	einfo "  make menuconfig ${copt[@]}"
}