From 65f99fae2270d133ca528c209959925884019c77 Mon Sep 17 00:00:00 2001
From: Ionen Wolkens <ionen@gentoo.org>
Date: Tue, 27 Dec 2022 03:03:09 -0500
Subject: x11-drivers/nvidia-drivers: more thorough kernel toolchain handling

Should "hopefully" cover most use cases without regressions.

Makes some degree of sense to do this on (at least) nvidia-drivers,
given it's widely used and compiles a lot of non-modules things and
users may not want to use the same toolchain for these.

e.g. can now do
  clang+lld+thinlto kernel + gcc+bfd nvidia
or
  gcc+bfd kernel + clang+lld+thinlto nvidia
Not that going to support every custom mixing possible, and please
consider clang kernel an unsupported configuration despite this
(hardly tested).

Could be interesting to have linux-mod handle this, but that may
be better to consider for EAPI=9 so it doesn't unexpectedly break
anything (meanwhile it's simple to use a package.env for non-nvidia).

Closes: https://bugs.gentoo.org/888587
Signed-off-by: Ionen Wolkens <ionen@gentoo.org>
---
 .../nvidia-drivers/nvidia-drivers-390.157.ebuild   | 62 +++++++++++++++++----
 .../nvidia-drivers-470.161.03.ebuild               | 62 +++++++++++++++++----
 .../nvidia-drivers-510.108.03.ebuild               | 62 +++++++++++++++++----
 .../nvidia-drivers/nvidia-drivers-515.86.01.ebuild | 64 ++++++++++++++++++----
 .../nvidia-drivers/nvidia-drivers-525.47.04.ebuild | 64 ++++++++++++++++++----
 .../nvidia-drivers/nvidia-drivers-525.60.13.ebuild | 64 ++++++++++++++++++----
 6 files changed, 306 insertions(+), 72 deletions(-)

(limited to 'x11-drivers/nvidia-drivers')

diff --git a/x11-drivers/nvidia-drivers/nvidia-drivers-390.157.ebuild b/x11-drivers/nvidia-drivers/nvidia-drivers-390.157.ebuild
index 9257ed94a9b4..3bda88a05d31 100644
--- a/x11-drivers/nvidia-drivers/nvidia-drivers-390.157.ebuild
+++ b/x11-drivers/nvidia-drivers/nvidia-drivers-390.157.ebuild
@@ -180,20 +180,58 @@ pkg_setup() {
 	use x86 && BUILD_PARAMS+=' ARCH=i386'
 	BUILD_TARGETS="modules"
 
-	if linux_chkconfig_present CC_IS_CLANG; then
-		ewarn "Warning: clang-built kernel detected, using clang for modules (experimental)"
-		ewarn "Can use KERNEL_CC and KERNEL_LD environment variables to override if needed."
-
-		tc-is-clang || : "${KERNEL_CC:=${CHOST}-clang}"
-		if linux_chkconfig_present LD_IS_LLD; then
-			: "${KERNEL_LD:=ld.lld}"
-			if linux_chkconfig_present LTO_CLANG_THIN; then
-				# kernel enables cache by default leading to sandbox violations
-				BUILD_PARAMS+=' ldflags-y=--thinlto-cache-dir= LDFLAGS_MODULE=--thinlto-cache-dir='
-			fi
+	# Try to match toolchain with kernel only for modules
+	# (experimental, ideally this should be handled in linux-mod.eclass)
+	nvidia-tc-set() {
+		local -n var=KERNEL_${1}
+		if [[ ! -v var ]]; then
+			read -r var < <(type -P "${@:2}") ||
+				die "failed to find in PATH at least one of: ${*:2}"
+			einfo "Forcing '${var}' for modules (set ${!var} to override)"
+		fi
+	}
+
+	local tool switch
+	if linux_chkconfig_present CC_IS_GCC; then
+		if ! tc-is-gcc; then
+			switch=
+			nvidia-tc-set CC {${CHOST}-,}gcc
 		fi
+	elif linux_chkconfig_present CC_IS_CLANG; then
+		ewarn "Warning: using ${PN} with a clang-built kernel is largely untested"
+		if ! tc-is-clang; then
+			switch=llvm-
+			nvidia-tc-set CC {${CHOST}-,}clang
+		fi
+	fi
+
+	if linux_chkconfig_present LD_IS_BFD; then
+		# tc-ld-is-bfd needs https://github.com/gentoo/gentoo/pull/28355
+		[[ $(LC_ALL=C $(tc-getLD) --version 2>/dev/null) == "GNU ld"* ]] ||
+			nvidia-tc-set LD {${CHOST}-,}{ld.bfd,ld}
+	elif linux_chkconfig_present LD_IS_LLD; then
+		tc-ld-is-lld || nvidia-tc-set LD {${CHOST}-,}{ld.lld,lld}
+	fi
+
+	if [[ -v switch ]]; then
+		# only need llvm-nm for lto, but use complete set to be safe
+		for tool in AR NM OBJCOPY OBJDUMP READELF STRIP; do
+			case $(LC_ALL=C $(tc-get${tool}) --version 2>/dev/null) in
+				LLVM*|llvm*) [[ ! ${switch} ]];;
+				*) [[ ${switch} ]];;
+			esac && nvidia-tc-set ${tool} {${CHOST}-,}${switch}${tool,,}
+		done
+	fi
+
+	# pass unconditionally given exports are semi-ignored except CC/LD
+	for tool in CC LD AR NM OBJCOPY OBJDUMP READELF STRIP; do
+		BUILD_PARAMS+=" ${tool}=\"\${KERNEL_${tool}:-\$(tc-get${tool})}\""
+	done
+
+	if linux_chkconfig_present LTO_CLANG_THIN; then
+		# kernel enables cache by default leading to sandbox violations
+		BUILD_PARAMS+=' ldflags-y=--thinlto-cache-dir= LDFLAGS_MODULE=--thinlto-cache-dir='
 	fi
