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