xref: /qemu/meson.build (revision 146b5fa505fc21baa129c7538936fbdd9875b6ed)
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                        '-fsanitize-coverage=trace-pc'] )
217    add_global_arguments('-fsanitize-coverage-allowlist=instrumentation-filter',
218                         native: false, language: ['c', 'cpp', 'objc'])
219  endif
220
221  if get_option('fuzzing_engine') == ''
222    # Add CFLAGS to tell clang to add fuzzer-related instrumentation to all the
223    # compiled code.  To build non-fuzzer binaries with --enable-fuzzing, link
224    # everything with fsanitize=fuzzer-no-link. Otherwise, the linker will be
225    # unable to bind the fuzzer-related callbacks added by instrumentation.
226    add_global_arguments('-fsanitize=fuzzer-no-link',
227                         native: false, language: ['c', 'cpp', 'objc'])
228    add_global_link_arguments('-fsanitize=fuzzer-no-link',
229                              native: false, language: ['c', 'cpp', 'objc'])
230    # For the actual fuzzer binaries, we need to link against the libfuzzer
231    # library. They need to be configurable, to support OSS-Fuzz
232    fuzz_exe_ldflags = ['-fsanitize=fuzzer']
233  else
234    # LIB_FUZZING_ENGINE was set; assume we are running on OSS-Fuzz, and
235    # the needed CFLAGS have already been provided
236    fuzz_exe_ldflags = get_option('fuzzing_engine').split()
237  endif
238endif
239
240add_global_arguments(qemu_cflags, native: false, language: ['c'])
241add_global_arguments(qemu_cxxflags, native: false, language: ['cpp'])
242add_global_arguments(qemu_objcflags, native: false, language: ['objc'])
243add_global_link_arguments(qemu_ldflags, native: false, language: ['c', 'cpp', 'objc'])
244
245if targetos == 'linux'
246  add_project_arguments('-isystem', meson.current_source_dir() / 'linux-headers',
247                        '-isystem', 'linux-headers',
248                        language: ['c', 'cpp'])
249endif
250
251add_project_arguments('-iquote', '.',
252                      '-iquote', meson.current_source_dir(),
253                      '-iquote', meson.current_source_dir() / 'include',
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', 'CoreVideo'],
587                   required: get_option('cocoa'))
588if cocoa.found() and get_option('sdl').enabled()
589  error('Cocoa and SDL cannot be enabled at the same time')
590endif
591if cocoa.found() and get_option('gtk').enabled()
592  error('Cocoa and GTK+ cannot be enabled at the same time')
593endif
594
595vmnet = dependency('appleframeworks', modules: 'vmnet', required: get_option('vmnet'))
596if vmnet.found() and not cc.has_header_symbol('vmnet/vmnet.h',
597                                              'VMNET_BRIDGED_MODE',
598                                              dependencies: vmnet)
599  vmnet = not_found
600  if get_option('vmnet').enabled()
601    error('vmnet.framework API is outdated')
602  else
603    warning('vmnet.framework API is outdated, disabling')
604  endif
605endif
606
607seccomp = not_found
608if not get_option('seccomp').auto() or have_system or have_tools
609  seccomp = dependency('libseccomp', version: '>=2.3.0',
610                       required: get_option('seccomp'),
611                       method: 'pkg-config', kwargs: static_kwargs)
612endif
613
614libcap_ng = not_found
615if not get_option('cap_ng').auto() or have_system or have_tools
616  libcap_ng = cc.find_library('cap-ng', has_headers: ['cap-ng.h'],
617                              required: get_option('cap_ng'),
618                              kwargs: static_kwargs)
619endif
620if libcap_ng.found() and not cc.links('''
621   #include <cap-ng.h>
622   int main(void)
623   {
624     capng_capability_to_name(CAPNG_EFFECTIVE);
625     return 0;
626   }''', dependencies: libcap_ng)
627  libcap_ng = not_found
628  if get_option('cap_ng').enabled()
629    error('could not link libcap-ng')
630  else
631    warning('could not link libcap-ng, disabling')
632  endif
633endif
634
635if get_option('xkbcommon').auto() and not have_system and not have_tools
636  xkbcommon = not_found
637else
638  xkbcommon = dependency('xkbcommon', required: get_option('xkbcommon'),
639                         method: 'pkg-config', kwargs: static_kwargs)
640endif
641
642vde = not_found
643if not get_option('vde').auto() or have_system or have_tools
644  vde = cc.find_library('vdeplug', has_headers: ['libvdeplug.h'],
645                           required: get_option('vde'),
646                           kwargs: static_kwargs)
647endif
648if vde.found() and not cc.links('''
649   #include <libvdeplug.h>
650   int main(void)
651   {
652     struct vde_open_args a = {0, 0, 0};
653     char s[] = "";
654     vde_open(s, s, &a);
655     return 0;
656   }''', dependencies: vde)
657  vde = not_found
658  if get_option('cap_ng').enabled()
659    error('could not link libvdeplug')
660  else
661    warning('could not link libvdeplug, disabling')
662  endif
663endif
664
665pulse = not_found
666if not get_option('pa').auto() or (targetos == 'linux' and have_system)
667  pulse = dependency('libpulse', required: get_option('pa'),
668                     method: 'pkg-config', kwargs: static_kwargs)
669endif
670alsa = not_found
671if not get_option('alsa').auto() or (targetos == 'linux' and have_system)
672  alsa = dependency('alsa', required: get_option('alsa'),
673                    method: 'pkg-config', kwargs: static_kwargs)
674endif
675jack = not_found
676if not get_option('jack').auto() or have_system
677  jack = dependency('jack', required: get_option('jack'),
678                    method: 'pkg-config', kwargs: static_kwargs)
679endif
680
681spice_protocol = not_found
682if not get_option('spice_protocol').auto() or have_system
683  spice_protocol = dependency('spice-protocol', version: '>=0.12.3',
684                              required: get_option('spice_protocol'),
685                              method: 'pkg-config', kwargs: static_kwargs)
686endif
687spice = not_found
688if not get_option('spice').auto() or have_system
689  spice = dependency('spice-server', version: '>=0.12.5',
690                     required: get_option('spice'),
691                     method: 'pkg-config', kwargs: static_kwargs)
692endif
693spice_headers = spice.partial_dependency(compile_args: true, includes: true)
694
695rt = cc.find_library('rt', required: false)
696
697libiscsi = not_found
698if not get_option('libiscsi').auto() or have_block
699  libiscsi = dependency('libiscsi', version: '>=1.9.0',
700                         required: get_option('libiscsi'),
701                         method: 'pkg-config', kwargs: static_kwargs)
702endif
703zstd = not_found
704if not get_option('zstd').auto() or have_block
705  zstd = dependency('libzstd', version: '>=1.4.0',
706                    required: get_option('zstd'),
707                    method: 'pkg-config', kwargs: static_kwargs)
708endif
709virgl = not_found
710
711have_vhost_user_gpu = have_tools and targetos == 'linux' and pixman.found()
712if not get_option('virglrenderer').auto() or have_system or have_vhost_user_gpu
713  virgl = dependency('virglrenderer',
714                     method: 'pkg-config',
715                     required: get_option('virglrenderer'),
716                     kwargs: static_kwargs)
717endif
718curl = not_found
719if not get_option('curl').auto() or have_block
720  curl = dependency('libcurl', version: '>=7.29.0',
721                    method: 'pkg-config',
722                    required: get_option('curl'),
723                    kwargs: static_kwargs)
724endif
725libudev = not_found
726if targetos == 'linux' and (have_system or have_tools)
727  libudev = dependency('libudev',
728                       method: 'pkg-config',
729                       required: get_option('libudev'),
730                       kwargs: static_kwargs)
731endif
732
733mpathlibs = [libudev]
734mpathpersist = not_found
735mpathpersist_new_api = false
736if targetos == 'linux' and have_tools and get_option('mpath').allowed()
737  mpath_test_source_new = '''
738    #include <libudev.h>
739    #include <mpath_persist.h>
740    unsigned mpath_mx_alloc_len = 1024;
741    int logsink;
742    static struct config *multipath_conf;
743    extern struct udev *udev;
744    extern struct config *get_multipath_config(void);
745    extern void put_multipath_config(struct config *conf);
746    struct udev *udev;
747    struct config *get_multipath_config(void) { return multipath_conf; }
748    void put_multipath_config(struct config *conf) { }
749    int main(void) {
750        udev = udev_new();
751        multipath_conf = mpath_lib_init();
752        return 0;
753    }'''
754  mpath_test_source_old = '''
755      #include <libudev.h>
756      #include <mpath_persist.h>
757      unsigned mpath_mx_alloc_len = 1024;
758      int logsink;
759      int main(void) {
760          struct udev *udev = udev_new();
761          mpath_lib_init(udev);
762          return 0;
763      }'''
764  libmpathpersist = cc.find_library('mpathpersist',
765                                    required: get_option('mpath'),
766                                    kwargs: static_kwargs)
767  if libmpathpersist.found()
768    mpathlibs += libmpathpersist
769    if enable_static
770      mpathlibs += cc.find_library('devmapper',
771                                     required: get_option('mpath'),
772                                     kwargs: static_kwargs)
773    endif
774    mpathlibs += cc.find_library('multipath',
775                                 required: get_option('mpath'),
776                                 kwargs: static_kwargs)
777    foreach lib: mpathlibs
778      if not lib.found()
779        mpathlibs = []
780        break
781      endif
782    endforeach
783    if mpathlibs.length() == 0
784      msg = 'Dependencies missing for libmpathpersist'
785    elif cc.links(mpath_test_source_new, dependencies: mpathlibs)
786      mpathpersist = declare_dependency(dependencies: mpathlibs)
787      mpathpersist_new_api = true
788    elif cc.links(mpath_test_source_old, dependencies: mpathlibs)
789      mpathpersist = declare_dependency(dependencies: mpathlibs)
790    else
791      msg = 'Cannot detect libmpathpersist API'
792    endif
793    if not mpathpersist.found()
794      if get_option('mpath').enabled()
795        error(msg)
796      else
797        warning(msg + ', disabling')
798      endif
799    endif
800  endif
801endif
802
803iconv = not_found
804curses = not_found
805if have_system and get_option('curses').allowed()
806  curses_test = '''
807    #if defined(__APPLE__) || defined(__OpenBSD__)
808    #define _XOPEN_SOURCE_EXTENDED 1
809    #endif
810    #include <locale.h>
811    #include <curses.h>
812    #include <wchar.h>
813    int main(void) {
814      wchar_t wch = L'w';
815      setlocale(LC_ALL, "");
816      resize_term(0, 0);
817      addwstr(L"wide chars\n");
818      addnwstr(&wch, 1);
819      add_wch(WACS_DEGREE);
820      return 0;
821    }'''
822
823  curses_dep_list = targetos == 'windows' ? ['ncurses', 'ncursesw'] : ['ncursesw']
824  foreach curses_dep : curses_dep_list
825    if not curses.found()
826      curses = dependency(curses_dep,
827                          required: false,
828                          method: 'pkg-config',
829                          kwargs: static_kwargs)
830    endif
831  endforeach
832  msg = get_option('curses').enabled() ? 'curses library not found' : ''
833  curses_compile_args = ['-DNCURSES_WIDECHAR=1']
834  if curses.found()
835    if cc.links(curses_test, args: curses_compile_args, dependencies: [curses])
836      curses = declare_dependency(compile_args: curses_compile_args, dependencies: [curses])
837    else
838      msg = 'curses package not usable'
839      curses = not_found
840    endif
841  endif
842  if not curses.found()
843    has_curses_h = cc.has_header('curses.h', args: curses_compile_args)
844    if targetos != 'windows' and not has_curses_h
845      message('Trying with /usr/include/ncursesw')
846      curses_compile_args += ['-I/usr/include/ncursesw']
847      has_curses_h = cc.has_header('curses.h', args: curses_compile_args)
848    endif
849    if has_curses_h
850      curses_libname_list = (targetos == 'windows' ? ['pdcurses'] : ['ncursesw', 'cursesw'])
851      foreach curses_libname : curses_libname_list
852        libcurses = cc.find_library(curses_libname,
853                                    required: false,
854                                    kwargs: static_kwargs)
855        if libcurses.found()
856          if cc.links(curses_test, args: curses_compile_args, dependencies: libcurses)
857            curses = declare_dependency(compile_args: curses_compile_args,
858                                        dependencies: [libcurses])
859            break
860          else
861            msg = 'curses library not usable'
862          endif
863        endif
864      endforeach
865    endif
866  endif
867  if get_option('iconv').allowed()
868    foreach link_args : [ ['-liconv'], [] ]
869      # Programs will be linked with glib and this will bring in libiconv on FreeBSD.
870      # We need to use libiconv if available because mixing libiconv's headers with
871      # the system libc does not work.
872      # However, without adding glib to the dependencies -L/usr/local/lib will not be
873      # included in the command line and libiconv will not be found.
874      if cc.links('''
875        #include <iconv.h>
876        int main(void) {
877          iconv_t conv = iconv_open("WCHAR_T", "UCS-2");
878          return conv != (iconv_t) -1;
879        }''', args: config_host['GLIB_CFLAGS'].split() + config_host['GLIB_LIBS'].split() + link_args)
880        iconv = declare_dependency(link_args: link_args, dependencies: glib)
881        break
882      endif
883    endforeach
884  endif
885  if curses.found() and not iconv.found()
886    if get_option('iconv').enabled()
887      error('iconv not available')
888    endif
889    msg = 'iconv required for curses UI but not available'
890    curses = not_found
891  endif
892  if not curses.found() and msg != ''
893    if get_option('curses').enabled()
894      error(msg)
895    else
896      warning(msg + ', disabling')
897    endif
898  endif
899endif
900
901brlapi = not_found
902if not get_option('brlapi').auto() or have_system
903  brlapi = cc.find_library('brlapi', has_headers: ['brlapi.h'],
904                         required: get_option('brlapi'),
905                         kwargs: static_kwargs)
906  if brlapi.found() and not cc.links('''
907     #include <brlapi.h>
908     #include <stddef.h>
909     int main(void) { return brlapi__openConnection (NULL, NULL, NULL); }''', dependencies: brlapi)
910    brlapi = not_found
911    if get_option('brlapi').enabled()
912      error('could not link brlapi')
913    else
914      warning('could not link brlapi, disabling')
915    endif
916  endif
917endif
918
919sdl = not_found
920if not get_option('sdl').auto() or (have_system and not cocoa.found())
921  sdl = dependency('sdl2', required: get_option('sdl'), kwargs: static_kwargs)
922  sdl_image = not_found
923endif
924if sdl.found()
925  # work around 2.0.8 bug
926  sdl = declare_dependency(compile_args: '-Wno-undef',
927                           dependencies: sdl)
928  sdl_image = dependency('SDL2_image', required: get_option('sdl_image'),
929                         method: 'pkg-config', kwargs: static_kwargs)
930else
931  if get_option('sdl_image').enabled()
932    error('sdl-image required, but SDL was @0@'.format(
933          get_option('sdl').disabled() ? 'disabled' : 'not found'))
934  endif
935  sdl_image = not_found
936endif
937
938rbd = not_found
939if not get_option('rbd').auto() or have_block
940  librados = cc.find_library('rados', required: get_option('rbd'),
941                             kwargs: static_kwargs)
942  librbd = cc.find_library('rbd', has_headers: ['rbd/librbd.h'],
943                           required: get_option('rbd'),
944                           kwargs: static_kwargs)
945  if librados.found() and librbd.found()
946    if cc.links('''
947      #include <stdio.h>
948      #include <rbd/librbd.h>
949      int main(void) {
950        rados_t cluster;
951        rados_create(&cluster, NULL);
952        #if LIBRBD_VERSION_CODE < LIBRBD_VERSION(1, 12, 0)
953        #error
954        #endif
955        return 0;
956      }''', dependencies: [librbd, librados])
957      rbd = declare_dependency(dependencies: [librbd, librados])
958    elif get_option('rbd').enabled()
959      error('librbd >= 1.12.0 required')
960    else
961      warning('librbd >= 1.12.0 not found, disabling')
962    endif
963  endif
964endif
965
966glusterfs = not_found
967glusterfs_ftruncate_has_stat = false
968glusterfs_iocb_has_stat = false
969if not get_option('glusterfs').auto() or have_block
970  glusterfs = dependency('glusterfs-api', version: '>=3',
971                         required: get_option('glusterfs'),
972                         method: 'pkg-config', kwargs: static_kwargs)
973  if glusterfs.found()
974    glusterfs_ftruncate_has_stat = cc.links('''
975      #include <glusterfs/api/glfs.h>
976
977      int
978      main(void)
979      {
980          /* new glfs_ftruncate() passes two additional args */
981          return glfs_ftruncate(NULL, 0, NULL, NULL);
982      }
983    ''', dependencies: glusterfs)
984    glusterfs_iocb_has_stat = cc.links('''
985      #include <glusterfs/api/glfs.h>
986
987      /* new glfs_io_cbk() passes two additional glfs_stat structs */
988      static void
989      glusterfs_iocb(glfs_fd_t *fd, ssize_t ret, struct glfs_stat *prestat, struct glfs_stat *poststat, void *data)
990      {}
991
992      int
993      main(void)
994      {
995          glfs_io_cbk iocb = &glusterfs_iocb;
996          iocb(NULL, 0 , NULL, NULL, NULL);
997          return 0;
998      }
999    ''', dependencies: glusterfs)
1000  endif
1001endif
1002
1003libssh = not_found
1004if not get_option('libssh').auto() or have_block
1005  libssh = dependency('libssh', version: '>=0.8.7',
1006                    method: 'pkg-config',
1007                    required: get_option('libssh'),
1008                    kwargs: static_kwargs)
1009endif
1010
1011libbzip2 = not_found
1012if not get_option('bzip2').auto() or have_block
1013  libbzip2 = cc.find_library('bz2', has_headers: ['bzlib.h'],
1014                             required: get_option('bzip2'),
1015                             kwargs: static_kwargs)
1016  if libbzip2.found() and not cc.links('''
1017     #include <bzlib.h>
1018     int main(void) { BZ2_bzlibVersion(); return 0; }''', dependencies: libbzip2)
1019    libbzip2 = not_found
1020    if get_option('bzip2').enabled()
1021      error('could not link libbzip2')
1022    else
1023      warning('could not link libbzip2, disabling')
1024    endif
1025  endif
1026endif
1027
1028liblzfse = not_found
1029if not get_option('lzfse').auto() or have_block
1030  liblzfse = cc.find_library('lzfse', has_headers: ['lzfse.h'],
1031                             required: get_option('lzfse'),
1032                             kwargs: static_kwargs)
1033endif
1034if liblzfse.found() and not cc.links('''
1035   #include <lzfse.h>
1036   int main(void) { lzfse_decode_scratch_size(); return 0; }''', dependencies: liblzfse)
1037  liblzfse = not_found
1038  if get_option('lzfse').enabled()
1039    error('could not link liblzfse')
1040  else
1041    warning('could not link liblzfse, disabling')
1042  endif
1043endif
1044
1045oss = not_found
1046if get_option('oss').allowed() and have_system
1047  if not cc.has_header('sys/soundcard.h')
1048    # not found
1049  elif targetos == 'netbsd'
1050    oss = cc.find_library('ossaudio', required: get_option('oss'),
1051                          kwargs: static_kwargs)
1052  else
1053    oss = declare_dependency()
1054  endif
1055
1056  if not oss.found()
1057    if get_option('oss').enabled()
1058      error('OSS not found')
1059    endif
1060  endif
1061endif
1062dsound = not_found
1063if not get_option('dsound').auto() or (targetos == 'windows' and have_system)
1064  if cc.has_header('dsound.h')
1065    dsound = declare_dependency(link_args: ['-lole32', '-ldxguid'])
1066  endif
1067
1068  if not dsound.found()
1069    if get_option('dsound').enabled()
1070      error('DirectSound not found')
1071    endif
1072  endif
1073endif
1074
1075coreaudio = not_found
1076if not get_option('coreaudio').auto() or (targetos == 'darwin' and have_system)
1077  coreaudio = dependency('appleframeworks', modules: 'CoreAudio',
1078                         required: get_option('coreaudio'))
1079endif
1080
1081opengl = not_found
1082if not get_option('opengl').auto() or have_system or have_vhost_user_gpu
1083  epoxy = dependency('epoxy', method: 'pkg-config',
1084                      required: get_option('opengl'), kwargs: static_kwargs)
1085  if cc.has_header('epoxy/egl.h', dependencies: epoxy)
1086    opengl = epoxy
1087  elif get_option('opengl').enabled()
1088    error('epoxy/egl.h not found')
1089  endif
1090endif
1091gbm = not_found
1092if (have_system or have_tools) and (virgl.found() or opengl.found())
1093  gbm = dependency('gbm', method: 'pkg-config', required: false,
1094                   kwargs: static_kwargs)
1095endif
1096have_vhost_user_gpu = have_vhost_user_gpu and virgl.found() and gbm.found()
1097
1098gnutls = not_found
1099gnutls_crypto = not_found
1100if get_option('gnutls').enabled() or (get_option('gnutls').auto() and have_system)
1101  # For general TLS support our min gnutls matches
1102  # that implied by our platform support matrix
1103  #
1104  # For the crypto backends, we look for a newer
1105  # gnutls:
1106  #
1107  #   Version 3.6.8  is needed to get XTS
1108  #   Version 3.6.13 is needed to get PBKDF
1109  #   Version 3.6.14 is needed to get HW accelerated XTS
1110  #
1111  # If newer enough gnutls isn't available, we can
1112  # still use a different crypto backend to satisfy
1113  # the platform support requirements
1114  gnutls_crypto = dependency('gnutls', version: '>=3.6.14',
1115                             method: 'pkg-config',
1116                             required: false,
1117                             kwargs: static_kwargs)
1118  if gnutls_crypto.found()
1119    gnutls = gnutls_crypto
1120  else
1121    # Our min version if all we need is TLS
1122    gnutls = dependency('gnutls', version: '>=3.5.18',
1123                        method: 'pkg-config',
1124                        required: get_option('gnutls'),
1125                        kwargs: static_kwargs)
1126  endif
1127endif
1128
1129# We prefer use of gnutls for crypto, unless the options
1130# explicitly asked for nettle or gcrypt.
1131#
1132# If gnutls isn't available for crypto, then we'll prefer
1133# gcrypt over nettle for performance reasons.
1134gcrypt = not_found
1135nettle = not_found
1136hogweed = not_found
1137xts = 'none'
1138
1139if get_option('nettle').enabled() and get_option('gcrypt').enabled()
1140  error('Only one of gcrypt & nettle can be enabled')
1141endif
1142
1143# Explicit nettle/gcrypt request, so ignore gnutls for crypto
1144if get_option('nettle').enabled() or get_option('gcrypt').enabled()
1145  gnutls_crypto = not_found
1146endif
1147
1148if not gnutls_crypto.found()
1149  if (not get_option('gcrypt').auto() or have_system) and not get_option('nettle').enabled()
1150    gcrypt = dependency('libgcrypt', version: '>=1.8',
1151                        method: 'config-tool',
1152                        required: get_option('gcrypt'),
1153                        kwargs: static_kwargs)
1154    # Debian has removed -lgpg-error from libgcrypt-config
1155    # as it "spreads unnecessary dependencies" which in
1156    # turn breaks static builds...
1157    if gcrypt.found() and enable_static
1158      gcrypt = declare_dependency(dependencies: [
1159        gcrypt,
1160        cc.find_library('gpg-error', required: true, kwargs: static_kwargs)])
1161    endif
1162  endif
1163  if (not get_option('nettle').auto() or have_system) and not gcrypt.found()
1164    nettle = dependency('nettle', version: '>=3.4',
1165                        method: 'pkg-config',
1166                        required: get_option('nettle'),
1167                        kwargs: static_kwargs)
1168    if nettle.found() and not cc.has_header('nettle/xts.h', dependencies: nettle)
1169      xts = 'private'
1170    endif
1171  endif
1172endif
1173
1174gmp = dependency('gmp', required: false, method: 'pkg-config', kwargs: static_kwargs)
1175if nettle.found() and gmp.found()
1176  hogweed = dependency('hogweed', version: '>=3.4',
1177                       method: 'pkg-config',
1178                       required: get_option('nettle'),
1179                       kwargs: static_kwargs)
1180endif
1181
1182
1183gtk = not_found
1184gtkx11 = not_found
1185vte = not_found
1186if not get_option('gtk').auto() or (have_system and not cocoa.found())
1187  gtk = dependency('gtk+-3.0', version: '>=3.22.0',
1188                   method: 'pkg-config',
1189                   required: get_option('gtk'),
1190                   kwargs: static_kwargs)
1191  if gtk.found()
1192    gtkx11 = dependency('gtk+-x11-3.0', version: '>=3.22.0',
1193                        method: 'pkg-config',
1194                        required: false,
1195                        kwargs: static_kwargs)
1196    gtk = declare_dependency(dependencies: [gtk, gtkx11])
1197
1198    if not get_option('vte').auto() or have_system
1199      vte = dependency('vte-2.91',
1200                       method: 'pkg-config',
1201                       required: get_option('vte'),
1202                       kwargs: static_kwargs)
1203    endif
1204  endif
1205endif
1206
1207x11 = not_found
1208if gtkx11.found()
1209  x11 = dependency('x11', method: 'pkg-config', required: gtkx11.found(),
1210                   kwargs: static_kwargs)
1211endif
1212png = not_found
1213if get_option('png').allowed() and have_system
1214   png = dependency('libpng', version: '>=1.6.34', required: get_option('png'),
1215                    method: 'pkg-config', kwargs: static_kwargs)
1216endif
1217vnc = not_found
1218jpeg = not_found
1219sasl = not_found
1220if get_option('vnc').allowed() and have_system
1221  vnc = declare_dependency() # dummy dependency
1222  jpeg = dependency('libjpeg', required: get_option('vnc_jpeg'),
1223                    method: 'pkg-config', kwargs: static_kwargs)
1224  sasl = cc.find_library('sasl2', has_headers: ['sasl/sasl.h'],
1225                         required: get_option('vnc_sasl'),
1226                         kwargs: static_kwargs)
1227  if sasl.found()
1228    sasl = declare_dependency(dependencies: sasl,
1229                              compile_args: '-DSTRUCT_IOVEC_DEFINED')
1230  endif
1231endif
1232
1233pam = not_found
1234if not get_option('auth_pam').auto() or have_system
1235  pam = cc.find_library('pam', has_headers: ['security/pam_appl.h'],
1236                        required: get_option('auth_pam'),
1237                        kwargs: static_kwargs)
1238endif
1239if pam.found() and not cc.links('''
1240   #include <stddef.h>
1241   #include <security/pam_appl.h>
1242   int main(void) {
1243     const char *service_name = "qemu";
1244     const char *user = "frank";
1245     const struct pam_conv pam_conv = { 0 };
1246     pam_handle_t *pamh = NULL;
1247     pam_start(service_name, user, &pam_conv, &pamh);
1248     return 0;
1249   }''', dependencies: pam)
1250  pam = not_found
1251  if get_option('auth_pam').enabled()
1252    error('could not link libpam')
1253  else
1254    warning('could not link libpam, disabling')
1255  endif
1256endif
1257
1258snappy = not_found
1259if not get_option('snappy').auto() or have_system
1260  snappy = cc.find_library('snappy', has_headers: ['snappy-c.h'],
1261                           required: get_option('snappy'),
1262                           kwargs: static_kwargs)
1263endif
1264if snappy.found() and not linker.links('''
1265   #include <snappy-c.h>
1266   int main(void) { snappy_max_compressed_length(4096); return 0; }''', dependencies: snappy)
1267  snappy = not_found
1268  if get_option('snappy').enabled()
1269    error('could not link libsnappy')
1270  else
1271    warning('could not link libsnappy, disabling')
1272  endif
1273endif
1274
1275lzo = not_found
1276if not get_option('lzo').auto() or have_system
1277  lzo = cc.find_library('lzo2', has_headers: ['lzo/lzo1x.h'],
1278                        required: get_option('lzo'),
1279                        kwargs: static_kwargs)
1280endif
1281if lzo.found() and not cc.links('''
1282   #include <lzo/lzo1x.h>
1283   int main(void) { lzo_version(); return 0; }''', dependencies: lzo)
1284  lzo = not_found
1285  if get_option('lzo').enabled()
1286    error('could not link liblzo2')
1287  else
1288    warning('could not link liblzo2, disabling')
1289  endif
1290endif
1291
1292numa = not_found
1293if not get_option('numa').auto() or have_system or have_tools
1294  numa = cc.find_library('numa', has_headers: ['numa.h'],
1295                              required: get_option('numa'),
1296                              kwargs: static_kwargs)
1297endif
1298if numa.found() and not cc.links('''
1299   #include <numa.h>
1300   int main(void) { return numa_available(); }
1301   ''', dependencies: numa)
1302  numa = not_found
1303  if get_option('numa').enabled()
1304    error('could not link numa')
1305  else
1306    warning('could not link numa, disabling')
1307  endif
1308endif
1309
1310rdma = not_found
1311if not get_option('rdma').auto() or have_system
1312  libumad = cc.find_library('ibumad', required: get_option('rdma'))
1313  rdma_libs = [cc.find_library('rdmacm', has_headers: ['rdma/rdma_cma.h'],
1314                               required: get_option('rdma'),
1315                               kwargs: static_kwargs),
1316               cc.find_library('ibverbs', required: get_option('rdma'),
1317                               kwargs: static_kwargs),
1318               libumad]
1319  rdma = declare_dependency(dependencies: rdma_libs)
1320  foreach lib: rdma_libs
1321    if not lib.found()
1322      rdma = not_found
1323    endif
1324  endforeach
1325endif
1326
1327xen = not_found
1328if get_option('xen').enabled() or (get_option('xen').auto() and have_system)
1329  xencontrol = dependency('xencontrol', required: false,
1330                          method: 'pkg-config', kwargs: static_kwargs)
1331  if xencontrol.found()
1332    xen_pc = declare_dependency(version: xencontrol.version(),
1333      dependencies: [
1334        xencontrol,
1335        # disabler: true makes xen_pc.found() return false if any is not found
1336        dependency('xenstore', required: false,
1337                   method: 'pkg-config', kwargs: static_kwargs,
1338                   disabler: true),
1339        dependency('xenforeignmemory', required: false,
1340                   method: 'pkg-config', kwargs: static_kwargs,
1341                   disabler: true),
1342        dependency('xengnttab', required: false,
1343                   method: 'pkg-config', kwargs: static_kwargs,
1344                   disabler: true),
1345        dependency('xenevtchn', required: false,
1346                   method: 'pkg-config', kwargs: static_kwargs,
1347                   disabler: true),
1348        dependency('xendevicemodel', required: false,
1349                   method: 'pkg-config', kwargs: static_kwargs,
1350                   disabler: true),
1351        # optional, no "disabler: true"
1352        dependency('xentoolcore', required: false,
1353                   method: 'pkg-config', kwargs: static_kwargs)])
1354    if xen_pc.found()
1355      xen = xen_pc
1356    endif
1357  endif
1358  if not xen.found()
1359    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' ]
1360    xen_libs = {
1361      '4.11.0': [ 'xenstore', 'xenctrl', 'xendevicemodel', 'xenforeignmemory', 'xengnttab', 'xenevtchn', 'xentoolcore' ],
1362      '4.10.0': [ 'xenstore', 'xenctrl', 'xendevicemodel', 'xenforeignmemory', 'xengnttab', 'xenevtchn', 'xentoolcore' ],
1363      '4.9.0': [ 'xenstore', 'xenctrl', 'xendevicemodel', 'xenforeignmemory', 'xengnttab', 'xenevtchn' ],
1364      '4.8.0': [ 'xenstore', 'xenctrl', 'xenforeignmemory', 'xengnttab', 'xenevtchn' ],
1365      '4.7.1': [ 'xenstore', 'xenctrl', 'xenforeignmemory', 'xengnttab', 'xenevtchn' ],
1366      '4.6.0': [ 'xenstore', 'xenctrl' ],
1367      '4.5.0': [ 'xenstore', 'xenctrl' ],
1368      '4.2.0': [ 'xenstore', 'xenctrl' ],
1369    }
1370    xen_deps = {}
1371    foreach ver: xen_tests
1372      # cache the various library tests to avoid polluting the logs
1373      xen_test_deps = []
1374      foreach l: xen_libs[ver]
1375        if l not in xen_deps
1376          xen_deps += { l: cc.find_library(l, required: false) }
1377        endif
1378        xen_test_deps += xen_deps[l]
1379      endforeach
1380
1381      # Use -D to pick just one of the test programs in scripts/xen-detect.c
1382      xen_version = ver.split('.')
1383      xen_ctrl_version = xen_version[0] + \
1384        ('0' + xen_version[1]).substring(-2) + \
1385        ('0' + xen_version[2]).substring(-2)
1386      if cc.links(files('scripts/xen-detect.c'),
1387                  args: '-DCONFIG_XEN_CTRL_INTERFACE_VERSION=' + xen_ctrl_version,
1388                  dependencies: xen_test_deps)
1389        xen = declare_dependency(version: ver, dependencies: xen_test_deps)
1390        break
1391      endif
1392    endforeach
1393  endif
1394  if xen.found()
1395    accelerators += 'CONFIG_XEN'
1396  elif get_option('xen').enabled()
1397    error('could not compile and link Xen test program')
1398  endif
1399endif
1400have_xen_pci_passthrough = get_option('xen_pci_passthrough') \
1401  .require(xen.found(),
1402           error_message: 'Xen PCI passthrough requested but Xen not enabled') \
1403  .require(targetos == 'linux',
1404           error_message: 'Xen PCI passthrough not available on this platform') \
1405  .allowed()
1406
1407
1408cacard = not_found
1409if not get_option('smartcard').auto() or have_system
1410  cacard = dependency('libcacard', required: get_option('smartcard'),
1411                      version: '>=2.5.1', method: 'pkg-config',
1412                      kwargs: static_kwargs)
1413endif
1414u2f = not_found
1415if have_system
1416  u2f = dependency('u2f-emu', required: get_option('u2f'),
1417                   method: 'pkg-config',
1418                   kwargs: static_kwargs)
1419endif
1420canokey = not_found
1421if have_system
1422  canokey = dependency('canokey-qemu', required: get_option('canokey'),
1423                   method: 'pkg-config',
1424                   kwargs: static_kwargs)
1425endif
1426usbredir = not_found
1427if not get_option('usb_redir').auto() or have_system
1428  usbredir = dependency('libusbredirparser-0.5', required: get_option('usb_redir'),
1429                        version: '>=0.6', method: 'pkg-config',
1430                        kwargs: static_kwargs)
1431endif
1432libusb = not_found
1433if not get_option('libusb').auto() or have_system
1434  libusb = dependency('libusb-1.0', required: get_option('libusb'),
1435                      version: '>=1.0.13', method: 'pkg-config',
1436                      kwargs: static_kwargs)
1437endif
1438
1439libpmem = not_found
1440if not get_option('libpmem').auto() or have_system
1441  libpmem = dependency('libpmem', required: get_option('libpmem'),
1442                       method: 'pkg-config', kwargs: static_kwargs)
1443endif
1444libdaxctl = not_found
1445if not get_option('libdaxctl').auto() or have_system
1446  libdaxctl = dependency('libdaxctl', required: get_option('libdaxctl'),
1447                         version: '>=57', method: 'pkg-config',
1448                         kwargs: static_kwargs)
1449endif
1450tasn1 = not_found
1451if gnutls.found()
1452  tasn1 = dependency('libtasn1',
1453                     method: 'pkg-config',
1454                     kwargs: static_kwargs)
1455endif
1456keyutils = dependency('libkeyutils', required: false,
1457                      method: 'pkg-config', kwargs: static_kwargs)
1458
1459has_gettid = cc.has_function('gettid')
1460
1461# libselinux
1462selinux = dependency('libselinux',
1463                     required: get_option('selinux'),
1464                     method: 'pkg-config', kwargs: static_kwargs)
1465
1466# Malloc tests
1467
1468malloc = []
1469if get_option('malloc') == 'system'
1470  has_malloc_trim = \
1471    get_option('malloc_trim').allowed() and \
1472    cc.links('''#include <malloc.h>
1473                int main(void) { malloc_trim(0); return 0; }''')
1474else
1475  has_malloc_trim = false
1476  malloc = cc.find_library(get_option('malloc'), required: true)
1477endif
1478if not has_malloc_trim and get_option('malloc_trim').enabled()
1479  if get_option('malloc') == 'system'
1480    error('malloc_trim not available on this platform.')
1481  else
1482    error('malloc_trim not available with non-libc memory allocator')
1483  endif
1484endif
1485
1486# Check whether the glibc provides statx()
1487
1488gnu_source_prefix = '''
1489  #ifndef _GNU_SOURCE
1490  #define _GNU_SOURCE
1491  #endif
1492'''
1493statx_test = gnu_source_prefix + '''
1494  #include <sys/stat.h>
1495  int main(void) {
1496    struct statx statxbuf;
1497    statx(0, "", 0, STATX_BASIC_STATS, &statxbuf);
1498    return 0;
1499  }'''
1500
1501has_statx = cc.links(statx_test)
1502
1503# Check whether statx() provides mount ID information
1504
1505statx_mnt_id_test = gnu_source_prefix + '''
1506  #include <sys/stat.h>
1507  int main(void) {
1508    struct statx statxbuf;
1509    statx(0, "", 0, STATX_BASIC_STATS | STATX_MNT_ID, &statxbuf);
1510    return statxbuf.stx_mnt_id;
1511  }'''
1512
1513has_statx_mnt_id = cc.links(statx_mnt_id_test)
1514
1515have_vhost_user_blk_server = get_option('vhost_user_blk_server') \
1516  .require(targetos == 'linux',
1517           error_message: 'vhost_user_blk_server requires linux') \
1518  .require(have_vhost_user,
1519           error_message: 'vhost_user_blk_server requires vhost-user support') \
1520  .disable_auto_if(not have_tools and not have_system) \
1521  .allowed()
1522
1523if get_option('fuse').disabled() and get_option('fuse_lseek').enabled()
1524  error('Cannot enable fuse-lseek while fuse is disabled')
1525endif
1526
1527fuse = dependency('fuse3', required: get_option('fuse'),
1528                  version: '>=3.1', method: 'pkg-config',
1529                  kwargs: static_kwargs)
1530
1531fuse_lseek = not_found
1532if get_option('fuse_lseek').allowed()
1533  if fuse.version().version_compare('>=3.8')
1534    # Dummy dependency
1535    fuse_lseek = declare_dependency()
1536  elif get_option('fuse_lseek').enabled()
1537    if fuse.found()
1538      error('fuse-lseek requires libfuse >=3.8, found ' + fuse.version())
1539    else
1540      error('fuse-lseek requires libfuse, which was not found')
1541    endif
1542  endif
1543endif
1544
1545have_libvduse = (targetos == 'linux')
1546if get_option('libvduse').enabled()
1547    if targetos != 'linux'
1548        error('libvduse requires linux')
1549    endif
1550elif get_option('libvduse').disabled()
1551    have_libvduse = false
1552endif
1553
1554have_vduse_blk_export = (have_libvduse and targetos == 'linux')
1555if get_option('vduse_blk_export').enabled()
1556    if targetos != 'linux'
1557        error('vduse_blk_export requires linux')
1558    elif not have_libvduse
1559        error('vduse_blk_export requires libvduse support')
1560    endif
1561elif get_option('vduse_blk_export').disabled()
1562    have_vduse_blk_export = false
1563endif
1564
1565# libbpf
1566libbpf = dependency('libbpf', required: get_option('bpf'), method: 'pkg-config')
1567if libbpf.found() and not cc.links('''
1568   #include <bpf/libbpf.h>
1569   int main(void)
1570   {
1571     bpf_object__destroy_skeleton(NULL);
1572     return 0;
1573   }''', dependencies: libbpf)
1574  libbpf = not_found
1575  if get_option('bpf').enabled()
1576    error('libbpf skeleton test failed')
1577  else
1578    warning('libbpf skeleton test failed, disabling')
1579  endif
1580endif
1581
1582#################
1583# config-host.h #
1584#################
1585
1586audio_drivers_selected = []
1587if have_system
1588  audio_drivers_available = {
1589    'alsa': alsa.found(),
1590    'coreaudio': coreaudio.found(),
1591    'dsound': dsound.found(),
1592    'jack': jack.found(),
1593    'oss': oss.found(),
1594    'pa': pulse.found(),
1595    'sdl': sdl.found(),
1596  }
1597  foreach k, v: audio_drivers_available
1598    config_host_data.set('CONFIG_AUDIO_' + k.to_upper(), v)
1599  endforeach
1600
1601  # Default to native drivers first, OSS second, SDL third
1602  audio_drivers_priority = \
1603    [ 'pa', 'coreaudio', 'dsound', 'oss' ] + \
1604    (targetos == 'linux' ? [] : [ 'sdl' ])
1605  audio_drivers_default = []
1606  foreach k: audio_drivers_priority
1607    if audio_drivers_available[k]
1608      audio_drivers_default += k
1609    endif
1610  endforeach
1611
1612  foreach k: get_option('audio_drv_list')
1613    if k == 'default'
1614      audio_drivers_selected += audio_drivers_default
1615    elif not audio_drivers_available[k]
1616      error('Audio driver "@0@" not available.'.format(k))
1617    else
1618      audio_drivers_selected += k
1619    endif
1620  endforeach
1621endif
1622config_host_data.set('CONFIG_AUDIO_DRIVERS',
1623                     '"' + '", "'.join(audio_drivers_selected) + '", ')
1624
1625if get_option('cfi')
1626  cfi_flags=[]
1627  # Check for dependency on LTO
1628  if not get_option('b_lto')
1629    error('Selected Control-Flow Integrity but LTO is disabled')
1630  endif
1631  if config_host.has_key('CONFIG_MODULES')
1632    error('Selected Control-Flow Integrity is not compatible with modules')
1633  endif
1634  # Check for cfi flags. CFI requires LTO so we can't use
1635  # get_supported_arguments, but need a more complex "compiles" which allows
1636  # custom arguments
1637  if cc.compiles('int main () { return 0; }', name: '-fsanitize=cfi-icall',
1638                 args: ['-flto', '-fsanitize=cfi-icall'] )
1639    cfi_flags += '-fsanitize=cfi-icall'
1640  else
1641    error('-fsanitize=cfi-icall is not supported by the compiler')
1642  endif
1643  if cc.compiles('int main () { return 0; }',
1644                 name: '-fsanitize-cfi-icall-generalize-pointers',
1645                 args: ['-flto', '-fsanitize=cfi-icall',
1646                        '-fsanitize-cfi-icall-generalize-pointers'] )
1647    cfi_flags += '-fsanitize-cfi-icall-generalize-pointers'
1648  else
1649    error('-fsanitize-cfi-icall-generalize-pointers is not supported by the compiler')
1650  endif
1651  if get_option('cfi_debug')
1652    if cc.compiles('int main () { return 0; }',
1653                   name: '-fno-sanitize-trap=cfi-icall',
1654                   args: ['-flto', '-fsanitize=cfi-icall',
1655                          '-fno-sanitize-trap=cfi-icall'] )
1656      cfi_flags += '-fno-sanitize-trap=cfi-icall'
1657    else
1658      error('-fno-sanitize-trap=cfi-icall is not supported by the compiler')
1659    endif
1660  endif
1661  add_global_arguments(cfi_flags, native: false, language: ['c', 'cpp', 'objc'])
1662  add_global_link_arguments(cfi_flags, native: false, language: ['c', 'cpp', 'objc'])
1663endif
1664
1665have_host_block_device = (targetos != 'darwin' or
1666    cc.has_header('IOKit/storage/IOMedia.h'))
1667
1668# FIXME enable_modules shouldn't be necessary, but: https://github.com/mesonbuild/meson/issues/8333
1669dbus_display = get_option('dbus_display') \
1670  .require(gio.version().version_compare('>=2.64'),
1671           error_message: '-display dbus requires glib>=2.64') \
1672  .require(enable_modules,
1673           error_message: '-display dbus requires --enable-modules') \
1674  .require(gdbus_codegen.found(),
1675           error_message: '-display dbus requires gdbus-codegen') \
1676  .require(opengl.found(),
1677           error_message: '-display dbus requires epoxy/egl') \
1678  .allowed()
1679
1680have_virtfs = get_option('virtfs') \
1681    .require(targetos == 'linux' or targetos == 'darwin',
1682             error_message: 'virtio-9p (virtfs) requires Linux or macOS') \
1683    .require(targetos == 'linux' or cc.has_function('pthread_fchdir_np'),
1684             error_message: 'virtio-9p (virtfs) on macOS requires the presence of pthread_fchdir_np') \
1685    .require(targetos == 'darwin' or (libattr.found() and libcap_ng.found()),
1686             error_message: 'virtio-9p (virtfs) on Linux requires libcap-ng-devel and libattr-devel') \
1687    .disable_auto_if(not have_tools and not have_system) \
1688    .allowed()
1689
1690have_virtfs_proxy_helper = targetos != 'darwin' and have_virtfs and have_tools
1691
1692if get_option('block_drv_ro_whitelist') == ''
1693  config_host_data.set('CONFIG_BDRV_RO_WHITELIST', '')
1694else
1695  config_host_data.set('CONFIG_BDRV_RO_WHITELIST',
1696        '"' + get_option('block_drv_ro_whitelist').replace(',', '", "') + '", ')
1697endif
1698if get_option('block_drv_rw_whitelist') == ''
1699  config_host_data.set('CONFIG_BDRV_RW_WHITELIST', '')
1700else
1701  config_host_data.set('CONFIG_BDRV_RW_WHITELIST',
1702        '"' + get_option('block_drv_rw_whitelist').replace(',', '", "') + '", ')
1703endif
1704
1705foreach k : get_option('trace_backends')
1706  config_host_data.set('CONFIG_TRACE_' + k.to_upper(), true)
1707endforeach
1708config_host_data.set_quoted('CONFIG_TRACE_FILE', get_option('trace_file'))
1709config_host_data.set_quoted('CONFIG_TLS_PRIORITY', get_option('tls_priority'))
1710if iasl.found()
1711  config_host_data.set_quoted('CONFIG_IASL', iasl.full_path())
1712endif
1713config_host_data.set_quoted('CONFIG_BINDIR', get_option('prefix') / get_option('bindir'))
1714config_host_data.set_quoted('CONFIG_PREFIX', get_option('prefix'))
1715config_host_data.set_quoted('CONFIG_QEMU_CONFDIR', get_option('prefix') / qemu_confdir)
1716config_host_data.set_quoted('CONFIG_QEMU_DATADIR', get_option('prefix') / qemu_datadir)
1717config_host_data.set_quoted('CONFIG_QEMU_DESKTOPDIR', get_option('prefix') / qemu_desktopdir)
1718config_host_data.set_quoted('CONFIG_QEMU_FIRMWAREPATH', get_option('prefix') / get_option('qemu_firmwarepath'))
1719config_host_data.set_quoted('CONFIG_QEMU_HELPERDIR', get_option('prefix') / get_option('libexecdir'))
1720config_host_data.set_quoted('CONFIG_QEMU_ICONDIR', get_option('prefix') / qemu_icondir)
1721config_host_data.set_quoted('CONFIG_QEMU_LOCALEDIR', get_option('prefix') / get_option('localedir'))
1722config_host_data.set_quoted('CONFIG_QEMU_LOCALSTATEDIR', get_option('prefix') / get_option('localstatedir'))
1723config_host_data.set_quoted('CONFIG_QEMU_MODDIR', get_option('prefix') / qemu_moddir)
1724config_host_data.set_quoted('CONFIG_SYSCONFDIR', get_option('prefix') / get_option('sysconfdir'))
1725
1726if config_host.has_key('CONFIG_MODULES')
1727  config_host_data.set('CONFIG_STAMP', run_command(
1728      meson.current_source_dir() / 'scripts/qemu-stamp.py',
1729      meson.project_version(), get_option('pkgversion'), '--',
1730      meson.current_source_dir() / 'configure',
1731      capture: true, check: true).stdout().strip())
1732endif
1733
1734have_slirp_smbd = get_option('slirp_smbd') \
1735  .require(targetos != 'windows', error_message: 'Host smbd not supported on this platform.') \
1736  .allowed()
1737if have_slirp_smbd
1738  smbd_path = get_option('smbd')
1739  if smbd_path == ''
1740    smbd_path = (targetos == 'solaris' ? '/usr/sfw/sbin/smbd' : '/usr/sbin/smbd')
1741  endif
1742  config_host_data.set_quoted('CONFIG_SMBD_COMMAND', smbd_path)
1743endif
1744
1745config_host_data.set('HOST_' + host_arch.to_upper(), 1)
1746
1747if get_option('module_upgrades') and not enable_modules
1748  error('Cannot enable module-upgrades as modules are not enabled')
1749endif
1750config_host_data.set('CONFIG_MODULE_UPGRADES', get_option('module_upgrades'))
1751
1752config_host_data.set('CONFIG_ATTR', libattr.found())
1753config_host_data.set('CONFIG_BDRV_WHITELIST_TOOLS', get_option('block_drv_whitelist_in_tools'))
1754config_host_data.set('CONFIG_BRLAPI', brlapi.found())
1755config_host_data.set('CONFIG_COCOA', cocoa.found())
1756config_host_data.set('CONFIG_FUZZ', get_option('fuzzing'))
1757config_host_data.set('CONFIG_GCOV', get_option('b_coverage'))
1758config_host_data.set('CONFIG_LIBUDEV', libudev.found())
1759config_host_data.set('CONFIG_LZO', lzo.found())
1760config_host_data.set('CONFIG_MPATH', mpathpersist.found())
1761config_host_data.set('CONFIG_MPATH_NEW_API', mpathpersist_new_api)
1762config_host_data.set('CONFIG_CURL', curl.found())
1763config_host_data.set('CONFIG_CURSES', curses.found())
1764config_host_data.set('CONFIG_GBM', gbm.found())
1765config_host_data.set('CONFIG_GIO', gio.found())
1766config_host_data.set('CONFIG_GLUSTERFS', glusterfs.found())
1767if glusterfs.found()
1768  config_host_data.set('CONFIG_GLUSTERFS_XLATOR_OPT', glusterfs.version().version_compare('>=4'))
1769  config_host_data.set('CONFIG_GLUSTERFS_DISCARD', glusterfs.version().version_compare('>=5'))
1770  config_host_data.set('CONFIG_GLUSTERFS_FALLOCATE', glusterfs.version().version_compare('>=6'))
1771  config_host_data.set('CONFIG_GLUSTERFS_ZEROFILL', glusterfs.version().version_compare('>=6'))
1772  config_host_data.set('CONFIG_GLUSTERFS_FTRUNCATE_HAS_STAT', glusterfs_ftruncate_has_stat)
1773  config_host_data.set('CONFIG_GLUSTERFS_IOCB_HAS_STAT', glusterfs_iocb_has_stat)
1774endif
1775config_host_data.set('CONFIG_GTK', gtk.found())
1776config_host_data.set('CONFIG_VTE', vte.found())
1777config_host_data.set('CONFIG_LIBATTR', have_old_libattr)
1778config_host_data.set('CONFIG_LIBCAP_NG', libcap_ng.found())
1779config_host_data.set('CONFIG_EBPF', libbpf.found())
1780config_host_data.set('CONFIG_LIBDAXCTL', libdaxctl.found())
1781config_host_data.set('CONFIG_LIBISCSI', libiscsi.found())
1782config_host_data.set('CONFIG_LIBNFS', libnfs.found())
1783config_host_data.set('CONFIG_LIBSSH', libssh.found())
1784config_host_data.set('CONFIG_LINUX_AIO', libaio.found())
1785config_host_data.set('CONFIG_LINUX_IO_URING', linux_io_uring.found())
1786config_host_data.set('CONFIG_LIBURING_REGISTER_RING_FD', cc.has_function('io_uring_register_ring_fd', prefix: '#include <liburing.h>', dependencies:linux_io_uring))
1787config_host_data.set('CONFIG_LIBPMEM', libpmem.found())
1788config_host_data.set('CONFIG_NUMA', numa.found())
1789config_host_data.set('CONFIG_OPENGL', opengl.found())
1790config_host_data.set('CONFIG_PROFILER', get_option('profiler'))
1791config_host_data.set('CONFIG_RBD', rbd.found())
1792config_host_data.set('CONFIG_RDMA', rdma.found())
1793config_host_data.set('CONFIG_SDL', sdl.found())
1794config_host_data.set('CONFIG_SDL_IMAGE', sdl_image.found())
1795config_host_data.set('CONFIG_SECCOMP', seccomp.found())
1796config_host_data.set('CONFIG_SNAPPY', snappy.found())
1797config_host_data.set('CONFIG_TPM', have_tpm)
1798config_host_data.set('CONFIG_USB_LIBUSB', libusb.found())
1799config_host_data.set('CONFIG_VDE', vde.found())
1800config_host_data.set('CONFIG_VHOST_NET', have_vhost_net)
1801config_host_data.set('CONFIG_VHOST_NET_USER', have_vhost_net_user)
1802config_host_data.set('CONFIG_VHOST_NET_VDPA', have_vhost_net_vdpa)
1803config_host_data.set('CONFIG_VHOST_KERNEL', have_vhost_kernel)
1804config_host_data.set('CONFIG_VHOST_USER', have_vhost_user)
1805config_host_data.set('CONFIG_VHOST_CRYPTO', have_vhost_user_crypto)
1806config_host_data.set('CONFIG_VHOST_VDPA', have_vhost_vdpa)
1807config_host_data.set('CONFIG_VMNET', vmnet.found())
1808config_host_data.set('CONFIG_VHOST_USER_BLK_SERVER', have_vhost_user_blk_server)
1809config_host_data.set('CONFIG_VDUSE_BLK_EXPORT', have_vduse_blk_export)
1810config_host_data.set('CONFIG_PNG', png.found())
1811config_host_data.set('CONFIG_VNC', vnc.found())
1812config_host_data.set('CONFIG_VNC_JPEG', jpeg.found())
1813config_host_data.set('CONFIG_VNC_SASL', sasl.found())
1814config_host_data.set('CONFIG_VIRTFS', have_virtfs)
1815config_host_data.set('CONFIG_VTE', vte.found())
1816config_host_data.set('CONFIG_XKBCOMMON', xkbcommon.found())
1817config_host_data.set('CONFIG_KEYUTILS', keyutils.found())
1818config_host_data.set('CONFIG_GETTID', has_gettid)
1819config_host_data.set('CONFIG_GNUTLS', gnutls.found())
1820config_host_data.set('CONFIG_GNUTLS_CRYPTO', gnutls_crypto.found())
1821config_host_data.set('CONFIG_TASN1', tasn1.found())
1822config_host_data.set('CONFIG_GCRYPT', gcrypt.found())
1823config_host_data.set('CONFIG_NETTLE', nettle.found())
1824config_host_data.set('CONFIG_HOGWEED', hogweed.found())
1825config_host_data.set('CONFIG_QEMU_PRIVATE_XTS', xts == 'private')
1826config_host_data.set('CONFIG_MALLOC_TRIM', has_malloc_trim)
1827config_host_data.set('CONFIG_STATX', has_statx)
1828config_host_data.set('CONFIG_STATX_MNT_ID', has_statx_mnt_id)
1829config_host_data.set('CONFIG_ZSTD', zstd.found())
1830config_host_data.set('CONFIG_FUSE', fuse.found())
1831config_host_data.set('CONFIG_FUSE_LSEEK', fuse_lseek.found())
1832config_host_data.set('CONFIG_SPICE_PROTOCOL', spice_protocol.found())
1833if spice_protocol.found()
1834config_host_data.set('CONFIG_SPICE_PROTOCOL_MAJOR', spice_protocol.version().split('.')[0])
1835config_host_data.set('CONFIG_SPICE_PROTOCOL_MINOR', spice_protocol.version().split('.')[1])
1836config_host_data.set('CONFIG_SPICE_PROTOCOL_MICRO', spice_protocol.version().split('.')[2])
1837endif
1838config_host_data.set('CONFIG_SPICE', spice.found())
1839config_host_data.set('CONFIG_X11', x11.found())
1840config_host_data.set('CONFIG_DBUS_DISPLAY', dbus_display)
1841config_host_data.set('CONFIG_CFI', get_option('cfi'))
1842config_host_data.set('CONFIG_SELINUX', selinux.found())
1843config_host_data.set('CONFIG_XEN_BACKEND', xen.found())
1844if xen.found()
1845  # protect from xen.version() having less than three components
1846  xen_version = xen.version().split('.') + ['0', '0']
1847  xen_ctrl_version = xen_version[0] + \
1848    ('0' + xen_version[1]).substring(-2) + \
1849    ('0' + xen_version[2]).substring(-2)
1850  config_host_data.set('CONFIG_XEN_CTRL_INTERFACE_VERSION', xen_ctrl_version)
1851endif
1852config_host_data.set('QEMU_VERSION', '"@0@"'.format(meson.project_version()))
1853config_host_data.set('QEMU_VERSION_MAJOR', meson.project_version().split('.')[0])
1854config_host_data.set('QEMU_VERSION_MINOR', meson.project_version().split('.')[1])
1855config_host_data.set('QEMU_VERSION_MICRO', meson.project_version().split('.')[2])
1856
1857config_host_data.set_quoted('CONFIG_HOST_DSOSUF', host_dsosuf)
1858config_host_data.set('HAVE_HOST_BLOCK_DEVICE', have_host_block_device)
1859
1860have_coroutine_pool = get_option('coroutine_pool')
1861if get_option('debug_stack_usage') and have_coroutine_pool
1862  message('Disabling coroutine pool to measure stack usage')
1863  have_coroutine_pool = false
1864endif
1865config_host_data.set10('CONFIG_COROUTINE_POOL', have_coroutine_pool)
1866config_host_data.set('CONFIG_DEBUG_MUTEX', get_option('debug_mutex'))
1867config_host_data.set('CONFIG_DEBUG_STACK_USAGE', get_option('debug_stack_usage'))
1868config_host_data.set('CONFIG_GPROF', get_option('gprof'))
1869config_host_data.set('CONFIG_LIVE_BLOCK_MIGRATION', get_option('live_block_migration').allowed())
1870config_host_data.set('CONFIG_QOM_CAST_DEBUG', get_option('qom_cast_debug'))
1871config_host_data.set('CONFIG_REPLICATION', get_option('live_block_migration').allowed())
1872
1873# has_header
1874config_host_data.set('CONFIG_EPOLL', cc.has_header('sys/epoll.h'))
1875config_host_data.set('CONFIG_LINUX_MAGIC_H', cc.has_header('linux/magic.h'))
1876config_host_data.set('CONFIG_VALGRIND_H', cc.has_header('valgrind/valgrind.h'))
1877config_host_data.set('HAVE_BTRFS_H', cc.has_header('linux/btrfs.h'))
1878config_host_data.set('HAVE_DRM_H', cc.has_header('libdrm/drm.h'))
1879config_host_data.set('HAVE_PTY_H', cc.has_header('pty.h'))
1880config_host_data.set('HAVE_SYS_DISK_H', cc.has_header('sys/disk.h'))
1881config_host_data.set('HAVE_SYS_IOCCOM_H', cc.has_header('sys/ioccom.h'))
1882config_host_data.set('HAVE_SYS_KCOV_H', cc.has_header('sys/kcov.h'))
1883
1884# has_function
1885config_host_data.set('CONFIG_ACCEPT4', cc.has_function('accept4'))
1886config_host_data.set('CONFIG_CLOCK_ADJTIME', cc.has_function('clock_adjtime'))
1887config_host_data.set('CONFIG_DUP3', cc.has_function('dup3'))
1888config_host_data.set('CONFIG_FALLOCATE', cc.has_function('fallocate'))
1889config_host_data.set('CONFIG_POSIX_FALLOCATE', cc.has_function('posix_fallocate'))
1890# Note that we need to specify prefix: here to avoid incorrectly
1891# thinking that Windows has posix_memalign()
1892config_host_data.set('CONFIG_POSIX_MEMALIGN', cc.has_function('posix_memalign', prefix: '#include <stdlib.h>'))
1893config_host_data.set('CONFIG_ALIGNED_MALLOC', cc.has_function('_aligned_malloc'))
1894config_host_data.set('CONFIG_VALLOC', cc.has_function('valloc'))
1895config_host_data.set('CONFIG_MEMALIGN', cc.has_function('memalign'))
1896config_host_data.set('CONFIG_PPOLL', cc.has_function('ppoll'))
1897config_host_data.set('CONFIG_PREADV', cc.has_function('preadv', prefix: '#include <sys/uio.h>'))
1898config_host_data.set('CONFIG_PTHREAD_FCHDIR_NP', cc.has_function('pthread_fchdir_np'))
1899config_host_data.set('CONFIG_SENDFILE', cc.has_function('sendfile'))
1900config_host_data.set('CONFIG_SETNS', cc.has_function('setns') and cc.has_function('unshare'))
1901config_host_data.set('CONFIG_SYNCFS', cc.has_function('syncfs'))
1902config_host_data.set('CONFIG_SYNC_FILE_RANGE', cc.has_function('sync_file_range'))
1903config_host_data.set('CONFIG_TIMERFD', cc.has_function('timerfd_create'))
1904config_host_data.set('HAVE_COPY_FILE_RANGE', cc.has_function('copy_file_range'))
1905config_host_data.set('HAVE_GETIFADDRS', cc.has_function('getifaddrs'))
1906config_host_data.set('HAVE_OPENPTY', cc.has_function('openpty', dependencies: util))
1907config_host_data.set('HAVE_STRCHRNUL', cc.has_function('strchrnul'))
1908config_host_data.set('HAVE_SYSTEM_FUNCTION', cc.has_function('system', prefix: '#include <stdlib.h>'))
1909if rbd.found()
1910  config_host_data.set('HAVE_RBD_NAMESPACE_EXISTS',
1911                       cc.has_function('rbd_namespace_exists',
1912                                       dependencies: rbd,
1913                                       prefix: '#include <rbd/librbd.h>'))
1914endif
1915if rdma.found()
1916  config_host_data.set('HAVE_IBV_ADVISE_MR',
1917                       cc.has_function('ibv_advise_mr',
1918                                       dependencies: rdma,
1919                                       prefix: '#include <infiniband/verbs.h>'))
1920endif
1921
1922# has_header_symbol
1923config_host_data.set('CONFIG_BYTESWAP_H',
1924                     cc.has_header_symbol('byteswap.h', 'bswap_32'))
1925config_host_data.set('CONFIG_EPOLL_CREATE1',
1926                     cc.has_header_symbol('sys/epoll.h', 'epoll_create1'))
1927config_host_data.set('CONFIG_FALLOCATE_PUNCH_HOLE',
1928                     cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_PUNCH_HOLE') and
1929                     cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_KEEP_SIZE'))
1930config_host_data.set('CONFIG_FALLOCATE_ZERO_RANGE',
1931                     cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_ZERO_RANGE'))
1932config_host_data.set('CONFIG_FIEMAP',
1933                     cc.has_header('linux/fiemap.h') and
1934                     cc.has_header_symbol('linux/fs.h', 'FS_IOC_FIEMAP'))
1935config_host_data.set('CONFIG_GETRANDOM',
1936                     cc.has_function('getrandom') and
1937                     cc.has_header_symbol('sys/random.h', 'GRND_NONBLOCK'))
1938config_host_data.set('CONFIG_INOTIFY',
1939                     cc.has_header_symbol('sys/inotify.h', 'inotify_init'))
1940config_host_data.set('CONFIG_INOTIFY1',
1941                     cc.has_header_symbol('sys/inotify.h', 'inotify_init1'))
1942config_host_data.set('CONFIG_MACHINE_BSWAP_H',
1943                     cc.has_header_symbol('machine/bswap.h', 'bswap32',
1944                                          prefix: '''#include <sys/endian.h>
1945                                                     #include <sys/types.h>'''))
1946config_host_data.set('CONFIG_PRCTL_PR_SET_TIMERSLACK',
1947                     cc.has_header_symbol('sys/prctl.h', 'PR_SET_TIMERSLACK'))
1948config_host_data.set('CONFIG_RTNETLINK',
1949                     cc.has_header_symbol('linux/rtnetlink.h', 'IFLA_PROTO_DOWN'))
1950config_host_data.set('CONFIG_SYSMACROS',
1951                     cc.has_header_symbol('sys/sysmacros.h', 'makedev'))
1952config_host_data.set('HAVE_OPTRESET',
1953                     cc.has_header_symbol('getopt.h', 'optreset'))
1954config_host_data.set('HAVE_IPPROTO_MPTCP',
1955                     cc.has_header_symbol('netinet/in.h', 'IPPROTO_MPTCP'))
1956
1957# has_member
1958config_host_data.set('HAVE_SIGEV_NOTIFY_THREAD_ID',
1959                     cc.has_member('struct sigevent', 'sigev_notify_thread_id',
1960                                   prefix: '#include <signal.h>'))
1961config_host_data.set('HAVE_STRUCT_STAT_ST_ATIM',
1962                     cc.has_member('struct stat', 'st_atim',
1963                                   prefix: '#include <sys/stat.h>'))
1964
1965# has_type
1966config_host_data.set('CONFIG_IOVEC',
1967                     cc.has_type('struct iovec',
1968                                 prefix: '#include <sys/uio.h>'))
1969config_host_data.set('HAVE_UTMPX',
1970                     cc.has_type('struct utmpx',
1971                                 prefix: '#include <utmpx.h>'))
1972
1973config_host_data.set('CONFIG_EVENTFD', cc.links('''
1974  #include <sys/eventfd.h>
1975  int main(void) { return eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); }'''))
1976config_host_data.set('CONFIG_FDATASYNC', cc.links(gnu_source_prefix + '''
1977  #include <unistd.h>
1978  int main(void) {
1979  #if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
1980  return fdatasync(0);
1981  #else
1982  #error Not supported
1983  #endif
1984  }'''))
1985
1986has_madvise = cc.links(gnu_source_prefix + '''
1987  #include <sys/types.h>
1988  #include <sys/mman.h>
1989  #include <stddef.h>
1990  int main(void) { return madvise(NULL, 0, MADV_DONTNEED); }''')
1991missing_madvise_proto = false
1992if has_madvise
1993  # Some platforms (illumos and Solaris before Solaris 11) provide madvise()
1994  # but forget to prototype it. In this case, has_madvise will be true (the
1995  # test program links despite a compile warning). To detect the
1996  # missing-prototype case, we try again with a definitely-bogus prototype.
1997  # This will only compile if the system headers don't provide the prototype;
1998  # otherwise the conflicting prototypes will cause a compiler error.
1999  missing_madvise_proto = cc.links(gnu_source_prefix + '''
2000    #include <sys/types.h>
2001    #include <sys/mman.h>
2002    #include <stddef.h>
2003    extern int madvise(int);
2004    int main(void) { return madvise(0); }''')
2005endif
2006config_host_data.set('CONFIG_MADVISE', has_madvise)
2007config_host_data.set('HAVE_MADVISE_WITHOUT_PROTOTYPE', missing_madvise_proto)
2008
2009config_host_data.set('CONFIG_MEMFD', cc.links(gnu_source_prefix + '''
2010  #include <sys/mman.h>
2011  int main(void) { return memfd_create("foo", MFD_ALLOW_SEALING); }'''))
2012config_host_data.set('CONFIG_OPEN_BY_HANDLE', cc.links(gnu_source_prefix + '''
2013  #include <fcntl.h>
2014  #if !defined(AT_EMPTY_PATH)
2015  # error missing definition
2016  #else
2017  int main(void) { struct file_handle fh; return open_by_handle_at(0, &fh, 0); }
2018  #endif'''))
2019config_host_data.set('CONFIG_PIPE2', cc.links(gnu_source_prefix + '''
2020  #include <unistd.h>
2021  #include <fcntl.h>
2022
2023  int main(void)
2024  {
2025      int pipefd[2];
2026      return pipe2(pipefd, O_CLOEXEC);
2027  }'''))
2028config_host_data.set('CONFIG_POSIX_MADVISE', cc.links(gnu_source_prefix + '''
2029  #include <sys/mman.h>
2030  #include <stddef.h>
2031  int main(void) { return posix_madvise(NULL, 0, POSIX_MADV_DONTNEED); }'''))
2032
2033config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_W_TID', cc.links(gnu_source_prefix + '''
2034  #include <pthread.h>
2035
2036  static void *f(void *p) { return NULL; }
2037  int main(void)
2038  {
2039    pthread_t thread;
2040    pthread_create(&thread, 0, f, 0);
2041    pthread_setname_np(thread, "QEMU");
2042    return 0;
2043  }''', dependencies: threads))
2044config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_WO_TID', cc.links(gnu_source_prefix + '''
2045  #include <pthread.h>
2046
2047  static void *f(void *p) { pthread_setname_np("QEMU"); return NULL; }
2048  int main(void)
2049  {
2050    pthread_t thread;
2051    pthread_create(&thread, 0, f, 0);
2052    return 0;
2053  }''', dependencies: threads))
2054config_host_data.set('CONFIG_PTHREAD_CONDATTR_SETCLOCK', cc.links(gnu_source_prefix + '''
2055  #include <pthread.h>
2056  #include <time.h>
2057
2058  int main(void)
2059  {
2060    pthread_condattr_t attr
2061    pthread_condattr_init(&attr);
2062    pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
2063    return 0;
2064  }''', dependencies: threads))
2065
2066config_host_data.set('CONFIG_SIGNALFD', cc.links(gnu_source_prefix + '''
2067  #include <sys/signalfd.h>
2068  #include <stddef.h>
2069  int main(void) { return signalfd(-1, NULL, SFD_CLOEXEC); }'''))
2070config_host_data.set('CONFIG_SPLICE', cc.links(gnu_source_prefix + '''
2071  #include <unistd.h>
2072  #include <fcntl.h>
2073  #include <limits.h>
2074
2075  int main(void)
2076  {
2077    int len, fd = 0;
2078    len = tee(STDIN_FILENO, STDOUT_FILENO, INT_MAX, SPLICE_F_NONBLOCK);
2079    splice(STDIN_FILENO, NULL, fd, NULL, len, SPLICE_F_MOVE);
2080    return 0;
2081  }'''))
2082
2083config_host_data.set('HAVE_MLOCKALL', cc.links(gnu_source_prefix + '''
2084  #include <sys/mman.h>
2085  int main(int argc, char *argv[]) {
2086    return mlockall(MCL_FUTURE);
2087  }'''))
2088
2089have_l2tpv3 = false
2090if get_option('l2tpv3').allowed() and have_system
2091  have_l2tpv3 = cc.has_type('struct mmsghdr',
2092    prefix: gnu_source_prefix + '''
2093      #include <sys/socket.h>
2094      #include <linux/ip.h>''')
2095endif
2096config_host_data.set('CONFIG_L2TPV3', have_l2tpv3)
2097
2098have_netmap = false
2099if get_option('netmap').allowed() and have_system
2100  have_netmap = cc.compiles('''
2101    #include <inttypes.h>
2102    #include <net/if.h>
2103    #include <net/netmap.h>
2104    #include <net/netmap_user.h>
2105    #if (NETMAP_API < 11) || (NETMAP_API > 15)
2106    #error
2107    #endif
2108    int main(void) { return 0; }''')
2109  if not have_netmap and get_option('netmap').enabled()
2110    error('Netmap headers not available')
2111  endif
2112endif
2113config_host_data.set('CONFIG_NETMAP', have_netmap)
2114
2115# Work around a system header bug with some kernel/XFS header
2116# versions where they both try to define 'struct fsxattr':
2117# xfs headers will not try to redefine structs from linux headers
2118# if this macro is set.
2119config_host_data.set('HAVE_FSXATTR', cc.links('''
2120  #include <linux/fs.h>
2121  struct fsxattr foo;
2122  int main(void) {
2123    return 0;
2124  }'''))
2125
2126# Some versions of Mac OS X incorrectly define SIZE_MAX
2127config_host_data.set('HAVE_BROKEN_SIZE_MAX', not cc.compiles('''
2128    #include <stdint.h>
2129    #include <stdio.h>
2130    int main(int argc, char *argv[]) {
2131        return printf("%zu", SIZE_MAX);
2132    }''', args: ['-Werror']))
2133
2134atomic_test = '''
2135  #include <stdint.h>
2136  int main(void)
2137  {
2138    @0@ x = 0, y = 0;
2139    y = __atomic_load_n(&x, __ATOMIC_RELAXED);
2140    __atomic_store_n(&x, y, __ATOMIC_RELAXED);
2141    __atomic_compare_exchange_n(&x, &y, x, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
2142    __atomic_exchange_n(&x, y, __ATOMIC_RELAXED);
2143    __atomic_fetch_add(&x, y, __ATOMIC_RELAXED);
2144    return 0;
2145  }'''
2146
2147# See if 64-bit atomic operations are supported.
2148# Note that without __atomic builtins, we can only
2149# assume atomic loads/stores max at pointer size.
2150config_host_data.set('CONFIG_ATOMIC64', cc.links(atomic_test.format('uint64_t')))
2151
2152has_int128 = cc.links('''
2153  __int128_t a;
2154  __uint128_t b;
2155  int main (void) {
2156    a = a + b;
2157    b = a * b;
2158    a = a * a;
2159    return 0;
2160  }''')
2161
2162config_host_data.set('CONFIG_INT128', has_int128)
2163
2164if has_int128
2165  # "do we have 128-bit atomics which are handled inline and specifically not
2166  # via libatomic". The reason we can't use libatomic is documented in the
2167  # comment starting "GCC is a house divided" in include/qemu/atomic128.h.
2168  has_atomic128 = cc.links(atomic_test.format('unsigned __int128'))
2169
2170  config_host_data.set('CONFIG_ATOMIC128', has_atomic128)
2171
2172  if not has_atomic128
2173    has_cmpxchg128 = cc.links('''
2174      int main(void)
2175      {
2176        unsigned __int128 x = 0, y = 0;
2177        __sync_val_compare_and_swap_16(&x, y, x);
2178        return 0;
2179      }
2180    ''')
2181
2182    config_host_data.set('CONFIG_CMPXCHG128', has_cmpxchg128)
2183  endif
2184endif
2185
2186config_host_data.set('CONFIG_GETAUXVAL', cc.links(gnu_source_prefix + '''
2187  #include <sys/auxv.h>
2188  int main(void) {
2189    return getauxval(AT_HWCAP) == 0;
2190  }'''))
2191
2192config_host_data.set('CONFIG_USBFS', have_linux_user and cc.compiles('''
2193  #include <linux/usbdevice_fs.h>
2194
2195  #ifndef USBDEVFS_GET_CAPABILITIES
2196  #error "USBDEVFS_GET_CAPABILITIES undefined"
2197  #endif
2198
2199  #ifndef USBDEVFS_DISCONNECT_CLAIM
2200  #error "USBDEVFS_DISCONNECT_CLAIM undefined"
2201  #endif
2202
2203  int main(void) { return 0; }'''))
2204
2205have_keyring = get_option('keyring') \
2206  .require(targetos == 'linux', error_message: 'keyring is only available on Linux') \
2207  .require(cc.compiles('''
2208    #include <errno.h>
2209    #include <asm/unistd.h>
2210    #include <linux/keyctl.h>
2211    #include <sys/syscall.h>
2212    #include <unistd.h>
2213    int main(void) {
2214        return syscall(__NR_keyctl, KEYCTL_READ, 0, NULL, NULL, 0);
2215    }'''), error_message: 'keyctl syscall not available on this system').allowed()
2216config_host_data.set('CONFIG_SECRET_KEYRING', have_keyring)
2217
2218have_cpuid_h = cc.links('''
2219  #include <cpuid.h>
2220  int main(void) {
2221    unsigned a, b, c, d;
2222    unsigned max = __get_cpuid_max(0, 0);
2223
2224    if (max >= 1) {
2225        __cpuid(1, a, b, c, d);
2226    }
2227
2228    if (max >= 7) {
2229        __cpuid_count(7, 0, a, b, c, d);
2230    }
2231
2232    return 0;
2233  }''')
2234config_host_data.set('CONFIG_CPUID_H', have_cpuid_h)
2235
2236config_host_data.set('CONFIG_AVX2_OPT', get_option('avx2') \
2237  .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable AVX2') \
2238  .require(cc.links('''
2239    #pragma GCC push_options
2240    #pragma GCC target("avx2")
2241    #include <cpuid.h>
2242    #include <immintrin.h>
2243    static int bar(void *a) {
2244      __m256i x = *(__m256i *)a;
2245      return _mm256_testz_si256(x, x);
2246    }
2247    int main(int argc, char *argv[]) { return bar(argv[0]); }
2248  '''), error_message: 'AVX2 not available').allowed())
2249
2250config_host_data.set('CONFIG_AVX512F_OPT', get_option('avx512f') \
2251  .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable AVX512F') \
2252  .require(cc.links('''
2253    #pragma GCC push_options
2254    #pragma GCC target("avx512f")
2255    #include <cpuid.h>
2256    #include <immintrin.h>
2257    static int bar(void *a) {
2258      __m512i x = *(__m512i *)a;
2259      return _mm512_test_epi64_mask(x, x);
2260    }
2261    int main(int argc, char *argv[]) { return bar(argv[0]); }
2262  '''), error_message: 'AVX512F not available').allowed())
2263
2264have_pvrdma = get_option('pvrdma') \
2265  .require(rdma.found(), error_message: 'PVRDMA requires OpenFabrics libraries') \
2266  .require(cc.compiles(gnu_source_prefix + '''
2267    #include <sys/mman.h>
2268    int main(void)
2269    {
2270      char buf = 0;
2271      void *addr = &buf;
2272      addr = mremap(addr, 0, 1, MREMAP_MAYMOVE | MREMAP_FIXED);
2273
2274      return 0;
2275    }'''), error_message: 'PVRDMA requires mremap').allowed()
2276
2277if have_pvrdma
2278  config_host_data.set('LEGACY_RDMA_REG_MR', not cc.links('''
2279    #include <infiniband/verbs.h>
2280    int main(void)
2281    {
2282      struct ibv_mr *mr;
2283      struct ibv_pd *pd = NULL;
2284      size_t length = 10;
2285      uint64_t iova = 0;
2286      int access = 0;
2287      void *addr = NULL;
2288
2289      mr = ibv_reg_mr_iova(pd, addr, length, iova, access);
2290      ibv_dereg_mr(mr);
2291      return 0;
2292    }'''))
2293endif
2294
2295if get_option('membarrier').disabled()
2296  have_membarrier = false
2297elif targetos == 'windows'
2298  have_membarrier = true
2299elif targetos == 'linux'
2300  have_membarrier = cc.compiles('''
2301    #include <linux/membarrier.h>
2302    #include <sys/syscall.h>
2303    #include <unistd.h>
2304    #include <stdlib.h>
2305    int main(void) {
2306        syscall(__NR_membarrier, MEMBARRIER_CMD_QUERY, 0);
2307        syscall(__NR_membarrier, MEMBARRIER_CMD_SHARED, 0);
2308        exit(0);
2309    }''')
2310endif
2311config_host_data.set('CONFIG_MEMBARRIER', get_option('membarrier') \
2312  .require(have_membarrier, error_message: 'membarrier system call not available') \
2313  .allowed())
2314
2315have_afalg = get_option('crypto_afalg') \
2316  .require(cc.compiles(gnu_source_prefix + '''
2317    #include <errno.h>
2318    #include <sys/types.h>
2319    #include <sys/socket.h>
2320    #include <linux/if_alg.h>
2321    int main(void) {
2322      int sock;
2323      sock = socket(AF_ALG, SOCK_SEQPACKET, 0);
2324      return sock;
2325    }
2326  '''), error_message: 'AF_ALG requested but could not be detected').allowed()
2327config_host_data.set('CONFIG_AF_ALG', have_afalg)
2328
2329config_host_data.set('CONFIG_AF_VSOCK', cc.has_header_symbol(
2330  'linux/vm_sockets.h', 'AF_VSOCK',
2331  prefix: '#include <sys/socket.h>',
2332))
2333
2334have_vss = false
2335have_vss_sdk = false # old xp/2003 SDK
2336if targetos == 'windows' and link_language == 'cpp'
2337  have_vss = cxx.compiles('''
2338    #define __MIDL_user_allocate_free_DEFINED__
2339    #include <vss.h>
2340    int main(void) { return VSS_CTX_BACKUP; }''')
2341  have_vss_sdk = cxx.has_header('vscoordint.h')
2342endif
2343config_host_data.set('HAVE_VSS_SDK', have_vss_sdk)
2344
2345foreach k, v: config_host
2346  if k.startswith('CONFIG_')
2347    config_host_data.set(k, v == 'y' ? 1 : v)
2348  endif
2349endforeach
2350
2351# Older versions of MinGW do not import _lock_file and _unlock_file properly.
2352# This was fixed for v6.0.0 with commit b48e3ac8969d.
2353if targetos == 'windows'
2354  config_host_data.set('HAVE__LOCK_FILE', cc.links('''
2355    #include <stdio.h>
2356    int main(void) {
2357      _lock_file(NULL);
2358      _unlock_file(NULL);
2359      return 0;
2360    }''', name: '_lock_file and _unlock_file'))
2361endif
2362
2363########################
2364# Target configuration #
2365########################
2366
2367minikconf = find_program('scripts/minikconf.py')
2368config_all = {}
2369config_all_devices = {}
2370config_all_disas = {}
2371config_devices_mak_list = []
2372config_devices_h = {}
2373config_target_h = {}
2374config_target_mak = {}
2375
2376disassemblers = {
2377  'alpha' : ['CONFIG_ALPHA_DIS'],
2378  'avr' : ['CONFIG_AVR_DIS'],
2379  'cris' : ['CONFIG_CRIS_DIS'],
2380  'hexagon' : ['CONFIG_HEXAGON_DIS'],
2381  'hppa' : ['CONFIG_HPPA_DIS'],
2382  'i386' : ['CONFIG_I386_DIS'],
2383  'x86_64' : ['CONFIG_I386_DIS'],
2384  'm68k' : ['CONFIG_M68K_DIS'],
2385  'microblaze' : ['CONFIG_MICROBLAZE_DIS'],
2386  'mips' : ['CONFIG_MIPS_DIS'],
2387  'nios2' : ['CONFIG_NIOS2_DIS'],
2388  'or1k' : ['CONFIG_OPENRISC_DIS'],
2389  'ppc' : ['CONFIG_PPC_DIS'],
2390  'riscv' : ['CONFIG_RISCV_DIS'],
2391  'rx' : ['CONFIG_RX_DIS'],
2392  's390' : ['CONFIG_S390_DIS'],
2393  'sh4' : ['CONFIG_SH4_DIS'],
2394  'sparc' : ['CONFIG_SPARC_DIS'],
2395  'xtensa' : ['CONFIG_XTENSA_DIS'],
2396  'loongarch' : ['CONFIG_LOONGARCH_DIS'],
2397}
2398if link_language == 'cpp'
2399  disassemblers += {
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