-	BUILD_PARAMS+=' ${KERNEL_CC:+CC="${KERNEL_CC}"} ${KERNEL_LD:+LD="${KERNEL_LD}"}'
 
 	if kernel_is -gt ${NV_KERNEL_MAX/./ }; then
 		ewarn "Kernel ${KV_MAJOR}.${KV_MINOR} is either known to break this version of ${PN}"
diff --git a/x11-drivers/nvidia-drivers/nvidia-drivers-470.161.03.ebuild b/x11-drivers/nvidia-drivers/nvidia-drivers-470.161.03.ebuild
index 2f90ba9654fe..87a70528199f 100644
--- a/x11-drivers/nvidia-drivers/nvidia-drivers-470.161.03.ebuild
+++ b/x11-drivers/nvidia-drivers/nvidia-drivers-470.161.03.ebuild
@@ -183,20 +183,58 @@ pkg_setup() {
 	BUILD_PARAMS='NV_VERBOSE=1 IGNORE_CC_MISMATCH=yes SYSSRC="${KV_DIR}" SYSOUT="${KV_OUT_DIR}"'
 	BUILD_TARGETS="modules"
 
-	if linux_chkconfig_present CC_IS_CLANG; then
-		ewarn "Warning: clang-built kernel detected, using clang for modules (experimental)"
-		ewarn "Can use KERNEL_CC and KERNEL_LD environment variables to override if needed."
-
-		tc-is-clang || : "${KERNEL_CC:=${CHOST}-clang}"
-		if linux_chkconfig_present LD_IS_LLD; then
-			: "${KERNEL_LD:=ld.lld}"
-			if linux_chkconfig_present LTO_CLANG_THIN; then
-				# kernel enables cache by default leading to sandbox violations
-				BUILD_PARAMS+=' ldflags-y=--thinlto-cache-dir= LDFLAGS_MODULE=--thinlto-cache-dir='
-			fi
+	# Try to match toolchain with kernel only for modules
+	# (experimental, ideally this should be handled in linux-mod.eclass)
+	nvidia-tc-set() {
+		local -n var=KERNEL_${1}
+		if [[ ! -v var ]]; then
+			read -r var < <(type -P "${@:2}") ||
+				die "failed to find in PATH at least one of: ${*:2}"
+			einfo "Forcing '${var}' for modules (set ${!var} to override)"
+		fi
+	}
+
+	local tool switch
+	if linux_chkconfig_present CC_IS_GCC; then
+		if ! tc-is-gcc; then
+			switch=
+			nvidia-tc-set CC {${CHOST}-,}gcc
 		fi
+	elif linux_chkconfig_present CC_IS_CLANG; then
+		ewarn "Warning: using ${PN} with a clang-built kernel is largely untested"
+		if ! tc-is-clang; then
+			switch=llvm-
+			nvidia-tc-set CC {${CHOST}-,}clang
+		fi
+	fi
+
+	if linux_chkconfig_present LD_IS_BFD; then
+		# tc-ld-is-bfd needs https://github.com/gentoo/gentoo/pull/28355
+		[[ $(LC_ALL=C $(tc-getLD) --version 2>/dev/null) == "GNU ld"* ]] ||
+			nvidia-tc-set LD {${CHOST}-,}{ld.bfd,ld}
+	elif linux_chkconfig_present LD_IS_LLD; then
+		tc-ld-is-lld || nvidia-tc-set LD {${CHOST}-,}{ld.lld,lld}
+	fi
+
+	if [[ -v switch ]]; then
+		# only need llvm-nm for lto, but use complete set to be safe
+		for tool in AR NM OBJCOPY OBJDUMP READELF STRIP; do
+			case $(LC_ALL=C $(tc-get${tool}) --version 2>/dev/null) in
+				LLVM*|llvm*) [[ ! ${switch} ]];;
+				*) [[ ${switch} ]];;
+			esac && nvidia-tc-set ${tool} {${CHOST}-,}${switch}${tool,,}
+		done
+	fi
+
+	# pass unconditionally given exports are semi-ignored except CC/LD
+	for tool in CC LD AR NM OBJCOPY OBJDUMP READELF STRIP; do
+		BUILD_PARAMS+=" ${tool}=\"\${KERNEL_${tool}:-\$(tc-get${tool})}\""
+	done
+
+	if linux_chkconfig_present LTO_CLANG_THIN; then
+		# kernel enables cache by default leading to sandbox violations
+		BUILD_PARAMS+=' ldflags-y=--thinlto-cache-dir= LDFLAGS_MODULE=--thinlto-cache-dir='
 	fi
