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