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