qemu 的 configure 并没有使用 Autotools 那一套,而是手写的 configure shell 脚本,但是命令行选项模拟了 Autotools 的实现,如显式启用、禁用特性:
--enable-foo
, --disable-foo
configure 原理
特性的控制当前分两部分,一部分是 configure 脚本实现,一部分是 meson 构建工具实现,但最终会统一至 meson,如对 rbd 特性的修改:
rbd: convert to meson
https://github.com/qemu/qemu/commit/fabd1e93d93ef90ddf8574a42aee406314cc47c4
configure 脚本实现的开关
yes/no/""/default_feature
,如:libpmem="$default_feature"
default_feature
默认为 ""
--without-default-features
选项将设置 default_feature
为 no
default_feature=""
# parse CC options second
for opt do
optarg=$(expr "x$opt" : 'x[^=]*=\(.*\)')
case "$opt" in
--without-default-features)
default_feature="no"
;;
esac
done
以 rdma 为例:
## qemu/configure
rdma="$default_feature"
--enable-rdma) rdma="yes"
;;
--disable-rdma) rdma="no"
;;
# RDMA needs OpenFabrics libraries
if test "$rdma" != "no" ; then
cat > $TMPC <<EOF
#include <rdma/rdma_cma.h>
int main(void) { return 0; }
EOF
rdma_libs="-lrdmacm -libverbs -libumad"
if compile_prog "" "$rdma_libs" ; then
rdma="yes"
else
if test "$rdma" = "yes" ; then
error_exit \
" OpenFabrics librdmacm/libibverbs/libibumad not present." \
" Your options:" \
" (1) Fast: Install infiniband packages (devel) from your distro." \
" (2) Cleanest: Install libraries from www.openfabrics.org" \
" (3) Also: Install softiwarp if you don't have RDMA hardware"
fi
rdma="no"
fi
fi
meson 构建选项实现的开关
enabled/disabled/auto
,如:vnc="enabled"
If the value of a
feature
option is set to auto, that value is overridden by the globalauto_features
option (which defaults toauto
). This is intended to be used by packagers who want to have full control on which dependencies are required and which are disabled, and not rely on build-deps being installed (at the right version) to get a feature enabled. They could setauto_features=enabled
to enable all features and disable explicitly only the few they don’t want, if any.
Build options
https://mesonbuild.com/Build-options.html
## qemu/configure
NINJA=$ninja $meson setup \
$(if test "$default_feature" = no; then echo "-Dauto_features=disabled"; fi)
configure: Fix –without-default-features propagation to meson
https://github.com/qemu/qemu/commit/332008e0b9da33dee2c765db3e4e16b3c3ba3a92
显然,--without-default-features
选项决定了 auto_features
的行为。
以 rbd 为例:
## qemu/configure
rbd="auto"
--disable-rbd) rbd="disabled"
;;
--enable-rbd) rbd="enabled"
;;
NINJA=$ninja $meson setup \
-Drbd=$rbd
## qemu/meson_options.txt
option('rbd', type : 'feature', value : 'auto',
description: 'Ceph block device driver')
## qemu/configure
echo "TARGET_DIRS=$target_list" >> $config_host_mak
## qemu/meson.build
target_dirs = config_host['TARGET_DIRS'].split()
have_user = false
have_system = false
foreach target : target_dirs
have_user = have_user or target.endswith('-user')
have_system = have_system or target.endswith('-softmmu')
endforeach
have_tools = 'CONFIG_TOOLS' in config_host
have_block = have_system or have_tools
rbd = not_found
if not get_option('rbd').auto() or have_block
librados = cc.find_library('rados', required: get_option('rbd'),
kwargs: static_kwargs)
librbd = cc.find_library('rbd', has_headers: ['rbd/librbd.h'],
required: get_option('rbd'),
kwargs: static_kwargs)
if librados.found() and librbd.found()
if cc.links('''
#include <stdio.h>
#include <rbd/librbd.h>
int main(void) {
rados_t cluster;
rados_create(&cluster, NULL);
return 0;
}''', dependencies: [librbd, librados])
rbd = declare_dependency(dependencies: [librbd, librados])
elif get_option('rbd').enabled()
error('could not link librados')
else
warning('could not link librados, disabling')
endif
endif
endif
上面的判断 if not get_option('rbd').auto()
让人有点意外,看上去是个明显的错误(特别是对照 configure 版本的处理来看),当然,由于 have_block
的存在使得这个条件存在与否基本上无关紧要。
## qemu/block/meson.build
block_modules = {}
modsrc = []
foreach m : [
[curl, 'curl', [curl, glib], 'curl.c'],
[glusterfs, 'gluster', glusterfs, 'gluster.c'],
[libiscsi, 'iscsi', libiscsi, 'iscsi.c'],
[libnfs, 'nfs', libnfs, 'nfs.c'],
[libssh, 'ssh', libssh, 'ssh.c'],
[rbd, 'rbd', rbd, 'rbd.c'],
]
if m[0].found()
if enable_modules
modsrc += files(m[3])
endif
module_ss = ss.source_set()
module_ss.add(when: m[2], if_true: files(m[3]))
block_modules += {m[1] : module_ss}
endif
endforeach
同时需要注意的是,configure 脚本与 meson 构建选项之间通过 meson_option_parse
bash 函数建立了联系:
# everything else has the same name in configure and meson
--enable-* | --disable-*) meson_option_parse "$opt" "$optarg"
;;
因此,并不是所有选项都需要在 configure 脚本中进行显式的定义和解析。
v7.1.0+ 版本代码稍有改动如下:
# everything else has the same name in configure and meson
--*) meson_option_parse "$opt" "$optarg"
configure & build
$ wget https://download.qemu.org/qemu-6.1.0.tar.xz
$ tar xJf qemu-6.1.0.tar.xz
$ cd qemu-6.1.0/
$ mkdir build
$ cd build/
$ ../configure --prefix=$PWD/qemu-bin --target-list='x86_64-softmmu,aarch64-softmmu' \
--enable-kvm --enable-tools --without-default-features --enable-linux-aio --enable-rbd \
--enable-vnc --enable-vnc-png
$ make
$ make install
$ tree -L 2 qemu-bin/
qemu-bin/
├── bin
│ ├── qemu-edid
│ ├── qemu-img
│ ├── qemu-io
│ ├── qemu-nbd
│ ├── qemu-pr-helper
│ ├── qemu-storage-daemon
│ ├── qemu-system-aarch64
│ └── qemu-system-x86_64
├── libexec
│ └── qemu-bridge-helper
└── share
├── applications
├── icons
└── qemu
$ tree -L 1 qemu-bin/share/qemu/
qemu-bin/share/qemu/
├── bamboo.dtb
├── bios-256k.bin
├── bios.bin
├── bios-microvm.bin
├── canyonlands.dtb
├── edk2-aarch64-code.fd
├── edk2-arm-code.fd
├── edk2-arm-vars.fd
├── edk2-i386-code.fd
├── edk2-i386-secure-code.fd
├── edk2-i386-vars.fd
├── edk2-licenses.txt
├── edk2-x86_64-code.fd
├── edk2-x86_64-secure-code.fd
...
由于 --without-default-features
将可选特性都设置成了禁用,因此需要显式的使能 kvm
, tools
, aio
, rbd
, vnc
等可选特性。
把 qemu-bin/
文件夹拷贝至合适的地方,然后既可以将 qemu-bin/bin/
加入 PATH
,也可以直接以绝对定位的方式运行 qemu 工具。
最后修改于 2021-09-08