mirror of
				https://github.com/torvalds/linux.git
				synced 2025-10-31 16:48:26 +02:00 
			
		
		
		
	kbuild: check the minimum compiler version in Kconfig
Paul Gortmaker reported a regression in the GCC version check. [1]
If you use GCC 4.8, the build breaks before showing the error message
"error Sorry, your version of GCC is too old - please use 4.9 or newer."
I do not want to apply his fix-up since it implies we would not be able
to remove any cc-option test. Anyway, I admit checking the GCC version
in <linux/compiler-gcc.h> is too late.
Almost at the same time, Linus also suggested to move the compiler
version error to Kconfig time. [2]
I unified the two similar scripts, gcc-version.sh and clang-version.sh
into cc-version.sh. The old scripts invoked the compiler multiple times
(3 times for gcc-version.sh, 4 times for clang-version.sh). I refactored
the code so the new one invokes the compiler just once, and also tried
my best to use shell-builtin commands where possible.
The new script runs faster.
  $ time ./scripts/clang-version.sh clang
  120000
  real    0m0.029s
  user    0m0.012s
  sys     0m0.021s
  $ time ./scripts/cc-version.sh clang
  Clang 120000
  real    0m0.009s
  user    0m0.006s
  sys     0m0.004s
cc-version.sh also shows an error message if the compiler is too old:
  $ make defconfig CC=clang-9
  *** Default configuration is based on 'x86_64_defconfig'
  ***
  *** Compiler is too old.
  ***   Your Clang version:    9.0.1
  ***   Minimum Clang version: 10.0.1
  ***
  scripts/Kconfig.include:46: Sorry, this compiler is not supported.
  make[1]: *** [scripts/kconfig/Makefile:81: defconfig] Error 1
  make: *** [Makefile:602: defconfig] Error 2
The new script takes care of ICC because we have <linux/compiler-intel.h>
although I am not sure if building the kernel with ICC is well-supported.
[1]: https://lore.kernel.org/r/20210110190807.134996-1-paul.gortmaker@windriver.com
[2]: https://lore.kernel.org/r/CAHk-=wh-+TMHPTFo1qs-MYyK7tZh-OQovA=pP3=e06aCVp6_kA@mail.gmail.com
Fixes: 87de84c914 ("kbuild: remove cc-option test of -Werror=date-time")
Reported-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Tested-by: Nick Desaulniers <ndesaulniers@google.com>
Reviewed-by: Nathan Chancellor <natechancellor@gmail.com>
Tested-by: Nathan Chancellor <natechancellor@gmail.com>
Reviewed-by: Miguel Ojeda <ojeda@kernel.org>
Tested-by: Miguel Ojeda <ojeda@kernel.org>
Tested-by: Sedat Dilek <sedat.dilek@gmail.com>
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
			
			
This commit is contained in:
		
							parent
							
								
									052c805a18
								
							
						
					
					
						commit
						aec6c60a01
					
				
					 8 changed files with 93 additions and 65 deletions
				
			
		|  | @ -4314,7 +4314,6 @@ C:	irc://chat.freenode.net/clangbuiltlinux | |||
| F:	Documentation/kbuild/llvm.rst | ||||
| F:	include/linux/compiler-clang.h | ||||
| F:	scripts/clang-tools/ | ||||
| F:	scripts/clang-version.sh | ||||
| F:	scripts/lld-version.sh | ||||
| K:	\b(?i:clang|llvm)\b | ||||
| 
 | ||||
|  |  | |||
|  | @ -3,16 +3,6 @@ | |||
| #error "Please don't include <linux/compiler-clang.h> directly, include <linux/compiler.h> instead." | ||||
| #endif | ||||
| 
 | ||||
| #define CLANG_VERSION (__clang_major__ * 10000	\ | ||||
| 		     + __clang_minor__ * 100	\ | ||||
| 		     + __clang_patchlevel__) | ||||
| 
 | ||||
| #if CLANG_VERSION < 100001 | ||||
| #ifndef __BPF_TRACING__ | ||||
| # error Sorry, your version of Clang is too old - please use 10.0.1 or newer. | ||||
| #endif | ||||
| #endif | ||||
| 
 | ||||
| /* Compiler specific definitions for Clang compiler */ | ||||
| 
 | ||||
| /* same as gcc, this was present in clang-2.6 so we can assume it works
 | ||||
|  |  | |||
|  | @ -10,17 +10,6 @@ | |||
| 		     + __GNUC_MINOR__ * 100	\ | ||||
| 		     + __GNUC_PATCHLEVEL__) | ||||
| 
 | ||||
| /* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58145 */ | ||||
| #if GCC_VERSION < 40900 | ||||
| # error Sorry, your version of GCC is too old - please use 4.9 or newer. | ||||
| #elif defined(CONFIG_ARM64) && GCC_VERSION < 50100 | ||||
| /*
 | ||||
|  * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63293
 | ||||
|  * https://lore.kernel.org/r/20210107111841.GN1551@shell.armlinux.org.uk
 | ||||
|  */ | ||||
| # error Sorry, your version of GCC is too old - please use 5.1 or newer. | ||||
| #endif | ||||
| 
 | ||||
