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