summaryrefslogblamecommitdiff
path: root/eclass/linux-build.eclass
blob: 487fc8b0cc2f3c77b42e9916d53a709d8a5f0224 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
                                       
                                                                  


                             
                                         




                                    
            






                                                                      
                                  
 
                                               

              
                                                                                       
 
                                  

                                                 



                                             
                                 







                                                     
                                   

                                 
 
                   
                           
                          
                      
                      


                               
               


                                 
         
                               
                                         
                                
              

                      




















                                                                  






































                                                                              




















                                                     






                                       
                                                                                              
                                                                                                                       
                      


                        
                                                           
                                                                                                                


                                                                                                      
                                                                                                                               




                                                                                                                         

                                

                      

            
                


                                     

                
                                                           
                                                                                                
                                                                                      
                              
                                          
 
                                                                                                                           
                                                      
                                                                                                                  
                                                                                                         
 
                              
                                



                      

                

 




                                           


                          


















                                                                                        

 
                                  

               
                           
                               
 



                                                                                                                 



                                                          
                                                                                     
                                                                 

          





                                                                                       
                              
                                

                                                                                       
 


                                      







                                                                                               


                                      

                                                             

                            
 
                                                                
                                                                      
 
                                           



                                                                 
 


                                                           
 





                                                                                                              
                                                                 

                                                                                                

                                    

                                                                                                                 
 
                                                                                                 

                          










                                                                                                                  
                                                 



















                                                                                                                                       
                  
            
 
                                                  
                                                                                          

          



                                                                           



                                                                        

                                                                                                
 
                                                    

                                                                                      

                                                       

                                                                                        

                                                      
                                                          


                                                                              
                                                              


                                                                                
                                                          


                                                                             
                                                         

                                                                            
                                                      
                                                          

                                                                              
          





                                                                                    
 

                                                                     
                                                                  


                                                                                               
                                                                      






                                                                                                                           
                                                   


                                            
                                                             






                                                                                                 







                                                                                                     
                                         
 
                                                               
                                                             
                                                      
                                                                                                
                    
                                                      
                                                                    





                                                               
                                                       

                                                                                
                                                                                                                             







                                                                  
                                                                                                                                         

                                                                     

                                                                     
                                                              



                                                                             


                                                         

                                                                 


                                













                                                                                                            









                                                                                                    
                                           
                                                             
                                   



                                                
 




                                            

                                                                        
                                                                   
 

                                                                  

                                                                    
                                                                     
                                                                        
                                                             
                                                                    

                          

                                                              
                                                          
                                                            

                                                            



                                                                                  
                                                              


                                                              
                                                                

                                                             

                                                                     


                                                                 
         
 
                                                                                              
                                                            
                                                                                           

                                       

                                   


                           

                            
              

                                           

                                                    
                                                                               
                                                                     
                                                                   
                                        


              
                                                                    
                                         






















                                                                               


                                                           
                                                          



                                                  
                                              

                 
 







                                       


                                                













                                                        
                               
                           







                                                   


                                           




                                     
                                           

                                              






                                                          
 
                                  

                                                  




                                                                                               
 








                                                                                                             
                                                                                       
                                          








                                                                  








                                                                                     
          
 

                                                    
 

                                                  

          























                                                                                                                 

                                                       
                                                       

                                  
                                                           

          










                                                            


                                                                   




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

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

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

ETYPE="sources"

PYTHON_COMPAT=( python3_{11..13} )

inherit savedconfig llvm python-any-r1 kernel-2
detect_version

EXPORT_FUNCTIONS pkg_pretend pkg_setup src_prepare src_compile src_install pkg_postinst

: ${LINUX_BUILD_MOD_SIG_DAYS:=365}
: ${LINUX_BUILD_MOD_SIG_RSA_KEY_SIZE:=2048}
: ${LINUX_BUILD_MOD_SIG_ECC_KEY_CURVE:=secp384r1}

SLOT="${PV%.*}"

DESCRIPTION="Kernel stable sources and build"
HOMEPAGE="https://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 debug llvm rust source"
REQUIRED_USE="symlink? ( source )
	rust? ( llvm )"

