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