linux-stable/scripts/dummy-tools/gcc
Masahiro Yamada ba64beb174 kbuild: check the minimum assembler version in Kconfig
Documentation/process/changes.rst defines the minimum assembler version
(binutils version), but we have never checked it in the build time.

Kbuild never invokes 'as' directly because all assembly files in the
kernel tree are *.S, hence must be preprocessed. I do not expect
raw assembly source files (*.s) would be added to the kernel tree.

Therefore, we always use $(CC) as the assembler driver, and commit
aa824e0c96 ("kbuild: remove AS variable") removed 'AS'. However,
we are still interested in the version of the assembler acting behind.

As usual, the --version option prints the version string.

  $ as --version | head -n 1
  GNU assembler (GNU Binutils for Ubuntu) 2.35.1

But, we do not have $(AS). So, we can add the -Wa prefix so that
$(CC) passes --version down to the backing assembler.

  $ gcc -Wa,--version | head -n 1
  gcc: fatal error: no input files
  compilation terminated.

OK, we need to input something to satisfy gcc.

  $ gcc -Wa,--version -c -x assembler /dev/null -o /dev/null | head -n 1
  GNU assembler (GNU Binutils for Ubuntu) 2.35.1

The combination of Clang and GNU assembler works in the same way:

  $ clang -no-integrated-as -Wa,--version -c -x assembler /dev/null -o /dev/null | head -n 1
  GNU assembler (GNU Binutils for Ubuntu) 2.35.1

Clang with the integrated assembler fails like this:

  $ clang -integrated-as -Wa,--version -c -x assembler /dev/null -o /dev/null | head -n 1
  clang: error: unsupported argument '--version' to option 'Wa,'

For the last case, checking the error message is fragile. If the
proposal for -Wa,--version support [1] is accepted, this may not be
even an error in the future.

One easy way is to check if -integrated-as is present in the passed
arguments. We did not pass -integrated-as to CLANG_FLAGS before, but
we can make it explicit.

Nathan pointed out -integrated-as is the default for all of the
architectures/targets that the kernel cares about, but it goes
along with "explicit is better than implicit" policy. [2]

With all this in my mind, I implemented scripts/as-version.sh to
check the assembler version in Kconfig time.

  $ scripts/as-version.sh gcc
  GNU 23501
  $ scripts/as-version.sh clang -no-integrated-as
  GNU 23501
  $ scripts/as-version.sh clang -integrated-as
  LLVM 0

[1]: https://github.com/ClangBuiltLinux/linux/issues/1320
[2]: https://lore.kernel.org/linux-kbuild/20210307044253.v3h47ucq6ng25iay@archlinux-ax161/

Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
Reviewed-by: Nathan Chancellor <nathan@kernel.org>
2021-04-25 05:14:41 +09:00

107 lines
3 KiB
Bash
Executable file

#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-only
#
# Staring v4.18, Kconfig evaluates compiler capabilities, and hides CONFIG
# options your compiler does not support. This works well if you configure and
# build the kernel on the same host machine.
#
# It is inconvenient if you prepare the .config that is carried to a different
# build environment (typically this happens when you package the kernel for
# distros) because using a different compiler potentially produces different
# CONFIG options than the real build environment. So, you probably want to make
# as many options visible as possible. In other words, you need to create a
# super-set of CONFIG options that cover any build environment. If some of the
# CONFIG options turned out to be unsupported on the build machine, they are
# automatically disabled by the nature of Kconfig.
#
# However, it is not feasible to get a full-featured compiler for every arch.
# Hence these dummy toolchains to make all compiler tests pass.
#
# Usage:
#
# From the top directory of the source tree, run
#
# $ make CROSS_COMPILE=scripts/dummy-tools/ oldconfig
#
# Most of compiler features are tested by cc-option, which simply checks the
# exit code of $(CC). This script does nothing and just exits with 0 in most
# cases. So, $(cc-option, ...) is evaluated as 'y'.
#
# This scripts caters to more checks; handle --version and pre-process __GNUC__
# etc. to pretend to be GCC, and also do right things to satisfy some scripts.
# Check if the first parameter appears in the rest. Succeeds if found.
# This helper is useful if a particular option was passed to this script.
# Typically used like this:
# arg_contain <word-you-are-searching-for> "$@"
arg_contain ()
{
search="$1"
shift
while [ $# -gt 0 ]
do
if [ "$search" = "$1" ]; then
return 0
fi
shift
done
return 1
}
# To set CONFIG_CC_IS_GCC=y
if arg_contain --version "$@"; then
echo "gcc (scripts/dummy-tools/gcc)"
exit 0
fi
if arg_contain -E "$@"; then
# For scripts/cc-version.sh; This emulates GCC 20.0.0
if arg_contain - "$@"; then
sed -n '/^GCC/{s/__GNUC__/20/; s/__GNUC_MINOR__/0/; s/__GNUC_PATCHLEVEL__/0/; p;}'
exit 0
else
echo "no input files" >&2
exit 1
fi
fi
# To set CONFIG_AS_IS_GNU
if arg_contain -Wa,--version "$@"; then
echo "GNU assembler (scripts/dummy-tools) 2.50"
exit 0
fi
if arg_contain -S "$@"; then
# For scripts/gcc-x86-*-has-stack-protector.sh
if arg_contain -fstack-protector "$@"; then
echo "%gs"
exit 0
fi
# For arch/powerpc/tools/gcc-check-mprofile-kernel.sh
if arg_contain -m64 "$@" && arg_contain -mlittle-endian "$@" &&
arg_contain -mprofile-kernel "$@"; then
if ! test -t 0 && ! grep -q notrace; then
echo "_mcount"
fi
exit 0
fi
fi
# To set GCC_PLUGINS
if arg_contain -print-file-name=plugin "$@"; then
plugin_dir=$(mktemp -d)
mkdir -p $plugin_dir/include
touch $plugin_dir/include/plugin-version.h
echo $plugin_dir
exit 0
fi
# inverted return value
if arg_contain -D__SIZEOF_INT128__=0 "$@"; then
exit 1
fi