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