-	BUILD_PARAMS+=' ${KERNEL_CC:+CC="${KERNEL_CC}"} ${KERNEL_LD:+LD="${KERNEL_LD}"}'
 
 	if kernel_is -gt ${NV_KERNEL_MAX/./ }; then
 		ewarn "Kernel ${KV_MAJOR}.${KV_MINOR} is either known to break this version of ${PN}"
diff --git a/x11-drivers/nvidia-drivers/nvidia-drivers-510.108.03.ebuild b/x11-drivers/nvidia-drivers/nvidia-drivers-510.108.03.ebuild
index d1b90da591b3..fb50c6c899e2 100644
--- a/x11-drivers/nvidia-drivers/nvidia-drivers-510.108.03.ebuild
+++ b/x11-drivers/nvidia-drivers/nvidia-drivers-510.108.03.ebuild
@@ -185,20 +185,58 @@ pkg_setup() {
 	BUILD_PARAMS='NV_VERBOSE=1 IGNORE_CC_MISMATCH=yes SYSSRC="${KV_DIR}" SYSOUT="${KV_OUT_DIR}"'
 	BUILD_TARGETS="modules"
 
-	if linux_chkconfig_present CC_IS_CLANG; then
-		ewarn "Warning: clang-built kernel detected, using clang for modules (experimental)"
-		ewarn "Can use KERNEL_CC and KERNEL_LD environment variables to override if needed."
-
-		tc-is-clang || : "${KERNEL_CC:=${CHOST}-clang}"
-		if linux_chkconfig_present LD_IS_LLD; then
-			: "${KERNEL_LD:=ld.lld}"
-			if linux_chkconfig_present LTO_CLANG_THIN; then
-				# kernel enables cache by default leading to sandbox violations
-				BUILD_PARAMS+=' ldflags-y=--thinlto-cache-dir= LDFLAGS_MODULE=--thinlto-cache-dir='
-			fi
+	# Try to match toolchain with kernel only for modules
+	# (experimental, ideally this should be handled in linux-mod.eclass)
+	nvidia-tc-set() {
+		local -n var=KERNEL_${1}
+		if [[ ! -v var ]]; then
+			read -r var < <(type -P "${@:2}") ||
+				die "failed to find in PATH at least one of: ${*:2}"
+			einfo "Forcing '${var}' for modules (set ${!var} to override)"
+		fi
+	}
+
+	local tool switch
+	if linux_chkconfig_present CC_IS_GCC; then
+		if ! tc-is-gcc; then
+			switch=
+			nvidia-tc-set CC {${CHOST}-,}gcc
 		fi
+	elif linux_chkconfig_present CC_IS_CLANG; then
+		ewarn "Warning: using ${PN} with a clang-built kernel is largely untested"
+		if ! tc-is-clang; then
+			switch=llvm-
+			nvidia-tc-set CC {${CHOST}-,}clang
+		fi
+	fi
+
+	if linux_chkconfig_present LD_IS_BFD; then
+		# tc-ld-is-bfd needs https://github.com/gentoo/gentoo/pull/28355
+		[[ $(LC_ALL=C $(tc-getLD) --version 2>/dev/null) == "GNU ld"* ]] ||
+			nvidia-tc-set LD {${CHOST}-,}{ld.bfd,ld}
+	elif linux_chkconfig_present LD_IS_LLD; then
+		tc-ld-is-lld || nvidia-tc-set LD {${CHOST}-,}{ld.lld,lld}
+	fi
+
+	if [[ -v switch ]]; then
+		# only need llvm-nm for lto, but use complete set to be safe
+		for tool in AR NM OBJCOPY OBJDUMP READELF STRIP; do
+			case $(LC_ALL=C $(tc-get${tool}) --version 2>/dev/null) in
+				LLVM*|llvm*) [[ ! ${switch} ]];;
+				*) [[ ${switch} ]];;
+			esac && nvidia-tc-set ${tool} {${CHOST}-,}${switch}${tool,,}
+		done
+	fi
+
+	# pass unconditionally given exports are semi-ignored except CC/LD
+	for tool in CC LD AR NM OBJCOPY OBJDUMP READELF STRIP; do
+		BUILD_PARAMS+=" ${tool}=\"\${KERNEL_${tool}:-\$(tc-get${tool})}\""
+	done
+
+	if linux_chkconfig_present LTO_CLANG_THIN; then
+		# kernel enables cache by default leading to sandbox violations
+		BUILD_PARAMS+=' ldflags-y=--thinlto-cache-dir= LDFLAGS_MODULE=--thinlto-cache-dir='
 	fi