| /*
 | ||||
|  * This macro obfuscates arithmetic on a variable address so that gcc | ||||
|  * shouldn't recognize the original var, and make assumptions about it. | ||||
|  |  | |||
|  | @ -26,11 +26,11 @@ config CC_VERSION_TEXT | |||
| 	    and then every file will be rebuilt. | ||||
| 
 | ||||
| config CC_IS_GCC | ||||
| 	def_bool $(success,echo "$(CC_VERSION_TEXT)" | grep -q gcc) | ||||
| 	def_bool $(success,test "$(cc-name)" = GCC) | ||||
| 
 | ||||
| config GCC_VERSION | ||||
| 	int | ||||
| 	default $(shell,$(srctree)/scripts/gcc-version.sh $(CC)) if CC_IS_GCC | ||||
| 	default $(cc-version) if CC_IS_GCC | ||||
| 	default 0 | ||||
| 
 | ||||
| config LD_VERSION | ||||
|  | @ -38,14 +38,15 @@ config LD_VERSION | |||
| 	default $(shell,$(LD) --version | $(srctree)/scripts/ld-version.sh) | ||||
| 
 | ||||
| config CC_IS_CLANG | ||||
| 	def_bool $(success,echo "$(CC_VERSION_TEXT)" | grep -q clang) | ||||
| 	def_bool $(success,test "$(cc-name)" = Clang) | ||||
| 
 | ||||
| config LD_IS_LLD | ||||
| 	def_bool $(success,$(LD) -v | head -n 1 | grep -q LLD) | ||||
| 
 | ||||
| config CLANG_VERSION | ||||
| 	int | ||||
| 	default $(shell,$(srctree)/scripts/clang-version.sh $(CC)) | ||||
| 	default $(cc-version) if CC_IS_CLANG | ||||
| 	default 0 | ||||
| 
 | ||||
| config LLD_VERSION | ||||
| 	int | ||||
|  |  | |||
|  | @ -39,6 +39,12 @@ as-instr = $(success,printf "%b\n" "$(1)" | $(CC) $(CLANG_FLAGS) -c -x assembler | |||
| $(error-if,$(failure,command -v $(CC)),compiler '$(CC)' not found) | ||||
| $(error-if,$(failure,command -v $(LD)),linker '$(LD)' not found) | ||||
| 
 | ||||
| # Get the compiler name, version, and error out if it is not supported. | ||||
| cc-info := $(shell,$(srctree)/scripts/cc-version.sh $(CC)) | ||||
| $(error-if,$(success,test -z "$(cc-info)"),Sorry$(comma) this compiler is not supported.) | ||||
| cc-name := $(shell,set -- $(cc-info) && echo $1) | ||||
| cc-version := $(shell,set -- $(cc-info) && echo $2) | ||||
| 
 | ||||
| # Fail if the linker is gold as it's not capable of linking the kernel proper | ||||
| $(error-if,$(success, $(LD) -v | grep -q gold), gold linker '$(LD)' not supported) | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										82
									
								
								scripts/cc-version.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										82
									
								
								scripts/cc-version.sh
									
									
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,82 @@ | |||
| #!/bin/sh | ||||
| # SPDX-License-Identifier: GPL-2.0 | ||||
| # | ||||
| # Print the compiler name and its version in a 5 or 6-digit form. | ||||
| # Also, perform the minimum version check. | ||||
| 
 | ||||
| set -e | ||||
| 
 | ||||
| # When you raise the minimum compiler version, please update | ||||
| # Documentation/process/changes.rst as well. | ||||
| gcc_min_version=4.9.0 | ||||
| clang_min_version=10.0.1 | ||||
| icc_min_version=16.0.3 # temporary | ||||
| 
 | ||||
| # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63293 | ||||
| # https://lore.kernel.org/r/20210107111841.GN1551@shell.armlinux.org.uk | ||||
| if [ "$SRCARCH" = arm64 ]; then | ||||
| 	gcc_min_version=5.1.0 | ||||
| fi | ||||
| 
 | ||||
| # Print the compiler name and some version components. | ||||
| get_compiler_info() | ||||
| { | ||||
| 	cat <<- EOF | "$@" -E -P -x c - 2>/dev/null | ||||
| 	#if defined(__clang__) | ||||
| 	Clang	__clang_major__  __clang_minor__  __clang_patchlevel__ | ||||
| 	#elif defined(__INTEL_COMPILER) | ||||
| 	ICC	__INTEL_COMPILER  __INTEL_COMPILER_UPDATE | ||||
| 	#elif defined(__GNUC__) | ||||
| 	GCC	__GNUC__  __GNUC_MINOR__  __GNUC_PATCHLEVEL__ | ||||
| 	#else | ||||
| 	unknown | ||||
| 	#endif | ||||
| 	EOF | ||||
| } | ||||
| 
 | ||||
| # Convert the version string x.y.z to a canonical 5 or 6-digit form. | ||||
| get_canonical_version() | ||||
| { | ||||
| 	IFS=. | ||||
| 	set -- $1 | ||||
| 	echo $((10000 * $1 + 100 * $2 + $3)) | ||||
| } | ||||
| 
 | ||||
| # $@ instead of $1 because multiple words might be given, e.g. CC="ccache gcc". | ||||
| orig_args="$@" | ||||
| set -- $(get_compiler_info "$@") | ||||
| 
 | ||||
| name=$1 | ||||
| 
 | ||||
| case "$name" in | ||||
| GCC) | ||||
| 	version=$2.$3.$4 | ||||
| 	min_version=$gcc_min_version | ||||
| 	;; | ||||
| Clang) | ||||
| 	version=$2.$3.$4 | ||||
| 	min_version=$clang_min_version | ||||
| 	;; | ||||
| ICC) | ||||
| 	version=$(($2 / 100)).$(($2 % 100)).$3 | ||||
| 	min_version=$icc_min_version | ||||
| 	;; | ||||
| *) | ||||
| 	echo "$orig_args: unknown compiler" >&2 | ||||
| 	exit 1 | ||||
| 	;; | ||||
| esac | ||||
| 
 | ||||
| cversion=$(get_canonical_version $version) | ||||
| min_cversion=$(get_canonical_version $min_version) | ||||
| 
 | ||||
| if [ "$cversion" -lt "$min_cversion" ]; then | ||||
| 	echo >&2 "***" | ||||
| 	echo >&2 "*** Compiler is too old." | ||||
| 	echo >&2 "***   Your $name version:    $version" | ||||
| 	echo >&2 "***   Minimum $name version: $min_version" | ||||
| 	echo >&2 "***" | ||||
| 	exit 1 | ||||
| fi | ||||
| 
 | ||||
| echo $name $cversion | ||||
|  | @ -1,19 +0,0 @@ | |||
| #!/bin/sh | ||||
| # SPDX-License-Identifier: GPL-2.0 | ||||
| # | ||||
| # clang-version clang-command | ||||
| # | ||||
| # Print the compiler version of `clang-command' in a 5 or 6-digit form | ||||
| # such as `50001' for clang-5.0.1 etc. | ||||
| 
 | ||||
| compiler="$*" | ||||
| 
 | ||||
| if ! ( $compiler --version | grep -q clang) ; then | ||||
| 	echo 0 | ||||
| 	exit 1 | ||||
| fi | ||||
| 
 | ||||
| MAJOR=$(echo __clang_major__ | $compiler -E -x c - | tail -n 1) | ||||
| MINOR=$(echo __clang_minor__ | $compiler -E -x c - | tail -n 1) | ||||
| PATCHLEVEL=$(echo __clang_patchlevel__ | $compiler -E -x c - | tail -n 1) | ||||
| printf "%d%02d%02d\\n" $MAJOR $MINOR $PATCHLEVEL | ||||
|  | @ -1,20 +0,0 @@ | |||
| #!/bin/sh | ||||
| # SPDX-License-Identifier: GPL-2.0 | ||||
| # | ||||
| # gcc-version gcc-command | ||||
| # | ||||
| # Print the gcc version of `gcc-command' in a 5 or 6-digit form | ||||
| # such as `29503' for gcc-2.95.3, `30301' for gcc-3.3.1, etc. | ||||
| 
 | ||||
| compiler="$*" | ||||
| 
 | ||||
| if [ ${#compiler} -eq 0 ]; then | ||||
| 	echo "Error: No compiler specified." >&2 | ||||
| 	printf "Usage:\n\t$0 <gcc-command>\n" >&2 | ||||
| 	exit 1 | ||||
| fi | ||||
| 
 | ||||
| MAJOR=$(echo __GNUC__ | $compiler -E -x c - | tail -n 1) | ||||
| MINOR=$(echo __GNUC_MINOR__ | $compiler -E -x c - | tail -n 1) | ||||
| PATCHLEVEL=$(echo __GNUC_PATCHLEVEL__ | $compiler -E -x c - | tail -n 1) | ||||
| printf "%d%02d%02d\\n" $MAJOR $MINOR $PATCHLEVEL | ||||
		Loading…
	
		Reference in a new issue
	
	 Masahiro Yamada
						Masahiro Yamada