BDEPEND="${BDEPEND}
	app-alternatives/bc
	sys-apps/diffutils
	virtual/libelf
	${PYTHON_DEPS}
	debug? (
		dev-util/pahole
	)
	llvm? (
		sys-devel/clang:=
		sys-devel/llvm:=
		sys-devel/lld:=
	)
	rust? ( !arm? ( !x86? (
		dev-lang/rust:=[rust-src]
		dev-util/bindgen
	) ) )"
DEPEND="${DEPEND}
	sys-apps/kmod"

# @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_protect() {
	local _dir="${1%/*}"
	local _file="${1##*/}"
	local _path
	local i

	_path="${EPREFIX}/${_dir}/${_file}"
	if [[ ! -e "${_path}" ]] ; then
		echo "${_path}"
		return 0
	fi

	for (( i = 0 ; i < 9999 ; i++ )) ; do
		printf -v _path "${EPREFIX}/${_dir}/._cfg%04d_${_file}" "${i}"

		if [[ ! -e "${_path}" ]] ; then
			echo "${_path}"
			return 0
		fi
	done

	return 1
}

_linux-build_relpath() {
	local _file="${1}"
	local _mnt

	# FIXME find a way to identify path of file relative to mount point
	# when file does not exist yet, neither stat or findmnt support it,
	# until then, use a prefix whitelist
	case "${_file}" in
		/boot/*) _mnt="$(stat -c '%m' /boot)" ;;
		*) die "${FUNCNAME} does not handle ${_file}" ;;
	esac

	echo "${_file/#${_mnt}}"
}

_linux-build_get-portage-versions() {
	local -a _v
	local _rv

	if [[ "${PF}" != "${P}" ]] ; then
		_v+=( "${PF}" )
	fi

	_v+=( "${P}" )

	if [[ -n "${REPLACING_VERSIONS}" ]] ; then
		for _rv in ${REPLACING_VERSIONS} ; do
			_v+=( "${PN}-${_rv}" )
		done
	fi

	_v+=( "${PN}"  )

	echo "${_v[@]}"
}

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

	if ! use savedconfig ; then
		return 0
	fi

	if [[ -e "${PORTAGE_CONFIGROOT%/}/etc/portage/savedconfig/${CATEGORY}/${PF}" ]] ; then
		ebegin "Restoring configuration from ${PORTAGE_CONFIGROOT%/}/etc/portage/savedconfig/${CATEGORY}/${PF}"
		eend 0
		return 0
	fi

	for _v in $(_linux-build_get-portage-versions) ; do
		ebegin "Checking existence of ${PORTAGE_CONFIGROOT%/}/etc/portage/savedconfig/${CATEGORY}/${_v}"
		if [[ -e "${PORTAGE_CONFIGROOT%/}/etc/portage/savedconfig/${CATEGORY}/${_v}" ]] ; then
			eend 0

			ebegin "Restoring configuration from ${PORTAGE_CONFIGROOT%/}/etc/portage/savedconfig/${CATEGORY}/${_v}"
			cp "${PORTAGE_CONFIGROOT%/}/etc/portage/savedconfig/${CATEGORY}/${_v}" \
				"${PORTAGE_CONFIGROOT%/}/etc/portage/savedconfig/${CATEGORY}/${PF}" \
				|| die "Failed to copy ${PORTAGE_CONFIGROOT%/}/etc/portage/savedconfig/${CATEGORY}/${_v}"

			eend 0
			return 0
		fi

		eend 1
	done

	return 1
}

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

	for _v in $(_linux-build_get-portage-versions) ; do
		ebegin "Checking existence of ${PORTAGE_CONFIGROOT%/}/etc/ssl/private/${_v}.pem"
		if [[ -e "${PORTAGE_CONFIGROOT%/}/etc/ssl/private/${_v}.pem" ]] ; then
			eend 0
			mkdir "${T}/certs"

			ebegin "Restoring x509 pair from ${PORTAGE_CONFIGROOT%/}/etc/portage/savedconfig/${CATEGORY}/${_v}"
			cp --preserve=mode,ownership \
				"${PORTAGE_CONFIGROOT%/}/etc/ssl/private/${_v}.pem" "${T}/certs/signing_key.pem" \
				|| die "Failed to copy ${PORTAGE_CONFIGROOT%/}/etc/ssl/private/${_v}.pem"

			eend 0
			return 0
		fi

		eend 1
	done

	return 1
}

_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

	if use build ; then
		use llvm && llvm_pkg_setup
		python-any-r1_pkg_setup
		_linux-build_pkg_setup-build
	fi
}

linux-build_pkg_pretend() {
	if use llvm ; then
		case "${ARCH}" in
			arm|arm64) ;;
			amd64|x86) ;;
			*) die "USE=llvm is not supported by ARCH=${ARCH}" ;;
		esac

		if ver_test -lt 5.10 ; then
			die "USE=llvm is supported starting with ${CATEGORY}/${PN}-5.10"
		fi
	fi
}

_linux-build_src_prepare_build() {
	local i

	mkdir "${BUILDDIR}"
	mkdir "${WORKDIR}/boot"

	if [[ -e "${PORTAGE_CONFIGROOT%/}/etc/portage/savedconfig/${CATEGORY}/${PF}" ]] ; then
		cp "${PORTAGE_CONFIGROOT%/}/etc/portage/savedconfig/${CATEGORY}/${PF}" "${BUILDDIR}/.config" \
			|| die "Failed to copy ${PORTAGE_CONFIGROOT%/}/etc/portage/savedconfig/${CATEGORY}/${PF}"
	else
		ewarn "Generate .config using 'defconfig'"
		emake defconfig "${myopt[@]}"
	fi

	if _linux-build_configval EFI_STUB && ! _linux-build_configval CMDLINE ; then
		ewarn "CONFIG_EFI_STUB=y requires CONFIG_CMDLINE"
	fi

	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-apps/systemd
			/boot/loader/loader.conf "/boot/loader/entries/${KV_FULL}.conf"
	)

	case "${ARCH}" in
		amd64|x86)
			BOOTLOADERS+=(
				sys-boot/grub:0
					/boot/grub/grub.conf none
				sys-boot/grub:2
					/boot/grub/grub.cfg "/boot/grub/entries/${KV_FULL}.cfg"
				sys-boot/syslinux:0
					/boot/extlinux/syslinux.cfg none
				sys-boot/syslinux:0
					/boot/extlinux/extlinux.conf none
			) ;;
		arm|arm64)
			BOOTLOADERS+=(
				sys-boot/raspberrypi-firmware
					/boot/config.txt none
			) ;;
	esac

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

	# Generate bootloader configuration
	for (( i = 0 ; i < ${#BOOTLOADERS[@]} ; i += 3 )) ; do
		BOOTLOADER_PKG="${BOOTLOADERS[i]}"
		BOOTLOADER_CONFIG_FILE_MAIN="${BOOTLOADERS[i+1]}"
		BOOTLOADER_CONFIG_FILE_KV="${BOOTLOADERS[i+2]}"

		if ! has_version "${BOOTLOADER_PKG}" ; then
			continue
		fi

		# Handle collision protect
		WORKDIR_BOOTLOADER_CONFIG_FILE_MAIN="$(_linux-build_protect "${BOOTLOADER_CONFIG_FILE_MAIN}")"

		if [[ -n "${KV_INSTALLED}" && -e "${BOOTLOADER_CONFIG_FILE_MAIN}" ]] ; then
			einfo "Updating ${BOOTLOADER_CONFIG_FILE_MAIN}"
			mkdir -p "${WORKDIR}/bootloader/${WORKDIR_BOOTLOADER_CONFIG_FILE_MAIN%/*}"
			sed -e "s@${KV_INSTALLED}@${KV_FULL}@g" \
				"${BOOTLOADER_CONFIG_FILE_MAIN}" \
				> "${WORKDIR}/bootloader/${WORKDIR_BOOTLOADER_CONFIG_FILE_MAIN}"

			if diff -q \
				"${BOOTLOADER_CONFIG_FILE_MAIN}" \
				"${WORKDIR}/bootloader/${WORKDIR_BOOTLOADER_CONFIG_FILE_MAIN}" > /dev/null ; then

				rm "${WORKDIR}/bootloader/${WORKDIR_BOOTLOADER_CONFIG_FILE_MAIN}"
			fi

			_CONFIG_PROTECT+=( "${BOOTLOADER_CONFIG_FILE_MAIN}" )
		fi

		if [[ "${BOOTLOADER_CONFIG_FILE_KV}" != "none" ]] ; then
			# Handle collision protect
			WORKDIR_BOOTLOADER_CONFIG_FILE_KV="$(_linux-build_protect "${BOOTLOADER_CONFIG_FILE_KV}")"

			einfo "Generating ${BOOTLOADER_CONFIG_FILE_KV}"
			mkdir -p "${WORKDIR}/bootloader/${WORKDIR_BOOTLOADER_CONFIG_FILE_KV%/*}"

			case "${BOOTLOADER_PKG}" in
				sys-apps/systemd)
					cat > "${WORKDIR}/bootloader/${WORKDIR_BOOTLOADER_CONFIG_FILE_KV}" <<-EOF
						title Gentoo Linux
						version ${KV_FULL}
						linux $(_linux-build_relpath /boot/${KV_FULL}/kernel.img)
						options ${CONFIG_CMDLINE}
					EOF
					;;
				sys-boot/grub:2)
					cat > "${WORKDIR}/bootloader/${WORKDIR_BOOTLOADER_CONFIG_FILE_KV}" <<-EOF
						menuentry 'Gentoo Linux' --class gentoo --class gnu-linux --class gnu --class os {
						$(echo '  ')linux $(_linux-build_relpath /boot/${KV_FULL}/kernel.img) ${CONFIG_CMDLINE}
						}
					EOF
					;;
				*)
					die "${ECLASS} does not know how to generate bootloader configuration for ${BOOTLOADER_PKG}"
					;;
			esac

			_CONFIG_PROTECT+=( "${BOOTLOADER_CONFIG_FILE_KV}" )
		fi
	done

	if [[ -n "${_CONFIG_PROTECT[@]}" ]] ; then
		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"

	if ! _linux-build_configval DEBUG_INFO_BTF && ! use debug ; then
		ewarn "USE=debug is required for CONFIG_DEBUG_INFO_BTF"
	fi

	_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 KERNEL_GZIP ; then
		if ! has_version -b "app-alternatives/gzip" ; then
			die "app-alternatives/gzip is required for CONFIG_KERNEL_GZIP"
		fi
	elif _linux-build_configval KERNEL_BZIP2 ; then
		if ! has_version -b "app-alternatives/bzip2" ; then
			die "app-alternatives/bzip2 is required for CONFIG_KERNEL_BZIP2"
		fi
	elif _linux-build_configval KERNEL_LZMA ; then
		if ! has_version -b "app-arch/lzma" ; then
			die "app-arch/lzma is required for CONFIG_KERNEL_LZMA"
		fi
	elif _linux-build_configval KERNEL_XZ; then
		if ! has_version -b "app-arch/xz-utils" ; then
			die "app-arch/xz-utils is required for CONFIG_KERNEL_XZ"
		fi
	elif _linux-build_configval KERNEL_LZO ; then
		if ! has_version -b "app-arch/lzop" ; then
			die "app-arch/lzop is required for CONFIG_KERNEL_LZO"
		fi
	elif _linux-build_configval KERNEL_LZ4 ; then
		if ! has_version -b "app-arch/lz4" ; then
			die "app-arch/lz4 is required for CONFIG_KERNEL_LZ4"
		fi
	elif _linux-build_configval KERNEL_ZSTD ; then
		if ! has_version -b "app-arch/zstd" ; then
			die "app-arch/zstd is required for CONFIG_KERNEL_ZSTD"
		fi
	fi

	if _linux-build_configval IKHEADERS ; then
		if ! has_version -b "app-alternatives/cpio" ; then
			die "app-alternatives/cpio is required for CONFIG_IKHEADERS"
		fi
	fi

	if _linux-build_configval MODULE_COMPRESS ; then
		if _linux-build_configval MODULE_COMPRESS_GZIP ; then
			if ! has_version -b "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 -b "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
		local _OPENSSL_REQ_ALGORITHM
		local _OPENSSL_REQ_PKEYOPT

		if ! has_version -b "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 _linux-build_configval MODULE_SIG_KEY_TYPE_ECDSA ; then
			_OPENSSL_REQ_ALGORITHM="ec"
			_OPENSSL_REQ_PKEYOPT="ec_paramgen_curve:${LINUX_BUILD_MOD_SIG_ECC_KEY_CURVE}"
		else
			_OPENSSL_REQ_ALGORITHM="rsa"
			_OPENSSL_REQ_PKEYOPT="rsa_keygen_bits:${LINUX_BUILD_MOD_SIG_RSA_KEY_SIZE}"
		fi

		mkdir "${BUILDDIR}/certs"

		if [[ -e "${T}/certs/signing_key.pem" ]] ; then
			touch "${BUILDDIR}/certs/x509.genkey"
			cp --preserve=mode,ownership \
				"${T}/certs/signing_key.pem" "${BUILDDIR}/certs/signing_key.pem"
		else
			einfo "Generating x509 config"
			cat > "${BUILDDIR}/certs/x509.genkey" <<-EOF
				[ req ]
				prompt = no
				distinguished_name = ${PF}_subj
				x509_extensions    = ${PF}_exts

				[ ${PF}_subj ]
				O            = Pants On
				OU           = ${KBUILD_BUILD_HOST:-${HOSTNAME}}
				CN           = ${CATEGORY}/${PF}
				emailAddress = ${KBUILD_BUILD_USER:-${PORTAGE_BUILD_USER}}@${KBUILD_BUILD_HOST:-${HOSTNAME}}"

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

			einfo "Generating x509 ${_OPENSSL_REQ_ALGORITHM} pair with ${_OPENSSL_REQ_PKEYOPT} and ${CONFIG_MODULE_SIG_HASH}"
			openssl req -x509 -nodes -batch \
				-days "${LINUX_BUILD_MOD_SIG_DAYS}" \
				-newkey "${_OPENSSL_REQ_ALGORITHM}" \
				-pkeyopt "${_OPENSSL_REQ_PKEYOPT}" \
				"-${CONFIG_MODULE_SIG_HASH}" \
				-outform PEM \
				-config "${BUILDDIR}/certs/x509.genkey" \
				-out    "${BUILDDIR}/certs/signing_key.pem" \
				-keyout "${BUILDDIR}/certs/signing_key.pem" \
				|| die "openssl req fail"
		fi

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

	if _linux-build_configval WLAN ; then
		if ! has_version net-wireless/wireless-regdb ; then
			ewarn "net-wireless/wireless-regdb is required by CONFIG_WLAN"
		fi

		if ! _linux-build_configval EXTRA_FIRMWARE ; then
			ewarn "CONFIG_WLAN requires CONFIG_EXTRA_FIRMWARE='regulatory.db regulatory.db.p7s'"
		elif ! has regulatory.db ${CONFIG_EXTRA_FIRMWARE} ; then
			ewarn "CONFIG_WLAN requires CONFIG_EXTRA_FIRMWARE='regulatory.db regulatory.db.p7s'"
		elif ! has regulatory.db.p7s ${CONFIG_EXTRA_FIRMWARE} ; then
			ewarn "CONFIG_WLAN requires CONFIG_EXTRA_FIRMWARE='regulatory.db regulatory.db.p7s'"
		fi
	fi

	if _linux-build_configval EXTRA_FIRMWARE_DIR && _linux-build_configval EXTRA_FIRMWARE ; then
		for _fw in ${CONFIG_EXTRA_FIRMWARE} ; do
			_file="${CONFIG_EXTRA_FIRMWARE_DIR}/${_fw}"

			if [[ ! -e "${_file}" ]] ; then
				die "${_file} does not exist"
			fi
		done
	fi

	einfo "Checking configuration file"
	cp -a "${BUILDDIR}/.config" "${BUILDDIR}/.config.old"
	if kernel_is -le 3 5 ; then
		emake oldnoconfig "${myopt[@]}"
	else
		emake olddefconfig "${myopt[@]}"
	fi

	local -a _diff_opts=(
		# Empty lines and comments
		--ignore-matching-lines '^$'
		--ignore-matching-lines '^#'

		# Architecture
		--ignore-matching-lines '^CONFIG_ARCH_SUPPORTS_[A-Z_]*='
		--ignore-matching-lines '^CONFIG_ARCH_HAS_[A-Z_]*='

		# Compiler
		--ignore-matching-lines '^CONFIG_CC_VERSION_TEXT='
		--ignore-matching-lines '^CONFIG_AS_HAS_[A-Z0-9_]*='
		--ignore-matching-lines '^CONFIG_CC_HAS_[A-Z0-9_]*='
		--ignore-matching-lines '^CONFIG_CC_HAVE_[A-Z0-9_]*='
		--ignore-matching-lines '^CONFIG_HAVE_[A-Z_]*_COMPILER='
		--ignore-matching-lines '^CONFIG_AS_VERSION='
		--ignore-matching-lines '^CONFIG_RUST_IS_AVAILABLE='

		# GCC only
		--ignore-matching-lines '^CONFIG_CC_IS_GCC='
		--ignore-matching-lines '^CONFIG_GCC_VERSION='
		--ignore-matching-lines '^CONFIG_GCC_ASM_'
		--ignore-matching-lines '^CONFIG_GCC[0-9]+_'
		--ignore-matching-lines '^CONFIG_AS_IS_GNU='
		--ignore-matching-lines '^CONFIG_LD_IS_BFD='
		--ignore-matching-lines '^CONFIG_LD_VERSION='
		--ignore-matching-lines '^CONFIG_PLUGIN_HOSTCC=' # Removed in v5.7
		--ignore-matching-lines '^CONFIG_GCC_PLUGINS='
		--ignore-matching-lines '^CONFIG_GCC_PLUGIN_[A-Z_]*='
		--ignore-matching-lines '^CONFIG_KASAN_STACK='

		# Clang only
		--ignore-matching-lines '^CONFIG_CC_IS_CLANG='
		--ignore-matching-lines '^CONFIG_CLANG_VERSION='
		--ignore-matching-lines '^CONFIG_AS_IS_LLVM='
		--ignore-matching-lines '^CONFIG_LD_IS_LLD='
		--ignore-matching-lines '^CONFIG_LLD_VERSION='
		--ignore-matching-lines '^CONFIG_TOOLS_SUPPORT_RELR='

		# Various
		--ignore-matching-lines '^CONFIG_PAHOLE_VERSION='
	)

	if ! diff -q "${_diff_opts[@]}" "${BUILDDIR}/.config.old" "${BUILDDIR}/.config" ; then
		eerror "You configuration is not up to date"
		diff -Nu "${_diff_opts[@]}" "${BUILDDIR}/.config.old" "${BUILDDIR}/.config"
		die "Bad configuration"
	fi

	emake prepare "${myopt[@]}"
}

linux-build_src_prepare() {
	kernel-2_src_prepare

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

		KBUILD_BUILD_USER="${KBUILD_BUILD_USER:-${PORTAGE_BUILD_USER}}"
		KBUILD_BUILD_HOST="${KBUILD_BUILD_HOST:-${HOSTNAME}}"
		KBUILD_BUILD_TIMESTAMP="$(date --iso-8601=seconds)"
		KBUILD_BUILD_VERSION="1"
	)

	copt=(
		ARCH="$(tc-arch-kernel)" SUBARCH="$(tc-arch-kernel)"
		CROSS_COMPILE="${CHOST}-"
	)

	if use llvm ; then
		copt+=(
			LLVM=1 LLVM_IAS=1
			HOSTCC="${CBUILD}-clang" HOSTCXX="${CBUILD}-clang++"
			HOSTLD="ld.lld"
			HOSTAR="llvm-ar"
			CC="${CHOST}-clang" CXX="${CHOST}-clang++"
			LD="ld.lld"
			AR="llvm-ar"
			AS="llvm-as" # Removed in v5.7
			NM="llvm-nm"
			OBJCOPY="llvm-objcopy"
			OBJDUMP="llvm-objdump"
			READELF="llvm-readelf"
			STRIP="llvm-strip"
		)
	else
		copt+=(
			HOSTCC="$(tc-getBUILD_CC)" HOSTCXX="$(tc-getBUILD_CXX)"
			HOSTLD="$(tc-getBUILD_LD)"
			HOSTAR="$(tc-getBUILD_AR)"
			CC="$(tc-getCC)" CXX="$(tc-getCXX)"
			LD="$(tc-getLD)"
			AR="$(tc-getAR)"
			AS="$(tc-getAS)" # Removed in v5.7
			NM="$(tc-getNM)"
			OBJCOPY="$(tc-getOBJCOPY)"
			OBJDUMP="$(tc-getOBJDUMP)"
			READELF="$(tc-getREADELF)"
			STRIP="$(tc-getSTRIP)"
		)
	fi

	if use rust ; then
		copt+=(
			HOSTRUSTC=rustc
			RUSTC=rustc
			BINDGEN=bindgen
		)
	fi

	copt+=(
		PKG_CONFIG="$(tc-getPKG_CONFIG)"
		PYTHON3="${PYTHON}"
	)

	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 "${myopt[@]}"
}

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

_linux-build_src_install_sources() {
	kernel-2_src_install

	insinto "/usr/src/linux-${KV_FULL}"
	doins "${BUILDDIR}/.config"
}

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

	if _linux-build_configval ARM ||
		_linux-build_configval ARM64 ||
		_linux-build_configval MIPS ; then

		emake dtbs_install "${myopt[@]}" \
			INSTALL_DTBS_PATH="${WORKDIR}/dts"
	fi

	insinto "/boot/${KV_FULL}"
	newins "${BUILDDIR}/.config"    kernel.cfg
	newins "${BUILDDIR}/System.map" System.map

	case "$(tc-arch-kernel)" in
		x86) newins "${BUILDDIR}/arch/$(tc-arch-kernel)/boot/bzImage" kernel.img ;;
		arm|arm64) newins "${BUILDDIR}/arch/$(tc-arch-kernel)/boot/Image" kernel.img ;;
	esac

	if _linux-build_configval EFI_STUB ; then
		insinto "/boot/EFI/linux"

		case "$(tc-arch-kernel)" in
			x86) newins "${BUILDDIR}/arch/$(tc-arch-kernel)/boot/bzImage" "${KV_FULL}.efi" ;;
			arm|arm64) newins "${BUILDDIR}/arch/$(tc-arch-kernel)/boot/Image" "${KV_FULL}.efi" ;;
		esac
	fi

	if _linux-build_configval CMDLINE_BOOL && _linux-build_configval CMDLINE ; then
		insinto "/boot/${KV_FULL}"
		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"
	fi

	if [[ -e "${WORKDIR}/lib/firmware" ]] ; then
		einfo "Installing firmwares"

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

	if [[ -d "${WORKDIR}/dts" ]] ; then
		einfo "Installing device tree"

		while read ; do
			case "${REPLY}" in
				overlays)
					insinto /boot
					doins -r "${WORKDIR}/dts/${REPLY}"
					;;
				broadcom)
					insinto /boot
					doins -r "${WORKDIR}/dts/${REPLY}/."
					;;
				*)
					ewarn "device tree ${REPLY} is not known, installing in default location"
					insinto /boot
					doins -r "${WORKDIR}/dts/${REPLY}"
					;;
			esac
		done < <(
			find "${WORKDIR}/dts" -mindepth 1 -maxdepth 1 -type d -printf '%P\n'
		)
	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

	# FIXME https://github.com/gentoo/gentoo/pull/13031
	if ! use symlink && [[ -e "${EROOT}usr/src/linux" ]] ; then
		rm -rf "${EROOT}usr/src/linux"
	fi

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