xref: /openbmc/qemu/meson.build (revision e0091133)
1project('qemu', ['c'], meson_version: '>=0.61.3',
2        default_options: ['warning_level=1', 'c_std=gnu11', 'cpp_std=gnu++11', 'b_colorout=auto',
3                          'b_staticpic=false', 'stdsplit=false', 'optimization=2', 'b_pie=true'],
4        version: files('VERSION'))
5
6add_test_setup('quick', exclude_suites: ['slow', 'thorough'], is_default: true)
7add_test_setup('slow', exclude_suites: ['thorough'], env: ['G_TEST_SLOW=1', 'SPEED=slow'])
8add_test_setup('thorough', env: ['G_TEST_SLOW=1', 'SPEED=thorough'])
9
10meson.add_postconf_script(find_program('scripts/symlink-install-tree.py'))
11
12not_found = dependency('', required: false)
13keyval = import('keyval')
14ss = import('sourceset')
15fs = import('fs')
16
17sh = find_program('sh')
18cc = meson.get_compiler('c')
19config_host = keyval.load(meson.current_build_dir() / 'config-host.mak')
20enable_modules = 'CONFIG_MODULES' in config_host
21enable_static = 'CONFIG_STATIC' in config_host
22
23# Allow both shared and static libraries unless --enable-static
24static_kwargs = enable_static ? {'static': true} : {}
25
26# Temporary directory used for files created while
27# configure runs. Since it is in the build directory
28# we can safely blow away any previous version of it
29# (and we need not jump through hoops to try to delete
30# it when configure exits.)
31tmpdir = meson.current_build_dir() / 'meson-private/temp'
32
33if get_option('qemu_suffix').startswith('/')
34  error('qemu_suffix cannot start with a /')
35endif
36
37qemu_confdir = get_option('sysconfdir') / get_option('qemu_suffix')
38qemu_datadir = get_option('datadir') / get_option('qemu_suffix')
39qemu_docdir = get_option('docdir') / get_option('qemu_suffix')
40qemu_moddir = get_option('libdir') / get_option('qemu_suffix')
41
42qemu_desktopdir = get_option('datadir') / 'applications'
43qemu_icondir = get_option('datadir') / 'icons'
44
45config_host_data = configuration_data()
46genh = []
47qapi_trace_events = []
48
49bsd_oses = ['gnu/kfreebsd', 'freebsd', 'netbsd', 'openbsd', 'dragonfly', 'darwin']
50supported_oses = ['windows', 'freebsd', 'netbsd', 'openbsd', 'darwin', 'sunos', 'linux']
51supported_cpus = ['ppc', 'ppc64', 's390x', 'riscv', 'x86', 'x86_64',
52  'arm', 'aarch64', 'loongarch64', 'mips', 'mips64', 'sparc64']
53
54cpu = host_machine.cpu_family()
55
56# Unify riscv* to a single family.
57if cpu in ['riscv32', 'riscv64']
58  cpu = 'riscv'
59endif
60
61targetos = host_machine.system()
62
63target_dirs = config_host['TARGET_DIRS'].split()
64have_linux_user = false
65have_bsd_user = false
66have_system = false
67foreach target : target_dirs
68  have_linux_user = have_linux_user or target.endswith('linux-user')
69  have_bsd_user = have_bsd_user or target.endswith('bsd-user')
70  have_system = have_system or target.endswith('-softmmu')
71endforeach
72have_user = have_linux_user or have_bsd_user
73have_tools = get_option('tools') \
74  .disable_auto_if(not have_system) \
75  .allowed()
76have_ga = get_option('guest_agent') \
77  .disable_auto_if(not have_system and not have_tools) \
78  .require(targetos in ['sunos', 'linux', 'windows', 'freebsd'],
79           error_message: 'unsupported OS for QEMU guest agent') \
80  .allowed()
81have_block = have_system or have_tools
82
83python = import('python').find_installation()
84
85if cpu not in supported_cpus
86  host_arch = 'unknown'
87elif cpu == 'x86'
88  host_arch = 'i386'
89elif cpu == 'mips64'
90  host_arch = 'mips'
91else
92  host_arch = cpu
93endif
94
95if cpu in ['x86', 'x86_64']
96  kvm_targets = ['i386-softmmu', 'x86_64-softmmu']
97elif cpu == 'aarch64'
98  kvm_targets = ['aarch64-softmmu']
99elif cpu == 's390x'
100  kvm_targets = ['s390x-softmmu']
101elif cpu in ['ppc', 'ppc64']
102  kvm_targets = ['ppc-softmmu', 'ppc64-softmmu']
103elif cpu in ['mips', 'mips64']
104  kvm_targets = ['mips-softmmu', 'mipsel-softmmu', 'mips64-softmmu', 'mips64el-softmmu']
105elif cpu in ['riscv']
106  kvm_targets = ['riscv32-softmmu', 'riscv64-softmmu']
107else
108  kvm_targets = []
109endif
110
111kvm_targets_c = '""'
112if get_option('kvm').allowed() and targetos == 'linux'
113  kvm_targets_c = '"' + '" ,"'.join(kvm_targets) + '"'
114endif
115config_host_data.set('CONFIG_KVM_TARGETS', kvm_targets_c)
116
117accelerator_targets = { 'CONFIG_KVM': kvm_targets }
118
119if cpu in ['aarch64']
120  accelerator_targets += {
121    'CONFIG_HVF': ['aarch64-softmmu']
122  }
123endif
124
125if cpu in ['x86', 'x86_64', 'arm', 'aarch64']
126  # i386 emulator provides xenpv machine type for multiple architectures
127  accelerator_targets += {
128    'CONFIG_XEN': ['i386-softmmu', 'x86_64-softmmu'],
129  }
130endif
131if cpu in ['x86', 'x86_64']
132  accelerator_targets += {
133    'CONFIG_HAX': ['i386-softmmu', 'x86_64-softmmu'],
134    'CONFIG_HVF': ['x86_64-softmmu'],
135    'CONFIG_NVMM': ['i386-softmmu', 'x86_64-softmmu'],
136    'CONFIG_WHPX': ['i386-softmmu', 'x86_64-softmmu'],
137  }
138endif
139
140modular_tcg = []
141# Darwin does not support references to thread-local variables in modules
142if targetos != 'darwin'
143  modular_tcg = ['i386-softmmu', 'x86_64-softmmu']
144endif
145
146edk2_targets = [ 'arm-softmmu', 'aarch64-softmmu', 'i386-softmmu', 'x86_64-softmmu' ]
147unpack_edk2_blobs = false
148foreach target : edk2_targets
149  if target in target_dirs
150    bzip2 = find_program('bzip2', required: get_option('install_blobs'))
151    unpack_edk2_blobs = bzip2.found()
152    break
153  endif
154endforeach
155
156dtrace = not_found
157stap = not_found
158if 'dtrace' in get_option('trace_backends')
159  dtrace = find_program('dtrace', required: true)
160  stap = find_program('stap', required: false)
161  if stap.found()
162    # Workaround to avoid dtrace(1) producing a file with 'hidden' symbol
163    # visibility. Define STAP_SDT_V2 to produce 'default' symbol visibility
164    # instead. QEMU --enable-modules depends on this because the SystemTap
165    # semaphores are linked into the main binary and not the module's shared
166    # object.
167    add_global_arguments('-DSTAP_SDT_V2',
168                         native: false, language: ['c', 'cpp', 'objc'])
169  endif
170endif
171
172if get_option('iasl') == ''
173  iasl = find_program('iasl', required: false)
174else
175  iasl = find_program(get_option('iasl'), required: true)
176endif
177
178##################
179# Compiler flags #
180##################
181
182qemu_cflags = config_host['QEMU_CFLAGS'].split()
183qemu_objcflags = config_host['QEMU_OBJCFLAGS'].split()
184qemu_ldflags = config_host['QEMU_LDFLAGS'].split()
185
186if enable_static
187  qemu_ldflags += get_option('b_pie') ? '-static-pie' : '-static'
188endif
189
190# Detect support for PT_GNU_RELRO + DT_BIND_NOW.
191# The combination is known as "full relro", because .got.plt is read-only too.
192qemu_ldflags += cc.get_supported_link_arguments('-Wl,-z,relro', '-Wl,-z,now')
193
194if targetos == 'windows'
195  qemu_ldflags += cc.get_supported_link_arguments('-Wl,--no-seh', '-Wl,--nxcompat')
196  # Disable ASLR for debug builds to allow debugging with gdb
197  if get_option('optimization') == '0'
198    qemu_ldflags += cc.get_supported_link_arguments('-Wl,--dynamicbase')
199  endif
200endif
201
202if get_option('gprof')
203  qemu_cflags += ['-p']
204  qemu_objcflags += ['-p']
205  qemu_ldflags += ['-p']
206endif
207
208# Specify linker-script with add_project_link_arguments so that it is not placed
209# within a linker --start-group/--end-group pair
210if get_option('fuzzing')
211  add_project_link_arguments(['-Wl,-T,',
212                              (meson.current_source_dir() / 'tests/qtest/fuzz/fork_fuzz.ld')],
213                             native: false, language: ['c', 'cpp', 'objc'])
214
215  # Specify a filter to only instrument code that is directly related to
216  # virtual-devices.
217  configure_file(output: 'instrumentation-filter',
218                 input: 'scripts/oss-fuzz/instrumentation-filter-template',
219                 copy: true)
220
221  if cc.compiles('int main () { return 0; }',
222                  name: '-fsanitize-coverage-allowlist=/dev/null',
223                 args: ['-fsanitize-coverage-allowlist=/dev/null',
224                        '-fsanitize-coverage=trace-pc'] )
225    add_global_arguments('-fsanitize-coverage-allowlist=instrumentation-filter',
226                         native: false, language: ['c', 'cpp', 'objc'])
227  endif
228
229  if get_option('fuzzing_engine') == ''
230    # Add CFLAGS to tell clang to add fuzzer-related instrumentation to all the
231    # compiled code.  To build non-fuzzer binaries with --enable-fuzzing, link
232    # everything with fsanitize=fuzzer-no-link. Otherwise, the linker will be
233    # unable to bind the fuzzer-related callbacks added by instrumentation.
234    add_global_arguments('-fsanitize=fuzzer-no-link',
235                         native: false, language: ['c', 'cpp', 'objc'])
236    add_global_link_arguments('-fsanitize=fuzzer-no-link',
237                              native: false, language: ['c', 'cpp', 'objc'])
238    # For the actual fuzzer binaries, we need to link against the libfuzzer
239    # library. They need to be configurable, to support OSS-Fuzz
240    fuzz_exe_ldflags = ['-fsanitize=fuzzer']
241  else
242    # LIB_FUZZING_ENGINE was set; assume we are running on OSS-Fuzz, and
243    # the needed CFLAGS have already been provided
244    fuzz_exe_ldflags = get_option('fuzzing_engine').split()
245  endif
246endif
247
248add_global_arguments(qemu_cflags, native: false, language: ['c'])
249add_global_arguments(qemu_objcflags, native: false, language: ['objc'])
250
251# Check that the C++ compiler exists and works with the C compiler.
252link_language = 'c'
253linker = cc
254qemu_cxxflags = []
255if add_languages('cpp', required: false, native: false)
256  cxx = meson.get_compiler('cpp')
257  add_global_arguments(['-D__STDC_LIMIT_MACROS', '-D__STDC_CONSTANT_MACROS', '-D__STDC_FORMAT_MACROS'],
258                       native: false, language: 'cpp')
259  foreach k: qemu_cflags
260    if k not in ['-Wstrict-prototypes', '-Wmissing-prototypes', '-Wnested-externs',
261                 '-Wold-style-declaration', '-Wold-style-definition', '-Wredundant-decls']
262      qemu_cxxflags += [k]
263    endif
264  endforeach
265  add_global_arguments(qemu_cxxflags, native: false, language: 'cpp')
266
267  if cxx.links(files('scripts/main.c'), args: qemu_cflags)
268    link_language = 'cpp'
269    linker = cxx
270  else
271    message('C++ compiler does not work with C compiler')
272    message('Disabling C++-specific optional code')
273  endif
274endif
275
276# Exclude --warn-common with TSan to suppress warnings from the TSan libraries.
277if targetos != 'sunos' and not config_host.has_key('CONFIG_TSAN')
278  qemu_ldflags += linker.get_supported_link_arguments('-Wl,--warn-common')
279endif
280
281add_global_link_arguments(qemu_ldflags, native: false, language: ['c', 'cpp', 'objc'])
282
283if targetos == 'linux'
284  add_project_arguments('-isystem', meson.current_source_dir() / 'linux-headers',
285                        '-isystem', 'linux-headers',
286                        language: ['c', 'cpp'])
287endif
288
289add_project_arguments('-iquote', '.',
290                      '-iquote', meson.current_source_dir(),
291                      '-iquote', meson.current_source_dir() / 'include',
292                      language: ['c', 'cpp', 'objc'])
293
294if host_machine.system() == 'darwin'
295  add_languages('objc', required: false, native: false)
296endif
297
298sparse = find_program('cgcc', required: get_option('sparse'))
299if sparse.found()
300  run_target('sparse',
301             command: [find_program('scripts/check_sparse.py'),
302                       'compile_commands.json', sparse.full_path(), '-Wbitwise',
303                       '-Wno-transparent-union', '-Wno-old-initializer',
304                       '-Wno-non-pointer-null'])
305endif
306
307###########################################
308# Target-specific checks and dependencies #
309###########################################
310
311# Fuzzing
312if get_option('fuzzing') and get_option('fuzzing_engine') == '' and \
313    not cc.links('''
314          #include <stdint.h>
315          #include <sys/types.h>
316          int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
317          int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { return 0; }
318        ''',
319        args: ['-Werror', '-fsanitize=fuzzer'])
320  error('Your compiler does not support -fsanitize=fuzzer')
321endif
322
323# Tracing backends
324if 'ftrace' in get_option('trace_backends') and targetos != 'linux'
325  error('ftrace is supported only on Linux')
326endif
327if 'syslog' in get_option('trace_backends') and not cc.compiles('''
328    #include <syslog.h>
329    int main(void) {
330        openlog("qemu", LOG_PID, LOG_DAEMON);
331        syslog(LOG_INFO, "configure");
332        return 0;
333    }''')
334  error('syslog is not supported on this system')
335endif
336
337# Miscellaneous Linux-only features
338get_option('mpath') \
339  .require(targetos == 'linux', error_message: 'Multipath is supported only on Linux')
340
341multiprocess_allowed = get_option('multiprocess') \
342  .require(targetos == 'linux', error_message: 'Multiprocess QEMU is supported only on Linux') \
343  .allowed()
344
345vfio_user_server_allowed = get_option('vfio_user_server') \
346  .require(targetos == 'linux', error_message: 'vfio-user server is supported only on Linux') \
347  .allowed()
348
349have_tpm = get_option('tpm') \
350  .require(targetos != 'windows', error_message: 'TPM emulation only available on POSIX systems') \
351  .allowed()
352
353# vhost
354have_vhost_user = get_option('vhost_user') \
355  .disable_auto_if(targetos != 'linux') \
356  .require(targetos != 'windows',
357           error_message: 'vhost-user is not available on Windows').allowed()
358have_vhost_vdpa = get_option('vhost_vdpa') \
359  .require(targetos == 'linux',
360           error_message: 'vhost-vdpa is only available on Linux').allowed()
361have_vhost_kernel = get_option('vhost_kernel') \
362  .require(targetos == 'linux',
363           error_message: 'vhost-kernel is only available on Linux').allowed()
364have_vhost_user_crypto = get_option('vhost_crypto') \
365  .require(have_vhost_user,
366           error_message: 'vhost-crypto requires vhost-user to be enabled').allowed()
367
368have_vhost = have_vhost_user or have_vhost_vdpa or have_vhost_kernel
369
370have_vhost_net_user = have_vhost_user and get_option('vhost_net').allowed()
371have_vhost_net_vdpa = have_vhost_vdpa and get_option('vhost_net').allowed()
372have_vhost_net_kernel = have_vhost_kernel and get_option('vhost_net').allowed()
373have_vhost_net = have_vhost_net_kernel or have_vhost_net_user or have_vhost_net_vdpa
374
375# Target-specific libraries and flags
376libm = cc.find_library('m', required: false)
377threads = dependency('threads')
378util = cc.find_library('util', required: false)
379winmm = []
380socket = []
381version_res = []
382coref = []
383iokit = []
384emulator_link_args = []
385nvmm =not_found
386hvf = not_found
387midl = not_found
388widl = not_found
389pathcch = not_found
390host_dsosuf = '.so'
391if targetos == 'windows'
392  midl = find_program('midl', required: false)
393  widl = find_program('widl', required: false)
394  pathcch = cc.find_library('pathcch')
395  socket = cc.find_library('ws2_32')
396  winmm = cc.find_library('winmm')
397
398  win = import('windows')
399  version_res = win.compile_resources('version.rc',
400                                      depend_files: files('pc-bios/qemu-nsis.ico'),
401                                      include_directories: include_directories('.'))
402  host_dsosuf = '.dll'
403elif targetos == 'darwin'
404  coref = dependency('appleframeworks', modules: 'CoreFoundation')
405  iokit = dependency('appleframeworks', modules: 'IOKit', required: false)
406  host_dsosuf = '.dylib'
407elif targetos == 'sunos'
408  socket = [cc.find_library('socket'),
409            cc.find_library('nsl'),
410            cc.find_library('resolv')]
411elif targetos == 'haiku'
412  socket = [cc.find_library('posix_error_mapper'),
413            cc.find_library('network'),
414            cc.find_library('bsd')]
415elif targetos == 'openbsd'
416  if get_option('tcg').allowed() and target_dirs.length() > 0
417    # Disable OpenBSD W^X if available
418    emulator_link_args = cc.get_supported_link_arguments('-Wl,-z,wxneeded')
419  endif
420endif
421
422# Target-specific configuration of accelerators
423accelerators = []
424if get_option('kvm').allowed() and targetos == 'linux'
425  accelerators += 'CONFIG_KVM'
426endif
427if get_option('whpx').allowed() and targetos == 'windows'
428  if get_option('whpx').enabled() and host_machine.cpu() != 'x86_64'
429    error('WHPX requires 64-bit host')
430  elif cc.has_header('WinHvPlatform.h', required: get_option('whpx')) and \
431       cc.has_header('WinHvEmulation.h', required: get_option('whpx'))
432    accelerators += 'CONFIG_WHPX'
433  endif
434endif
435if get_option('hvf').allowed()
436  hvf = dependency('appleframeworks', modules: 'Hypervisor',
437                   required: get_option('hvf'))
438  if hvf.found()
439    accelerators += 'CONFIG_HVF'
440  endif
441endif
442if get_option('hax').allowed()
443  if get_option('hax').enabled() or targetos in ['windows', 'darwin', 'netbsd']
444    accelerators += 'CONFIG_HAX'
445  endif
446endif
447if targetos == 'netbsd'
448  nvmm = cc.find_library('nvmm', required: get_option('nvmm'))
449  if nvmm.found()
450    accelerators += 'CONFIG_NVMM'
451  endif
452endif
453
454tcg_arch = host_arch
455if get_option('tcg').allowed()
456  if host_arch == 'unknown'
457    if get_option('tcg_interpreter')
458      warning('Unsupported CPU @0@, will use TCG with TCI (slow)'.format(cpu))
459    else
460      error('Unsupported CPU @0@, try --enable-tcg-interpreter'.format(cpu))
461    endif
462  elif get_option('tcg_interpreter')
463    warning('Use of the TCG interpreter is not recommended on this host')
464    warning('architecture. There is a native TCG execution backend available')
465    warning('which provides substantially better performance and reliability.')
466    warning('It is strongly recommended to remove the --enable-tcg-interpreter')
467    warning('configuration option on this architecture to use the native')
468    warning('backend.')
469  endif
470  if get_option('tcg_interpreter')
471    tcg_arch = 'tci'
472  elif host_arch == 'x86_64'
473    tcg_arch = 'i386'
474  elif host_arch == 'ppc64'
475    tcg_arch = 'ppc'
476  endif
477  add_project_arguments('-iquote', meson.current_source_dir() / 'tcg' / tcg_arch,
478                        language: ['c', 'cpp', 'objc'])
479
480  accelerators += 'CONFIG_TCG'
481  config_host += { 'CONFIG_TCG': 'y' }
482endif
483
484if 'CONFIG_KVM' not in accelerators and get_option('kvm').enabled()
485  error('KVM not available on this platform')
486endif
487if 'CONFIG_HVF' not in accelerators and get_option('hvf').enabled()
488  error('HVF not available on this platform')
489endif
490if 'CONFIG_NVMM' not in accelerators and get_option('nvmm').enabled()
491  error('NVMM not available on this platform')
492endif
493if 'CONFIG_WHPX' not in accelerators and get_option('whpx').enabled()
494  error('WHPX not available on this platform')
495endif
496
497################
498# Dependencies #
499################
500
501# The path to glib.h is added to all compilation commands.  This was
502# grandfathered in from the QEMU Makefiles.
503add_project_arguments(config_host['GLIB_CFLAGS'].split(),
504                      native: false, language: ['c', 'cpp', 'objc'])
505glib = declare_dependency(compile_args: config_host['GLIB_CFLAGS'].split(),
506                          link_args: config_host['GLIB_LIBS'].split(),
507                          version: config_host['GLIB_VERSION'],
508                          variables: {
509                            'bindir': config_host['GLIB_BINDIR'],
510                          })
511# override glib dep with the configure results (for subprojects)
512meson.override_dependency('glib-2.0', glib)
513
514gio = not_found
515gdbus_codegen = not_found
516gdbus_codegen_error = '@0@ requires gdbus-codegen, please install libgio'
517if not get_option('gio').auto() or have_system
518  gio = dependency('gio-2.0', required: get_option('gio'),
519                   method: 'pkg-config', kwargs: static_kwargs)
520  if gio.found() and not cc.links('''
521    #include <gio/gio.h>
522    int main(void)
523    {
524      g_dbus_proxy_new_sync(0, 0, 0, 0, 0, 0, 0, 0);
525      return 0;
526    }''', dependencies: [glib, gio])
527    if get_option('gio').enabled()
528      error('The installed libgio is broken for static linking')
529    endif
530    gio = not_found
531  endif
532  if gio.found()
533    gdbus_codegen = find_program(gio.get_variable('gdbus_codegen'),
534                                 required: get_option('gio'))
535    gio_unix = dependency('gio-unix-2.0', required: get_option('gio'),
536                          method: 'pkg-config', kwargs: static_kwargs)
537    gio = declare_dependency(dependencies: [gio, gio_unix],
538                             version: gio.version())
539  endif
540endif
541if gdbus_codegen.found() and get_option('cfi')
542  gdbus_codegen = not_found
543  gdbus_codegen_error = '@0@ uses gdbus-codegen, which does not support control flow integrity'
544endif
545
546lttng = not_found
547if 'ust' in get_option('trace_backends')
548  lttng = dependency('lttng-ust', required: true, version: '>= 2.1',
549                     method: 'pkg-config', kwargs: static_kwargs)
550endif
551pixman = not_found
552if have_system or have_tools
553  pixman = dependency('pixman-1', required: have_system, version:'>=0.21.8',
554                      method: 'pkg-config', kwargs: static_kwargs)
555endif
556zlib = dependency('zlib', required: true, kwargs: static_kwargs)
557
558libaio = not_found
559if not get_option('linux_aio').auto() or have_block
560  libaio = cc.find_library('aio', has_headers: ['libaio.h'],
561                           required: get_option('linux_aio'),
562                           kwargs: static_kwargs)
563endif
564
565linux_io_uring_test = '''
566  #include <liburing.h>
567  #include <linux/errqueue.h>
568
569  int main(void) { return 0; }'''
570
571linux_io_uring = not_found
572if not get_option('linux_io_uring').auto() or have_block
573  linux_io_uring = dependency('liburing', version: '>=0.3',
574                              required: get_option('linux_io_uring'),
575                              method: 'pkg-config', kwargs: static_kwargs)
576  if not cc.links(linux_io_uring_test)
577    linux_io_uring = not_found
578  endif
579endif
580
581libnfs = not_found
582if not get_option('libnfs').auto() or have_block
583  libnfs = dependency('libnfs', version: '>=1.9.3',
584                      required: get_option('libnfs'),
585                      method: 'pkg-config', kwargs: static_kwargs)
586endif
587
588libattr_test = '''
589  #include <stddef.h>
590  #include <sys/types.h>
591  #ifdef CONFIG_LIBATTR
592  #include <attr/xattr.h>
593  #else
594  #include <sys/xattr.h>
595  #endif
596  int main(void) { getxattr(NULL, NULL, NULL, 0); setxattr(NULL, NULL, NULL, 0, 0); return 0; }'''
597
598libattr = not_found
599have_old_libattr = false
600if get_option('attr').allowed()
601  if cc.links(libattr_test)
602    libattr = declare_dependency()
603  else
604    libattr = cc.find_library('attr', has_headers: ['attr/xattr.h'],
605                              required: get_option('attr'),
606                              kwargs: static_kwargs)
607    if libattr.found() and not \
608      cc.links(libattr_test, dependencies: libattr, args: '-DCONFIG_LIBATTR')
609      libattr = not_found
610      if get_option('attr').enabled()
611        error('could not link libattr')
612      else
613        warning('could not link libattr, disabling')
614      endif
615    else
616      have_old_libattr = libattr.found()
617    endif
618  endif
619endif
620
621cocoa = dependency('appleframeworks', modules: ['Cocoa', 'CoreVideo'],
622                   required: get_option('cocoa'))
623
624vmnet = dependency('appleframeworks', modules: 'vmnet', required: get_option('vmnet'))
625if vmnet.found() and not cc.has_header_symbol('vmnet/vmnet.h',
626                                              'VMNET_BRIDGED_MODE',
627                                              dependencies: vmnet)
628  vmnet = not_found
629  if get_option('vmnet').enabled()
630    error('vmnet.framework API is outdated')
631  else
632    warning('vmnet.framework API is outdated, disabling')
633  endif
634endif
635
636seccomp = not_found
637seccomp_has_sysrawrc = false
638if not get_option('seccomp').auto() or have_system or have_tools
639  seccomp = dependency('libseccomp', version: '>=2.3.0',
640                       required: get_option('seccomp'),
641                       method: 'pkg-config', kwargs: static_kwargs)
642  if seccomp.found()
643    seccomp_has_sysrawrc = cc.has_header_symbol('seccomp.h',
644                                                'SCMP_FLTATR_API_SYSRAWRC',
645                                                dependencies: seccomp)
646  endif
647endif
648
649libcap_ng = not_found
650if not get_option('cap_ng').auto() or have_system or have_tools
651  libcap_ng = cc.find_library('cap-ng', has_headers: ['cap-ng.h'],
652                              required: get_option('cap_ng'),
653                              kwargs: static_kwargs)
654endif
655if libcap_ng.found() and not cc.links('''
656   #include <cap-ng.h>
657   int main(void)
658   {
659     capng_capability_to_name(CAPNG_EFFECTIVE);
660     return 0;
661   }''', dependencies: libcap_ng)
662  libcap_ng = not_found
663  if get_option('cap_ng').enabled()
664    error('could not link libcap-ng')
665  else
666    warning('could not link libcap-ng, disabling')
667  endif
668endif
669
670if get_option('xkbcommon').auto() and not have_system and not have_tools
671  xkbcommon = not_found
672else
673  xkbcommon = dependency('xkbcommon', required: get_option('xkbcommon'),
674                         method: 'pkg-config', kwargs: static_kwargs)
675endif
676
677slirp = not_found
678if not get_option('slirp').auto() or have_system
679  slirp = dependency('slirp', required: get_option('slirp'),
680                     method: 'pkg-config', kwargs: static_kwargs)
681  # slirp < 4.7 is incompatible with CFI support in QEMU.  This is because
682  # it passes function pointers within libslirp as callbacks for timers.
683  # When using a system-wide shared libslirp, the type information for the
684  # callback is missing and the timer call produces a false positive with CFI.
685  # Do not use the "version" keyword argument to produce a better error.
686  # with control-flow integrity.
687  if get_option('cfi') and slirp.found() and slirp.version().version_compare('<4.7')
688    if get_option('slirp').enabled()
689      error('Control-Flow Integrity requires libslirp 4.7.')
690    else
691      warning('Cannot use libslirp since Control-Flow Integrity requires libslirp >= 4.7.')
692      slirp = not_found
693    endif
694  endif
695endif
696
697vde = not_found
698if not get_option('vde').auto() or have_system or have_tools
699  vde = cc.find_library('vdeplug', has_headers: ['libvdeplug.h'],
700                           required: get_option('vde'),
701                           kwargs: static_kwargs)
702endif
703if vde.found() and not cc.links('''
704   #include <libvdeplug.h>
705   int main(void)
706   {
707     struct vde_open_args a = {0, 0, 0};
708     char s[] = "";
709     vde_open(s, s, &a);
710     return 0;
711   }''', dependencies: vde)
712  vde = not_found
713  if get_option('cap_ng').enabled()
714    error('could not link libvdeplug')
715  else
716    warning('could not link libvdeplug, disabling')
717  endif
718endif
719
720pulse = not_found
721if not get_option('pa').auto() or (targetos == 'linux' and have_system)
722  pulse = dependency('libpulse', required: get_option('pa'),
723                     method: 'pkg-config', kwargs: static_kwargs)
724endif
725alsa = not_found
726if not get_option('alsa').auto() or (targetos == 'linux' and have_system)
727  alsa = dependency('alsa', required: get_option('alsa'),
728                    method: 'pkg-config', kwargs: static_kwargs)
729endif
730jack = not_found
731if not get_option('jack').auto() or have_system
732  jack = dependency('jack', required: get_option('jack'),
733                    method: 'pkg-config', kwargs: static_kwargs)
734endif
735sndio = not_found
736if not get_option('sndio').auto() or have_system
737  sndio = dependency('sndio', required: get_option('sndio'),
738                    method: 'pkg-config', kwargs: static_kwargs)
739endif
740
741spice_protocol = not_found
742if not get_option('spice_protocol').auto() or have_system
743  spice_protocol = dependency('spice-protocol', version: '>=0.12.3',
744                              required: get_option('spice_protocol'),
745                              method: 'pkg-config', kwargs: static_kwargs)
746endif
747spice = not_found
748if not get_option('spice').auto() or have_system
749  spice = dependency('spice-server', version: '>=0.12.5',
750                     required: get_option('spice'),
751                     method: 'pkg-config', kwargs: static_kwargs)
752endif
753spice_headers = spice.partial_dependency(compile_args: true, includes: true)
754
755rt = cc.find_library('rt', required: false)
756
757libiscsi = not_found
758if not get_option('libiscsi').auto() or have_block
759  libiscsi = dependency('libiscsi', version: '>=1.9.0',
760                         required: get_option('libiscsi'),
761                         method: 'pkg-config', kwargs: static_kwargs)
762endif
763zstd = not_found
764if not get_option('zstd').auto() or have_block
765  zstd = dependency('libzstd', version: '>=1.4.0',
766                    required: get_option('zstd'),
767                    method: 'pkg-config', kwargs: static_kwargs)
768endif
769virgl = not_found
770
771have_vhost_user_gpu = have_tools and targetos == 'linux' and pixman.found()
772if not get_option('virglrenderer').auto() or have_system or have_vhost_user_gpu
773  virgl = dependency('virglrenderer',
774                     method: 'pkg-config',
775                     required: get_option('virglrenderer'),
776                     kwargs: static_kwargs)
777endif
778blkio = not_found
779if not get_option('blkio').auto() or have_block
780  blkio = dependency('blkio',
781                     method: 'pkg-config',
782                     required: get_option('blkio'),
783                     kwargs: static_kwargs)
784endif
785curl = not_found
786if not get_option('curl').auto() or have_block
787  curl = dependency('libcurl', version: '>=7.29.0',
788                    method: 'pkg-config',
789                    required: get_option('curl'),
790                    kwargs: static_kwargs)
791endif
792libudev = not_found
793if targetos == 'linux' and (have_system or have_tools)
794  libudev = dependency('libudev',
795                       method: 'pkg-config',
796                       required: get_option('libudev'),
797                       kwargs: static_kwargs)
798endif
799
800mpathlibs = [libudev]
801mpathpersist = not_found
802mpathpersist_new_api = false
803if targetos == 'linux' and have_tools and get_option('mpath').allowed()
804  mpath_test_source_new = '''
805    #include <libudev.h>
806    #include <mpath_persist.h>
807    unsigned mpath_mx_alloc_len = 1024;
808    int logsink;
809    static struct config *multipath_conf;
810    extern struct udev *udev;
811    extern struct config *get_multipath_config(void);
812    extern void put_multipath_config(struct config *conf);
813    struct udev *udev;
814    struct config *get_multipath_config(void) { return multipath_conf; }
815    void put_multipath_config(struct config *conf) { }
816    int main(void) {
817        udev = udev_new();
818        multipath_conf = mpath_lib_init();
819        return 0;
820    }'''
821  mpath_test_source_old = '''
822      #include <libudev.h>
823      #include <mpath_persist.h>
824      unsigned mpath_mx_alloc_len = 1024;
825      int logsink;
826      int main(void) {
827          struct udev *udev = udev_new();
828          mpath_lib_init(udev);
829          return 0;
830      }'''
831  libmpathpersist = cc.find_library('mpathpersist',
832                                    required: get_option('mpath'),
833                                    kwargs: static_kwargs)
834  if libmpathpersist.found()
835    mpathlibs += libmpathpersist
836    if enable_static
837      mpathlibs += cc.find_library('devmapper',
838                                     required: get_option('mpath'),
839                                     kwargs: static_kwargs)
840    endif
841    mpathlibs += cc.find_library('multipath',
842                                 required: get_option('mpath'),
843                                 kwargs: static_kwargs)
844    foreach lib: mpathlibs
845      if not lib.found()
846        mpathlibs = []
847        break
848      endif
849    endforeach
850    if mpathlibs.length() == 0
851      msg = 'Dependencies missing for libmpathpersist'
852    elif cc.links(mpath_test_source_new, dependencies: mpathlibs)
853      mpathpersist = declare_dependency(dependencies: mpathlibs)
854      mpathpersist_new_api = true
855    elif cc.links(mpath_test_source_old, dependencies: mpathlibs)
856      mpathpersist = declare_dependency(dependencies: mpathlibs)
857    else
858      msg = 'Cannot detect libmpathpersist API'
859    endif
860    if not mpathpersist.found()
861      if get_option('mpath').enabled()
862        error(msg)
863      else
864        warning(msg + ', disabling')
865      endif
866    endif
867  endif
868endif
869
870iconv = not_found
871curses = not_found
872if have_system and get_option('curses').allowed()
873  curses_test = '''
874    #if defined(__APPLE__) || defined(__OpenBSD__)
875    #define _XOPEN_SOURCE_EXTENDED 1
876    #endif
877    #include <locale.h>
878    #include <curses.h>
879    #include <wchar.h>
880    int main(void) {
881      wchar_t wch = L'w';
882      setlocale(LC_ALL, "");
883      resize_term(0, 0);
884      addwstr(L"wide chars\n");
885      addnwstr(&wch, 1);
886      add_wch(WACS_DEGREE);
887      return 0;
888    }'''
889
890  curses_dep_list = targetos == 'windows' ? ['ncurses', 'ncursesw'] : ['ncursesw']
891  curses = dependency(curses_dep_list,
892                      required: false,
893                      method: 'pkg-config',
894                      kwargs: static_kwargs)
895  msg = get_option('curses').enabled() ? 'curses library not found' : ''
896  curses_compile_args = ['-DNCURSES_WIDECHAR=1']
897  if curses.found()
898    if cc.links(curses_test, args: curses_compile_args, dependencies: [curses])
899      curses = declare_dependency(compile_args: curses_compile_args, dependencies: [curses])
900    else
901      msg = 'curses package not usable'
902      curses = not_found
903    endif
904  endif
905  if not curses.found()
906    has_curses_h = cc.has_header('curses.h', args: curses_compile_args)
907    if targetos != 'windows' and not has_curses_h
908      message('Trying with /usr/include/ncursesw')
909      curses_compile_args += ['-I/usr/include/ncursesw']
910      has_curses_h = cc.has_header('curses.h', args: curses_compile_args)
911    endif
912    if has_curses_h
913      curses_libname_list = (targetos == 'windows' ? ['pdcurses'] : ['ncursesw', 'cursesw'])
914      foreach curses_libname : curses_libname_list
915        libcurses = cc.find_library(curses_libname,
916                                    required: false,
917                                    kwargs: static_kwargs)
918        if libcurses.found()
919          if cc.links(curses_test, args: curses_compile_args, dependencies: libcurses)
920            curses = declare_dependency(compile_args: curses_compile_args,
921                                        dependencies: [libcurses])
922            break
923          else
924            msg = 'curses library not usable'
925          endif
926        endif
927      endforeach
928    endif
929  endif
930  if get_option('iconv').allowed()
931    foreach link_args : [ ['-liconv'], [] ]
932      # Programs will be linked with glib and this will bring in libiconv on FreeBSD.
933      # We need to use libiconv if available because mixing libiconv's headers with
934      # the system libc does not work.
935      # However, without adding glib to the dependencies -L/usr/local/lib will not be
936      # included in the command line and libiconv will not be found.
937      if cc.links('''
938        #include <iconv.h>
939        int main(void) {
940          iconv_t conv = iconv_open("WCHAR_T", "UCS-2");
941          return conv != (iconv_t) -1;
942        }''', args: config_host['GLIB_CFLAGS'].split() + config_host['GLIB_LIBS'].split() + link_args)
943        iconv = declare_dependency(link_args: link_args, dependencies: glib)
944        break
945      endif
946    endforeach
947  endif
948  if curses.found() and not iconv.found()
949    if get_option('iconv').enabled()
950      error('iconv not available')
951    endif
952    msg = 'iconv required for curses UI but not available'
953    curses = not_found
954  endif
955  if not curses.found() and msg != ''
956    if get_option('curses').enabled()
957      error(msg)
958    else
959      warning(msg + ', disabling')
960    endif
961  endif
962endif
963
964brlapi = not_found
965if not get_option('brlapi').auto() or have_system
966  brlapi = cc.find_library('brlapi', has_headers: ['brlapi.h'],
967                         required: get_option('brlapi'),
968                         kwargs: static_kwargs)
969  if brlapi.found() and not cc.links('''
970     #include <brlapi.h>
971     #include <stddef.h>
972     int main(void) { return brlapi__openConnection (NULL, NULL, NULL); }''', dependencies: brlapi)
973    brlapi = not_found
974    if get_option('brlapi').enabled()
975      error('could not link brlapi')
976    else
977      warning('could not link brlapi, disabling')
978    endif
979  endif
980endif
981
982sdl = not_found
983if not get_option('sdl').auto() or have_system
984  sdl = dependency('sdl2', required: get_option('sdl'), kwargs: static_kwargs)
985  sdl_image = not_found
986endif
987if sdl.found()
988  # work around 2.0.8 bug
989  sdl = declare_dependency(compile_args: '-Wno-undef',
990                           dependencies: sdl)
991  sdl_image = dependency('SDL2_image', required: get_option('sdl_image'),
992                         method: 'pkg-config', kwargs: static_kwargs)
993else
994  if get_option('sdl_image').enabled()
995    error('sdl-image required, but SDL was @0@'.format(
996          get_option('sdl').disabled() ? 'disabled' : 'not found'))
997  endif
998  sdl_image = not_found
999endif
1000
1001rbd = not_found
1002if not get_option('rbd').auto() or have_block
1003  librados = cc.find_library('rados', required: get_option('rbd'),
1004                             kwargs: static_kwargs)
1005  librbd = cc.find_library('rbd', has_headers: ['rbd/librbd.h'],
1006                           required: get_option('rbd'),
1007                           kwargs: static_kwargs)
1008  if librados.found() and librbd.found()
1009    if cc.links('''
1010      #include <stdio.h>
1011      #include <rbd/librbd.h>
1012      int main(void) {
1013        rados_t cluster;
1014        rados_create(&cluster, NULL);
1015        #if LIBRBD_VERSION_CODE < LIBRBD_VERSION(1, 12, 0)
1016        #error
1017        #endif
1018        return 0;
1019      }''', dependencies: [librbd, librados])
1020      rbd = declare_dependency(dependencies: [librbd, librados])
1021    elif get_option('rbd').enabled()
1022      error('librbd >= 1.12.0 required')
1023    else
1024      warning('librbd >= 1.12.0 not found, disabling')
1025    endif
1026  endif
1027endif
1028
1029glusterfs = not_found
1030glusterfs_ftruncate_has_stat = false
1031glusterfs_iocb_has_stat = false
1032if not get_option('glusterfs').auto() or have_block
1033  glusterfs = dependency('glusterfs-api', version: '>=3',
1034                         required: get_option('glusterfs'),
1035                         method: 'pkg-config', kwargs: static_kwargs)
1036  if glusterfs.found()
1037    glusterfs_ftruncate_has_stat = cc.links('''
1038      #include <glusterfs/api/glfs.h>
1039
1040      int
1041      main(void)
1042      {
1043          /* new glfs_ftruncate() passes two additional args */
1044          return glfs_ftruncate(NULL, 0, NULL, NULL);
1045      }
1046    ''', dependencies: glusterfs)
1047    glusterfs_iocb_has_stat = cc.links('''
1048      #include <glusterfs/api/glfs.h>
1049
1050      /* new glfs_io_cbk() passes two additional glfs_stat structs */
1051      static void
1052      glusterfs_iocb(glfs_fd_t *fd, ssize_t ret, struct glfs_stat *prestat, struct glfs_stat *poststat, void *data)
1053      {}
1054
1055      int
1056      main(void)
1057      {
1058          glfs_io_cbk iocb = &glusterfs_iocb;
1059          iocb(NULL, 0 , NULL, NULL, NULL);
1060          return 0;
1061      }
1062    ''', dependencies: glusterfs)
1063  endif
1064endif
1065
1066libssh = not_found
1067if not get_option('libssh').auto() or have_block
1068  libssh = dependency('libssh', version: '>=0.8.7',
1069                    method: 'pkg-config',
1070                    required: get_option('libssh'),
1071                    kwargs: static_kwargs)
1072endif
1073
1074libbzip2 = not_found
1075if not get_option('bzip2').auto() or have_block
1076  libbzip2 = cc.find_library('bz2', has_headers: ['bzlib.h'],
1077                             required: get_option('bzip2'),
1078                             kwargs: static_kwargs)
1079  if libbzip2.found() and not cc.links('''
1080     #include <bzlib.h>
1081     int main(void) { BZ2_bzlibVersion(); return 0; }''', dependencies: libbzip2)
1082    libbzip2 = not_found
1083    if get_option('bzip2').enabled()
1084      error('could not link libbzip2')
1085    else
1086      warning('could not link libbzip2, disabling')
1087    endif
1088  endif
1089endif
1090
1091liblzfse = not_found
1092if not get_option('lzfse').auto() or have_block
1093  liblzfse = cc.find_library('lzfse', has_headers: ['lzfse.h'],
1094                             required: get_option('lzfse'),
1095                             kwargs: static_kwargs)
1096endif
1097if liblzfse.found() and not cc.links('''
1098   #include <lzfse.h>
1099   int main(void) { lzfse_decode_scratch_size(); return 0; }''', dependencies: liblzfse)
1100  liblzfse = not_found
1101  if get_option('lzfse').enabled()
1102    error('could not link liblzfse')
1103  else
1104    warning('could not link liblzfse, disabling')
1105  endif
1106endif
1107
1108oss = not_found
1109if get_option('oss').allowed() and have_system
1110  if not cc.has_header('sys/soundcard.h')
1111    # not found
1112  elif targetos == 'netbsd'
1113    oss = cc.find_library('ossaudio', required: get_option('oss'),
1114                          kwargs: static_kwargs)
1115  else
1116    oss = declare_dependency()
1117  endif
1118
1119  if not oss.found()
1120    if get_option('oss').enabled()
1121      error('OSS not found')
1122    endif
1123  endif
1124endif
1125dsound = not_found
1126if not get_option('dsound').auto() or (targetos == 'windows' and have_system)
1127  if cc.has_header('dsound.h')
1128    dsound = declare_dependency(link_args: ['-lole32', '-ldxguid'])
1129  endif
1130
1131  if not dsound.found()
1132    if get_option('dsound').enabled()
1133      error('DirectSound not found')
1134    endif
1135  endif
1136endif
1137
1138coreaudio = not_found
1139if not get_option('coreaudio').auto() or (targetos == 'darwin' and have_system)
1140  coreaudio = dependency('appleframeworks', modules: 'CoreAudio',
1141                         required: get_option('coreaudio'))
1142endif
1143
1144opengl = not_found
1145if not get_option('opengl').auto() or have_system or have_vhost_user_gpu
1146  epoxy = dependency('epoxy', method: 'pkg-config',
1147                      required: get_option('opengl'), kwargs: static_kwargs)
1148  if cc.has_header('epoxy/egl.h', dependencies: epoxy)
1149    opengl = epoxy
1150  elif get_option('opengl').enabled()
1151    error('epoxy/egl.h not found')
1152  endif
1153endif
1154gbm = not_found
1155if (have_system or have_tools) and (virgl.found() or opengl.found())
1156  gbm = dependency('gbm', method: 'pkg-config', required: false,
1157                   kwargs: static_kwargs)
1158endif
1159have_vhost_user_gpu = have_vhost_user_gpu and virgl.found() and opengl.found() and gbm.found()
1160
1161gnutls = not_found
1162gnutls_crypto = not_found
1163if get_option('gnutls').enabled() or (get_option('gnutls').auto() and have_system)
1164  # For general TLS support our min gnutls matches
1165  # that implied by our platform support matrix
1166  #
1167  # For the crypto backends, we look for a newer
1168  # gnutls:
1169  #
1170  #   Version 3.6.8  is needed to get XTS
1171  #   Version 3.6.13 is needed to get PBKDF
1172  #   Version 3.6.14 is needed to get HW accelerated XTS
1173  #
1174  # If newer enough gnutls isn't available, we can
1175  # still use a different crypto backend to satisfy
1176  # the platform support requirements
1177  gnutls_crypto = dependency('gnutls', version: '>=3.6.14',
1178                             method: 'pkg-config',
1179                             required: false,
1180                             kwargs: static_kwargs)
1181  if gnutls_crypto.found()
1182    gnutls = gnutls_crypto
1183  else
1184    # Our min version if all we need is TLS
1185    gnutls = dependency('gnutls', version: '>=3.5.18',
1186                        method: 'pkg-config',
1187                        required: get_option('gnutls'),
1188                        kwargs: static_kwargs)
1189  endif
1190endif
1191
1192# We prefer use of gnutls for crypto, unless the options
1193# explicitly asked for nettle or gcrypt.
1194#
1195# If gnutls isn't available for crypto, then we'll prefer
1196# gcrypt over nettle for performance reasons.
1197gcrypt = not_found
1198nettle = not_found
1199hogweed = not_found
1200xts = 'none'
1201
1202if get_option('nettle').enabled() and get_option('gcrypt').enabled()
1203  error('Only one of gcrypt & nettle can be enabled')
1204endif
1205
1206# Explicit nettle/gcrypt request, so ignore gnutls for crypto
1207if get_option('nettle').enabled() or get_option('gcrypt').enabled()
1208  gnutls_crypto = not_found
1209endif
1210
1211if not gnutls_crypto.found()
1212  if (not get_option('gcrypt').auto() or have_system) and not get_option('nettle').enabled()
1213    gcrypt = dependency('libgcrypt', version: '>=1.8',
1214                        method: 'config-tool',
1215                        required: get_option('gcrypt'),
1216                        kwargs: static_kwargs)
1217    # Debian has removed -lgpg-error from libgcrypt-config
1218    # as it "spreads unnecessary dependencies" which in
1219    # turn breaks static builds...
1220    if gcrypt.found() and enable_static
1221      gcrypt = declare_dependency(dependencies: [
1222        gcrypt,
1223        cc.find_library('gpg-error', required: true, kwargs: static_kwargs)])
1224    endif
1225  endif
1226  if (not get_option('nettle').auto() or have_system) and not gcrypt.found()
1227    nettle = dependency('nettle', version: '>=3.4',
1228                        method: 'pkg-config',
1229                        required: get_option('nettle'),
1230                        kwargs: static_kwargs)
1231    if nettle.found() and not cc.has_header('nettle/xts.h', dependencies: nettle)
1232      xts = 'private'
1233    endif
1234  endif
1235endif
1236
1237gmp = dependency('gmp', required: false, method: 'pkg-config', kwargs: static_kwargs)
1238if nettle.found() and gmp.found()
1239  hogweed = dependency('hogweed', version: '>=3.4',
1240                       method: 'pkg-config',
1241                       required: get_option('nettle'),
1242                       kwargs: static_kwargs)
1243endif
1244
1245
1246gtk = not_found
1247gtkx11 = not_found
1248vte = not_found
1249if not get_option('gtk').auto() or have_system
1250  gtk = dependency('gtk+-3.0', version: '>=3.22.0',
1251                   method: 'pkg-config',
1252                   required: get_option('gtk'),
1253                   kwargs: static_kwargs)
1254  if gtk.found()
1255    gtkx11 = dependency('gtk+-x11-3.0', version: '>=3.22.0',
1256                        method: 'pkg-config',
1257                        required: false,
1258                        kwargs: static_kwargs)
1259    gtk = declare_dependency(dependencies: [gtk, gtkx11])
1260
1261    if not get_option('vte').auto() or have_system
1262      vte = dependency('vte-2.91',
1263                       method: 'pkg-config',
1264                       required: get_option('vte'),
1265                       kwargs: static_kwargs)
1266    endif
1267  endif
1268endif
1269
1270x11 = not_found
1271if gtkx11.found()
1272  x11 = dependency('x11', method: 'pkg-config', required: gtkx11.found(),
1273                   kwargs: static_kwargs)
1274endif
1275png = not_found
1276if get_option('png').allowed() and have_system
1277   png = dependency('libpng', version: '>=1.6.34', required: get_option('png'),
1278                    method: 'pkg-config', kwargs: static_kwargs)
1279endif
1280vnc = not_found
1281jpeg = not_found
1282sasl = not_found
1283if get_option('vnc').allowed() and have_system
1284  vnc = declare_dependency() # dummy dependency
1285  jpeg = dependency('libjpeg', required: get_option('vnc_jpeg'),
1286                    method: 'pkg-config', kwargs: static_kwargs)
1287  sasl = cc.find_library('sasl2', has_headers: ['sasl/sasl.h'],
1288                         required: get_option('vnc_sasl'),
1289                         kwargs: static_kwargs)
1290  if sasl.found()
1291    sasl = declare_dependency(dependencies: sasl,
1292                              compile_args: '-DSTRUCT_IOVEC_DEFINED')
1293  endif
1294endif
1295
1296pam = not_found
1297if not get_option('auth_pam').auto() or have_system
1298  pam = cc.find_library('pam', has_headers: ['security/pam_appl.h'],
1299                        required: get_option('auth_pam'),
1300                        kwargs: static_kwargs)
1301endif
1302if pam.found() and not cc.links('''
1303   #include <stddef.h>
1304   #include <security/pam_appl.h>
1305   int main(void) {
1306     const char *service_name = "qemu";
1307     const char *user = "frank";
1308     const struct pam_conv pam_conv = { 0 };
1309     pam_handle_t *pamh = NULL;
1310     pam_start(service_name, user, &pam_conv, &pamh);
1311     return 0;
1312   }''', dependencies: pam)
1313  pam = not_found
1314  if get_option('auth_pam').enabled()
1315    error('could not link libpam')
1316  else
1317    warning('could not link libpam, disabling')
1318  endif
1319endif
1320
1321snappy = not_found
1322if not get_option('snappy').auto() or have_system
1323  snappy = cc.find_library('snappy', has_headers: ['snappy-c.h'],
1324                           required: get_option('snappy'),
1325                           kwargs: static_kwargs)
1326endif
1327if snappy.found() and not linker.links('''
1328   #include <snappy-c.h>
1329   int main(void) { snappy_max_compressed_length(4096); return 0; }''', dependencies: snappy)
1330  snappy = not_found
1331  if get_option('snappy').enabled()
1332    error('could not link libsnappy')
1333  else
1334    warning('could not link libsnappy, disabling')
1335  endif
1336endif
1337
1338lzo = not_found
1339if not get_option('lzo').auto() or have_system
1340  lzo = cc.find_library('lzo2', has_headers: ['lzo/lzo1x.h'],
1341                        required: get_option('lzo'),
1342                        kwargs: static_kwargs)
1343endif
1344if lzo.found() and not cc.links('''
1345   #include <lzo/lzo1x.h>
1346   int main(void) { lzo_version(); return 0; }''', dependencies: lzo)
1347  lzo = not_found
1348  if get_option('lzo').enabled()
1349    error('could not link liblzo2')
1350  else
1351    warning('could not link liblzo2, disabling')
1352  endif
1353endif
1354
1355numa = not_found
1356if not get_option('numa').auto() or have_system or have_tools
1357  numa = cc.find_library('numa', has_headers: ['numa.h'],
1358                              required: get_option('numa'),
1359                              kwargs: static_kwargs)
1360endif
1361if numa.found() and not cc.links('''
1362   #include <numa.h>
1363   int main(void) { return numa_available(); }
1364   ''', dependencies: numa)
1365  numa = not_found
1366  if get_option('numa').enabled()
1367    error('could not link numa')
1368  else
1369    warning('could not link numa, disabling')
1370  endif
1371endif
1372
1373rdma = not_found
1374if not get_option('rdma').auto() or have_system
1375  libumad = cc.find_library('ibumad', required: get_option('rdma'))
1376  rdma_libs = [cc.find_library('rdmacm', has_headers: ['rdma/rdma_cma.h'],
1377                               required: get_option('rdma'),
1378                               kwargs: static_kwargs),
1379               cc.find_library('ibverbs', required: get_option('rdma'),
1380                               kwargs: static_kwargs),
1381               libumad]
1382  rdma = declare_dependency(dependencies: rdma_libs)
1383  foreach lib: rdma_libs
1384    if not lib.found()
1385      rdma = not_found
1386    endif
1387  endforeach
1388endif
1389
1390xen = not_found
1391if get_option('xen').enabled() or (get_option('xen').auto() and have_system)
1392  xencontrol = dependency('xencontrol', required: false,
1393                          method: 'pkg-config', kwargs: static_kwargs)
1394  if xencontrol.found()
1395    xen_pc = declare_dependency(version: xencontrol.version(),
1396      dependencies: [
1397        xencontrol,
1398        # disabler: true makes xen_pc.found() return false if any is not found
1399        dependency('xenstore', required: false,
1400                   method: 'pkg-config', kwargs: static_kwargs,
1401                   disabler: true),
1402        dependency('xenforeignmemory', required: false,
1403                   method: 'pkg-config', kwargs: static_kwargs,
1404                   disabler: true),
1405        dependency('xengnttab', required: false,
1406                   method: 'pkg-config', kwargs: static_kwargs,
1407                   disabler: true),
1408        dependency('xenevtchn', required: false,
1409                   method: 'pkg-config', kwargs: static_kwargs,
1410                   disabler: true),
1411        dependency('xendevicemodel', required: false,
1412                   method: 'pkg-config', kwargs: static_kwargs,
1413                   disabler: true),
1414        # optional, no "disabler: true"
1415        dependency('xentoolcore', required: false,
1416                   method: 'pkg-config', kwargs: static_kwargs)])
1417    if xen_pc.found()
1418      xen = xen_pc
1419    endif
1420  endif
1421  if not xen.found()
1422    xen_tests = [ '4.11.0', '4.10.0', '4.9.0', '4.8.0', '4.7.1', '4.6.0', '4.5.0', '4.2.0' ]
1423    xen_libs = {
1424      '4.11.0': [ 'xenstore', 'xenctrl', 'xendevicemodel', 'xenforeignmemory', 'xengnttab', 'xenevtchn', 'xentoolcore' ],
1425      '4.10.0': [ 'xenstore', 'xenctrl', 'xendevicemodel', 'xenforeignmemory', 'xengnttab', 'xenevtchn', 'xentoolcore' ],
1426      '4.9.0': [ 'xenstore', 'xenctrl', 'xendevicemodel', 'xenforeignmemory', 'xengnttab', 'xenevtchn' ],
1427      '4.8.0': [ 'xenstore', 'xenctrl', 'xenforeignmemory', 'xengnttab', 'xenevtchn' ],
1428      '4.7.1': [ 'xenstore', 'xenctrl', 'xenforeignmemory', 'xengnttab', 'xenevtchn' ],
1429      '4.6.0': [ 'xenstore', 'xenctrl' ],
1430      '4.5.0': [ 'xenstore', 'xenctrl' ],
1431      '4.2.0': [ 'xenstore', 'xenctrl' ],
1432    }
1433    xen_deps = {}
1434    foreach ver: xen_tests
1435      # cache the various library tests to avoid polluting the logs
1436      xen_test_deps = []
1437      foreach l: xen_libs[ver]
1438        if l not in xen_deps
1439          xen_deps += { l: cc.find_library(l, required: false) }
1440        endif
1441        xen_test_deps += xen_deps[l]
1442      endforeach
1443
1444      # Use -D to pick just one of the test programs in scripts/xen-detect.c
1445      xen_version = ver.split('.')
1446      xen_ctrl_version = xen_version[0] + \
1447        ('0' + xen_version[1]).substring(-2) + \
1448        ('0' + xen_version[2]).substring(-2)
1449      if cc.links(files('scripts/xen-detect.c'),
1450                  args: '-DCONFIG_XEN_CTRL_INTERFACE_VERSION=' + xen_ctrl_version,
1451                  dependencies: xen_test_deps)
1452        xen = declare_dependency(version: ver, dependencies: xen_test_deps)
1453        break
1454      endif
1455    endforeach
1456  endif
1457  if xen.found()
1458    accelerators += 'CONFIG_XEN'
1459  elif get_option('xen').enabled()
1460    error('could not compile and link Xen test program')
1461  endif
1462endif
1463have_xen_pci_passthrough = get_option('xen_pci_passthrough') \
1464  .require(xen.found(),
1465           error_message: 'Xen PCI passthrough requested but Xen not enabled') \
1466  .require(targetos == 'linux',
1467           error_message: 'Xen PCI passthrough not available on this platform') \
1468  .allowed()
1469
1470
1471cacard = not_found
1472if not get_option('smartcard').auto() or have_system
1473  cacard = dependency('libcacard', required: get_option('smartcard'),
1474                      version: '>=2.5.1', method: 'pkg-config',
1475                      kwargs: static_kwargs)
1476endif
1477u2f = not_found
1478if have_system
1479  u2f = dependency('u2f-emu', required: get_option('u2f'),
1480                   method: 'pkg-config',
1481                   kwargs: static_kwargs)
1482endif
1483canokey = not_found
1484if have_system
1485  canokey = dependency('canokey-qemu', required: get_option('canokey'),
1486                   method: 'pkg-config',
1487                   kwargs: static_kwargs)
1488endif
1489usbredir = not_found
1490if not get_option('usb_redir').auto() or have_system
1491  usbredir = dependency('libusbredirparser-0.5', required: get_option('usb_redir'),
1492                        version: '>=0.6', method: 'pkg-config',
1493                        kwargs: static_kwargs)
1494endif
1495libusb = not_found
1496if not get_option('libusb').auto() or have_system
1497  libusb = dependency('libusb-1.0', required: get_option('libusb'),
1498                      version: '>=1.0.13', method: 'pkg-config',
1499                      kwargs: static_kwargs)
1500endif
1501
1502libpmem = not_found
1503if not get_option('libpmem').auto() or have_system
1504  libpmem = dependency('libpmem', required: get_option('libpmem'),
1505                       method: 'pkg-config', kwargs: static_kwargs)
1506endif
1507libdaxctl = not_found
1508if not get_option('libdaxctl').auto() or have_system
1509  libdaxctl = dependency('libdaxctl', required: get_option('libdaxctl'),
1510                         version: '>=57', method: 'pkg-config',
1511                         kwargs: static_kwargs)
1512endif
1513tasn1 = not_found
1514if gnutls.found()
1515  tasn1 = dependency('libtasn1',
1516                     method: 'pkg-config',
1517                     kwargs: static_kwargs)
1518endif
1519keyutils = dependency('libkeyutils', required: false,
1520                      method: 'pkg-config', kwargs: static_kwargs)
1521
1522has_gettid = cc.has_function('gettid')
1523
1524# libselinux
1525selinux = dependency('libselinux',
1526                     required: get_option('selinux'),
1527                     method: 'pkg-config', kwargs: static_kwargs)
1528
1529# Malloc tests
1530
1531malloc = []
1532if get_option('malloc') == 'system'
1533  has_malloc_trim = \
1534    get_option('malloc_trim').allowed() and \
1535    cc.links('''#include <malloc.h>
1536                int main(void) { malloc_trim(0); return 0; }''')
1537else
1538  has_malloc_trim = false
1539  malloc = cc.find_library(get_option('malloc'), required: true)
1540endif
1541if not has_malloc_trim and get_option('malloc_trim').enabled()
1542  if get_option('malloc') == 'system'
1543    error('malloc_trim not available on this platform.')
1544  else
1545    error('malloc_trim not available with non-libc memory allocator')
1546  endif
1547endif
1548
1549# Check whether the glibc provides statx()
1550
1551gnu_source_prefix = '''
1552  #ifndef _GNU_SOURCE
1553  #define _GNU_SOURCE
1554  #endif
1555'''
1556statx_test = gnu_source_prefix + '''
1557  #include <sys/stat.h>
1558  int main(void) {
1559    struct statx statxbuf;
1560    statx(0, "", 0, STATX_BASIC_STATS, &statxbuf);
1561    return 0;
1562  }'''
1563
1564has_statx = cc.links(statx_test)
1565
1566# Check whether statx() provides mount ID information
1567
1568statx_mnt_id_test = gnu_source_prefix + '''
1569  #include <sys/stat.h>
1570  int main(void) {
1571    struct statx statxbuf;
1572    statx(0, "", 0, STATX_BASIC_STATS | STATX_MNT_ID, &statxbuf);
1573    return statxbuf.stx_mnt_id;
1574  }'''
1575
1576has_statx_mnt_id = cc.links(statx_mnt_id_test)
1577
1578have_vhost_user_blk_server = get_option('vhost_user_blk_server') \
1579  .require(targetos == 'linux',
1580           error_message: 'vhost_user_blk_server requires linux') \
1581  .require(have_vhost_user,
1582           error_message: 'vhost_user_blk_server requires vhost-user support') \
1583  .disable_auto_if(not have_tools and not have_system) \
1584  .allowed()
1585
1586if get_option('fuse').disabled() and get_option('fuse_lseek').enabled()
1587  error('Cannot enable fuse-lseek while fuse is disabled')
1588endif
1589
1590fuse = dependency('fuse3', required: get_option('fuse'),
1591                  version: '>=3.1', method: 'pkg-config',
1592                  kwargs: static_kwargs)
1593
1594fuse_lseek = not_found
1595if get_option('fuse_lseek').allowed()
1596  if fuse.version().version_compare('>=3.8')
1597    # Dummy dependency
1598    fuse_lseek = declare_dependency()
1599  elif get_option('fuse_lseek').enabled()
1600    if fuse.found()
1601      error('fuse-lseek requires libfuse >=3.8, found ' + fuse.version())
1602    else
1603      error('fuse-lseek requires libfuse, which was not found')
1604    endif
1605  endif
1606endif
1607
1608have_libvduse = (targetos == 'linux')
1609if get_option('libvduse').enabled()
1610    if targetos != 'linux'
1611        error('libvduse requires linux')
1612    endif
1613elif get_option('libvduse').disabled()
1614    have_libvduse = false
1615endif
1616
1617have_vduse_blk_export = (have_libvduse and targetos == 'linux')
1618if get_option('vduse_blk_export').enabled()
1619    if targetos != 'linux'
1620        error('vduse_blk_export requires linux')
1621    elif not have_libvduse
1622        error('vduse_blk_export requires libvduse support')
1623    endif
1624elif get_option('vduse_blk_export').disabled()
1625    have_vduse_blk_export = false
1626endif
1627
1628# libbpf
1629libbpf = dependency('libbpf', required: get_option('bpf'), method: 'pkg-config')
1630if libbpf.found() and not cc.links('''
1631   #include <bpf/libbpf.h>
1632   int main(void)
1633   {
1634     bpf_object__destroy_skeleton(NULL);
1635     return 0;
1636   }''', dependencies: libbpf)
1637  libbpf = not_found
1638  if get_option('bpf').enabled()
1639    error('libbpf skeleton test failed')
1640  else
1641    warning('libbpf skeleton test failed, disabling')
1642  endif
1643endif
1644
1645#################
1646# config-host.h #
1647#################
1648
1649audio_drivers_selected = []
1650if have_system
1651  audio_drivers_available = {
1652    'alsa': alsa.found(),
1653    'coreaudio': coreaudio.found(),
1654    'dsound': dsound.found(),
1655    'jack': jack.found(),
1656    'oss': oss.found(),
1657    'pa': pulse.found(),
1658    'sdl': sdl.found(),
1659    'sndio': sndio.found(),
1660  }
1661  foreach k, v: audio_drivers_available
1662    config_host_data.set('CONFIG_AUDIO_' + k.to_upper(), v)
1663  endforeach
1664
1665  # Default to native drivers first, OSS second, SDL third
1666  audio_drivers_priority = \
1667    [ 'pa', 'coreaudio', 'dsound', 'sndio', 'oss' ] + \
1668    (targetos == 'linux' ? [] : [ 'sdl' ])
1669  audio_drivers_default = []
1670  foreach k: audio_drivers_priority
1671    if audio_drivers_available[k]
1672      audio_drivers_default += k
1673    endif
1674  endforeach
1675
1676  foreach k: get_option('audio_drv_list')
1677    if k == 'default'
1678      audio_drivers_selected += audio_drivers_default
1679    elif not audio_drivers_available[k]
1680      error('Audio driver "@0@" not available.'.format(k))
1681    else
1682      audio_drivers_selected += k
1683    endif
1684  endforeach
1685endif
1686config_host_data.set('CONFIG_AUDIO_DRIVERS',
1687                     '"' + '", "'.join(audio_drivers_selected) + '", ')
1688
1689if get_option('cfi')
1690  cfi_flags=[]
1691  # Check for dependency on LTO
1692  if not get_option('b_lto')
1693    error('Selected Control-Flow Integrity but LTO is disabled')
1694  endif
1695  if config_host.has_key('CONFIG_MODULES')
1696    error('Selected Control-Flow Integrity is not compatible with modules')
1697  endif
1698  # Check for cfi flags. CFI requires LTO so we can't use
1699  # get_supported_arguments, but need a more complex "compiles" which allows
1700  # custom arguments
1701  if cc.compiles('int main () { return 0; }', name: '-fsanitize=cfi-icall',
1702                 args: ['-flto', '-fsanitize=cfi-icall'] )
1703    cfi_flags += '-fsanitize=cfi-icall'
1704  else
1705    error('-fsanitize=cfi-icall is not supported by the compiler')
1706  endif
1707  if cc.compiles('int main () { return 0; }',
1708                 name: '-fsanitize-cfi-icall-generalize-pointers',
1709                 args: ['-flto', '-fsanitize=cfi-icall',
1710                        '-fsanitize-cfi-icall-generalize-pointers'] )
1711    cfi_flags += '-fsanitize-cfi-icall-generalize-pointers'
1712  else
1713    error('-fsanitize-cfi-icall-generalize-pointers is not supported by the compiler')
1714  endif
1715  if get_option('cfi_debug')
1716    if cc.compiles('int main () { return 0; }',
1717                   name: '-fno-sanitize-trap=cfi-icall',
1718                   args: ['-flto', '-fsanitize=cfi-icall',
1719                          '-fno-sanitize-trap=cfi-icall'] )
1720      cfi_flags += '-fno-sanitize-trap=cfi-icall'
1721    else
1722      error('-fno-sanitize-trap=cfi-icall is not supported by the compiler')
1723    endif
1724  endif
1725  add_global_arguments(cfi_flags, native: false, language: ['c', 'cpp', 'objc'])
1726  add_global_link_arguments(cfi_flags, native: false, language: ['c', 'cpp', 'objc'])
1727endif
1728
1729have_host_block_device = (targetos != 'darwin' or
1730    cc.has_header('IOKit/storage/IOMedia.h'))
1731
1732dbus_display = get_option('dbus_display') \
1733  .require(gio.version().version_compare('>=2.64'),
1734           error_message: '-display dbus requires glib>=2.64') \
1735  .require(gdbus_codegen.found(),
1736           error_message: gdbus_codegen_error.format('-display dbus')) \
1737  .require(opengl.found() and gbm.found(),
1738           error_message: '-display dbus requires epoxy/egl and gbm') \
1739  .allowed()
1740
1741have_virtfs = get_option('virtfs') \
1742    .require(targetos == 'linux' or targetos == 'darwin',
1743             error_message: 'virtio-9p (virtfs) requires Linux or macOS') \
1744    .require(targetos == 'linux' or cc.has_function('pthread_fchdir_np'),
1745             error_message: 'virtio-9p (virtfs) on macOS requires the presence of pthread_fchdir_np') \
1746    .require(targetos == 'darwin' or (libattr.found() and libcap_ng.found()),
1747             error_message: 'virtio-9p (virtfs) on Linux requires libcap-ng-devel and libattr-devel') \
1748    .disable_auto_if(not have_tools and not have_system) \
1749    .allowed()
1750
1751have_virtfs_proxy_helper = targetos != 'darwin' and have_virtfs and have_tools
1752
1753if get_option('block_drv_ro_whitelist') == ''
1754  config_host_data.set('CONFIG_BDRV_RO_WHITELIST', '')
1755else
1756  config_host_data.set('CONFIG_BDRV_RO_WHITELIST',
1757        '"' + get_option('block_drv_ro_whitelist').replace(',', '", "') + '", ')
1758endif
1759if get_option('block_drv_rw_whitelist') == ''
1760  config_host_data.set('CONFIG_BDRV_RW_WHITELIST', '')
1761else
1762  config_host_data.set('CONFIG_BDRV_RW_WHITELIST',
1763        '"' + get_option('block_drv_rw_whitelist').replace(',', '", "') + '", ')
1764endif
1765
1766foreach k : get_option('trace_backends')
1767  config_host_data.set('CONFIG_TRACE_' + k.to_upper(), true)
1768endforeach
1769config_host_data.set_quoted('CONFIG_TRACE_FILE', get_option('trace_file'))
1770config_host_data.set_quoted('CONFIG_TLS_PRIORITY', get_option('tls_priority'))
1771if iasl.found()
1772  config_host_data.set_quoted('CONFIG_IASL', iasl.full_path())
1773endif
1774config_host_data.set_quoted('CONFIG_BINDIR', get_option('prefix') / get_option('bindir'))
1775config_host_data.set_quoted('CONFIG_PREFIX', get_option('prefix'))
1776config_host_data.set_quoted('CONFIG_QEMU_CONFDIR', get_option('prefix') / qemu_confdir)
1777config_host_data.set_quoted('CONFIG_QEMU_DATADIR', get_option('prefix') / qemu_datadir)
1778config_host_data.set_quoted('CONFIG_QEMU_DESKTOPDIR', get_option('prefix') / qemu_desktopdir)
1779
1780qemu_firmwarepath = ''
1781foreach k : get_option('qemu_firmwarepath')
1782  qemu_firmwarepath += '"' + get_option('prefix') / k + '", '
1783endforeach
1784config_host_data.set('CONFIG_QEMU_FIRMWAREPATH', qemu_firmwarepath)
1785
1786config_host_data.set_quoted('CONFIG_QEMU_HELPERDIR', get_option('prefix') / get_option('libexecdir'))
1787config_host_data.set_quoted('CONFIG_QEMU_ICONDIR', get_option('prefix') / qemu_icondir)
1788config_host_data.set_quoted('CONFIG_QEMU_LOCALEDIR', get_option('prefix') / get_option('localedir'))
1789config_host_data.set_quoted('CONFIG_QEMU_LOCALSTATEDIR', get_option('prefix') / get_option('localstatedir'))
1790config_host_data.set_quoted('CONFIG_QEMU_MODDIR', get_option('prefix') / qemu_moddir)
1791config_host_data.set_quoted('CONFIG_SYSCONFDIR', get_option('prefix') / get_option('sysconfdir'))
1792
1793if config_host.has_key('CONFIG_MODULES')
1794  config_host_data.set('CONFIG_STAMP', run_command(
1795      meson.current_source_dir() / 'scripts/qemu-stamp.py',
1796      meson.project_version(), get_option('pkgversion'), '--',
1797      meson.current_source_dir() / 'configure',
1798      capture: true, check: true).stdout().strip())
1799endif
1800
1801have_slirp_smbd = get_option('slirp_smbd') \
1802  .require(targetos != 'windows', error_message: 'Host smbd not supported on this platform.') \
1803  .allowed()
1804if have_slirp_smbd
1805  smbd_path = get_option('smbd')
1806  if smbd_path == ''
1807    smbd_path = (targetos == 'solaris' ? '/usr/sfw/sbin/smbd' : '/usr/sbin/smbd')
1808  endif
1809  config_host_data.set_quoted('CONFIG_SMBD_COMMAND', smbd_path)
1810endif
1811
1812config_host_data.set('HOST_' + host_arch.to_upper(), 1)
1813
1814if get_option('module_upgrades') and not enable_modules
1815  error('Cannot enable module-upgrades as modules are not enabled')
1816endif
1817config_host_data.set('CONFIG_MODULE_UPGRADES', get_option('module_upgrades'))
1818
1819config_host_data.set('CONFIG_ATTR', libattr.found())
1820config_host_data.set('CONFIG_BDRV_WHITELIST_TOOLS', get_option('block_drv_whitelist_in_tools'))
1821config_host_data.set('CONFIG_BRLAPI', brlapi.found())
1822config_host_data.set('CONFIG_COCOA', cocoa.found())
1823config_host_data.set('CONFIG_FUZZ', get_option('fuzzing'))
1824config_host_data.set('CONFIG_GCOV', get_option('b_coverage'))
1825config_host_data.set('CONFIG_LIBUDEV', libudev.found())
1826config_host_data.set('CONFIG_LZO', lzo.found())
1827config_host_data.set('CONFIG_MPATH', mpathpersist.found())
1828config_host_data.set('CONFIG_MPATH_NEW_API', mpathpersist_new_api)
1829config_host_data.set('CONFIG_BLKIO', blkio.found())
1830config_host_data.set('CONFIG_CURL', curl.found())
1831config_host_data.set('CONFIG_CURSES', curses.found())
1832config_host_data.set('CONFIG_GBM', gbm.found())
1833config_host_data.set('CONFIG_GIO', gio.found())
1834config_host_data.set('CONFIG_GLUSTERFS', glusterfs.found())
1835if glusterfs.found()
1836  config_host_data.set('CONFIG_GLUSTERFS_XLATOR_OPT', glusterfs.version().version_compare('>=4'))
1837  config_host_data.set('CONFIG_GLUSTERFS_DISCARD', glusterfs.version().version_compare('>=5'))
1838  config_host_data.set('CONFIG_GLUSTERFS_FALLOCATE', glusterfs.version().version_compare('>=6'))
1839  config_host_data.set('CONFIG_GLUSTERFS_ZEROFILL', glusterfs.version().version_compare('>=6'))
1840  config_host_data.set('CONFIG_GLUSTERFS_FTRUNCATE_HAS_STAT', glusterfs_ftruncate_has_stat)
1841  config_host_data.set('CONFIG_GLUSTERFS_IOCB_HAS_STAT', glusterfs_iocb_has_stat)
1842endif
1843config_host_data.set('CONFIG_GTK', gtk.found())
1844config_host_data.set('CONFIG_VTE', vte.found())
1845config_host_data.set('CONFIG_LIBATTR', have_old_libattr)
1846config_host_data.set('CONFIG_LIBCAP_NG', libcap_ng.found())
1847config_host_data.set('CONFIG_EBPF', libbpf.found())
1848config_host_data.set('CONFIG_LIBDAXCTL', libdaxctl.found())
1849config_host_data.set('CONFIG_LIBISCSI', libiscsi.found())
1850config_host_data.set('CONFIG_LIBNFS', libnfs.found())
1851config_host_data.set('CONFIG_LIBSSH', libssh.found())
1852config_host_data.set('CONFIG_LINUX_AIO', libaio.found())
1853config_host_data.set('CONFIG_LINUX_IO_URING', linux_io_uring.found())
1854config_host_data.set('CONFIG_LIBPMEM', libpmem.found())
1855config_host_data.set('CONFIG_NUMA', numa.found())
1856config_host_data.set('CONFIG_OPENGL', opengl.found())
1857config_host_data.set('CONFIG_PROFILER', get_option('profiler'))
1858config_host_data.set('CONFIG_RBD', rbd.found())
1859config_host_data.set('CONFIG_RDMA', rdma.found())
1860config_host_data.set('CONFIG_SDL', sdl.found())
1861config_host_data.set('CONFIG_SDL_IMAGE', sdl_image.found())
1862config_host_data.set('CONFIG_SECCOMP', seccomp.found())
1863if seccomp.found()
1864  config_host_data.set('CONFIG_SECCOMP_SYSRAWRC', seccomp_has_sysrawrc)
1865endif
1866config_host_data.set('CONFIG_SNAPPY', snappy.found())
1867config_host_data.set('CONFIG_TPM', have_tpm)
1868config_host_data.set('CONFIG_USB_LIBUSB', libusb.found())
1869config_host_data.set('CONFIG_VDE', vde.found())
1870config_host_data.set('CONFIG_VHOST_NET', have_vhost_net)
1871config_host_data.set('CONFIG_VHOST_NET_USER', have_vhost_net_user)
1872config_host_data.set('CONFIG_VHOST_NET_VDPA', have_vhost_net_vdpa)
1873config_host_data.set('CONFIG_VHOST_KERNEL', have_vhost_kernel)
1874config_host_data.set('CONFIG_VHOST_USER', have_vhost_user)
1875config_host_data.set('CONFIG_VHOST_CRYPTO', have_vhost_user_crypto)
1876config_host_data.set('CONFIG_VHOST_VDPA', have_vhost_vdpa)
1877config_host_data.set('CONFIG_VMNET', vmnet.found())
1878config_host_data.set('CONFIG_VHOST_USER_BLK_SERVER', have_vhost_user_blk_server)
1879config_host_data.set('CONFIG_VDUSE_BLK_EXPORT', have_vduse_blk_export)
1880config_host_data.set('CONFIG_PNG', png.found())
1881config_host_data.set('CONFIG_VNC', vnc.found())
1882config_host_data.set('CONFIG_VNC_JPEG', jpeg.found())
1883config_host_data.set('CONFIG_VNC_SASL', sasl.found())
1884config_host_data.set('CONFIG_VIRTFS', have_virtfs)
1885config_host_data.set('CONFIG_VTE', vte.found())
1886config_host_data.set('CONFIG_XKBCOMMON', xkbcommon.found())
1887config_host_data.set('CONFIG_KEYUTILS', keyutils.found())
1888config_host_data.set('CONFIG_GETTID', has_gettid)
1889config_host_data.set('CONFIG_GNUTLS', gnutls.found())
1890config_host_data.set('CONFIG_GNUTLS_CRYPTO', gnutls_crypto.found())
1891config_host_data.set('CONFIG_TASN1', tasn1.found())
1892config_host_data.set('CONFIG_GCRYPT', gcrypt.found())
1893config_host_data.set('CONFIG_NETTLE', nettle.found())
1894config_host_data.set('CONFIG_HOGWEED', hogweed.found())
1895config_host_data.set('CONFIG_QEMU_PRIVATE_XTS', xts == 'private')
1896config_host_data.set('CONFIG_MALLOC_TRIM', has_malloc_trim)
1897config_host_data.set('CONFIG_STATX', has_statx)
1898config_host_data.set('CONFIG_STATX_MNT_ID', has_statx_mnt_id)
1899config_host_data.set('CONFIG_ZSTD', zstd.found())
1900config_host_data.set('CONFIG_FUSE', fuse.found())
1901config_host_data.set('CONFIG_FUSE_LSEEK', fuse_lseek.found())
1902config_host_data.set('CONFIG_SPICE_PROTOCOL', spice_protocol.found())
1903if spice_protocol.found()
1904config_host_data.set('CONFIG_SPICE_PROTOCOL_MAJOR', spice_protocol.version().split('.')[0])
1905config_host_data.set('CONFIG_SPICE_PROTOCOL_MINOR', spice_protocol.version().split('.')[1])
1906config_host_data.set('CONFIG_SPICE_PROTOCOL_MICRO', spice_protocol.version().split('.')[2])
1907endif
1908config_host_data.set('CONFIG_SPICE', spice.found())
1909config_host_data.set('CONFIG_X11', x11.found())
1910config_host_data.set('CONFIG_DBUS_DISPLAY', dbus_display)
1911config_host_data.set('CONFIG_CFI', get_option('cfi'))
1912config_host_data.set('CONFIG_SELINUX', selinux.found())
1913config_host_data.set('CONFIG_XEN_BACKEND', xen.found())
1914if xen.found()
1915  # protect from xen.version() having less than three components
1916  xen_version = xen.version().split('.') + ['0', '0']
1917  xen_ctrl_version = xen_version[0] + \
1918    ('0' + xen_version[1]).substring(-2) + \
1919    ('0' + xen_version[2]).substring(-2)
1920  config_host_data.set('CONFIG_XEN_CTRL_INTERFACE_VERSION', xen_ctrl_version)
1921endif
1922config_host_data.set('QEMU_VERSION', '"@0@"'.format(meson.project_version()))
1923config_host_data.set('QEMU_VERSION_MAJOR', meson.project_version().split('.')[0])
1924config_host_data.set('QEMU_VERSION_MINOR', meson.project_version().split('.')[1])
1925config_host_data.set('QEMU_VERSION_MICRO', meson.project_version().split('.')[2])
1926
1927config_host_data.set_quoted('CONFIG_HOST_DSOSUF', host_dsosuf)
1928config_host_data.set('HAVE_HOST_BLOCK_DEVICE', have_host_block_device)
1929
1930have_coroutine_pool = get_option('coroutine_pool')
1931if get_option('debug_stack_usage') and have_coroutine_pool
1932  message('Disabling coroutine pool to measure stack usage')
1933  have_coroutine_pool = false
1934endif
1935config_host_data.set10('CONFIG_COROUTINE_POOL', have_coroutine_pool)
1936config_host_data.set('CONFIG_DEBUG_MUTEX', get_option('debug_mutex'))
1937config_host_data.set('CONFIG_DEBUG_STACK_USAGE', get_option('debug_stack_usage'))
1938config_host_data.set('CONFIG_GPROF', get_option('gprof'))
1939config_host_data.set('CONFIG_LIVE_BLOCK_MIGRATION', get_option('live_block_migration').allowed())
1940config_host_data.set('CONFIG_QOM_CAST_DEBUG', get_option('qom_cast_debug'))
1941config_host_data.set('CONFIG_REPLICATION', get_option('replication').allowed())
1942
1943# has_header
1944config_host_data.set('CONFIG_EPOLL', cc.has_header('sys/epoll.h'))
1945config_host_data.set('CONFIG_LINUX_MAGIC_H', cc.has_header('linux/magic.h'))
1946config_host_data.set('CONFIG_VALGRIND_H', cc.has_header('valgrind/valgrind.h'))
1947config_host_data.set('HAVE_BTRFS_H', cc.has_header('linux/btrfs.h'))
1948config_host_data.set('HAVE_DRM_H', cc.has_header('libdrm/drm.h'))
1949config_host_data.set('HAVE_PTY_H', cc.has_header('pty.h'))
1950config_host_data.set('HAVE_SYS_DISK_H', cc.has_header('sys/disk.h'))
1951config_host_data.set('HAVE_SYS_IOCCOM_H', cc.has_header('sys/ioccom.h'))
1952config_host_data.set('HAVE_SYS_KCOV_H', cc.has_header('sys/kcov.h'))
1953if targetos == 'windows'
1954  config_host_data.set('HAVE_AFUNIX_H', cc.has_header('afunix.h'))
1955endif
1956
1957# has_function
1958config_host_data.set('CONFIG_CLOSE_RANGE', cc.has_function('close_range'))
1959config_host_data.set('CONFIG_ACCEPT4', cc.has_function('accept4'))
1960config_host_data.set('CONFIG_CLOCK_ADJTIME', cc.has_function('clock_adjtime'))
1961config_host_data.set('CONFIG_DUP3', cc.has_function('dup3'))
1962config_host_data.set('CONFIG_FALLOCATE', cc.has_function('fallocate'))
1963config_host_data.set('CONFIG_POSIX_FALLOCATE', cc.has_function('posix_fallocate'))
1964# Note that we need to specify prefix: here to avoid incorrectly
1965# thinking that Windows has posix_memalign()
1966config_host_data.set('CONFIG_POSIX_MEMALIGN', cc.has_function('posix_memalign', prefix: '#include <stdlib.h>'))
1967config_host_data.set('CONFIG_ALIGNED_MALLOC', cc.has_function('_aligned_malloc'))
1968config_host_data.set('CONFIG_VALLOC', cc.has_function('valloc'))
1969config_host_data.set('CONFIG_MEMALIGN', cc.has_function('memalign'))
1970config_host_data.set('CONFIG_PPOLL', cc.has_function('ppoll'))
1971config_host_data.set('CONFIG_PREADV', cc.has_function('preadv', prefix: '#include <sys/uio.h>'))
1972config_host_data.set('CONFIG_PTHREAD_FCHDIR_NP', cc.has_function('pthread_fchdir_np'))
1973config_host_data.set('CONFIG_SENDFILE', cc.has_function('sendfile'))
1974config_host_data.set('CONFIG_SETNS', cc.has_function('setns') and cc.has_function('unshare'))
1975config_host_data.set('CONFIG_SYNCFS', cc.has_function('syncfs'))
1976config_host_data.set('CONFIG_SYNC_FILE_RANGE', cc.has_function('sync_file_range'))
1977config_host_data.set('CONFIG_TIMERFD', cc.has_function('timerfd_create'))
1978config_host_data.set('HAVE_COPY_FILE_RANGE', cc.has_function('copy_file_range'))
1979config_host_data.set('HAVE_GETIFADDRS', cc.has_function('getifaddrs'))
1980config_host_data.set('HAVE_OPENPTY', cc.has_function('openpty', dependencies: util))
1981config_host_data.set('HAVE_STRCHRNUL', cc.has_function('strchrnul'))
1982config_host_data.set('HAVE_SYSTEM_FUNCTION', cc.has_function('system', prefix: '#include <stdlib.h>'))
1983if rbd.found()
1984  config_host_data.set('HAVE_RBD_NAMESPACE_EXISTS',
1985                       cc.has_function('rbd_namespace_exists',
1986                                       dependencies: rbd,
1987                                       prefix: '#include <rbd/librbd.h>'))
1988endif
1989if rdma.found()
1990  config_host_data.set('HAVE_IBV_ADVISE_MR',
1991                       cc.has_function('ibv_advise_mr',
1992                                       dependencies: rdma,
1993                                       prefix: '#include <infiniband/verbs.h>'))
1994endif
1995
1996# has_header_symbol
1997config_host_data.set('CONFIG_BYTESWAP_H',
1998                     cc.has_header_symbol('byteswap.h', 'bswap_32'))
1999config_host_data.set('CONFIG_EPOLL_CREATE1',
2000                     cc.has_header_symbol('sys/epoll.h', 'epoll_create1'))
2001config_host_data.set('CONFIG_FALLOCATE_PUNCH_HOLE',
2002                     cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_PUNCH_HOLE') and
2003                     cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_KEEP_SIZE'))
2004config_host_data.set('CONFIG_FALLOCATE_ZERO_RANGE',
2005                     cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_ZERO_RANGE'))
2006config_host_data.set('CONFIG_FIEMAP',
2007                     cc.has_header('linux/fiemap.h') and
2008                     cc.has_header_symbol('linux/fs.h', 'FS_IOC_FIEMAP'))
2009config_host_data.set('CONFIG_GETRANDOM',
2010                     cc.has_function('getrandom') and
2011                     cc.has_header_symbol('sys/random.h', 'GRND_NONBLOCK'))
2012config_host_data.set('CONFIG_INOTIFY',
2013                     cc.has_header_symbol('sys/inotify.h', 'inotify_init'))
2014config_host_data.set('CONFIG_INOTIFY1',
2015                     cc.has_header_symbol('sys/inotify.h', 'inotify_init1'))
2016config_host_data.set('CONFIG_MACHINE_BSWAP_H',
2017                     cc.has_header_symbol('machine/bswap.h', 'bswap32',
2018                                          prefix: '''#include <sys/endian.h>
2019                                                     #include <sys/types.h>'''))
2020config_host_data.set('CONFIG_PRCTL_PR_SET_TIMERSLACK',
2021                     cc.has_header_symbol('sys/prctl.h', 'PR_SET_TIMERSLACK'))
2022config_host_data.set('CONFIG_RTNETLINK',
2023                     cc.has_header_symbol('linux/rtnetlink.h', 'IFLA_PROTO_DOWN'))
2024config_host_data.set('CONFIG_SYSMACROS',
2025                     cc.has_header_symbol('sys/sysmacros.h', 'makedev'))
2026config_host_data.set('HAVE_OPTRESET',
2027                     cc.has_header_symbol('getopt.h', 'optreset'))
2028config_host_data.set('HAVE_IPPROTO_MPTCP',
2029                     cc.has_header_symbol('netinet/in.h', 'IPPROTO_MPTCP'))
2030config_host_data.set('HAVE_SYS_MOUNT_FSCONFIG',
2031                     cc.has_header_symbol('sys/mount.h', 'FSCONFIG_SET_FLAG'))
2032
2033# has_member
2034config_host_data.set('HAVE_SIGEV_NOTIFY_THREAD_ID',
2035                     cc.has_member('struct sigevent', 'sigev_notify_thread_id',
2036                                   prefix: '#include <signal.h>'))
2037config_host_data.set('HAVE_STRUCT_STAT_ST_ATIM',
2038                     cc.has_member('struct stat', 'st_atim',
2039                                   prefix: '#include <sys/stat.h>'))
2040
2041# has_type
2042config_host_data.set('CONFIG_IOVEC',
2043                     cc.has_type('struct iovec',
2044                                 prefix: '#include <sys/uio.h>'))
2045config_host_data.set('HAVE_UTMPX',
2046                     cc.has_type('struct utmpx',
2047                                 prefix: '#include <utmpx.h>'))
2048
2049config_host_data.set('CONFIG_EVENTFD', cc.links('''
2050  #include <sys/eventfd.h>
2051  int main(void) { return eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); }'''))
2052config_host_data.set('CONFIG_FDATASYNC', cc.links(gnu_source_prefix + '''
2053  #include <unistd.h>
2054  int main(void) {
2055  #if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
2056  return fdatasync(0);
2057  #else
2058  #error Not supported
2059  #endif
2060  }'''))
2061
2062has_madvise = cc.links(gnu_source_prefix + '''
2063  #include <sys/types.h>
2064  #include <sys/mman.h>
2065  #include <stddef.h>
2066  int main(void) { return madvise(NULL, 0, MADV_DONTNEED); }''')
2067missing_madvise_proto = false
2068if has_madvise
2069  # Some platforms (illumos and Solaris before Solaris 11) provide madvise()
2070  # but forget to prototype it. In this case, has_madvise will be true (the
2071  # test program links despite a compile warning). To detect the
2072  # missing-prototype case, we try again with a definitely-bogus prototype.
2073  # This will only compile if the system headers don't provide the prototype;
2074  # otherwise the conflicting prototypes will cause a compiler error.
2075  missing_madvise_proto = cc.links(gnu_source_prefix + '''
2076    #include <sys/types.h>
2077    #include <sys/mman.h>
2078    #include <stddef.h>
2079    extern int madvise(int);
2080    int main(void) { return madvise(0); }''')
2081endif
2082config_host_data.set('CONFIG_MADVISE', has_madvise)
2083config_host_data.set('HAVE_MADVISE_WITHOUT_PROTOTYPE', missing_madvise_proto)
2084
2085config_host_data.set('CONFIG_MEMFD', cc.links(gnu_source_prefix + '''
2086  #include <sys/mman.h>
2087  int main(void) { return memfd_create("foo", MFD_ALLOW_SEALING); }'''))
2088config_host_data.set('CONFIG_OPEN_BY_HANDLE', cc.links(gnu_source_prefix + '''
2089  #include <fcntl.h>
2090  #if !defined(AT_EMPTY_PATH)
2091  # error missing definition
2092  #else
2093  int main(void) { struct file_handle fh; return open_by_handle_at(0, &fh, 0); }
2094  #endif'''))
2095config_host_data.set('CONFIG_POSIX_MADVISE', cc.links(gnu_source_prefix + '''
2096  #include <sys/mman.h>
2097  #include <stddef.h>
2098  int main(void) { return posix_madvise(NULL, 0, POSIX_MADV_DONTNEED); }'''))
2099
2100config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_W_TID', cc.links(gnu_source_prefix + '''
2101  #include <pthread.h>
2102
2103  static void *f(void *p) { return NULL; }
2104  int main(void)
2105  {
2106    pthread_t thread;
2107    pthread_create(&thread, 0, f, 0);
2108    pthread_setname_np(thread, "QEMU");
2109    return 0;
2110  }''', dependencies: threads))
2111config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_WO_TID', cc.links(gnu_source_prefix + '''
2112  #include <pthread.h>
2113
2114  static void *f(void *p) { pthread_setname_np("QEMU"); return NULL; }
2115  int main(void)
2116  {
2117    pthread_t thread;
2118    pthread_create(&thread, 0, f, 0);
2119    return 0;
2120  }''', dependencies: threads))
2121config_host_data.set('CONFIG_PTHREAD_CONDATTR_SETCLOCK', cc.links(gnu_source_prefix + '''
2122  #include <pthread.h>
2123  #include <time.h>
2124
2125  int main(void)
2126  {
2127    pthread_condattr_t attr
2128    pthread_condattr_init(&attr);
2129    pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
2130    return 0;
2131  }''', dependencies: threads))
2132config_host_data.set('CONFIG_PTHREAD_AFFINITY_NP', cc.links(gnu_source_prefix + '''
2133  #include <pthread.h>
2134
2135  static void *f(void *p) { return NULL; }
2136  int main(void)
2137  {
2138    int setsize = CPU_ALLOC_SIZE(64);
2139    pthread_t thread;
2140    cpu_set_t *cpuset;
2141    pthread_create(&thread, 0, f, 0);
2142    cpuset = CPU_ALLOC(64);
2143    CPU_ZERO_S(setsize, cpuset);
2144    pthread_setaffinity_np(thread, setsize, cpuset);
2145    pthread_getaffinity_np(thread, setsize, cpuset);
2146    CPU_FREE(cpuset);
2147    return 0;
2148  }''', dependencies: threads))
2149config_host_data.set('CONFIG_SIGNALFD', cc.links(gnu_source_prefix + '''
2150  #include <sys/signalfd.h>
2151  #include <stddef.h>
2152  int main(void) { return signalfd(-1, NULL, SFD_CLOEXEC); }'''))
2153config_host_data.set('CONFIG_SPLICE', cc.links(gnu_source_prefix + '''
2154  #include <unistd.h>
2155  #include <fcntl.h>
2156  #include <limits.h>
2157
2158  int main(void)
2159  {
2160    int len, fd = 0;
2161    len = tee(STDIN_FILENO, STDOUT_FILENO, INT_MAX, SPLICE_F_NONBLOCK);
2162    splice(STDIN_FILENO, NULL, fd, NULL, len, SPLICE_F_MOVE);
2163    return 0;
2164  }'''))
2165
2166config_host_data.set('HAVE_MLOCKALL', cc.links(gnu_source_prefix + '''
2167  #include <sys/mman.h>
2168  int main(void) {
2169    return mlockall(MCL_FUTURE);
2170  }'''))
2171
2172have_l2tpv3 = false
2173if get_option('l2tpv3').allowed() and have_system
2174  have_l2tpv3 = cc.has_type('struct mmsghdr',
2175    prefix: gnu_source_prefix + '''
2176      #include <sys/socket.h>
2177      #include <linux/ip.h>''')
2178endif
2179config_host_data.set('CONFIG_L2TPV3', have_l2tpv3)
2180
2181have_netmap = false
2182if get_option('netmap').allowed() and have_system
2183  have_netmap = cc.compiles('''
2184    #include <inttypes.h>
2185    #include <net/if.h>
2186    #include <net/netmap.h>
2187    #include <net/netmap_user.h>
2188    #if (NETMAP_API < 11) || (NETMAP_API > 15)
2189    #error
2190    #endif
2191    int main(void) { return 0; }''')
2192  if not have_netmap and get_option('netmap').enabled()
2193    error('Netmap headers not available')
2194  endif
2195endif
2196config_host_data.set('CONFIG_NETMAP', have_netmap)
2197
2198# Work around a system header bug with some kernel/XFS header
2199# versions where they both try to define 'struct fsxattr':
2200# xfs headers will not try to redefine structs from linux headers
2201# if this macro is set.
2202config_host_data.set('HAVE_FSXATTR', cc.links('''
2203  #include <linux/fs.h>
2204  struct fsxattr foo;
2205  int main(void) {
2206    return 0;
2207  }'''))
2208
2209# Some versions of Mac OS X incorrectly define SIZE_MAX
2210config_host_data.set('HAVE_BROKEN_SIZE_MAX', not cc.compiles('''
2211    #include <stdint.h>
2212    #include <stdio.h>
2213    int main(void) {
2214        return printf("%zu", SIZE_MAX);
2215    }''', args: ['-Werror']))
2216
2217atomic_test = '''
2218  #include <stdint.h>
2219  int main(void)
2220  {
2221    @0@ x = 0, y = 0;
2222    y = __atomic_load_n(&x, __ATOMIC_RELAXED);
2223    __atomic_store_n(&x, y, __ATOMIC_RELAXED);
2224    __atomic_compare_exchange_n(&x, &y, x, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
2225    __atomic_exchange_n(&x, y, __ATOMIC_RELAXED);
2226    __atomic_fetch_add(&x, y, __ATOMIC_RELAXED);
2227    return 0;
2228  }'''
2229
2230# See if 64-bit atomic operations are supported.
2231# Note that without __atomic builtins, we can only
2232# assume atomic loads/stores max at pointer size.
2233config_host_data.set('CONFIG_ATOMIC64', cc.links(atomic_test.format('uint64_t')))
2234
2235has_int128 = cc.links('''
2236  __int128_t a;
2237  __uint128_t b;
2238  int main (void) {
2239    a = a + b;
2240    b = a * b;
2241    a = a * a;
2242    return 0;
2243  }''')
2244
2245config_host_data.set('CONFIG_INT128', has_int128)
2246
2247if has_int128
2248  # "do we have 128-bit atomics which are handled inline and specifically not
2249  # via libatomic". The reason we can't use libatomic is documented in the
2250  # comment starting "GCC is a house divided" in include/qemu/atomic128.h.
2251  has_atomic128 = cc.links(atomic_test.format('unsigned __int128'))
2252
2253  config_host_data.set('CONFIG_ATOMIC128', has_atomic128)
2254
2255  if not has_atomic128
2256    has_cmpxchg128 = cc.links('''
2257      int main(void)
2258      {
2259        unsigned __int128 x = 0, y = 0;
2260        __sync_val_compare_and_swap_16(&x, y, x);
2261        return 0;
2262      }
2263    ''')
2264
2265    config_host_data.set('CONFIG_CMPXCHG128', has_cmpxchg128)
2266  endif
2267endif
2268
2269config_host_data.set('CONFIG_GETAUXVAL', cc.links(gnu_source_prefix + '''
2270  #include <sys/auxv.h>
2271  int main(void) {
2272    return getauxval(AT_HWCAP) == 0;
2273  }'''))
2274
2275config_host_data.set('CONFIG_USBFS', have_linux_user and cc.compiles('''
2276  #include <linux/usbdevice_fs.h>
2277
2278  #ifndef USBDEVFS_GET_CAPABILITIES
2279  #error "USBDEVFS_GET_CAPABILITIES undefined"
2280  #endif
2281
2282  #ifndef USBDEVFS_DISCONNECT_CLAIM
2283  #error "USBDEVFS_DISCONNECT_CLAIM undefined"
2284  #endif
2285
2286  int main(void) { return 0; }'''))
2287
2288have_keyring = get_option('keyring') \
2289  .require(targetos == 'linux', error_message: 'keyring is only available on Linux') \
2290  .require(cc.compiles('''
2291    #include <errno.h>
2292    #include <asm/unistd.h>
2293    #include <linux/keyctl.h>
2294    #include <sys/syscall.h>
2295    #include <unistd.h>
2296    int main(void) {
2297        return syscall(__NR_keyctl, KEYCTL_READ, 0, NULL, NULL, 0);
2298    }'''), error_message: 'keyctl syscall not available on this system').allowed()
2299config_host_data.set('CONFIG_SECRET_KEYRING', have_keyring)
2300
2301have_cpuid_h = cc.links('''
2302  #include <cpuid.h>
2303  int main(void) {
2304    unsigned a, b, c, d;
2305    unsigned max = __get_cpuid_max(0, 0);
2306
2307    if (max >= 1) {
2308        __cpuid(1, a, b, c, d);
2309    }
2310
2311    if (max >= 7) {
2312        __cpuid_count(7, 0, a, b, c, d);
2313    }
2314
2315    return 0;
2316  }''')
2317config_host_data.set('CONFIG_CPUID_H', have_cpuid_h)
2318
2319config_host_data.set('CONFIG_AVX2_OPT', get_option('avx2') \
2320  .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable AVX2') \
2321  .require(cc.links('''
2322    #pragma GCC push_options
2323    #pragma GCC target("avx2")
2324    #include <cpuid.h>
2325    #include <immintrin.h>
2326    static int bar(void *a) {
2327      __m256i x = *(__m256i *)a;
2328      return _mm256_testz_si256(x, x);
2329    }
2330    int main(int argc, char *argv[]) { return bar(argv[argc - 1]); }
2331  '''), error_message: 'AVX2 not available').allowed())
2332
2333config_host_data.set('CONFIG_AVX512F_OPT', get_option('avx512f') \
2334  .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable AVX512F') \
2335  .require(cc.links('''
2336    #pragma GCC push_options
2337    #pragma GCC target("avx512f")
2338    #include <cpuid.h>
2339    #include <immintrin.h>
2340    static int bar(void *a) {
2341      __m512i x = *(__m512i *)a;
2342      return _mm512_test_epi64_mask(x, x);
2343    }
2344    int main(int argc, char *argv[]) { return bar(argv[argc - 1]); }
2345  '''), error_message: 'AVX512F not available').allowed())
2346
2347have_pvrdma = get_option('pvrdma') \
2348  .require(rdma.found(), error_message: 'PVRDMA requires OpenFabrics libraries') \
2349  .require(cc.compiles(gnu_source_prefix + '''
2350    #include <sys/mman.h>
2351    int main(void)
2352    {
2353      char buf = 0;
2354      void *addr = &buf;
2355      addr = mremap(addr, 0, 1, MREMAP_MAYMOVE | MREMAP_FIXED);
2356
2357      return 0;
2358    }'''), error_message: 'PVRDMA requires mremap').allowed()
2359
2360if have_pvrdma
2361  config_host_data.set('LEGACY_RDMA_REG_MR', not cc.links('''
2362    #include <infiniband/verbs.h>
2363    int main(void)
2364    {
2365      struct ibv_mr *mr;
2366      struct ibv_pd *pd = NULL;
2367      size_t length = 10;
2368      uint64_t iova = 0;
2369      int access = 0;
2370      void *addr = NULL;
2371
2372      mr = ibv_reg_mr_iova(pd, addr, length, iova, access);
2373      ibv_dereg_mr(mr);
2374      return 0;
2375    }'''))
2376endif
2377
2378if get_option('membarrier').disabled()
2379  have_membarrier = false
2380elif targetos == 'windows'
2381  have_membarrier = true
2382elif targetos == 'linux'
2383  have_membarrier = cc.compiles('''
2384    #include <linux/membarrier.h>
2385    #include <sys/syscall.h>
2386    #include <unistd.h>
2387    #include <stdlib.h>
2388    int main(void) {
2389        syscall(__NR_membarrier, MEMBARRIER_CMD_QUERY, 0);
2390        syscall(__NR_membarrier, MEMBARRIER_CMD_SHARED, 0);
2391        exit(0);
2392    }''')
2393endif
2394config_host_data.set('CONFIG_MEMBARRIER', get_option('membarrier') \
2395  .require(have_membarrier, error_message: 'membarrier system call not available') \
2396  .allowed())
2397
2398have_afalg = get_option('crypto_afalg') \
2399  .require(cc.compiles(gnu_source_prefix + '''
2400    #include <errno.h>
2401    #include <sys/types.h>
2402    #include <sys/socket.h>
2403    #include <linux/if_alg.h>
2404    int main(void) {
2405      int sock;
2406      sock = socket(AF_ALG, SOCK_SEQPACKET, 0);
2407      return sock;
2408    }
2409  '''), error_message: 'AF_ALG requested but could not be detected').allowed()
2410config_host_data.set('CONFIG_AF_ALG', have_afalg)
2411
2412config_host_data.set('CONFIG_AF_VSOCK', cc.has_header_symbol(
2413  'linux/vm_sockets.h', 'AF_VSOCK',
2414  prefix: '#include <sys/socket.h>',
2415))
2416
2417have_vss = false
2418have_vss_sdk = false # old xp/2003 SDK
2419if targetos == 'windows' and link_language == 'cpp'
2420  have_vss = cxx.compiles('''
2421    #define __MIDL_user_allocate_free_DEFINED__
2422    #include <vss.h>
2423    int main(void) { return VSS_CTX_BACKUP; }''')
2424  have_vss_sdk = cxx.has_header('vscoordint.h')
2425endif
2426config_host_data.set('HAVE_VSS_SDK', have_vss_sdk)
2427
2428foreach k, v: config_host
2429  if k.startswith('CONFIG_')
2430    config_host_data.set(k, v == 'y' ? 1 : v)
2431  endif
2432endforeach
2433
2434# Older versions of MinGW do not import _lock_file and _unlock_file properly.
2435# This was fixed for v6.0.0 with commit b48e3ac8969d.
2436if targetos == 'windows'
2437  config_host_data.set('HAVE__LOCK_FILE', cc.links('''
2438    #include <stdio.h>
2439    int main(void) {
2440      _lock_file(NULL);
2441      _unlock_file(NULL);
2442      return 0;
2443    }''', name: '_lock_file and _unlock_file'))
2444endif
2445
2446########################
2447# Target configuration #
2448########################
2449
2450minikconf = find_program('scripts/minikconf.py')
2451config_all = {}
2452config_all_devices = {}
2453config_all_disas = {}
2454config_devices_mak_list = []
2455config_devices_h = {}
2456config_target_h = {}
2457config_target_mak = {}
2458
2459disassemblers = {
2460  'alpha' : ['CONFIG_ALPHA_DIS'],
2461  'avr' : ['CONFIG_AVR_DIS'],
2462  'cris' : ['CONFIG_CRIS_DIS'],
2463  'hexagon' : ['CONFIG_HEXAGON_DIS'],
2464  'hppa' : ['CONFIG_HPPA_DIS'],
2465  'i386' : ['CONFIG_I386_DIS'],
2466  'x86_64' : ['CONFIG_I386_DIS'],
2467  'm68k' : ['CONFIG_M68K_DIS'],
2468  'microblaze' : ['CONFIG_MICROBLAZE_DIS'],
2469  'mips' : ['CONFIG_MIPS_DIS'],
2470  'nios2' : ['CONFIG_NIOS2_DIS'],
2471  'or1k' : ['CONFIG_OPENRISC_DIS'],
2472  'ppc' : ['CONFIG_PPC_DIS'],
2473  'riscv' : ['CONFIG_RISCV_DIS'],
2474  'rx' : ['CONFIG_RX_DIS'],
2475  's390' : ['CONFIG_S390_DIS'],
2476  'sh4' : ['CONFIG_SH4_DIS'],
2477  'sparc' : ['CONFIG_SPARC_DIS'],
2478  'xtensa' : ['CONFIG_XTENSA_DIS'],
2479  'loongarch' : ['CONFIG_LOONGARCH_DIS'],
2480}
2481if link_language == 'cpp'
2482  disassemblers += {
2483    'mips' : [ 'CONFIG_MIPS_DIS', 'CONFIG_NANOMIPS_DIS'],
2484  }
2485endif
2486
2487have_ivshmem = config_host_data.get('CONFIG_EVENTFD')
2488host_kconfig = \
2489  (get_option('fuzzing') ? ['CONFIG_FUZZ=y'] : []) + \
2490  (have_tpm ? ['CONFIG_TPM=y'] : []) + \
2491  (spice.found() ? ['CONFIG_SPICE=y'] : []) + \
2492  (have_ivshmem ? ['CONFIG_IVSHMEM=y'] : []) + \
2493  (opengl.found() ? ['CONFIG_OPENGL=y'] : []) + \
2494  (x11.found() ? ['CONFIG_X11=y'] : []) + \
2495  (have_vhost_user ? ['CONFIG_VHOST_USER=y'] : []) + \
2496  (have_vhost_vdpa ? ['CONFIG_VHOST_VDPA=y'] : []) + \
2497  (have_vhost_kernel ? ['CONFIG_VHOST_KERNEL=y'] : []) + \
2498  (have_virtfs ? ['CONFIG_VIRTFS=y'] : []) + \
2499  ('CONFIG_LINUX' in config_host ? ['CONFIG_LINUX=y'] : []) + \
2500  (have_pvrdma ? ['CONFIG_PVRDMA=y'] : []) + \
2501  (multiprocess_allowed ? ['CONFIG_MULTIPROCESS_ALLOWED=y'] : []) + \
2502  (vfio_user_server_allowed ? ['CONFIG_VFIO_USER_SERVER_ALLOWED=y'] : [])
2503
2504ignored = [ 'TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_ARCH' ]
2505
2506default_targets = 'CONFIG_DEFAULT_TARGETS' in config_host
2507actual_target_dirs = []
2508fdt_required = []
2509foreach target : target_dirs
2510  config_target = { 'TARGET_NAME': target.split('-')[0] }
2511  if target.endswith('linux-user')
2512    if targetos != 'linux'
2513      if default_targets
2514        continue
2515      endif
2516      error('Target @0@ is only available on a Linux host'.format(target))
2517    endif
2518    config_target += { 'CONFIG_LINUX_USER': 'y' }
2519  elif target.endswith('bsd-user')
2520    if 'CONFIG_BSD' not in config_host
2521      if default_targets
2522        continue
2523      endif
2524      error('Target @0@ is only available on a BSD host'.format(target))
2525    endif
2526    config_target += { 'CONFIG_BSD_USER': 'y' }
2527  elif target.endswith('softmmu')
2528    config_target += { 'CONFIG_SOFTMMU': 'y' }
2529  endif
2530  if target.endswith('-user')
2531    config_target += {
2532      'CONFIG_USER_ONLY': 'y',
2533      'CONFIG_QEMU_INTERP_PREFIX':
2534        get_option('interp_prefix').replace('%M', config_target['TARGET_NAME'])
2535    }
2536  endif
2537
2538  accel_kconfig = []
2539  foreach sym: accelerators
2540    if sym == 'CONFIG_TCG' or target in accelerator_targets.get(sym, [])
2541      config_target += { sym: 'y' }
2542      config_all += { sym: 'y' }
2543      if sym == 'CONFIG_TCG' and tcg_arch == 'tci'
2544        config_target += { 'CONFIG_TCG_INTERPRETER': 'y' }
2545      endif
2546      if target in modular_tcg
2547        config_target += { 'CONFIG_TCG_MODULAR': 'y' }
2548      else
2549        config_target += { 'CONFIG_TCG_BUILTIN': 'y' }
2550      endif
2551      accel_kconfig += [ sym + '=y' ]
2552    endif
2553  endforeach
2554  if accel_kconfig.length() == 0
2555    if default_targets
2556      continue
2557    endif
2558    error('No accelerator available for target @0@'.format(target))
2559  endif
2560
2561  actual_target_dirs += target
2562  config_target += keyval.load('configs/targets' / target + '.mak')
2563  config_target += { 'TARGET_' + config_target['TARGET_ARCH'].to_upper(): 'y' }
2564
2565  if 'TARGET_NEED_FDT' in config_target
2566    fdt_required += target
2567  endif
2568
2569  # Add default keys
2570  if 'TARGET_BASE_ARCH' not in config_target
2571    config_target += {'TARGET_BASE_ARCH': config_target['TARGET_ARCH']}
2572  endif
2573  if 'TARGET_ABI_DIR' not in config_target
2574    config_target += {'TARGET_ABI_DIR': config_target['TARGET_ARCH']}
2575  endif
2576  if 'TARGET_BIG_ENDIAN' not in config_target
2577    config_target += {'TARGET_BIG_ENDIAN': 'n'}
2578  endif
2579
2580  foreach k, v: disassemblers
2581    if host_arch.startswith(k) or config_target['TARGET_BASE_ARCH'].startswith(k)
2582      foreach sym: v
2583        config_target += { sym: 'y' }
2584        config_all_disas += { sym: 'y' }
2585      endforeach
2586    endif
2587  endforeach
2588
2589  config_target_data = configuration_data()
2590  foreach k, v: config_target
2591    if not k.startswith('TARGET_') and not k.startswith('CONFIG_')
2592      # do nothing
2593    elif ignored.contains(k)
2594      # do nothing
2595    elif k == 'TARGET_BASE_ARCH'
2596      # Note that TARGET_BASE_ARCH ends up in config-target.h but it is
2597      # not used to select files from sourcesets.
2598      config_target_data.set('TARGET_' + v.to_upper(), 1)
2599    elif k == 'TARGET_NAME' or k == 'CONFIG_QEMU_INTERP_PREFIX'
2600      config_target_data.set_quoted(k, v)
2601    elif v == 'y'
2602      config_target_data.set(k, 1)
2603    elif v == 'n'
2604      config_target_data.set(k, 0)
2605    else
2606      config_target_data.set(k, v)
2607    endif
2608  endforeach
2609  config_target_data.set('QEMU_ARCH',
2610                         'QEMU_ARCH_' + config_target['TARGET_BASE_ARCH'].to_upper())
2611  config_target_h += {target: configure_file(output: target + '-config-target.h',
2612                                               configuration: config_target_data)}
2613
2614  if target.endswith('-softmmu')
2615    config_input = meson.get_external_property(target, 'default')
2616    config_devices_mak = target + '-config-devices.mak'
2617    config_devices_mak = configure_file(
2618      input: ['configs/devices' / target / config_input + '.mak', 'Kconfig'],
2619      output: config_devices_mak,
2620      depfile: config_devices_mak + '.d',
2621      capture: true,
2622      command: [minikconf,
2623                get_option('default_devices') ? '--defconfig' : '--allnoconfig',
2624                config_devices_mak, '@DEPFILE@', '@INPUT@',
2625                host_kconfig, accel_kconfig,
2626                'CONFIG_' + config_target['TARGET_ARCH'].to_upper() + '=y'])
2627
2628    config_devices_data = configuration_data()
2629    config_devices = keyval.load(config_devices_mak)
2630    foreach k, v: config_devices
2631      config_devices_data.set(k, 1)
2632    endforeach
2633    config_devices_mak_list += config_devices_mak
2634    config_devices_h += {target: configure_file(output: target + '-config-devices.h',
2635                                                configuration: config_devices_data)}
2636    config_target += config_devices
2637    config_all_devices += config_devices
2638  endif
2639  config_target_mak += {target: config_target}
2640endforeach
2641target_dirs = actual_target_dirs
2642
2643# This configuration is used to build files that are shared by
2644# multiple binaries, and then extracted out of the "common"
2645# static_library target.
2646#
2647# We do not use all_sources()/all_dependencies(), because it would
2648# build literally all source files, including devices only used by
2649# targets that are not built for this compilation.  The CONFIG_ALL
2650# pseudo symbol replaces it.
2651
2652config_all += config_all_devices
2653config_all += config_host
2654config_all += config_all_disas
2655config_all += {
2656  'CONFIG_XEN': xen.found(),
2657  'CONFIG_SOFTMMU': have_system,
2658  'CONFIG_USER_ONLY': have_user,
2659  'CONFIG_ALL': true,
2660}
2661
2662target_configs_h = []
2663foreach target: target_dirs
2664  target_configs_h += config_target_h[target]
2665  target_configs_h += config_devices_h.get(target, [])
2666endforeach
2667genh += custom_target('config-poison.h',
2668                      input: [target_configs_h],
2669                      output: 'config-poison.h',
2670                      capture: true,
2671                      command: [find_program('scripts/make-config-poison.sh'),
2672                                target_configs_h])
2673
2674##############
2675# Submodules #
2676##############
2677
2678capstone = not_found
2679if not get_option('capstone').auto() or have_system or have_user
2680  capstone = dependency('capstone', version: '>=3.0.5',
2681                        kwargs: static_kwargs, method: 'pkg-config',
2682                        required: get_option('capstone'))
2683
2684  # Some versions of capstone have broken pkg-config file
2685  # that reports a wrong -I path, causing the #include to
2686  # fail later. If the system has such a broken version
2687  # do not use it.
2688  if capstone.found() and not cc.compiles('#include <capstone.h>',
2689                                          dependencies: [capstone])
2690    capstone = not_found
2691    if get_option('capstone').enabled()
2692      error('capstone requested, but it does not appear to work')
2693    endif
2694  endif
2695endif
2696
2697libvfio_user_dep = not_found
2698if have_system and vfio_user_server_allowed
2699  have_internal = fs.exists(meson.current_source_dir() / 'subprojects/libvfio-user/meson.build')
2700
2701  if not have_internal
2702    error('libvfio-user source not found - please pull git submodule')
2703  endif
2704
2705  libvfio_user_proj = subproject('libvfio-user')
2706
2707  libvfio_user_lib = libvfio_user_proj.get_variable('libvfio_user_dep')
2708
2709  libvfio_user_dep = declare_dependency(dependencies: [libvfio_user_lib])
2710endif
2711
2712fdt = not_found
2713if have_system
2714  fdt_opt = get_option('fdt')
2715  if fdt_opt in ['enabled', 'auto', 'system']
2716    have_internal = fs.exists(meson.current_source_dir() / 'dtc/libfdt/Makefile.libfdt')
2717    fdt = cc.find_library('fdt', kwargs: static_kwargs,
2718                          required: fdt_opt == 'system' or
2719                                    fdt_opt == 'enabled' and not have_internal)
2720    if fdt.found() and cc.links('''
2721       #include <libfdt.h>
2722       #include <libfdt_env.h>
2723       int main(void) { fdt_find_max_phandle(NULL, NULL); return 0; }''',
2724         dependencies: fdt)
2725      fdt_opt = 'system'
2726    elif fdt_opt == 'system'
2727       error('system libfdt requested, but it is too old (1.5.1 or newer required)')
2728    elif have_internal
2729      fdt_opt = 'internal'
2730    else
2731      fdt_opt = 'disabled'
2732      fdt = not_found
2733    endif
2734  endif
2735  if fdt_opt == 'internal'
2736    fdt_files = files(
2737      'dtc/libfdt/fdt.c',
2738      'dtc/libfdt/fdt_ro.c',
2739      'dtc/libfdt/fdt_wip.c',
2740      'dtc/libfdt/fdt_sw.c',
2741      'dtc/libfdt/fdt_rw.c',
2742      'dtc/libfdt/fdt_strerror.c',
2743      'dtc/libfdt/fdt_empty_tree.c',
2744      'dtc/libfdt/fdt_addresses.c',
2745      'dtc/libfdt/fdt_overlay.c',
2746      'dtc/libfdt/fdt_check.c',
2747    )
2748
2749    fdt_inc = include_directories('dtc/libfdt')
2750    libfdt = static_library('fdt',
2751                            build_by_default: false,
2752                            sources: fdt_files,
2753                            include_directories: fdt_inc)
2754    fdt = declare_dependency(link_with: libfdt,
2755                             include_directories: fdt_inc)
2756  endif
2757else
2758  fdt_opt = 'disabled'
2759endif
2760if not fdt.found() and fdt_required.length() > 0
2761  error('fdt not available but required by targets ' + ', '.join(fdt_required))
2762endif
2763
2764config_host_data.set('CONFIG_CAPSTONE', capstone.found())
2765config_host_data.set('CONFIG_FDT', fdt.found())
2766config_host_data.set('CONFIG_SLIRP', slirp.found())
2767
2768#####################
2769# Generated sources #
2770#####################
2771
2772genh += configure_file(output: 'config-host.h', configuration: config_host_data)
2773
2774hxtool = find_program('scripts/hxtool')
2775shaderinclude = find_program('scripts/shaderinclude.pl')
2776qapi_gen = find_program('scripts/qapi-gen.py')
2777qapi_gen_depends = [ meson.current_source_dir() / 'scripts/qapi/__init__.py',
2778                     meson.current_source_dir() / 'scripts/qapi/commands.py',
2779                     meson.current_source_dir() / 'scripts/qapi/common.py',
2780                     meson.current_source_dir() / 'scripts/qapi/error.py',
2781                     meson.current_source_dir() / 'scripts/qapi/events.py',
2782                     meson.current_source_dir() / 'scripts/qapi/expr.py',
2783                     meson.current_source_dir() / 'scripts/qapi/gen.py',
2784                     meson.current_source_dir() / 'scripts/qapi/introspect.py',
2785                     meson.current_source_dir() / 'scripts/qapi/parser.py',
2786                     meson.current_source_dir() / 'scripts/qapi/schema.py',
2787                     meson.current_source_dir() / 'scripts/qapi/source.py',
2788                     meson.current_source_dir() / 'scripts/qapi/types.py',
2789                     meson.current_source_dir() / 'scripts/qapi/visit.py',
2790                     meson.current_source_dir() / 'scripts/qapi/common.py',
2791                     meson.current_source_dir() / 'scripts/qapi-gen.py'
2792]
2793
2794tracetool = [
2795  python, files('scripts/tracetool.py'),
2796   '--backend=' + ','.join(get_option('trace_backends'))
2797]
2798tracetool_depends = files(
2799  'scripts/tracetool/backend/log.py',
2800  'scripts/tracetool/backend/__init__.py',
2801  'scripts/tracetool/backend/dtrace.py',
2802  'scripts/tracetool/backend/ftrace.py',
2803  'scripts/tracetool/backend/simple.py',
2804  'scripts/tracetool/backend/syslog.py',
2805  'scripts/tracetool/backend/ust.py',
2806  'scripts/tracetool/format/ust_events_c.py',
2807  'scripts/tracetool/format/ust_events_h.py',
2808  'scripts/tracetool/format/__init__.py',
2809  'scripts/tracetool/format/d.py',
2810  'scripts/tracetool/format/simpletrace_stap.py',
2811  'scripts/tracetool/format/c.py',
2812  'scripts/tracetool/format/h.py',
2813  'scripts/tracetool/format/log_stap.py',
2814  'scripts/tracetool/format/stap.py',
2815  'scripts/tracetool/__init__.py',
2816  'scripts/tracetool/transform.py',
2817  'scripts/tracetool/vcpu.py'
2818)
2819
2820qemu_version_cmd = [find_program('scripts/qemu-version.sh'),
2821                    meson.current_source_dir(),
2822                    get_option('pkgversion'), meson.project_version()]
2823qemu_version = custom_target('qemu-version.h',
2824                             output: 'qemu-version.h',
2825                             command: qemu_version_cmd,
2826                             capture: true,
2827                             build_by_default: true,
2828                             build_always_stale: true)
2829genh += qemu_version
2830
2831hxdep = []
2832hx_headers = [
2833  ['qemu-options.hx', 'qemu-options.def'],
2834  ['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
2835]
2836if have_system
2837  hx_headers += [
2838    ['hmp-commands.hx', 'hmp-commands.h'],
2839    ['hmp-commands-info.hx', 'hmp-commands-info.h'],
2840  ]
2841endif
2842foreach d : hx_headers
2843  hxdep += custom_target(d[1],
2844                input: files(d[0]),
2845                output: d[1],
2846                capture: true,
2847                build_by_default: true, # to be removed when added to a target
2848                command: [hxtool, '-h', '@INPUT0@'])
2849endforeach
2850genh += hxdep
2851
2852###################
2853# Collect sources #
2854###################
2855
2856authz_ss = ss.source_set()
2857blockdev_ss = ss.source_set()
2858block_ss = ss.source_set()
2859chardev_ss = ss.source_set()
2860common_ss = ss.source_set()
2861crypto_ss = ss.source_set()
2862hwcore_ss = ss.source_set()
2863io_ss = ss.source_set()
2864qmp_ss = ss.source_set()
2865qom_ss = ss.source_set()
2866softmmu_ss = ss.source_set()
2867specific_fuzz_ss = ss.source_set()
2868specific_ss = ss.source_set()
2869stub_ss = ss.source_set()
2870trace_ss = ss.source_set()
2871user_ss = ss.source_set()
2872util_ss = ss.source_set()
2873
2874# accel modules
2875qtest_module_ss = ss.source_set()
2876tcg_module_ss = ss.source_set()
2877
2878modules = {}
2879target_modules = {}
2880hw_arch = {}
2881target_arch = {}
2882target_softmmu_arch = {}
2883target_user_arch = {}
2884
2885###############
2886# Trace files #
2887###############
2888
2889# TODO: add each directory to the subdirs from its own meson.build, once
2890# we have those
2891trace_events_subdirs = [
2892  'crypto',
2893  'qapi',
2894  'qom',
2895  'monitor',
2896  'util',
2897  'gdbstub',
2898]
2899if have_linux_user
2900  trace_events_subdirs += [ 'linux-user' ]
2901endif
2902if have_bsd_user
2903  trace_events_subdirs += [ 'bsd-user' ]
2904endif
2905if have_block
2906  trace_events_subdirs += [
2907    'authz',
2908    'block',
2909    'io',
2910    'nbd',
2911    'scsi',
2912  ]
2913endif
2914if have_system
2915  trace_events_subdirs += [
2916    'accel/kvm',
2917    'audio',
2918    'backends',
2919    'backends/tpm',
2920    'chardev',
2921    'ebpf',
2922    'hw/9pfs',
2923    'hw/acpi',
2924    'hw/adc',
2925    'hw/alpha',
2926    'hw/arm',
2927    'hw/audio',
2928    'hw/block',
2929    'hw/block/dataplane',
2930    'hw/char',
2931    'hw/display',
2932    'hw/dma',
2933    'hw/hyperv',
2934    'hw/i2c',
2935    'hw/i386',
2936    'hw/i386/xen',
2937    'hw/ide',
2938    'hw/input',
2939    'hw/intc',
2940    'hw/isa',
2941    'hw/mem',
2942    'hw/mips',
2943    'hw/misc',
2944    'hw/misc/macio',
2945    'hw/net',
2946    'hw/net/can',
2947    'hw/nubus',
2948    'hw/nvme',
2949    'hw/nvram',
2950    'hw/pci',
2951    'hw/pci-host',
2952    'hw/ppc',
2953    'hw/rdma',
2954    'hw/rdma/vmw',
2955    'hw/rtc',
2956    'hw/s390x',
2957    'hw/scsi',
2958    'hw/sd',
2959    'hw/sh4',
2960    'hw/sparc',
2961    'hw/sparc64',
2962    'hw/ssi',
2963    'hw/timer',
2964    'hw/tpm',
2965    'hw/usb',
2966    'hw/vfio',
2967    'hw/virtio',
2968    'hw/watchdog',
2969    'hw/xen',
2970    'hw/gpio',
2971    'migration',
2972    'net',
2973    'softmmu',
2974    'ui',
2975    'hw/remote',
2976  ]
2977endif
2978if have_system or have_user
2979  trace_events_subdirs += [
2980    'accel/tcg',
2981    'hw/core',
2982    'target/arm',
2983    'target/arm/hvf',
2984    'target/hppa',
2985    'target/i386',
2986    'target/i386/kvm',
2987    'target/mips/tcg',
2988    'target/nios2',
2989    'target/ppc',
2990    'target/riscv',
2991    'target/s390x',
2992    'target/s390x/kvm',
2993    'target/sparc',
2994  ]
2995endif
2996
2997vhost_user = not_found
2998if targetos == 'linux' and have_vhost_user
2999  libvhost_user = subproject('libvhost-user')
3000  vhost_user = libvhost_user.get_variable('vhost_user_dep')
3001endif
3002
3003libvduse = not_found
3004if have_libvduse
3005  libvduse_proj = subproject('libvduse')
3006  libvduse = libvduse_proj.get_variable('libvduse_dep')
3007endif
3008
3009# NOTE: the trace/ subdirectory needs the qapi_trace_events variable
3010# that is filled in by qapi/.
3011subdir('qapi')
3012subdir('qobject')
3013subdir('stubs')
3014subdir('trace')
3015subdir('util')
3016subdir('qom')
3017subdir('authz')
3018subdir('crypto')
3019subdir('ui')
3020subdir('hw')
3021subdir('gdbstub')
3022
3023
3024if enable_modules
3025  libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
3026  modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
3027endif
3028
3029qom_ss = qom_ss.apply(config_host, strict: false)
3030libqom = static_library('qom', qom_ss.sources() + genh,
3031                        dependencies: [qom_ss.dependencies()],
3032                        name_suffix: 'fa')
3033qom = declare_dependency(link_whole: libqom)
3034
3035event_loop_base = files('event-loop-base.c')
3036event_loop_base = static_library('event-loop-base', sources: event_loop_base + genh,
3037                                 build_by_default: true)
3038event_loop_base = declare_dependency(link_whole: event_loop_base,
3039                                     dependencies: [qom])
3040
3041stub_ss = stub_ss.apply(config_all, strict: false)
3042
3043util_ss.add_all(trace_ss)
3044util_ss = util_ss.apply(config_all, strict: false)
3045libqemuutil = static_library('qemuutil',
3046                             sources: util_ss.sources() + stub_ss.sources() + genh,
3047                             dependencies: [util_ss.dependencies(), libm, threads, glib, socket, malloc, pixman])
3048qemuutil = declare_dependency(link_with: libqemuutil,
3049                              sources: genh + version_res,
3050                              dependencies: [event_loop_base])
3051
3052if have_system or have_user
3053  decodetree = generator(find_program('scripts/decodetree.py'),
3054                         output: 'decode-@BASENAME@.c.inc',
3055                         arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
3056  subdir('libdecnumber')
3057  subdir('target')
3058endif
3059
3060subdir('audio')
3061subdir('io')
3062subdir('chardev')
3063subdir('fsdev')
3064subdir('dump')
3065
3066if have_block
3067  block_ss.add(files(
3068    'block.c',
3069    'blockjob.c',
3070    'job.c',
3071    'qemu-io-cmds.c',
3072  ))
3073  if config_host_data.get('CONFIG_REPLICATION')
3074    block_ss.add(files('replication.c'))
3075  endif
3076
3077  subdir('nbd')
3078  subdir('scsi')
3079  subdir('block')
3080
3081  blockdev_ss.add(files(
3082    'blockdev.c',
3083    'blockdev-nbd.c',
3084    'iothread.c',
3085    'job-qmp.c',
3086  ), gnutls)
3087
3088  # os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
3089  # os-win32.c does not
3090  blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c'))
3091  softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')])
3092endif
3093
3094common_ss.add(files('cpus-common.c'))
3095
3096subdir('softmmu')
3097
3098common_ss.add(capstone)
3099specific_ss.add(files('cpu.c', 'disas.c'), capstone)
3100
3101# Work around a gcc bug/misfeature wherein constant propagation looks
3102# through an alias:
3103#   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99696
3104# to guess that a const variable is always zero.  Without lto, this is
3105# impossible, as the alias is restricted to page-vary-common.c.  Indeed,
3106# without lto, not even the alias is required -- we simply use different
3107# declarations in different compilation units.
3108pagevary = files('page-vary-common.c')
3109if get_option('b_lto')
3110  pagevary_flags = ['-fno-lto']
3111  if get_option('cfi')
3112    pagevary_flags += '-fno-sanitize=cfi-icall'
3113  endif
3114  pagevary = static_library('page-vary-common', sources: pagevary + genh,
3115                            c_args: pagevary_flags)
3116  pagevary = declare_dependency(link_with: pagevary)
3117endif
3118common_ss.add(pagevary)
3119specific_ss.add(files('page-vary.c'))
3120
3121subdir('backends')
3122subdir('disas')
3123subdir('migration')
3124subdir('monitor')
3125subdir('net')
3126subdir('replay')
3127subdir('semihosting')
3128subdir('tcg')
3129subdir('fpu')
3130subdir('accel')
3131subdir('plugins')
3132subdir('ebpf')
3133
3134common_user_inc = []
3135
3136subdir('common-user')
3137subdir('bsd-user')
3138subdir('linux-user')
3139
3140# needed for fuzzing binaries
3141subdir('tests/qtest/libqos')
3142subdir('tests/qtest/fuzz')
3143
3144# accel modules
3145tcg_real_module_ss = ss.source_set()
3146tcg_real_module_ss.add_all(when: 'CONFIG_TCG_MODULAR', if_true: tcg_module_ss)
3147specific_ss.add_all(when: 'CONFIG_TCG_BUILTIN', if_true: tcg_module_ss)
3148target_modules += { 'accel' : { 'qtest': qtest_module_ss,
3149                                'tcg': tcg_real_module_ss }}
3150
3151########################
3152# Library dependencies #
3153########################
3154
3155modinfo_collect = find_program('scripts/modinfo-collect.py')
3156modinfo_generate = find_program('scripts/modinfo-generate.py')
3157modinfo_files = []
3158
3159block_mods = []
3160softmmu_mods = []
3161foreach d, list : modules
3162  foreach m, module_ss : list
3163    if enable_modules and targetos != 'windows'
3164      module_ss = module_ss.apply(config_all, strict: false)
3165      sl = static_library(d + '-' + m, [genh, module_ss.sources()],
3166                          dependencies: [modulecommon, module_ss.dependencies()], pic: true)
3167      if d == 'block'
3168        block_mods += sl
3169      else
3170        softmmu_mods += sl
3171      endif
3172      if module_ss.sources() != []
3173        # FIXME: Should use sl.extract_all_objects(recursive: true) as
3174        # input. Sources can be used multiple times but objects are
3175        # unique when it comes to lookup in compile_commands.json.
3176        # Depnds on a mesion version with
3177        # https://github.com/mesonbuild/meson/pull/8900
3178        modinfo_files += custom_target(d + '-' + m + '.modinfo',
3179                                       output: d + '-' + m + '.modinfo',
3180                                       input: module_ss.sources() + genh,
3181                                       capture: true,
3182                                       command: [modinfo_collect, module_ss.sources()])
3183      endif
3184    else
3185      if d == 'block'
3186        block_ss.add_all(module_ss)
3187      else
3188        softmmu_ss.add_all(module_ss)
3189      endif
3190    endif
3191  endforeach
3192endforeach
3193
3194foreach d, list : target_modules
3195  foreach m, module_ss : list
3196    if enable_modules and targetos != 'windows'
3197      foreach target : target_dirs
3198        if target.endswith('-softmmu')
3199          config_target = config_target_mak[target]
3200          config_target += config_host
3201          target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
3202          c_args = ['-DNEED_CPU_H',
3203                    '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
3204                    '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
3205          target_module_ss = module_ss.apply(config_target, strict: false)
3206          if target_module_ss.sources() != []
3207            module_name = d + '-' + m + '-' + config_target['TARGET_NAME']
3208            sl = static_library(module_name,
3209                                [genh, target_module_ss.sources()],
3210                                dependencies: [modulecommon, target_module_ss.dependencies()],
3211                                include_directories: target_inc,
3212                                c_args: c_args,
3213                                pic: true)
3214            softmmu_mods += sl
3215            # FIXME: Should use sl.extract_all_objects(recursive: true) too.
3216            modinfo_files += custom_target(module_name + '.modinfo',
3217                                           output: module_name + '.modinfo',
3218                                           input: target_module_ss.sources() + genh,
3219                                           capture: true,
3220                                           command: [modinfo_collect, '--target', target, target_module_ss.sources()])
3221          endif
3222        endif
3223      endforeach
3224    else
3225      specific_ss.add_all(module_ss)
3226    endif
3227  endforeach
3228endforeach
3229
3230if enable_modules
3231  foreach target : target_dirs
3232    if target.endswith('-softmmu')
3233      config_target = config_target_mak[target]
3234      config_devices_mak = target + '-config-devices.mak'
3235      modinfo_src = custom_target('modinfo-' + target + '.c',
3236                                  output: 'modinfo-' + target + '.c',
3237                                  input: modinfo_files,
3238                                  command: [modinfo_generate, '--devices', config_devices_mak, '@INPUT@'],
3239                                  capture: true)
3240
3241      modinfo_lib = static_library('modinfo-' + target + '.c', modinfo_src)
3242      modinfo_dep = declare_dependency(link_with: modinfo_lib)
3243
3244      arch = config_target['TARGET_NAME'] == 'sparc64' ? 'sparc64' : config_target['TARGET_BASE_ARCH']
3245      hw_arch[arch].add(modinfo_dep)
3246    endif
3247  endforeach
3248endif
3249
3250nm = find_program('nm')
3251undefsym = find_program('scripts/undefsym.py')
3252block_syms = custom_target('block.syms', output: 'block.syms',
3253                             input: [libqemuutil, block_mods],
3254                             capture: true,
3255                             command: [undefsym, nm, '@INPUT@'])
3256qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
3257                             input: [libqemuutil, softmmu_mods],
3258                             capture: true,
3259                             command: [undefsym, nm, '@INPUT@'])
3260
3261authz_ss = authz_ss.apply(config_host, strict: false)
3262libauthz = static_library('authz', authz_ss.sources() + genh,
3263                          dependencies: [authz_ss.dependencies()],
3264                          name_suffix: 'fa',
3265                          build_by_default: false)
3266
3267authz = declare_dependency(link_whole: libauthz,
3268                           dependencies: qom)
3269
3270crypto_ss = crypto_ss.apply(config_host, strict: false)
3271libcrypto = static_library('crypto', crypto_ss.sources() + genh,
3272                           dependencies: [crypto_ss.dependencies()],
3273                           name_suffix: 'fa',
3274                           build_by_default: false)
3275
3276crypto = declare_dependency(link_whole: libcrypto,
3277                            dependencies: [authz, qom])
3278
3279io_ss = io_ss.apply(config_host, strict: false)
3280libio = static_library('io', io_ss.sources() + genh,
3281                       dependencies: [io_ss.dependencies()],
3282                       link_with: libqemuutil,
3283                       name_suffix: 'fa',
3284                       build_by_default: false)
3285
3286io = declare_dependency(link_whole: libio, dependencies: [crypto, qom])
3287
3288libmigration = static_library('migration', sources: migration_files + genh,
3289                              name_suffix: 'fa',
3290                              build_by_default: false)
3291migration = declare_dependency(link_with: libmigration,
3292                               dependencies: [zlib, qom, io])
3293softmmu_ss.add(migration)
3294
3295block_ss = block_ss.apply(config_host, strict: false)
3296libblock = static_library('block', block_ss.sources() + genh,
3297                          dependencies: block_ss.dependencies(),
3298                          link_depends: block_syms,
3299                          name_suffix: 'fa',
3300                          build_by_default: false)
3301
3302block = declare_dependency(link_whole: [libblock],
3303                           link_args: '@block.syms',
3304                           dependencies: [crypto, io])
3305
3306blockdev_ss = blockdev_ss.apply(config_host, strict: false)
3307libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
3308                             dependencies: blockdev_ss.dependencies(),
3309                             name_suffix: 'fa',
3310                             build_by_default: false)
3311
3312blockdev = declare_dependency(link_whole: [libblockdev],
3313                              dependencies: [block, event_loop_base])
3314
3315qmp_ss = qmp_ss.apply(config_host, strict: false)
3316libqmp = static_library('qmp', qmp_ss.sources() + genh,
3317                        dependencies: qmp_ss.dependencies(),
3318                        name_suffix: 'fa',
3319                        build_by_default: false)
3320
3321qmp = declare_dependency(link_whole: [libqmp])
3322
3323libchardev = static_library('chardev', chardev_ss.sources() + genh,
3324                            name_suffix: 'fa',
3325                            dependencies: chardev_ss.dependencies(),
3326                            build_by_default: false)
3327
3328chardev = declare_dependency(link_whole: libchardev)
3329
3330hwcore_ss = hwcore_ss.apply(config_host, strict: false)
3331libhwcore = static_library('hwcore', sources: hwcore_ss.sources() + genh,
3332                           name_suffix: 'fa',
3333                           build_by_default: false)
3334hwcore = declare_dependency(link_whole: libhwcore)
3335common_ss.add(hwcore)
3336
3337###########
3338# Targets #
3339###########
3340
3341emulator_modules = []
3342foreach m : block_mods + softmmu_mods
3343  emulator_modules += shared_module(m.name(),
3344                build_by_default: true,
3345                name_prefix: '',
3346                link_whole: m,
3347                install: true,
3348                install_dir: qemu_moddir)
3349endforeach
3350if emulator_modules.length() > 0
3351  alias_target('modules', emulator_modules)
3352endif
3353
3354softmmu_ss.add(authz, blockdev, chardev, crypto, io, qmp)
3355common_ss.add(qom, qemuutil)
3356
3357common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss])
3358common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
3359
3360common_all = common_ss.apply(config_all, strict: false)
3361common_all = static_library('common',
3362                            build_by_default: false,
3363                            sources: common_all.sources() + genh,
3364                            include_directories: common_user_inc,
3365                            implicit_include_directories: false,
3366                            dependencies: common_all.dependencies(),
3367                            name_suffix: 'fa')
3368
3369feature_to_c = find_program('scripts/feature_to_c.sh')
3370
3371if targetos == 'darwin'
3372  entitlement = find_program('scripts/entitlement.sh')
3373endif
3374
3375emulators = {}
3376foreach target : target_dirs
3377  config_target = config_target_mak[target]
3378  target_name = config_target['TARGET_NAME']
3379  target_base_arch = config_target['TARGET_BASE_ARCH']
3380  arch_srcs = [config_target_h[target]]
3381  arch_deps = []
3382  c_args = ['-DNEED_CPU_H',
3383            '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
3384            '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
3385  link_args = emulator_link_args
3386
3387  config_target += config_host
3388  target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
3389  if targetos == 'linux'
3390    target_inc += include_directories('linux-headers', is_system: true)
3391  endif
3392  if target.endswith('-softmmu')
3393    target_type='system'
3394    t = target_softmmu_arch[target_base_arch].apply(config_target, strict: false)
3395    arch_srcs += t.sources()
3396    arch_deps += t.dependencies()
3397
3398    hw_dir = target_name == 'sparc64' ? 'sparc64' : target_base_arch
3399    hw = hw_arch[hw_dir].apply(config_target, strict: false)
3400    arch_srcs += hw.sources()
3401    arch_deps += hw.dependencies()
3402
3403    arch_srcs += config_devices_h[target]
3404    link_args += ['@block.syms', '@qemu.syms']
3405  else
3406    abi = config_target['TARGET_ABI_DIR']
3407    target_type='user'
3408    target_inc += common_user_inc
3409    if target_base_arch in target_user_arch
3410      t = target_user_arch[target_base_arch].apply(config_target, strict: false)
3411      arch_srcs += t.sources()
3412      arch_deps += t.dependencies()
3413    endif
3414    if 'CONFIG_LINUX_USER' in config_target
3415      base_dir = 'linux-user'
3416    endif
3417    if 'CONFIG_BSD_USER' in config_target
3418      base_dir = 'bsd-user'
3419      target_inc += include_directories('bsd-user/' / targetos)
3420      target_inc += include_directories('bsd-user/host/' / host_arch)
3421      dir = base_dir / abi
3422      arch_srcs += files(dir / 'signal.c', dir / 'target_arch_cpu.c')
3423    endif
3424    target_inc += include_directories(
3425      base_dir,
3426      base_dir / abi,
3427    )
3428    if 'CONFIG_LINUX_USER' in config_target
3429      dir = base_dir / abi
3430      arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
3431      if config_target.has_key('TARGET_SYSTBL_ABI')
3432        arch_srcs += \
3433          syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
3434                                             extra_args : config_target['TARGET_SYSTBL_ABI'])
3435      endif
3436    endif
3437  endif
3438
3439  if 'TARGET_XML_FILES' in config_target
3440    gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
3441                                output: target + '-gdbstub-xml.c',
3442                                input: files(config_target['TARGET_XML_FILES'].split()),
3443                                command: [feature_to_c, '@INPUT@'],
3444                                capture: true)
3445    arch_srcs += gdbstub_xml
3446  endif
3447
3448  t = target_arch[target_base_arch].apply(config_target, strict: false)
3449  arch_srcs += t.sources()
3450  arch_deps += t.dependencies()
3451
3452  target_common = common_ss.apply(config_target, strict: false)
3453  objects = common_all.extract_objects(target_common.sources())
3454  deps = target_common.dependencies()
3455
3456  target_specific = specific_ss.apply(config_target, strict: false)
3457  arch_srcs += target_specific.sources()
3458  arch_deps += target_specific.dependencies()
3459
3460  lib = static_library('qemu-' + target,
3461                 sources: arch_srcs + genh,
3462                 dependencies: arch_deps,
3463                 objects: objects,
3464                 include_directories: target_inc,
3465                 c_args: c_args,
3466                 build_by_default: false,
3467                 name_suffix: 'fa')
3468
3469  if target.endswith('-softmmu')
3470    execs = [{
3471      'name': 'qemu-system-' + target_name,
3472      'win_subsystem': 'console',
3473      'sources': files('softmmu/main.c'),
3474      'dependencies': []
3475    }]
3476    if targetos == 'windows' and (sdl.found() or gtk.found())
3477      execs += [{
3478        'name': 'qemu-system-' + target_name + 'w',
3479        'win_subsystem': 'windows',
3480        'sources': files('softmmu/main.c'),
3481        'dependencies': []
3482      }]
3483    endif
3484    if get_option('fuzzing')
3485      specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
3486      execs += [{
3487        'name': 'qemu-fuzz-' + target_name,
3488        'win_subsystem': 'console',
3489        'sources': specific_fuzz.sources(),
3490        'dependencies': specific_fuzz.dependencies(),
3491      }]
3492    endif
3493  else
3494    execs = [{
3495      'name': 'qemu-' + target_name,
3496      'win_subsystem': 'console',
3497      'sources': [],
3498      'dependencies': []
3499    }]
3500  endif
3501  foreach exe: execs
3502    exe_name = exe['name']
3503    if targetos == 'darwin'
3504      exe_name += '-unsigned'
3505    endif
3506
3507    emulator = executable(exe_name, exe['sources'],
3508               install: true,
3509               c_args: c_args,
3510               dependencies: arch_deps + deps + exe['dependencies'],
3511               objects: lib.extract_all_objects(recursive: true),
3512               link_language: link_language,
3513               link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
3514               link_args: link_args,
3515               win_subsystem: exe['win_subsystem'])
3516
3517    if targetos == 'darwin'
3518      icon = 'pc-bios/qemu.rsrc'
3519      build_input = [emulator, files(icon)]
3520      install_input = [
3521        get_option('bindir') / exe_name,
3522        meson.current_source_dir() / icon
3523      ]
3524      if 'CONFIG_HVF' in config_target
3525        entitlements = 'accel/hvf/entitlements.plist'
3526        build_input += files(entitlements)
3527        install_input += meson.current_source_dir() / entitlements
3528      endif
3529
3530      emulators += {exe['name'] : custom_target(exe['name'],
3531                   input: build_input,
3532                   output: exe['name'],
3533                   command: [entitlement, '@OUTPUT@', '@INPUT@'])
3534      }
3535
3536      meson.add_install_script(entitlement, '--install',
3537                               get_option('bindir') / exe['name'],
3538                               install_input)
3539    else
3540      emulators += {exe['name']: emulator}
3541    endif
3542
3543    if stap.found()
3544      foreach stp: [
3545        {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
3546        {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
3547        {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
3548        {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
3549      ]
3550        custom_target(exe['name'] + stp['ext'],
3551                      input: trace_events_all,
3552                      output: exe['name'] + stp['ext'],
3553                      install: stp['install'],
3554                      install_dir: get_option('datadir') / 'systemtap/tapset',
3555                      command: [
3556                        tracetool, '--group=all', '--format=' + stp['fmt'],
3557                        '--binary=' + stp['bin'],
3558                        '--target-name=' + target_name,
3559                        '--target-type=' + target_type,
3560                        '--probe-prefix=qemu.' + target_type + '.' + target_name,
3561                        '@INPUT@', '@OUTPUT@'
3562                      ],
3563                      depend_files: tracetool_depends)
3564      endforeach
3565    endif
3566  endforeach
3567endforeach
3568
3569# Other build targets
3570
3571if 'CONFIG_PLUGIN' in config_host
3572  install_headers('include/qemu/qemu-plugin.h')
3573endif
3574
3575subdir('qga')
3576
3577# Don't build qemu-keymap if xkbcommon is not explicitly enabled
3578# when we don't build tools or system
3579if xkbcommon.found()
3580  # used for the update-keymaps target, so include rules even if !have_tools
3581  qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
3582                           dependencies: [qemuutil, xkbcommon], install: have_tools)
3583endif
3584
3585if have_tools
3586  qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
3587             dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
3588  qemu_io = executable('qemu-io', files('qemu-io.c'),
3589             dependencies: [block, qemuutil], install: true)
3590  qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
3591               dependencies: [blockdev, qemuutil, gnutls, selinux],
3592               install: true)
3593
3594  subdir('storage-daemon')
3595  subdir('contrib/rdmacm-mux')
3596  subdir('contrib/elf2dmp')
3597
3598  executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
3599             dependencies: qemuutil,
3600             install: true)
3601
3602  if have_vhost_user
3603    subdir('contrib/vhost-user-blk')
3604    subdir('contrib/vhost-user-gpu')
3605    subdir('contrib/vhost-user-input')
3606    subdir('contrib/vhost-user-scsi')
3607  endif
3608
3609  if targetos == 'linux'
3610    executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
3611               dependencies: [qemuutil, libcap_ng],
3612               install: true,
3613               install_dir: get_option('libexecdir'))
3614
3615    executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
3616               dependencies: [authz, crypto, io, qom, qemuutil,
3617                              libcap_ng, mpathpersist],
3618               install: true)
3619  endif
3620
3621  if have_ivshmem
3622    subdir('contrib/ivshmem-client')
3623    subdir('contrib/ivshmem-server')
3624  endif
3625endif
3626
3627subdir('scripts')
3628subdir('tools')
3629subdir('pc-bios')
3630subdir('docs')
3631subdir('tests')
3632if gtk.found()
3633  subdir('po')
3634endif
3635
3636if host_machine.system() == 'windows'
3637  nsis_cmd = [
3638    find_program('scripts/nsis.py'),
3639    '@OUTPUT@',
3640    get_option('prefix'),
3641    meson.current_source_dir(),
3642    config_host['GLIB_BINDIR'],
3643    host_machine.cpu(),
3644    '--',
3645    '-DDISPLAYVERSION=' + meson.project_version(),
3646  ]
3647  if build_docs
3648    nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
3649  endif
3650  if gtk.found()
3651    nsis_cmd += '-DCONFIG_GTK=y'
3652  endif
3653
3654  nsis = custom_target('nsis',
3655                       output: 'qemu-setup-' + meson.project_version() + '.exe',
3656                       input: files('qemu.nsi'),
3657                       build_always_stale: true,
3658                       command: nsis_cmd + ['@INPUT@'])
3659  alias_target('installer', nsis)
3660endif
3661
3662#########################
3663# Configuration summary #
3664#########################
3665
3666# Directories
3667summary_info = {}
3668summary_info += {'Install prefix':    get_option('prefix')}
3669summary_info += {'BIOS directory':    qemu_datadir}
3670pathsep = targetos == 'windows' ? ';' : ':'
3671summary_info += {'firmware path':     pathsep.join(get_option('qemu_firmwarepath'))}
3672summary_info += {'binary directory':  get_option('prefix') / get_option('bindir')}
3673summary_info += {'library directory': get_option('prefix') / get_option('libdir')}
3674summary_info += {'module directory':  qemu_moddir}
3675summary_info += {'libexec directory': get_option('prefix') / get_option('libexecdir')}
3676summary_info += {'include directory': get_option('prefix') / get_option('includedir')}
3677summary_info += {'config directory':  get_option('prefix') / get_option('sysconfdir')}
3678if targetos != 'windows'
3679  summary_info += {'local state directory': get_option('prefix') / get_option('localstatedir')}
3680  summary_info += {'Manual directory':      get_option('prefix') / get_option('mandir')}
3681else
3682  summary_info += {'local state directory': 'queried at runtime'}
3683endif
3684summary_info += {'Doc directory':     get_option('prefix') / get_option('docdir')}
3685summary_info += {'Build directory':   meson.current_build_dir()}
3686summary_info += {'Source path':       meson.current_source_dir()}
3687summary_info += {'GIT submodules':    config_host['GIT_SUBMODULES']}
3688summary(summary_info, bool_yn: true, section: 'Directories')
3689
3690# Host binaries
3691summary_info = {}
3692summary_info += {'git':               config_host['GIT']}
3693summary_info += {'make':              config_host['MAKE']}
3694summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
3695summary_info += {'sphinx-build':      sphinx_build}
3696if config_host.has_key('HAVE_GDB_BIN')
3697  summary_info += {'gdb':             config_host['HAVE_GDB_BIN']}
3698endif
3699summary_info += {'iasl':              iasl}
3700summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
3701if targetos == 'windows' and have_ga
3702  summary_info += {'wixl':            wixl}
3703endif
3704if slirp.found() and have_system
3705  summary_info += {'smbd':            have_slirp_smbd ? smbd_path : false}
3706endif
3707summary(summary_info, bool_yn: true, section: 'Host binaries')
3708
3709# Configurable features
3710summary_info = {}
3711summary_info += {'Documentation':     build_docs}
3712summary_info += {'system-mode emulation': have_system}
3713summary_info += {'user-mode emulation': have_user}
3714summary_info += {'block layer':       have_block}
3715summary_info += {'Install blobs':     get_option('install_blobs')}
3716summary_info += {'module support':    config_host.has_key('CONFIG_MODULES')}
3717if config_host.has_key('CONFIG_MODULES')
3718  summary_info += {'alternative module path': get_option('module_upgrades')}
3719endif
3720summary_info += {'fuzzing support':   get_option('fuzzing')}
3721if have_system
3722  summary_info += {'Audio drivers':     ' '.join(audio_drivers_selected)}
3723endif
3724summary_info += {'Trace backends':    ','.join(get_option('trace_backends'))}
3725if 'simple' in get_option('trace_backends')
3726  summary_info += {'Trace output file': get_option('trace_file') + '-<pid>'}
3727endif
3728summary_info += {'D-Bus display':     dbus_display}
3729summary_info += {'QOM debugging':     get_option('qom_cast_debug')}
3730summary_info += {'vhost-kernel support': have_vhost_kernel}
3731summary_info += {'vhost-net support': have_vhost_net}
3732summary_info += {'vhost-user support': have_vhost_user}
3733summary_info += {'vhost-user-crypto support': have_vhost_user_crypto}
3734summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
3735summary_info += {'vhost-vdpa support': have_vhost_vdpa}
3736summary_info += {'build guest agent': have_ga}
3737summary(summary_info, bool_yn: true, section: 'Configurable features')
3738
3739# Compilation information
3740summary_info = {}
3741summary_info += {'host CPU':          cpu}
3742summary_info += {'host endianness':   build_machine.endian()}
3743summary_info += {'C compiler':        ' '.join(meson.get_compiler('c').cmd_array())}
3744summary_info += {'Host C compiler':   ' '.join(meson.get_compiler('c', native: true).cmd_array())}
3745if link_language == 'cpp'
3746  summary_info += {'C++ compiler':    ' '.join(meson.get_compiler('cpp').cmd_array())}
3747else
3748  summary_info += {'C++ compiler':      false}
3749endif
3750if targetos == 'darwin'
3751  summary_info += {'Objective-C compiler': ' '.join(meson.get_compiler('objc').cmd_array())}
3752endif
3753summary_info += {'CFLAGS':            ' '.join(get_option('c_args')
3754                                               + ['-O' + get_option('optimization')]
3755                                               + (get_option('debug') ? ['-g'] : []))}
3756if link_language == 'cpp'
3757  summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args')
3758                                               + ['-O' + get_option('optimization')]
3759                                               + (get_option('debug') ? ['-g'] : []))}
3760endif
3761if targetos == 'darwin'
3762  summary_info += {'OBJCFLAGS':       ' '.join(get_option('objc_args')
3763                                               + ['-O' + get_option('optimization')]
3764                                               + (get_option('debug') ? ['-g'] : []))}
3765endif
3766link_args = get_option(link_language + '_link_args')
3767if link_args.length() > 0
3768  summary_info += {'LDFLAGS':         ' '.join(link_args)}
3769endif
3770summary_info += {'QEMU_CFLAGS':       ' '.join(qemu_cflags)}
3771summary_info += {'QEMU_CXXFLAGS':     ' '.join(qemu_cxxflags)}
3772summary_info += {'QEMU_OBJCFLAGS':    ' '.join(qemu_objcflags)}
3773summary_info += {'QEMU_LDFLAGS':      ' '.join(qemu_ldflags)}
3774summary_info += {'profiler':          get_option('profiler')}
3775summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
3776summary_info += {'PIE':               get_option('b_pie')}
3777summary_info += {'static build':      config_host.has_key('CONFIG_STATIC')}
3778summary_info += {'malloc trim support': has_malloc_trim}
3779summary_info += {'membarrier':        have_membarrier}
3780summary_info += {'debug stack usage': get_option('debug_stack_usage')}
3781summary_info += {'mutex debugging':   get_option('debug_mutex')}
3782summary_info += {'memory allocator':  get_option('malloc')}
3783summary_info += {'avx2 optimization': config_host_data.get('CONFIG_AVX2_OPT')}
3784summary_info += {'avx512f optimization': config_host_data.get('CONFIG_AVX512F_OPT')}
3785summary_info += {'gprof enabled':     get_option('gprof')}
3786summary_info += {'gcov':              get_option('b_coverage')}
3787summary_info += {'thread sanitizer':  config_host.has_key('CONFIG_TSAN')}
3788summary_info += {'CFI support':       get_option('cfi')}
3789if get_option('cfi')
3790  summary_info += {'CFI debug support': get_option('cfi_debug')}
3791endif
3792summary_info += {'strip binaries':    get_option('strip')}
3793summary_info += {'sparse':            sparse}
3794summary_info += {'mingw32 support':   targetos == 'windows'}
3795summary(summary_info, bool_yn: true, section: 'Compilation')
3796
3797# snarf the cross-compilation information for tests
3798summary_info = {}
3799have_cross = false
3800foreach target: target_dirs
3801  tcg_mak = meson.current_build_dir() / 'tests/tcg' / target / 'config-target.mak'
3802  if fs.exists(tcg_mak)
3803    config_cross_tcg = keyval.load(tcg_mak)
3804    if 'CC' in config_cross_tcg
3805      summary_info += {config_cross_tcg['TARGET_NAME']: config_cross_tcg['CC']}
3806      have_cross = true
3807    endif
3808  endif
3809endforeach
3810if have_cross
3811  summary(summary_info, bool_yn: true, section: 'Cross compilers')
3812endif
3813
3814# Targets and accelerators
3815summary_info = {}
3816if have_system
3817  summary_info += {'KVM support':       config_all.has_key('CONFIG_KVM')}
3818  summary_info += {'HAX support':       config_all.has_key('CONFIG_HAX')}
3819  summary_info += {'HVF support':       config_all.has_key('CONFIG_HVF')}
3820  summary_info += {'WHPX support':      config_all.has_key('CONFIG_WHPX')}
3821  summary_info += {'NVMM support':      config_all.has_key('CONFIG_NVMM')}
3822  summary_info += {'Xen support':       xen.found()}
3823  if xen.found()
3824    summary_info += {'xen ctrl version':  xen.version()}
3825  endif
3826endif
3827summary_info += {'TCG support':       config_all.has_key('CONFIG_TCG')}
3828if config_all.has_key('CONFIG_TCG')
3829  if get_option('tcg_interpreter')
3830    summary_info += {'TCG backend':   'TCI (TCG with bytecode interpreter, slow)'}
3831  else
3832    summary_info += {'TCG backend':   'native (@0@)'.format(cpu)}
3833  endif
3834  summary_info += {'TCG plugins': config_host.has_key('CONFIG_PLUGIN')}
3835  summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')}
3836endif
3837summary_info += {'target list':       ' '.join(target_dirs)}
3838if have_system
3839  summary_info += {'default devices':   get_option('default_devices')}
3840  summary_info += {'out of process emulation': multiprocess_allowed}
3841  summary_info += {'vfio-user server': vfio_user_server_allowed}
3842endif
3843summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
3844
3845# Block layer
3846summary_info = {}
3847summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']}
3848summary_info += {'coroutine pool':    have_coroutine_pool}
3849if have_block
3850  summary_info += {'Block whitelist (rw)': get_option('block_drv_rw_whitelist')}
3851  summary_info += {'Block whitelist (ro)': get_option('block_drv_ro_whitelist')}
3852  summary_info += {'Use block whitelist in tools': get_option('block_drv_whitelist_in_tools')}
3853  summary_info += {'VirtFS support':    have_virtfs}
3854  summary_info += {'build virtiofs daemon': have_virtiofsd}
3855  summary_info += {'Live block migration': config_host_data.get('CONFIG_LIVE_BLOCK_MIGRATION')}
3856  summary_info += {'replication support': config_host_data.get('CONFIG_REPLICATION')}
3857  summary_info += {'bochs support':     get_option('bochs').allowed()}
3858  summary_info += {'cloop support':     get_option('cloop').allowed()}
3859  summary_info += {'dmg support':       get_option('dmg').allowed()}
3860  summary_info += {'qcow v1 support':   get_option('qcow1').allowed()}
3861  summary_info += {'vdi support':       get_option('vdi').allowed()}
3862  summary_info += {'vvfat support':     get_option('vvfat').allowed()}
3863  summary_info += {'qed support':       get_option('qed').allowed()}
3864  summary_info += {'parallels support': get_option('parallels').allowed()}
3865  summary_info += {'FUSE exports':      fuse}
3866  summary_info += {'VDUSE block exports': have_vduse_blk_export}
3867endif
3868summary(summary_info, bool_yn: true, section: 'Block layer support')
3869
3870# Crypto
3871summary_info = {}
3872summary_info += {'TLS priority':      get_option('tls_priority')}
3873summary_info += {'GNUTLS support':    gnutls}
3874if gnutls.found()
3875  summary_info += {'  GNUTLS crypto':   gnutls_crypto.found()}
3876endif
3877summary_info += {'libgcrypt':         gcrypt}
3878summary_info += {'nettle':            nettle}
3879if nettle.found()
3880   summary_info += {'  XTS':             xts != 'private'}
3881endif
3882summary_info += {'AF_ALG support':    have_afalg}
3883summary_info += {'rng-none':          get_option('rng_none')}
3884summary_info += {'Linux keyring':     have_keyring}
3885summary(summary_info, bool_yn: true, section: 'Crypto')
3886
3887# Libraries
3888summary_info = {}
3889if targetos == 'darwin'
3890  summary_info += {'Cocoa support':           cocoa}
3891  summary_info += {'vmnet.framework support': vmnet}
3892endif
3893summary_info += {'SDL support':       sdl}
3894summary_info += {'SDL image support': sdl_image}
3895summary_info += {'GTK support':       gtk}
3896summary_info += {'pixman':            pixman}
3897summary_info += {'VTE support':       vte}
3898summary_info += {'slirp support':     slirp}
3899summary_info += {'libtasn1':          tasn1}
3900summary_info += {'PAM':               pam}
3901summary_info += {'iconv support':     iconv}
3902summary_info += {'curses support':    curses}
3903summary_info += {'virgl support':     virgl}
3904summary_info += {'blkio support':     blkio}
3905summary_info += {'curl support':      curl}
3906summary_info += {'Multipath support': mpathpersist}
3907summary_info += {'PNG support':       png}
3908summary_info += {'VNC support':       vnc}
3909if vnc.found()
3910  summary_info += {'VNC SASL support':  sasl}
3911  summary_info += {'VNC JPEG support':  jpeg}
3912endif
3913if targetos not in ['darwin', 'haiku', 'windows']
3914  summary_info += {'OSS support':     oss}
3915  summary_info += {'sndio support':   sndio}
3916elif targetos == 'darwin'
3917  summary_info += {'CoreAudio support': coreaudio}
3918elif targetos == 'windows'
3919  summary_info += {'DirectSound support': dsound}
3920endif
3921if targetos == 'linux'
3922  summary_info += {'ALSA support':    alsa}
3923  summary_info += {'PulseAudio support': pulse}
3924endif
3925summary_info += {'JACK support':      jack}
3926summary_info += {'brlapi support':    brlapi}
3927summary_info += {'vde support':       vde}
3928summary_info += {'netmap support':    have_netmap}
3929summary_info += {'l2tpv3 support':    have_l2tpv3}
3930summary_info += {'Linux AIO support': libaio}
3931summary_info += {'Linux io_uring support': linux_io_uring}
3932summary_info += {'ATTR/XATTR support': libattr}
3933summary_info += {'RDMA support':      rdma}
3934summary_info += {'PVRDMA support':    have_pvrdma}
3935summary_info += {'fdt support':       fdt_opt == 'disabled' ? false : fdt_opt}
3936summary_info += {'libcap-ng support': libcap_ng}
3937summary_info += {'bpf support':       libbpf}
3938summary_info += {'spice protocol support': spice_protocol}
3939if spice_protocol.found()
3940  summary_info += {'  spice server support': spice}
3941endif
3942summary_info += {'rbd support':       rbd}
3943summary_info += {'smartcard support': cacard}
3944summary_info += {'U2F support':       u2f}
3945summary_info += {'libusb':            libusb}
3946summary_info += {'usb net redir':     usbredir}
3947summary_info += {'OpenGL support (epoxy)': opengl}
3948summary_info += {'GBM':               gbm}
3949summary_info += {'libiscsi support':  libiscsi}
3950summary_info += {'libnfs support':    libnfs}
3951if targetos == 'windows'
3952  if have_ga
3953    summary_info += {'QGA VSS support':   have_qga_vss}
3954  endif
3955endif
3956summary_info += {'seccomp support':   seccomp}
3957summary_info += {'GlusterFS support': glusterfs}
3958summary_info += {'TPM support':       have_tpm}
3959summary_info += {'libssh support':    libssh}
3960summary_info += {'lzo support':       lzo}
3961summary_info += {'snappy support':    snappy}
3962summary_info += {'bzip2 support':     libbzip2}
3963summary_info += {'lzfse support':     liblzfse}
3964summary_info += {'zstd support':      zstd}
3965summary_info += {'NUMA host support': numa}
3966summary_info += {'capstone':          capstone}
3967summary_info += {'libpmem support':   libpmem}
3968summary_info += {'libdaxctl support': libdaxctl}
3969summary_info += {'libudev':           libudev}
3970# Dummy dependency, keep .found()
3971summary_info += {'FUSE lseek':        fuse_lseek.found()}
3972summary_info += {'selinux':           selinux}
3973summary(summary_info, bool_yn: true, section: 'Dependencies')
3974
3975if not supported_cpus.contains(cpu)
3976  message()
3977  warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!')
3978  message()
3979  message('CPU host architecture ' + cpu + ' support is not currently maintained.')
3980  message('The QEMU project intends to remove support for this host CPU in')
3981  message('a future release if nobody volunteers to maintain it and to')
3982  message('provide a build host for our continuous integration setup.')
3983  message('configure has succeeded and you can continue to build, but')
3984  message('if you care about QEMU on this platform you should contact')
3985  message('us upstream at qemu-devel@nongnu.org.')
3986endif
3987
3988if not supported_oses.contains(targetos)
3989  message()
3990  warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!')
3991  message()
3992  message('Host OS ' + targetos + 'support is not currently maintained.')
3993  message('The QEMU project intends to remove support for this host OS in')
3994  message('a future release if nobody volunteers to maintain it and to')
3995  message('provide a build host for our continuous integration setup.')
3996  message('configure has succeeded and you can continue to build, but')
3997  message('if you care about QEMU on this platform you should contact')
3998  message('us upstream at qemu-devel@nongnu.org.')
3999endif
4000