概述
在编译linux内核时,linux会检查当前使用的gcc的版本,如果太老的话,就无法编译linux。
问题
执行命令make ARCH=x86_64 defconfig
时,提示如下错误:
*** Default configuration is based on 'x86_64_defconfig'
***
*** Compiler is too old.
*** Your GCC version: 4.8.5
*** Minimum GCC version: 5.1.0
***
scripts/Kconfig.include:44: Sorry, this compiler is not supported.
make[2]: *** [defconfig] Error 1
make[1]: *** [defconfig] Error 2
make: *** [__sub-make] Error 2
检查逻辑
以Linux-5.16.12为例:
Kconfig
--> scripts/Kconfig.include
--> 获取编译器的name和版本:
# 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)
上面调用cc-version.sh获取编译的name和版本,其中会检查版本是否符合要求。
cc-version.sh的实现
#!/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
# 获取编译器的name和版本
# 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命令可以修改$1 $2 $3 $4的值
set -- $(get_compiler_info "$@")
name=$1
min_tool_version=$(dirname $0)/min-tool-version.sh
case "$name" in
GCC)
version=$2.$3.$4
# 获取GCC的版本
min_version=$($min_tool_version gcc)
;;
Clang)
version=$2.$3.$4
min_version=$($min_tool_version llvm)
;;
ICC)
version=$(($2 / 100)).$(($2 % 100)).$3
min_version=$($min_tool_version icc)
;;
*)
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
如果成功的话,会返回编译器的名字和版本,否则会退出编译。
上面使用min-tool-version.sh来获取最低要求的编译器版本,内容如下:
min-tool-version.sh的实现
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-only
#
# Print the minimum supported version of the given tool.
# When you raise the minimum version, please update
# Documentation/process/changes.rst as well.
set -e
if [ $# != 1 ]; then
echo "Usage: $0 toolname" >&2
exit 1
fi
case "$1" in
binutils)
echo 2.23.0
;;
gcc)
echo 5.1.0
;;
icc)
# temporary
echo 16.0.3
;;
llvm)
# https://lore.kernel.org/r/YMtib5hKVyNknZt3@osiris/
if [ "$SRCARCH" = s390 ]; then
echo 13.0.0
else
echo 10.0.1
fi
;;
*)
echo "$1: unknown tool" >&2
exit 1
;;
esac
上面对GCC版本要求最低为5.1.0
- 之前的linux对gcc的检查
linux/compiler-gcc.h
或者:
cc-version.sh
下面是一些linux对GCC版本的要求
Linux版本 | 最低GCC版本 | CPU |
---|---|---|
5.15-rc2 | 5.1.0 | - |
5.10.13 | 5.1.0 | ARM64 |
5.8 | 4.9 | - |
4.18 | 4.6 | - |