-	BUILD_PARAMS+=' ${KERNEL_CC:+CC="${KERNEL_CC}"} ${KERNEL_LD:+LD="${KERNEL_LD}"}'
 
 	if kernel_is -gt ${NV_KERNEL_MAX/./ }; then
 		ewarn "Kernel ${KV_MAJOR}.${KV_MINOR} is either known to break this version of ${PN}"
diff --git a/x11-drivers/nvidia-drivers/nvidia-drivers-515.86.01.ebuild b/x11-drivers/nvidia-drivers/nvidia-drivers-515.86.01.ebuild
index 7cb7cee88bbe..c8a19fc25b38 100644
--- a/x11-drivers/nvidia-drivers/nvidia-drivers-515.86.01.ebuild
+++ b/x11-drivers/nvidia-drivers/nvidia-drivers-515.86.01.ebuild
@@ -195,20 +195,60 @@ pkg_setup() {
 	BUILD_PARAMS='NV_VERBOSE=1 IGNORE_CC_MISMATCH=yes SYSSRC="${KV_DIR}" SYSOUT="${KV_OUT_DIR}"'
 	BUILD_TARGETS="modules"
 
-	if linux_chkconfig_present CC_IS_CLANG; then
-		ewarn "Warning: clang-built kernel detected, using clang for modules (experimental)"
-		ewarn "Can use KERNEL_CC and KERNEL_LD environment variables to override if needed."
-
-		tc-is-clang || : "${KERNEL_CC:=${CHOST}-clang}"
-		if linux_chkconfig_present LD_IS_LLD; then
-			: "${KERNEL_LD:=ld.lld}"
-			if linux_chkconfig_present LTO_CLANG_THIN; then
-				# kernel enables cache by default leading to sandbox violations
-				BUILD_PARAMS+=' ldflags-y=--thinlto-cache-dir= LDFLAGS_MODULE=--thinlto-cache-dir='
-			fi
+	# Try to match toolchain with kernel only for modules
+	# (experimental, ideally this should be handled in linux-mod.eclass)
+	nvidia-tc-set() {
+		local -n var=KERNEL_${1}
+		if [[ ! -v var ]]; then
+			read -r var < <(type -P "${@:2}") ||
+				die "failed to find in PATH at least one of: ${*:2}"
+			einfo "Forcing '${var}' for modules (set ${!var} to override)"
+		fi
+	}
+
+	local tool switch
+	if linux_chkconfig_present CC_IS_GCC; then
+		if ! tc-is-gcc; then
+			switch=
+			nvidia-tc-set CC {${CHOST}-,}gcc
+			nvidia-tc-set CXX {${CHOST}-,}g++ # needed by kernel-open
+		fi
+	elif linux_chkconfig_present CC_IS_CLANG; then
+		ewarn "Warning: using ${PN} with a clang-built kernel is largely untested"
+		if ! tc-is-clang; then
+			switch=llvm-
+			nvidia-tc-set CC {${CHOST}-,}clang
+			nvidia-tc-set CXX {${CHOST}-,}clang++
 		fi
 	fi
-	BUILD_PARAMS+=' ${KERNEL_CC:+CC="${KERNEL_CC}"} ${KERNEL_LD:+LD="${KERNEL_LD}"}'
+
+	if linux_chkconfig_present LD_IS_BFD; then
+		# tc-ld-is-bfd needs https://github.com/gentoo/gentoo/pull/28355
+		[[ $(LC_ALL=C $(tc-getLD) --version 2>/dev/null) == "GNU ld"* ]] ||
+			nvidia-tc-set LD {${CHOST}-,}{ld.bfd,ld}
+	elif linux_chkconfig_present LD_IS_LLD; then
+		tc-ld-is-lld || nvidia-tc-set LD {${CHOST}-,}{ld.lld,lld}
+	fi
+
+	if [[ -v switch ]]; then
+		# only need llvm-nm for lto, but use complete set to be safe
+		for tool in AR NM OBJCOPY OBJDUMP READELF STRIP; do
+			case $(LC_ALL=C $(tc-get${tool}) --version 2>/dev/null) in
+				LLVM*|llvm*) [[ ! ${switch} ]];;
+				*) [[ ${switch} ]];;
+			esac && nvidia-tc-set ${tool} {${CHOST}-,}${switch}${tool,,}
+		done
+	fi
+
+	# pass unconditionally given exports are semi-ignored except CC/LD
+	for tool in CC CXX LD AR NM OBJCOPY OBJDUMP READELF STRIP; do
+		BUILD_PARAMS+=" ${tool}=\"\${KERNEL_${tool}:-\$(tc-get${tool})}\""
+	done
+
+	if linux_chkconfig_present LTO_CLANG_THIN; then
+		# kernel enables cache by default leading to sandbox violations
+		BUILD_PARAMS+=' ldflags-y=--thinlto-cache-dir= LDFLAGS_MODULE=--thinlto-cache-dir='
+	fi
 
 	if kernel_is -gt ${NV_KERNEL_MAX/./ }; then
 		ewarn "Kernel ${KV_MAJOR}.${KV_MINOR} is either known to break this version of ${PN}"
