QEMU configure脚本内函数分析
@(QEMU)[QEMU|configure]
[TOC]
前言
QEMU版本:2.5。
error_exit - 出错结束函数
该函数用户输出错误信息,并结束脚本运行。
参数1:错误信息。
参数...:【可选】错误补充说明。
error_exit() {
echo
echo "ERROR: $1"
while test -n "$2"; do
echo " $2"
shift
done
echo
exit 1
}
在该函数中使用了while+shift遍历参数并输出,该函数的参数个数可以是多个,如:error_exit <错误> <补充说明1> <补充说明2> <补充说明3>。
do_compiler - 编译函数
编译。
参数1:编译器。如:cc、c++、gcc、g++等。
参数...:编译选项。
do_compiler() {
......
}
下面对该函数进行分析。
将第一个参数保存到局部变量"compiler"中。然后执行shift命令对函数参数进行位移,第一个参数被丢弃。 "echo $compiler "$@" >> config.log"将编译命令输出到日志文件config.log中。代码:
# Run the compiler, capturing its output to the log. First argument
# is compiler binary to execute.
local compiler="$1"
shift
下面的第一条语句将编译命令输出到日志文件config.log中。第二条语句执行编译命令,并将编译输出和错误输出写入config.log文件中,如果编译失败则执行"return $?"。代码:
echo $compiler "$@" >> config.log
$compiler "$@" >> config.log 2>&1 || return $?
剩下的代码会检查是否需要添加"-Werror"编译选项,如果需要则添加"-Werror"编译选项后再次进行编译,如果编译失败则会调用error_exit函数输出错误信息。代码:
# Test passed. If this is an --enable-werror build, rerun
# the test with -Werror and bail out if it fails. This
# makes warning-generating-errors in configure test code
# obvious to developers.
if test "$werror" != "yes"; then
return 0
fi
# Don't bother rerunning the compile if we were already using -Werror
case "$*" in
*-Werror*)
return 0
;;
esac
echo $compiler -Werror "$@" >> config.log
$compiler -Werror "$@" >> config.log 2>&1 && return $?
error_exit "configure test passed without -Werror but failed with -Werror." \
"This is probably a bug in the configure script. The failing command" \
"will be at the bottom of config.log." \
"You can run configure with --disable-werror to bypass this check."
do_cc - 编译函数
使用"$cc"进行编译。
参数:编译选项。
do_cc() {
do_compiler "$cc" "$@"
}
do_cxx - 编译函数
使用"$cxx"进行编译。
参数:编译选项。
do_cxx() {
do_compiler "$cxx" "$@"
}
update_cxxflags - 更新cxxflags
更新"QEMU_CXXFLAGS"的值,过滤掉对一些GCC C++某些版本的编译器无用的编译器选项,因为那些选项只对C程序有意义。
update_cxxflags() {
# Set QEMU_CXXFLAGS from QEMU_CFLAGS by filtering out those
# options which some versions of GCC's C++ compiler complain about
# because they only make sense for C programs.
QEMU_CXXFLAGS=
for arg in $QEMU_CFLAGS; do
case $arg in
-Wstrict-prototypes|-Wmissing-prototypes|-Wnested-externs|\
-Wold-style-declaration|-Wold-style-definition|-Wredundant-decls)
;;
*)
QEMU_CXXFLAGS=${QEMU_CXXFLAGS:+$QEMU_CXXFLAGS }$arg
;;
esac
done
}
该函数做了下面三个事情:
- 在函数的开始处将"QEMU_CXXFLAGS"置空。
- 然后for循环遍历"QEMU_CFLAGS"中的值,并在for中过滤编译选项。
- 将未被过滤的编译选项追加到"QEMU_CXXFLAGS"中。
compile_object - 编译函数
编译object文件。
参数1:cflags编译选项。
compile_object() {
local_cflags="$1"
do_cc $QEMU_CFLAGS $local_cflags -c -o $TMPO $TMPC
}
该函数调用do_cc函数将$TMPC文件编译为$TMPO。
这个函数只将临时文件(即,$TMPC所代表的文件)编译为object文件,这个object文件也是一个临时文件,这个函数只用于编译测试。
编译选项:$QEMU_CFLAGS,$local_cflags。
compile_prog - 编译函数
编译可执行程序。
参数1:cflags编译选项。
参数2:ldflags编译选项。
compile_prog() {
local_cflags="$1"
local_ldflags="$2"
do_cc $QEMU_CFLAGS $local_cflags -o $TMPE $TMPC $LDFLAGS $local_ldflags
}
该函数调用do_cc函数将$TMPC文件编译为$TMPE。
这个函数只将临时文件(即,$TMPC所代表的文件)编译为可执行文件,这个可执行文件也是一个临时文件,这个函数只用于编译测试。
编译选项:$QEMU_CFLAGS,$local_cflags,$LDFLAGS,$local_ldflags。
do_libtool和libtool_prog
用libtool编译程序。
symlink - 创建软链接
创建软链接。"ln -sf"的可移植版本。
参数1:原文件路径。
参数2:目标文件路径。
# symbolically link $1 to $2. Portable version of "ln -sf".
symlink() {
rm -rf "$2"
mkdir -p "$(dirname "$2")"
ln -s "$1" "$2"
}
- 无论目标文件是否存在,先删除。
- mkdir创建目标目录。
- 创建软链接。
has - 判断命令是否存在
检查命令在shell中是否可获得(可以用于判断一个內建命令,即,has可以判断出shell中是否定义了某个函数。如:在shell中定义了一个函数叫"abc",has可以判断出函数"abc"是存在的。可以判断一个非內建命令,如:ls、rm等。但has不能判断shell中是否存在某个变量)。
参数1:要判断的命令。
# check whether a command is available to this shell (may be either an
# executable or a builtin)
has() {
type "$1" >/dev/null 2>&1
}
path_of - 从PATH中查找可执行程序
从PATH中搜索可执行程序是否存在。
参数1:可执行程序路径。这个路径可以是一个相对路径也可以是一个绝对路径。
返回值:如果可执行文件存在,则通过echo返回可执行程序的路径,否则不会调用echo返回字符串。
# search for an executable in PATH
path_of() {
......
}
局部变量初始化:
local_command="$1"
local_ifs="$IFS"
local_dir=""
如果$local_command中有有目录字符(即,'/'字符),则"${local_command#*/}"与"$local_command"不会相等,那么就会进入if语句之内执行。内部的if语句会判断$local_command是否可执行,并且判断它是否不是目录,如果内部if判断为真,则echo会输出"$local_command"并且返回0。代码:
# pathname has a dir component?
if [ "${local_command#*/}" != "$local_command" ]; then
if [ -x "$local_command" ] && [ ! -d "$local_command" ]; then
echo "$local_command"
return 0
fi
fi
如果"$local_command"字符串为空,则返回1:
if [ -z "$local_command" ]; then
return 1
fi
遍历$PATH中的路径,将这些路径与"$local_command"结合,判断结合后的路径是否可执行并且是否不是目录,如果if判断为真,则echo会输出结合后的路径并返回0,否则返回1。代码:
IFS=:
for local_dir in $PATH; do
if [ -x "$local_dir/$local_command" ] && [ ! -d "$local_dir/$local_command" ]; then
echo "$local_dir/$local_command"
IFS="${local_ifs:-$(printf ' \t\n')}"
return 0
fi
done
# not found
IFS="${local_ifs:-$(printf ' \t\n')}"
return 1
have_backend - 未知
不知道函数中的"$trace_backends"是什么东西。QEMU中的tracing使用可能是介绍这个东西的。
have_backend () {
echo "$trace_backends" | grep "$1" >/dev/null
}
query_pkg_config
check_define - 检查编译器宏定义
检查编译器的宏定义。
在该脚本中用于检查机器(如:linux、_WIN32等)和CPU架构(如:i386、x86_64、__arm__等)。
参数1:宏。
check_define() {
cat > $TMPC <<EOF
#if !defined($1)
#error $1 not defined
#endif
int main(void) { return 0; }
EOF
compile_object
}
check_include - 检查是否可找到头文件
参数1:头文件描述。如:stdlib.h、stdio.h等。
check_include() {
cat > $TMPC <<EOF
#include <$1>
int main(void) { return 0; }
EOF
compile_object
}
write_c_skeleton - 写C骨架
用于检测C编译器是否工作或做一些其他测试。
write_c_skeleton() {
cat > $TMPC <<EOF
int main(void) { return 0; }
EOF
}
cc_has_warning_flag
cc_has_warning_flag() {
write_c_skeleton;
# Use the positive sense of the flag when testing for -Wno-wombat
# support (gcc will happily accept the -Wno- form of unknown
# warning options).
optflag="$(echo $1 | sed -e 's/^-Wno-/-W/')"
compile_prog "-Werror $optflag" ""
}
feature_not_found - 特性未找到
当某个特性未找到时,会调用该函数输出这个问题,并输出解决办法,然后结束脚本运行。
参数1:特性。
参数2:解决办法。
feature_not_found() {
feature=$1
remedy=$2
error_exit "User requested feature $feature" \
"configure was not able to find it." \
"$remedy"
}
gnutls_works - 判断是否支持gnutls
gnutls_works() {
# Unfortunately some distros have bad pkg-config information for gnutls
# such that it claims to exist but you get a compiler error if you try
# to use the options returned by --libs. Specifically, Ubuntu for --static
# builds doesn't work:
# https://bugs.launchpad.net/ubuntu/+source/gnutls26/+bug/1478035
#
# So sanity check the cflags/libs before assuming gnutls can be used.
if ! $pkg_config --exists "gnutls"; then
return 1
fi
write_c_skeleton
compile_prog "$($pkg_config --cflags gnutls)" "$($pkg_config --libs gnutls)"
}
has_libgcrypt_config - 检查是否有libgcrypt-config
audio_drv_probe
upper - 将所有小写字母转换为大写字母
upper() {
echo "$@"| LC_ALL=C tr '[a-z]' '[A-Z]'
}
disas_config - 设置配置
参数1:要设置的配置。
disas_config() {
echo "CONFIG_${1}_DIS=y" >> $config_target_mak
echo "CONFIG_${1}_DIS=y" >> config-all-disas.mak
}