概述
在編譯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 | - |