diff --git a/x11-drivers/nvidia-drivers/nvidia-drivers-525.47.04.ebuild b/x11-drivers/nvidia-drivers/nvidia-drivers-525.47.04.ebuild
index 30fa4541ebe3..3d6e9c685aea 100644
--- a/x11-drivers/nvidia-drivers/nvidia-drivers-525.47.04.ebuild
+++ b/x11-drivers/nvidia-drivers/nvidia-drivers-525.47.04.ebuild
@@ -191,20 +191,60 @@ pkg_setup() {
 	BUILD_PARAMS='NV_VERBOSE=1 IGNORE_CC_MISMATCH=yes SYSSRC="${KV_DIR}" SYSOUT="${KV_OUT_DIR}"'
 	BUILD_TARGETS="modules"
 
-	if linux_chkconfig_present CC_IS_CLANG; then
-		ewarn "Warning: clang-built kernel detected, using clang for modules (experimental)"
-		ewarn "Can use KERNEL_CC and KERNEL_LD environment variables to override if needed."
-
-		tc-is-clang || : "${KERNEL_CC:=${CHOST}-clang}"
-		if linux_chkconfig_present LD_IS_LLD; then
-			: "${KERNEL_LD:=ld.lld}"
-			if linux_chkconfig_present LTO_CLANG_THIN; then
-				# kernel enables cache by default leading to sandbox violations
-				BUILD_PARAMS+=' ldflags-y=--thinlto-cache-dir= LDFLAGS_MODULE=--thinlto-cache-dir='
-			fi
+	# Try to match toolchain with kernel only for modules
+	# (experimental, ideally this should be handled in linux-mod.eclass)
+	nvidia-tc-set() {
+		local -n var=KERNEL_${1}
+		if [[ ! -v var ]]; then
+			read -r var < <(type -P "${@:2}") ||
+				die "failed to find in PATH at least one of: ${*:2}"
+			einfo "Forcing '${var}' for modules (set ${!var} to override)"
+		fi
+	}
+
+	local tool switch
+	if linux_chkconfig_present CC_IS_GCC; then
+		if ! tc-is-gcc; then
+			switch=
+			nvidia-tc-set CC {${CHOST}-,}gcc
+			nvidia-tc-set CXX {${CHOST}-,}g++ # needed by kernel-open
+		fi
+	elif linux_chkconfig_present CC_IS_CLANG; then
+		ewarn "Warning: using ${PN} with a clang-built kernel is largely untested"
+		if ! tc-is-clang; then
+			switch=llvm-
+			nvidia-tc-set CC {${CHOST}-,}clang
+			nvidia-tc-set CXX {${CHOST}-,}clang++
 		fi
 	fi
-	BUILD_PARAMS+=' ${KERNEL_CC:+CC="${KERNEL_CC}"} ${KERNEL_LD:+LD="${KERNEL_LD}"}'
+
+	if linux_chkconfig_present LD_IS_BFD; then
+		# tc-ld-is-bfd needs https://github.com/gentoo/gentoo/pull/28355
+		[[ $(LC_ALL=C $(tc-getLD) --version 2>/dev/null) == "GNU ld"* ]] ||
+			nvidia-tc-set LD {${CHOST}-,}{ld.bfd,ld}
+	elif linux_chkconfig_present LD_IS_LLD; then
+		tc-ld-is-lld || nvidia-tc-set LD {${CHOST}-,}{ld.lld,lld}
+	fi
+
+	if [[ -v switch ]]; then
+		# only need llvm-nm for lto, but use complete set to be safe
+		for tool in AR NM OBJCOPY OBJDUMP READELF STRIP; do
+			case $(LC_ALL=C $(tc-get${tool}) --version 2>/dev/null) in
+				LLVM*|llvm*) [[ ! ${switch} ]];;
+				*) [[ ${switch} ]];;
+			esac && nvidia-tc-set ${tool} {${CHOST}-,}${switch}${tool,,}
+		done
+	fi
+
+	# pass unconditionally given exports are semi-ignored except CC/LD
+	for tool in CC CXX LD AR NM OBJCOPY OBJDUMP READELF STRIP; do
+		BUILD_PARAMS+=" ${tool}=\"\${KERNEL_${tool}:-\$(tc-get${tool})}\""
+	done
+
+	if linux_chkconfig_present LTO_CLANG_THIN; then
+		# kernel enables cache by default leading to sandbox violations
+		BUILD_PARAMS+=' ldflags-y=--thinlto-cache-dir= LDFLAGS_MODULE=--thinlto-cache-dir='
+	fi
 
 	if kernel_is -gt ${NV_KERNEL_MAX/./ }; then
 		ewarn "Kernel ${KV_MAJOR}.${KV_MINOR} is either known to break this version of ${PN}"
