All of lore.kernel.org
 help / color / mirror / Atom feed
From: Nathan Chancellor <natechancellor@gmail.com>
To: Masahiro Yamada <masahiroy@kernel.org>
Cc: linux-kbuild@vger.kernel.org,
	Paul Gortmaker <paul.gortmaker@windriver.com>,
	Linus Torvalds <torvalds@linux-foundation.org>,
	Nick Desaulniers <ndesaulniers@google.com>,
	Will Deacon <will@kernel.org>,
	clang-built-linux@googlegroups.com, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v2] kbuild: check the minimum compiler version in Kconfig
Date: Thu, 14 Jan 2021 10:07:10 -0700	[thread overview]
Message-ID: <20210114170710.GA259754@ubuntu-m3-large-x86> (raw)
In-Reply-To: <20210114042420.229524-1-masahiroy@kernel.org>

On Thu, Jan 14, 2021 at 01:24:19PM +0900, Masahiro Yamada wrote:
> 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 similar two scripts, gcc-version.sh and clang-version.sh
> into the new 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
> 
> The cc-version.sh also shows the error if the compiler is 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 unsupported.
>   make[1]: *** [scripts/kconfig/Makefile:81: defconfig] Error 1
>   make: *** [Makefile:602: defconfig] Error 2
> 
> I removed the clang version check from <linux/compiler-clang.h>
> 
> For now, I did not touch <linux/compiler-gcc.h> in order to avoid
> merge conflict with [3], which has been queued up in the arm64 tree.
> We will be able to clean it up later.
> 
> I put the stub for ICC because I see <linux/compiler-intel.h> although
> I am not sure if building the kernel with ICC is well-supported.
> 
> [1] https://lkml.org/lkml/2021/1/10/250
> [2] https://lkml.org/lkml/2021/1/12/1708
> [3] https://lkml.org/lkml/2021/1/12/1533

I would recommend the lore version of these links:

[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
[3]: https://lore.kernel.org/r/20210112224832.10980-1-will@kernel.org

> Fixes: 87de84c9140e ("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>
> Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>

I like this a lot, I think that erroring as early as possible when
something is misconfigured is a good user experience.

Reviewed-by: Nathan Chancellor <natechancellor@gmail.com>
Tested-by: Nathan Chancellor <natechancellor@gmail.com>

> ---
> 
> Changes in v2:
>   - fix the function name
> 
>  include/linux/compiler-clang.h | 10 -----
>  init/Kconfig                   |  9 +++--
>  scripts/Kconfig.include        |  6 +++
>  scripts/cc-version.sh          | 69 ++++++++++++++++++++++++++++++++++
>  scripts/clang-version.sh       | 19 ----------
>  scripts/gcc-version.sh         | 20 ----------
>  6 files changed, 80 insertions(+), 53 deletions(-)
>  create mode 100755 scripts/cc-version.sh
>  delete mode 100755 scripts/clang-version.sh
>  delete mode 100755 scripts/gcc-version.sh
> 
> diff --git a/include/linux/compiler-clang.h b/include/linux/compiler-clang.h
> index 98cff1b4b088..04c0a5a717f7 100644
> --- a/include/linux/compiler-clang.h
> +++ b/include/linux/compiler-clang.h
> @@ -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
> diff --git a/init/Kconfig b/init/Kconfig
> index b77c60f8b963..01108dd1318b 100644
> --- a/init/Kconfig
> +++ b/init/Kconfig
> @@ -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
> diff --git a/scripts/Kconfig.include b/scripts/Kconfig.include
> index a5fe72c504ff..cdc8726d2904 100644
> --- a/scripts/Kconfig.include
> +++ b/scripts/Kconfig.include
> @@ -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 unsupported.
> +cc-info := $(shell,scripts/cc-version.sh $(CC))
> +$(error-if,$(success,test -z "$(cc-info)"),Sorry$(comma) this compiler is unsupported.)
> +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)
>  
> diff --git a/scripts/cc-version.sh b/scripts/cc-version.sh
> new file mode 100755
> index 000000000000..9c17c1de401c
> --- /dev/null
> +++ b/scripts/cc-version.sh
> @@ -0,0 +1,69 @@
> +#!/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 compiler version, please update
> +# Documentation/process/changes.rst as well.
> +gcc_min_version=4.9.0
> +clang_min_version=10.0.1
> +
> +# print the compiler name, major version, minor version, patchlevel version
> +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)
> +	/* How to get the version of intel compiler? */
> +	ICC	0		0		0
> +	#elif defined(__GNUC__)
> +	GCC	__GNUC__	__GNUC_MINOR__	__GNUC_PATCHLEVEL__
> +	#else
> +	unsupported	0		0		0
> +	#endif
> +	EOF
> +}
> +
> +# convert the version to a canonical 5 or 6-digit form for numerical comparison
> +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
> +version=$2.$3.$4
> +
> +case "$name" in
> +GCC) min_version=$gcc_min_version;;
> +Clang) min_version=$clang_min_version;;
> +ICC) ;; # ICC min version undefined?
> +*) echo "$orig_args: unknown compiler" >&2; exit 1;;
> +esac
> +
> +cversion=$(get_canonical_version $version)
> +
> +if [ -n "$min_version" ]; then
> +
> +	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
> +fi
> +
> +echo $name $cversion
> diff --git a/scripts/clang-version.sh b/scripts/clang-version.sh
> deleted file mode 100755
> index 6fabf0695761..000000000000
> --- a/scripts/clang-version.sh
> +++ /dev/null
> @@ -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
> diff --git a/scripts/gcc-version.sh b/scripts/gcc-version.sh
> deleted file mode 100755
> index ae353432539b..000000000000
> --- a/scripts/gcc-version.sh
> +++ /dev/null
> @@ -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
> -- 
> 2.27.0
> 

  parent reply	other threads:[~2021-01-14 17:08 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-01-14  4:24 [PATCH v2] kbuild: check the minimum compiler version in Kconfig Masahiro Yamada
2021-01-14  7:54 ` Ilie Halip
2021-01-14  8:09   ` Sedat Dilek
2021-01-14  9:20   ` Masahiro Yamada
2021-01-14 16:49     ` Nathan Chancellor
2021-01-14 15:41 ` kernel test robot
2021-01-14 17:07 ` Nathan Chancellor [this message]
2021-01-14 18:14 ` Miguel Ojeda
2021-01-15 22:54   ` Masahiro Yamada
2021-01-16  1:33     ` Miguel Ojeda

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210114170710.GA259754@ubuntu-m3-large-x86 \
    --to=natechancellor@gmail.com \
    --cc=clang-built-linux@googlegroups.com \
    --cc=linux-kbuild@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=masahiroy@kernel.org \
    --cc=ndesaulniers@google.com \
    --cc=paul.gortmaker@windriver.com \
    --cc=torvalds@linux-foundation.org \
    --cc=will@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.