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