diff --git a/x11-drivers/nvidia-drivers/nvidia-drivers-525.60.13.ebuild b/x11-drivers/nvidia-drivers/nvidia-drivers-525.60.13.ebuild
index 5238f7c81ae7..6060ff5b02d2 100644
--- a/x11-drivers/nvidia-drivers/nvidia-drivers-525.60.13.ebuild
+++ b/x11-drivers/nvidia-drivers/nvidia-drivers-525.60.13.ebuild
@@ -190,20 +190,60 @@ pkg_setup() {
 	BUILD_PARAMS='NV_VERBOSE=1 IGNORE_CC_MISMATCH=yes SYSSRC="${KV_DIR}" SYSOUT="${KV_OUT_DIR}"'
 	BUILD_TARGETS="modules"
 
-	if linux_chkconfig_present CC_IS_CLANG; then
-		ewarn "Warning: clang-built kernel detected, using clang for modules (experimental)"
-		ewarn "Can use KERNEL_CC and KERNEL_LD environment variables to override if needed."
-
-		tc-is-clang || : "${KERNEL_CC:=${CHOST}-clang}"
-		if linux_chkconfig_present LD_IS_LLD; then
-			: "${KERNEL_LD:=ld.lld}"
-			if linux_chkconfig_present LTO_CLANG_THIN; then
-				# kernel enables cache by default leading to sandbox violations
-				BUILD_PARAMS+=' ldflags-y=--thinlto-cache-dir= LDFLAGS_MODULE=--thinlto-cache-dir='
-			fi
+	# Try to match toolchain with kernel only for modules
+	# (experimental, ideally this should be handled in linux-mod.eclass)
+	nvidia-tc-set() {
+		local -n var=KERNEL_${1}
+		if [[ ! -v var ]]; then
+			read -r var < <(type -P "${@:2}") ||
+				die "failed to find in PATH at least one of: ${*:2}"
+			einfo "Forcing '${var}' for modules (set ${!var} to override)"
+		fi
+	}
+
+	local tool switch
+	if linux_chkconfig_present CC_IS_GCC; then
+		if ! tc-is-gcc; then
+			switch=
+			nvidia-tc-set CC {${CHOST}-,}gcc
+			nvidia-tc-set CXX {${CHOST}-,}g++ # needed by kernel-open
+		fi
+	elif linux_chkconfig_present CC_IS_CLANG; then
+		ewarn "Warning: using ${PN} with a clang-built kernel is largely untested"
+		if ! tc-is-clang; then
+			switch=llvm-
+			nvidia-tc-set CC {${CHOST}-,}clang
+			nvidia-tc-set CXX {${CHOST}-,}clang++
 		fi
 	fi
-	BUILD_PARAMS+=' ${KERNEL_CC:+CC="${KERNEL_CC}"} ${KERNEL_LD:+LD="${KERNEL_LD}"}'
+
+	if linux_chkconfig_present LD_IS_BFD; then
+		# tc-ld-is-bfd needs https://github.com/gentoo/gentoo/pull/28355
+		[[ $(LC_ALL=C $(tc-getLD) --version 2>/dev/null) == "GNU ld"* ]] ||
+			nvidia-tc-set LD {${CHOST}-,}{ld.bfd,ld}
+	elif linux_chkconfig_present LD_IS_LLD; then
+		tc-ld-is-lld || nvidia-tc-set LD {${CHOST}-,}{ld.lld,lld}
+	fi
+
+	if [[ -v switch ]]; then
+		# only need llvm-nm for lto, but use complete set to be safe
+		for tool in AR NM OBJCOPY OBJDUMP READELF STRIP; do
+			case $(LC_ALL=C $(tc-get${tool}) --version 2>/dev/null) in
+				LLVM*|llvm*) [[ ! ${switch} ]];;
+				*) [[ ${switch} ]];;
+			esac && nvidia-tc-set ${tool} {${CHOST}-,}${switch}${tool,,}
+		done
+	fi
+
+	# pass unconditionally given exports are semi-ignored except CC/LD
+	for tool in CC CXX LD AR NM OBJCOPY OBJDUMP READELF STRIP; do
+		BUILD_PARAMS+=" ${tool}=\"\${KERNEL_${tool}:-\$(tc-get${tool})}\""
+	done
+
+	if linux_chkconfig_present LTO_CLANG_THIN; then
+		# kernel enables cache by default leading to sandbox violations
+		BUILD_PARAMS+=' ldflags-y=--thinlto-cache-dir= LDFLAGS_MODULE=--thinlto-cache-dir='
+	fi
 
 	if kernel_is -gt ${NV_KERNEL_MAX/./ }; then
 		ewarn "Kernel ${KV_MAJOR}.${KV_MINOR} is either known to break this version of ${PN}"
-- 
cgit v1.2.3-65-gdbad