Merge tag 'pull-xen-20220609' of https://xenbits.xen.org/git-http/people/aperard...
[qemu.git] / meson.build
blob21cd949082dc7fb5251db771920793c6b9e40e81
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 usbredir = not_found
1412 if not get_option('usb_redir').auto() or have_system
1413   usbredir = dependency('libusbredirparser-0.5', required: get_option('usb_redir'),
1414                         version: '>=0.6', method: 'pkg-config',
1415                         kwargs: static_kwargs)
1416 endif
1417 libusb = not_found
1418 if not get_option('libusb').auto() or have_system
1419   libusb = dependency('libusb-1.0', required: get_option('libusb'),
1420                       version: '>=1.0.13', method: 'pkg-config',
1421                       kwargs: static_kwargs)
1422 endif
1424 libpmem = not_found
1425 if not get_option('libpmem').auto() or have_system
1426   libpmem = dependency('libpmem', required: get_option('libpmem'),
1427                        method: 'pkg-config', kwargs: static_kwargs)
1428 endif
1429 libdaxctl = not_found
1430 if not get_option('libdaxctl').auto() or have_system
1431   libdaxctl = dependency('libdaxctl', required: get_option('libdaxctl'),
1432                          version: '>=57', method: 'pkg-config',
1433                          kwargs: static_kwargs)
1434 endif
1435 tasn1 = not_found
1436 if gnutls.found()
1437   tasn1 = dependency('libtasn1',
1438                      method: 'pkg-config',
1439                      kwargs: static_kwargs)
1440 endif
1441 keyutils = dependency('libkeyutils', required: false,
1442                       method: 'pkg-config', kwargs: static_kwargs)
1444 has_gettid = cc.has_function('gettid')
1446 # libselinux
1447 selinux = dependency('libselinux',
1448                      required: get_option('selinux'),
1449                      method: 'pkg-config', kwargs: static_kwargs)
1451 # Malloc tests
1453 malloc = []
1454 if get_option('malloc') == 'system'
1455   has_malloc_trim = \
1456     get_option('malloc_trim').allowed() and \
1457     cc.links('''#include <malloc.h>
1458                 int main(void) { malloc_trim(0); return 0; }''')
1459 else
1460   has_malloc_trim = false
1461   malloc = cc.find_library(get_option('malloc'), required: true)
1462 endif
1463 if not has_malloc_trim and get_option('malloc_trim').enabled()
1464   if get_option('malloc') == 'system'
1465     error('malloc_trim not available on this platform.')
1466   else
1467     error('malloc_trim not available with non-libc memory allocator')
1468   endif
1469 endif
1471 # Check whether the glibc provides statx()
1473 gnu_source_prefix = '''
1474   #ifndef _GNU_SOURCE
1475   #define _GNU_SOURCE
1476   #endif
1478 statx_test = gnu_source_prefix + '''
1479   #include <sys/stat.h>
1480   int main(void) {
1481     struct statx statxbuf;
1482     statx(0, "", 0, STATX_BASIC_STATS, &statxbuf);
1483     return 0;
1484   }'''
1486 has_statx = cc.links(statx_test)
1488 # Check whether statx() provides mount ID information
1490 statx_mnt_id_test = gnu_source_prefix + '''
1491   #include <sys/stat.h>
1492   int main(void) {
1493     struct statx statxbuf;
1494     statx(0, "", 0, STATX_BASIC_STATS | STATX_MNT_ID, &statxbuf);
1495     return statxbuf.stx_mnt_id;
1496   }'''
1498 has_statx_mnt_id = cc.links(statx_mnt_id_test)
1500 have_vhost_user_blk_server = get_option('vhost_user_blk_server') \
1501   .require(targetos == 'linux',
1502            error_message: 'vhost_user_blk_server requires linux') \
1503   .require(have_vhost_user,
1504            error_message: 'vhost_user_blk_server requires vhost-user support') \
1505   .disable_auto_if(not have_system) \
1506   .allowed()
1508 if get_option('fuse').disabled() and get_option('fuse_lseek').enabled()
1509   error('Cannot enable fuse-lseek while fuse is disabled')
1510 endif
1512 fuse = dependency('fuse3', required: get_option('fuse'),
1513                   version: '>=3.1', method: 'pkg-config',
1514                   kwargs: static_kwargs)
1516 fuse_lseek = not_found
1517 if get_option('fuse_lseek').allowed()
1518   if fuse.version().version_compare('>=3.8')
1519     # Dummy dependency
1520     fuse_lseek = declare_dependency()
1521   elif get_option('fuse_lseek').enabled()
1522     if fuse.found()
1523       error('fuse-lseek requires libfuse >=3.8, found ' + fuse.version())
1524     else
1525       error('fuse-lseek requires libfuse, which was not found')
1526     endif
1527   endif
1528 endif
1530 # libbpf
1531 libbpf = dependency('libbpf', required: get_option('bpf'), method: 'pkg-config')
1532 if libbpf.found() and not cc.links('''
1533    #include <bpf/libbpf.h>
1534    int main(void)
1535    {
1536      bpf_object__destroy_skeleton(NULL);
1537      return 0;
1538    }''', dependencies: libbpf)
1539   libbpf = not_found
1540   if get_option('bpf').enabled()
1541     error('libbpf skeleton test failed')
1542   else
1543     warning('libbpf skeleton test failed, disabling')
1544   endif
1545 endif
1547 #################
1548 # config-host.h #
1549 #################
1551 audio_drivers_selected = []
1552 if have_system
1553   audio_drivers_available = {
1554     'alsa': alsa.found(),
1555     'coreaudio': coreaudio.found(),
1556     'dsound': dsound.found(),
1557     'jack': jack.found(),
1558     'oss': oss.found(),
1559     'pa': pulse.found(),
1560     'sdl': sdl.found(),
1561   }
1562   foreach k, v: audio_drivers_available
1563     config_host_data.set('CONFIG_AUDIO_' + k.to_upper(), v)
1564   endforeach
1566   # Default to native drivers first, OSS second, SDL third
1567   audio_drivers_priority = \
1568     [ 'pa', 'coreaudio', 'dsound', 'oss' ] + \
1569     (targetos == 'linux' ? [] : [ 'sdl' ])
1570   audio_drivers_default = []
1571   foreach k: audio_drivers_priority
1572     if audio_drivers_available[k]
1573       audio_drivers_default += k
1574     endif
1575   endforeach
1577   foreach k: get_option('audio_drv_list')
1578     if k == 'default'
1579       audio_drivers_selected += audio_drivers_default
1580     elif not audio_drivers_available[k]
1581       error('Audio driver "@0@" not available.'.format(k))
1582     else
1583       audio_drivers_selected += k
1584     endif
1585   endforeach
1586 endif
1587 config_host_data.set('CONFIG_AUDIO_DRIVERS',
1588                      '"' + '", "'.join(audio_drivers_selected) + '", ')
1590 if get_option('cfi')
1591   cfi_flags=[]
1592   # Check for dependency on LTO
1593   if not get_option('b_lto')
1594     error('Selected Control-Flow Integrity but LTO is disabled')
1595   endif
1596   if config_host.has_key('CONFIG_MODULES')
1597     error('Selected Control-Flow Integrity is not compatible with modules')
1598   endif
1599   # Check for cfi flags. CFI requires LTO so we can't use
1600   # get_supported_arguments, but need a more complex "compiles" which allows
1601   # custom arguments
1602   if cc.compiles('int main () { return 0; }', name: '-fsanitize=cfi-icall',
1603                  args: ['-flto', '-fsanitize=cfi-icall'] )
1604     cfi_flags += '-fsanitize=cfi-icall'
1605   else
1606     error('-fsanitize=cfi-icall is not supported by the compiler')
1607   endif
1608   if cc.compiles('int main () { return 0; }',
1609                  name: '-fsanitize-cfi-icall-generalize-pointers',
1610                  args: ['-flto', '-fsanitize=cfi-icall',
1611                         '-fsanitize-cfi-icall-generalize-pointers'] )
1612     cfi_flags += '-fsanitize-cfi-icall-generalize-pointers'
1613   else
1614     error('-fsanitize-cfi-icall-generalize-pointers is not supported by the compiler')
1615   endif
1616   if get_option('cfi_debug')
1617     if cc.compiles('int main () { return 0; }',
1618                    name: '-fno-sanitize-trap=cfi-icall',
1619                    args: ['-flto', '-fsanitize=cfi-icall',
1620                           '-fno-sanitize-trap=cfi-icall'] )
1621       cfi_flags += '-fno-sanitize-trap=cfi-icall'
1622     else
1623       error('-fno-sanitize-trap=cfi-icall is not supported by the compiler')
1624     endif
1625   endif
1626   add_global_arguments(cfi_flags, native: false, language: ['c', 'cpp', 'objc'])
1627   add_global_link_arguments(cfi_flags, native: false, language: ['c', 'cpp', 'objc'])
1628 endif
1630 have_host_block_device = (targetos != 'darwin' or
1631     cc.has_header('IOKit/storage/IOMedia.h'))
1633 # FIXME enable_modules shouldn't be necessary, but: https://github.com/mesonbuild/meson/issues/8333
1634 dbus_display = get_option('dbus_display') \
1635   .require(gio.version().version_compare('>=2.64'),
1636            error_message: '-display dbus requires glib>=2.64') \
1637   .require(enable_modules,
1638            error_message: '-display dbus requires --enable-modules') \
1639   .require(gdbus_codegen.found(),
1640            error_message: '-display dbus requires gdbus-codegen') \
1641   .allowed()
1643 have_virtfs = get_option('virtfs') \
1644     .require(targetos == 'linux' or targetos == 'darwin',
1645              error_message: 'virtio-9p (virtfs) requires Linux or macOS') \
1646     .require(targetos == 'linux' or cc.has_function('pthread_fchdir_np'),
1647              error_message: 'virtio-9p (virtfs) on macOS requires the presence of pthread_fchdir_np') \
1648     .require(targetos == 'darwin' or (libattr.found() and libcap_ng.found()),
1649              error_message: 'virtio-9p (virtfs) on Linux requires libcap-ng-devel and libattr-devel') \
1650     .disable_auto_if(not have_tools and not have_system) \
1651     .allowed()
1653 have_virtfs_proxy_helper = targetos != 'darwin' and have_virtfs and have_tools
1655 if get_option('block_drv_ro_whitelist') == ''
1656   config_host_data.set('CONFIG_BDRV_RO_WHITELIST', '')
1657 else
1658   config_host_data.set('CONFIG_BDRV_RO_WHITELIST',
1659         '"' + get_option('block_drv_ro_whitelist').replace(',', '", "') + '", ')
1660 endif
1661 if get_option('block_drv_rw_whitelist') == ''
1662   config_host_data.set('CONFIG_BDRV_RW_WHITELIST', '')
1663 else
1664   config_host_data.set('CONFIG_BDRV_RW_WHITELIST',
1665         '"' + get_option('block_drv_rw_whitelist').replace(',', '", "') + '", ')
1666 endif
1668 foreach k : get_option('trace_backends')
1669   config_host_data.set('CONFIG_TRACE_' + k.to_upper(), true)
1670 endforeach
1671 config_host_data.set_quoted('CONFIG_TRACE_FILE', get_option('trace_file'))
1672 config_host_data.set_quoted('CONFIG_TLS_PRIORITY', get_option('tls_priority'))
1673 if iasl.found()
1674   config_host_data.set_quoted('CONFIG_IASL', iasl.full_path())
1675 endif
1676 config_host_data.set_quoted('CONFIG_BINDIR', get_option('prefix') / get_option('bindir'))
1677 config_host_data.set_quoted('CONFIG_PREFIX', get_option('prefix'))
1678 config_host_data.set_quoted('CONFIG_QEMU_CONFDIR', get_option('prefix') / qemu_confdir)
1679 config_host_data.set_quoted('CONFIG_QEMU_DATADIR', get_option('prefix') / qemu_datadir)
1680 config_host_data.set_quoted('CONFIG_QEMU_DESKTOPDIR', get_option('prefix') / qemu_desktopdir)
1681 config_host_data.set_quoted('CONFIG_QEMU_FIRMWAREPATH', get_option('prefix') / get_option('qemu_firmwarepath'))
1682 config_host_data.set_quoted('CONFIG_QEMU_HELPERDIR', get_option('prefix') / get_option('libexecdir'))
1683 config_host_data.set_quoted('CONFIG_QEMU_ICONDIR', get_option('prefix') / qemu_icondir)
1684 config_host_data.set_quoted('CONFIG_QEMU_LOCALEDIR', get_option('prefix') / get_option('localedir'))
1685 config_host_data.set_quoted('CONFIG_QEMU_LOCALSTATEDIR', get_option('prefix') / get_option('localstatedir'))
1686 config_host_data.set_quoted('CONFIG_QEMU_MODDIR', get_option('prefix') / qemu_moddir)
1687 config_host_data.set_quoted('CONFIG_SYSCONFDIR', get_option('prefix') / get_option('sysconfdir'))
1689 if config_host.has_key('CONFIG_MODULES')
1690   config_host_data.set('CONFIG_STAMP', run_command(
1691       meson.current_source_dir() / 'scripts/qemu-stamp.py',
1692       meson.project_version(), get_option('pkgversion'), '--',
1693       meson.current_source_dir() / 'configure',
1694       capture: true, check: true).stdout().strip())
1695 endif
1697 have_slirp_smbd = get_option('slirp_smbd') \
1698   .require(targetos != 'windows', error_message: 'Host smbd not supported on this platform.') \
1699   .allowed()
1700 if have_slirp_smbd
1701   smbd_path = get_option('smbd')
1702   if smbd_path == ''
1703     smbd_path = (targetos == 'solaris' ? '/usr/sfw/sbin/smbd' : '/usr/sbin/smbd')
1704   endif
1705   config_host_data.set_quoted('CONFIG_SMBD_COMMAND', smbd_path)
1706 endif
1708 config_host_data.set('HOST_' + host_arch.to_upper(), 1)
1710 if get_option('module_upgrades') and not enable_modules
1711   error('Cannot enable module-upgrades as modules are not enabled')
1712 endif
1713 config_host_data.set('CONFIG_MODULE_UPGRADES', get_option('module_upgrades'))
1715 config_host_data.set('CONFIG_ATTR', libattr.found())
1716 config_host_data.set('CONFIG_BDRV_WHITELIST_TOOLS', get_option('block_drv_whitelist_in_tools'))
1717 config_host_data.set('CONFIG_BRLAPI', brlapi.found())
1718 config_host_data.set('CONFIG_COCOA', cocoa.found())
1719 config_host_data.set('CONFIG_FUZZ', get_option('fuzzing'))
1720 config_host_data.set('CONFIG_GCOV', get_option('b_coverage'))
1721 config_host_data.set('CONFIG_LIBUDEV', libudev.found())
1722 config_host_data.set('CONFIG_LZO', lzo.found())
1723 config_host_data.set('CONFIG_MPATH', mpathpersist.found())
1724 config_host_data.set('CONFIG_MPATH_NEW_API', mpathpersist_new_api)
1725 config_host_data.set('CONFIG_CURL', curl.found())
1726 config_host_data.set('CONFIG_CURSES', curses.found())
1727 config_host_data.set('CONFIG_GBM', gbm.found())
1728 config_host_data.set('CONFIG_GIO', gio.found())
1729 config_host_data.set('CONFIG_GLUSTERFS', glusterfs.found())
1730 if glusterfs.found()
1731   config_host_data.set('CONFIG_GLUSTERFS_XLATOR_OPT', glusterfs.version().version_compare('>=4'))
1732   config_host_data.set('CONFIG_GLUSTERFS_DISCARD', glusterfs.version().version_compare('>=5'))
1733   config_host_data.set('CONFIG_GLUSTERFS_FALLOCATE', glusterfs.version().version_compare('>=6'))
1734   config_host_data.set('CONFIG_GLUSTERFS_ZEROFILL', glusterfs.version().version_compare('>=6'))
1735   config_host_data.set('CONFIG_GLUSTERFS_FTRUNCATE_HAS_STAT', glusterfs_ftruncate_has_stat)
1736   config_host_data.set('CONFIG_GLUSTERFS_IOCB_HAS_STAT', glusterfs_iocb_has_stat)
1737 endif
1738 config_host_data.set('CONFIG_GTK', gtk.found())
1739 config_host_data.set('CONFIG_VTE', vte.found())
1740 config_host_data.set('CONFIG_LIBATTR', have_old_libattr)
1741 config_host_data.set('CONFIG_LIBCAP_NG', libcap_ng.found())
1742 config_host_data.set('CONFIG_EBPF', libbpf.found())
1743 config_host_data.set('CONFIG_LIBDAXCTL', libdaxctl.found())
1744 config_host_data.set('CONFIG_LIBISCSI', libiscsi.found())
1745 config_host_data.set('CONFIG_LIBNFS', libnfs.found())
1746 config_host_data.set('CONFIG_LIBSSH', libssh.found())
1747 config_host_data.set('CONFIG_LINUX_AIO', libaio.found())
1748 config_host_data.set('CONFIG_LINUX_IO_URING', linux_io_uring.found())
1749 config_host_data.set('CONFIG_LIBPMEM', libpmem.found())
1750 config_host_data.set('CONFIG_NUMA', numa.found())
1751 config_host_data.set('CONFIG_OPENGL', opengl.found())
1752 config_host_data.set('CONFIG_PROFILER', get_option('profiler'))
1753 config_host_data.set('CONFIG_RBD', rbd.found())
1754 config_host_data.set('CONFIG_RDMA', rdma.found())
1755 config_host_data.set('CONFIG_SDL', sdl.found())
1756 config_host_data.set('CONFIG_SDL_IMAGE', sdl_image.found())
1757 config_host_data.set('CONFIG_SECCOMP', seccomp.found())
1758 config_host_data.set('CONFIG_SNAPPY', snappy.found())
1759 config_host_data.set('CONFIG_TPM', have_tpm)
1760 config_host_data.set('CONFIG_USB_LIBUSB', libusb.found())
1761 config_host_data.set('CONFIG_VDE', vde.found())
1762 config_host_data.set('CONFIG_VHOST_NET', have_vhost_net)
1763 config_host_data.set('CONFIG_VHOST_NET_USER', have_vhost_net_user)
1764 config_host_data.set('CONFIG_VHOST_NET_VDPA', have_vhost_net_vdpa)
1765 config_host_data.set('CONFIG_VHOST_KERNEL', have_vhost_kernel)
1766 config_host_data.set('CONFIG_VHOST_USER', have_vhost_user)
1767 config_host_data.set('CONFIG_VHOST_CRYPTO', have_vhost_user_crypto)
1768 config_host_data.set('CONFIG_VHOST_VDPA', have_vhost_vdpa)
1769 config_host_data.set('CONFIG_VMNET', vmnet.found())
1770 config_host_data.set('CONFIG_VHOST_USER_BLK_SERVER', have_vhost_user_blk_server)
1771 config_host_data.set('CONFIG_PNG', png.found())
1772 config_host_data.set('CONFIG_VNC', vnc.found())
1773 config_host_data.set('CONFIG_VNC_JPEG', jpeg.found())
1774 config_host_data.set('CONFIG_VNC_SASL', sasl.found())
1775 config_host_data.set('CONFIG_VIRTFS', have_virtfs)
1776 config_host_data.set('CONFIG_VTE', vte.found())
1777 config_host_data.set('CONFIG_XKBCOMMON', xkbcommon.found())
1778 config_host_data.set('CONFIG_KEYUTILS', keyutils.found())
1779 config_host_data.set('CONFIG_GETTID', has_gettid)
1780 config_host_data.set('CONFIG_GNUTLS', gnutls.found())
1781 config_host_data.set('CONFIG_GNUTLS_CRYPTO', gnutls_crypto.found())
1782 config_host_data.set('CONFIG_TASN1', tasn1.found())
1783 config_host_data.set('CONFIG_GCRYPT', gcrypt.found())
1784 config_host_data.set('CONFIG_NETTLE', nettle.found())
1785 config_host_data.set('CONFIG_HOGWEED', hogweed.found())
1786 config_host_data.set('CONFIG_QEMU_PRIVATE_XTS', xts == 'private')
1787 config_host_data.set('CONFIG_MALLOC_TRIM', has_malloc_trim)
1788 config_host_data.set('CONFIG_STATX', has_statx)
1789 config_host_data.set('CONFIG_STATX_MNT_ID', has_statx_mnt_id)
1790 config_host_data.set('CONFIG_ZSTD', zstd.found())
1791 config_host_data.set('CONFIG_FUSE', fuse.found())
1792 config_host_data.set('CONFIG_FUSE_LSEEK', fuse_lseek.found())
1793 config_host_data.set('CONFIG_SPICE_PROTOCOL', spice_protocol.found())
1794 if spice_protocol.found()
1795 config_host_data.set('CONFIG_SPICE_PROTOCOL_MAJOR', spice_protocol.version().split('.')[0])
1796 config_host_data.set('CONFIG_SPICE_PROTOCOL_MINOR', spice_protocol.version().split('.')[1])
1797 config_host_data.set('CONFIG_SPICE_PROTOCOL_MICRO', spice_protocol.version().split('.')[2])
1798 endif
1799 config_host_data.set('CONFIG_SPICE', spice.found())
1800 config_host_data.set('CONFIG_X11', x11.found())
1801 config_host_data.set('CONFIG_DBUS_DISPLAY', dbus_display)
1802 config_host_data.set('CONFIG_CFI', get_option('cfi'))
1803 config_host_data.set('CONFIG_SELINUX', selinux.found())
1804 config_host_data.set('CONFIG_XEN_BACKEND', xen.found())
1805 if xen.found()
1806   # protect from xen.version() having less than three components
1807   xen_version = xen.version().split('.') + ['0', '0']
1808   xen_ctrl_version = xen_version[0] + \
1809     ('0' + xen_version[1]).substring(-2) + \
1810     ('0' + xen_version[2]).substring(-2)
1811   config_host_data.set('CONFIG_XEN_CTRL_INTERFACE_VERSION', xen_ctrl_version)
1812 endif
1813 config_host_data.set('QEMU_VERSION', '"@0@"'.format(meson.project_version()))
1814 config_host_data.set('QEMU_VERSION_MAJOR', meson.project_version().split('.')[0])
1815 config_host_data.set('QEMU_VERSION_MINOR', meson.project_version().split('.')[1])
1816 config_host_data.set('QEMU_VERSION_MICRO', meson.project_version().split('.')[2])
1818 config_host_data.set_quoted('CONFIG_HOST_DSOSUF', host_dsosuf)
1819 config_host_data.set('HAVE_HOST_BLOCK_DEVICE', have_host_block_device)
1821 have_coroutine_pool = get_option('coroutine_pool')
1822 if get_option('debug_stack_usage') and have_coroutine_pool
1823   message('Disabling coroutine pool to measure stack usage')
1824   have_coroutine_pool = false
1825 endif
1826 config_host_data.set10('CONFIG_COROUTINE_POOL', have_coroutine_pool)
1827 config_host_data.set('CONFIG_DEBUG_MUTEX', get_option('debug_mutex'))
1828 config_host_data.set('CONFIG_DEBUG_STACK_USAGE', get_option('debug_stack_usage'))
1829 config_host_data.set('CONFIG_GPROF', get_option('gprof'))
1830 config_host_data.set('CONFIG_LIVE_BLOCK_MIGRATION', get_option('live_block_migration').allowed())
1831 config_host_data.set('CONFIG_QOM_CAST_DEBUG', get_option('qom_cast_debug'))
1832 config_host_data.set('CONFIG_REPLICATION', get_option('live_block_migration').allowed())
1834 # has_header
1835 config_host_data.set('CONFIG_EPOLL', cc.has_header('sys/epoll.h'))
1836 config_host_data.set('CONFIG_LINUX_MAGIC_H', cc.has_header('linux/magic.h'))
1837 config_host_data.set('CONFIG_VALGRIND_H', cc.has_header('valgrind/valgrind.h'))
1838 config_host_data.set('HAVE_BTRFS_H', cc.has_header('linux/btrfs.h'))
1839 config_host_data.set('HAVE_DRM_H', cc.has_header('libdrm/drm.h'))
1840 config_host_data.set('HAVE_PTY_H', cc.has_header('pty.h'))
1841 config_host_data.set('HAVE_SYS_DISK_H', cc.has_header('sys/disk.h'))
1842 config_host_data.set('HAVE_SYS_IOCCOM_H', cc.has_header('sys/ioccom.h'))
1843 config_host_data.set('HAVE_SYS_KCOV_H', cc.has_header('sys/kcov.h'))
1845 # has_function
1846 config_host_data.set('CONFIG_ACCEPT4', cc.has_function('accept4'))
1847 config_host_data.set('CONFIG_CLOCK_ADJTIME', cc.has_function('clock_adjtime'))
1848 config_host_data.set('CONFIG_DUP3', cc.has_function('dup3'))
1849 config_host_data.set('CONFIG_FALLOCATE', cc.has_function('fallocate'))
1850 config_host_data.set('CONFIG_POSIX_FALLOCATE', cc.has_function('posix_fallocate'))
1851 # Note that we need to specify prefix: here to avoid incorrectly
1852 # thinking that Windows has posix_memalign()
1853 config_host_data.set('CONFIG_POSIX_MEMALIGN', cc.has_function('posix_memalign', prefix: '#include <stdlib.h>'))
1854 config_host_data.set('CONFIG_ALIGNED_MALLOC', cc.has_function('_aligned_malloc'))
1855 config_host_data.set('CONFIG_VALLOC', cc.has_function('valloc'))
1856 config_host_data.set('CONFIG_MEMALIGN', cc.has_function('memalign'))
1857 config_host_data.set('CONFIG_PPOLL', cc.has_function('ppoll'))
1858 config_host_data.set('CONFIG_PREADV', cc.has_function('preadv', prefix: '#include <sys/uio.h>'))
1859 config_host_data.set('CONFIG_PTHREAD_FCHDIR_NP', cc.has_function('pthread_fchdir_np'))
1860 config_host_data.set('CONFIG_SENDFILE', cc.has_function('sendfile'))
1861 config_host_data.set('CONFIG_SETNS', cc.has_function('setns') and cc.has_function('unshare'))
1862 config_host_data.set('CONFIG_SYNCFS', cc.has_function('syncfs'))
1863 config_host_data.set('CONFIG_SYNC_FILE_RANGE', cc.has_function('sync_file_range'))
1864 config_host_data.set('CONFIG_TIMERFD', cc.has_function('timerfd_create'))
1865 config_host_data.set('HAVE_COPY_FILE_RANGE', cc.has_function('copy_file_range'))
1866 config_host_data.set('HAVE_GETIFADDRS', cc.has_function('getifaddrs'))
1867 config_host_data.set('HAVE_OPENPTY', cc.has_function('openpty', dependencies: util))
1868 config_host_data.set('HAVE_STRCHRNUL', cc.has_function('strchrnul'))
1869 config_host_data.set('HAVE_SYSTEM_FUNCTION', cc.has_function('system', prefix: '#include <stdlib.h>'))
1870 if rdma.found()
1871   config_host_data.set('HAVE_IBV_ADVISE_MR',
1872                        cc.has_function('ibv_advise_mr',
1873                                        dependencies: rdma,
1874                                        prefix: '#include <infiniband/verbs.h>'))
1875 endif
1877 # has_header_symbol
1878 config_host_data.set('CONFIG_BYTESWAP_H',
1879                      cc.has_header_symbol('byteswap.h', 'bswap_32'))
1880 config_host_data.set('CONFIG_EPOLL_CREATE1',
1881                      cc.has_header_symbol('sys/epoll.h', 'epoll_create1'))
1882 config_host_data.set('CONFIG_FALLOCATE_PUNCH_HOLE',
1883                      cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_PUNCH_HOLE') and
1884                      cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_KEEP_SIZE'))
1885 config_host_data.set('CONFIG_FALLOCATE_ZERO_RANGE',
1886                      cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_ZERO_RANGE'))
1887 config_host_data.set('CONFIG_FIEMAP',
1888                      cc.has_header('linux/fiemap.h') and
1889                      cc.has_header_symbol('linux/fs.h', 'FS_IOC_FIEMAP'))
1890 config_host_data.set('CONFIG_GETRANDOM',
1891                      cc.has_function('getrandom') and
1892                      cc.has_header_symbol('sys/random.h', 'GRND_NONBLOCK'))
1893 config_host_data.set('CONFIG_INOTIFY',
1894                      cc.has_header_symbol('sys/inotify.h', 'inotify_init'))
1895 config_host_data.set('CONFIG_INOTIFY1',
1896                      cc.has_header_symbol('sys/inotify.h', 'inotify_init1'))
1897 config_host_data.set('CONFIG_MACHINE_BSWAP_H',
1898                      cc.has_header_symbol('machine/bswap.h', 'bswap32',
1899                                           prefix: '''#include <sys/endian.h>
1900                                                      #include <sys/types.h>'''))
1901 config_host_data.set('CONFIG_PRCTL_PR_SET_TIMERSLACK',
1902                      cc.has_header_symbol('sys/prctl.h', 'PR_SET_TIMERSLACK'))
1903 config_host_data.set('CONFIG_RTNETLINK',
1904                      cc.has_header_symbol('linux/rtnetlink.h', 'IFLA_PROTO_DOWN'))
1905 config_host_data.set('CONFIG_SYSMACROS',
1906                      cc.has_header_symbol('sys/sysmacros.h', 'makedev'))
1907 config_host_data.set('HAVE_OPTRESET',
1908                      cc.has_header_symbol('getopt.h', 'optreset'))
1909 config_host_data.set('HAVE_IPPROTO_MPTCP',
1910                      cc.has_header_symbol('netinet/in.h', 'IPPROTO_MPTCP'))
1912 # has_member
1913 config_host_data.set('HAVE_SIGEV_NOTIFY_THREAD_ID',
1914                      cc.has_member('struct sigevent', 'sigev_notify_thread_id',
1915                                    prefix: '#include <signal.h>'))
1916 config_host_data.set('HAVE_STRUCT_STAT_ST_ATIM',
1917                      cc.has_member('struct stat', 'st_atim',
1918                                    prefix: '#include <sys/stat.h>'))
1920 # has_type
1921 config_host_data.set('CONFIG_IOVEC',
1922                      cc.has_type('struct iovec',
1923                                  prefix: '#include <sys/uio.h>'))
1924 config_host_data.set('HAVE_UTMPX',
1925                      cc.has_type('struct utmpx',
1926                                  prefix: '#include <utmpx.h>'))
1928 config_host_data.set('CONFIG_EVENTFD', cc.links('''
1929   #include <sys/eventfd.h>
1930   int main(void) { return eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); }'''))
1931 config_host_data.set('CONFIG_FDATASYNC', cc.links(gnu_source_prefix + '''
1932   #include <unistd.h>
1933   int main(void) {
1934   #if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
1935   return fdatasync(0);
1936   #else
1937   #error Not supported
1938   #endif
1939   }'''))
1941 has_madvise = cc.links(gnu_source_prefix + '''
1942   #include <sys/types.h>
1943   #include <sys/mman.h>
1944   #include <stddef.h>
1945   int main(void) { return madvise(NULL, 0, MADV_DONTNEED); }''')
1946 missing_madvise_proto = false
1947 if has_madvise
1948   # Some platforms (illumos and Solaris before Solaris 11) provide madvise()
1949   # but forget to prototype it. In this case, has_madvise will be true (the
1950   # test program links despite a compile warning). To detect the
1951   # missing-prototype case, we try again with a definitely-bogus prototype.
1952   # This will only compile if the system headers don't provide the prototype;
1953   # otherwise the conflicting prototypes will cause a compiler error.
1954   missing_madvise_proto = cc.links(gnu_source_prefix + '''
1955     #include <sys/types.h>
1956     #include <sys/mman.h>
1957     #include <stddef.h>
1958     extern int madvise(int);
1959     int main(void) { return madvise(0); }''')
1960 endif
1961 config_host_data.set('CONFIG_MADVISE', has_madvise)
1962 config_host_data.set('HAVE_MADVISE_WITHOUT_PROTOTYPE', missing_madvise_proto)
1964 config_host_data.set('CONFIG_MEMFD', cc.links(gnu_source_prefix + '''
1965   #include <sys/mman.h>
1966   int main(void) { return memfd_create("foo", MFD_ALLOW_SEALING); }'''))
1967 config_host_data.set('CONFIG_OPEN_BY_HANDLE', cc.links(gnu_source_prefix + '''
1968   #include <fcntl.h>
1969   #if !defined(AT_EMPTY_PATH)
1970   # error missing definition
1971   #else
1972   int main(void) { struct file_handle fh; return open_by_handle_at(0, &fh, 0); }
1973   #endif'''))
1974 config_host_data.set('CONFIG_PIPE2', cc.links(gnu_source_prefix + '''
1975   #include <unistd.h>
1976   #include <fcntl.h>
1978   int main(void)
1979   {
1980       int pipefd[2];
1981       return pipe2(pipefd, O_CLOEXEC);
1982   }'''))
1983 config_host_data.set('CONFIG_POSIX_MADVISE', cc.links(gnu_source_prefix + '''
1984   #include <sys/mman.h>
1985   #include <stddef.h>
1986   int main(void) { return posix_madvise(NULL, 0, POSIX_MADV_DONTNEED); }'''))
1988 config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_W_TID', cc.links(gnu_source_prefix + '''
1989   #include <pthread.h>
1991   static void *f(void *p) { return NULL; }
1992   int main(void)
1993   {
1994     pthread_t thread;
1995     pthread_create(&thread, 0, f, 0);
1996     pthread_setname_np(thread, "QEMU");
1997     return 0;
1998   }''', dependencies: threads))
1999 config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_WO_TID', cc.links(gnu_source_prefix + '''
2000   #include <pthread.h>
2002   static void *f(void *p) { pthread_setname_np("QEMU"); return NULL; }
2003   int main(void)
2004   {
2005     pthread_t thread;
2006     pthread_create(&thread, 0, f, 0);
2007     return 0;
2008   }''', dependencies: threads))
2009 config_host_data.set('CONFIG_PTHREAD_CONDATTR_SETCLOCK', cc.links(gnu_source_prefix + '''
2010   #include <pthread.h>
2011   #include <time.h>
2013   int main(void)
2014   {
2015     pthread_condattr_t attr
2016     pthread_condattr_init(&attr);
2017     pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
2018     return 0;
2019   }''', dependencies: threads))
2021 config_host_data.set('CONFIG_SIGNALFD', cc.links(gnu_source_prefix + '''
2022   #include <sys/signalfd.h>
2023   #include <stddef.h>
2024   int main(void) { return signalfd(-1, NULL, SFD_CLOEXEC); }'''))
2025 config_host_data.set('CONFIG_SPLICE', cc.links(gnu_source_prefix + '''
2026   #include <unistd.h>
2027   #include <fcntl.h>
2028   #include <limits.h>
2030   int main(void)
2031   {
2032     int len, fd = 0;
2033     len = tee(STDIN_FILENO, STDOUT_FILENO, INT_MAX, SPLICE_F_NONBLOCK);
2034     splice(STDIN_FILENO, NULL, fd, NULL, len, SPLICE_F_MOVE);
2035     return 0;
2036   }'''))
2038 config_host_data.set('HAVE_MLOCKALL', cc.links(gnu_source_prefix + '''
2039   #include <sys/mman.h>
2040   int main(int argc, char *argv[]) {
2041     return mlockall(MCL_FUTURE);
2042   }'''))
2044 have_l2tpv3 = false
2045 if get_option('l2tpv3').allowed() and have_system
2046   have_l2tpv3 = cc.has_type('struct mmsghdr',
2047     prefix: gnu_source_prefix + '''
2048       #include <sys/socket.h>
2049       #include <linux/ip.h>''')
2050 endif
2051 config_host_data.set('CONFIG_L2TPV3', have_l2tpv3)
2053 have_netmap = false
2054 if get_option('netmap').allowed() and have_system
2055   have_netmap = cc.compiles('''
2056     #include <inttypes.h>
2057     #include <net/if.h>
2058     #include <net/netmap.h>
2059     #include <net/netmap_user.h>
2060     #if (NETMAP_API < 11) || (NETMAP_API > 15)
2061     #error
2062     #endif
2063     int main(void) { return 0; }''')
2064   if not have_netmap and get_option('netmap').enabled()
2065     error('Netmap headers not available')
2066   endif
2067 endif
2068 config_host_data.set('CONFIG_NETMAP', have_netmap)
2070 # Work around a system header bug with some kernel/XFS header
2071 # versions where they both try to define 'struct fsxattr':
2072 # xfs headers will not try to redefine structs from linux headers
2073 # if this macro is set.
2074 config_host_data.set('HAVE_FSXATTR', cc.links('''
2075   #include <linux/fs.h>
2076   struct fsxattr foo;
2077   int main(void) {
2078     return 0;
2079   }'''))
2081 # Some versions of Mac OS X incorrectly define SIZE_MAX
2082 config_host_data.set('HAVE_BROKEN_SIZE_MAX', not cc.compiles('''
2083     #include <stdint.h>
2084     #include <stdio.h>
2085     int main(int argc, char *argv[]) {
2086         return printf("%zu", SIZE_MAX);
2087     }''', args: ['-Werror']))
2089 atomic_test = '''
2090   #include <stdint.h>
2091   int main(void)
2092   {
2093     @0@ x = 0, y = 0;
2094     y = __atomic_load_n(&x, __ATOMIC_RELAXED);
2095     __atomic_store_n(&x, y, __ATOMIC_RELAXED);
2096     __atomic_compare_exchange_n(&x, &y, x, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
2097     __atomic_exchange_n(&x, y, __ATOMIC_RELAXED);
2098     __atomic_fetch_add(&x, y, __ATOMIC_RELAXED);
2099     return 0;
2100   }'''
2102 # See if 64-bit atomic operations are supported.
2103 # Note that without __atomic builtins, we can only
2104 # assume atomic loads/stores max at pointer size.
2105 config_host_data.set('CONFIG_ATOMIC64', cc.links(atomic_test.format('uint64_t')))
2107 has_int128 = cc.links('''
2108   __int128_t a;
2109   __uint128_t b;
2110   int main (void) {
2111     a = a + b;
2112     b = a * b;
2113     a = a * a;
2114     return 0;
2115   }''')
2117 config_host_data.set('CONFIG_INT128', has_int128)
2119 if has_int128
2120   # "do we have 128-bit atomics which are handled inline and specifically not
2121   # via libatomic". The reason we can't use libatomic is documented in the
2122   # comment starting "GCC is a house divided" in include/qemu/atomic128.h.
2123   has_atomic128 = cc.links(atomic_test.format('unsigned __int128'))
2125   config_host_data.set('CONFIG_ATOMIC128', has_atomic128)
2127   if not has_atomic128
2128     has_cmpxchg128 = cc.links('''
2129       int main(void)
2130       {
2131         unsigned __int128 x = 0, y = 0;
2132         __sync_val_compare_and_swap_16(&x, y, x);
2133         return 0;
2134       }
2135     ''')
2137     config_host_data.set('CONFIG_CMPXCHG128', has_cmpxchg128)
2138   endif
2139 endif
2141 config_host_data.set('CONFIG_GETAUXVAL', cc.links(gnu_source_prefix + '''
2142   #include <sys/auxv.h>
2143   int main(void) {
2144     return getauxval(AT_HWCAP) == 0;
2145   }'''))
2147 config_host_data.set('CONFIG_USBFS', have_linux_user and cc.compiles('''
2148   #include <linux/usbdevice_fs.h>
2150   #ifndef USBDEVFS_GET_CAPABILITIES
2151   #error "USBDEVFS_GET_CAPABILITIES undefined"
2152   #endif
2154   #ifndef USBDEVFS_DISCONNECT_CLAIM
2155   #error "USBDEVFS_DISCONNECT_CLAIM undefined"
2156   #endif
2158   int main(void) { return 0; }'''))
2160 have_keyring = get_option('keyring') \
2161   .require(targetos == 'linux', error_message: 'keyring is only available on Linux') \
2162   .require(cc.compiles('''
2163     #include <errno.h>
2164     #include <asm/unistd.h>
2165     #include <linux/keyctl.h>
2166     #include <sys/syscall.h>
2167     #include <unistd.h>
2168     int main(void) {
2169         return syscall(__NR_keyctl, KEYCTL_READ, 0, NULL, NULL, 0);
2170     }'''), error_message: 'keyctl syscall not available on this system').allowed()
2171 config_host_data.set('CONFIG_SECRET_KEYRING', have_keyring)
2173 have_cpuid_h = cc.links('''
2174   #include <cpuid.h>
2175   int main(void) {
2176     unsigned a, b, c, d;
2177     unsigned max = __get_cpuid_max(0, 0);
2179     if (max >= 1) {
2180         __cpuid(1, a, b, c, d);
2181     }
2183     if (max >= 7) {
2184         __cpuid_count(7, 0, a, b, c, d);
2185     }
2187     return 0;
2188   }''')
2189 config_host_data.set('CONFIG_CPUID_H', have_cpuid_h)
2191 config_host_data.set('CONFIG_AVX2_OPT', get_option('avx2') \
2192   .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable AVX2') \
2193   .require(cc.links('''
2194     #pragma GCC push_options
2195     #pragma GCC target("avx2")
2196     #include <cpuid.h>
2197     #include <immintrin.h>
2198     static int bar(void *a) {
2199       __m256i x = *(__m256i *)a;
2200       return _mm256_testz_si256(x, x);
2201     }
2202     int main(int argc, char *argv[]) { return bar(argv[0]); }
2203   '''), error_message: 'AVX2 not available').allowed())
2205 config_host_data.set('CONFIG_AVX512F_OPT', get_option('avx512f') \
2206   .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable AVX512F') \
2207   .require(cc.links('''
2208     #pragma GCC push_options
2209     #pragma GCC target("avx512f")
2210     #include <cpuid.h>
2211     #include <immintrin.h>
2212     static int bar(void *a) {
2213       __m512i x = *(__m512i *)a;
2214       return _mm512_test_epi64_mask(x, x);
2215     }
2216     int main(int argc, char *argv[]) { return bar(argv[0]); }
2217   '''), error_message: 'AVX512F not available').allowed())
2219 have_pvrdma = get_option('pvrdma') \
2220   .require(rdma.found(), error_message: 'PVRDMA requires OpenFabrics libraries') \
2221   .require(cc.compiles(gnu_source_prefix + '''
2222     #include <sys/mman.h>
2223     int main(void)
2224     {
2225       char buf = 0;
2226       void *addr = &buf;
2227       addr = mremap(addr, 0, 1, MREMAP_MAYMOVE | MREMAP_FIXED);
2229       return 0;
2230     }'''), error_message: 'PVRDMA requires mremap').allowed()
2232 if have_pvrdma
2233   config_host_data.set('LEGACY_RDMA_REG_MR', not cc.links('''
2234     #include <infiniband/verbs.h>
2235     int main(void)
2236     {
2237       struct ibv_mr *mr;
2238       struct ibv_pd *pd = NULL;
2239       size_t length = 10;
2240       uint64_t iova = 0;
2241       int access = 0;
2242       void *addr = NULL;
2244       mr = ibv_reg_mr_iova(pd, addr, length, iova, access);
2245       ibv_dereg_mr(mr);
2246       return 0;
2247     }'''))
2248 endif
2250 if get_option('membarrier').disabled()
2251   have_membarrier = false
2252 elif targetos == 'windows'
2253   have_membarrier = true
2254 elif targetos == 'linux'
2255   have_membarrier = cc.compiles('''
2256     #include <linux/membarrier.h>
2257     #include <sys/syscall.h>
2258     #include <unistd.h>
2259     #include <stdlib.h>
2260     int main(void) {
2261         syscall(__NR_membarrier, MEMBARRIER_CMD_QUERY, 0);
2262         syscall(__NR_membarrier, MEMBARRIER_CMD_SHARED, 0);
2263         exit(0);
2264     }''')
2265 endif
2266 config_host_data.set('CONFIG_MEMBARRIER', get_option('membarrier') \
2267   .require(have_membarrier, error_message: 'membarrier system call not available') \
2268   .allowed())
2270 have_afalg = get_option('crypto_afalg') \
2271   .require(cc.compiles(gnu_source_prefix + '''
2272     #include <errno.h>
2273     #include <sys/types.h>
2274     #include <sys/socket.h>
2275     #include <linux/if_alg.h>
2276     int main(void) {
2277       int sock;
2278       sock = socket(AF_ALG, SOCK_SEQPACKET, 0);
2279       return sock;
2280     }
2281   '''), error_message: 'AF_ALG requested but could not be detected').allowed()
2282 config_host_data.set('CONFIG_AF_ALG', have_afalg)
2284 config_host_data.set('CONFIG_AF_VSOCK', cc.has_header_symbol(
2285   'linux/vm_sockets.h', 'AF_VSOCK',
2286   prefix: '#include <sys/socket.h>',
2289 have_vss = false
2290 have_vss_sdk = false # old xp/2003 SDK
2291 if targetos == 'windows' and link_language == 'cpp'
2292   have_vss = cxx.compiles('''
2293     #define __MIDL_user_allocate_free_DEFINED__
2294     #include <vss.h>
2295     int main(void) { return VSS_CTX_BACKUP; }''')
2296   have_vss_sdk = cxx.has_header('vscoordint.h')
2297 endif
2298 config_host_data.set('HAVE_VSS_SDK', have_vss_sdk)
2300 foreach k, v: config_host
2301   if k.startswith('CONFIG_')
2302     config_host_data.set(k, v == 'y' ? 1 : v)
2303   endif
2304 endforeach
2306 # Older versions of MinGW do not import _lock_file and _unlock_file properly.
2307 # This was fixed for v6.0.0 with commit b48e3ac8969d.
2308 if targetos == 'windows'
2309   config_host_data.set('HAVE__LOCK_FILE', cc.links('''
2310     #include <stdio.h>
2311     int main(void) {
2312       _lock_file(NULL);
2313       _unlock_file(NULL);
2314       return 0;
2315     }''', name: '_lock_file and _unlock_file'))
2316 endif
2318 ########################
2319 # Target configuration #
2320 ########################
2322 minikconf = find_program('scripts/minikconf.py')
2323 config_all = {}
2324 config_all_devices = {}
2325 config_all_disas = {}
2326 config_devices_mak_list = []
2327 config_devices_h = {}
2328 config_target_h = {}
2329 config_target_mak = {}
2331 disassemblers = {
2332   'alpha' : ['CONFIG_ALPHA_DIS'],
2333   'arm' : ['CONFIG_ARM_DIS'],
2334   'avr' : ['CONFIG_AVR_DIS'],
2335   'cris' : ['CONFIG_CRIS_DIS'],
2336   'hexagon' : ['CONFIG_HEXAGON_DIS'],
2337   'hppa' : ['CONFIG_HPPA_DIS'],
2338   'i386' : ['CONFIG_I386_DIS'],
2339   'x86_64' : ['CONFIG_I386_DIS'],
2340   'm68k' : ['CONFIG_M68K_DIS'],
2341   'microblaze' : ['CONFIG_MICROBLAZE_DIS'],
2342   'mips' : ['CONFIG_MIPS_DIS'],
2343   'nios2' : ['CONFIG_NIOS2_DIS'],
2344   'or1k' : ['CONFIG_OPENRISC_DIS'],
2345   'ppc' : ['CONFIG_PPC_DIS'],
2346   'riscv' : ['CONFIG_RISCV_DIS'],
2347   'rx' : ['CONFIG_RX_DIS'],
2348   's390' : ['CONFIG_S390_DIS'],
2349   'sh4' : ['CONFIG_SH4_DIS'],
2350   'sparc' : ['CONFIG_SPARC_DIS'],
2351   'xtensa' : ['CONFIG_XTENSA_DIS'],
2352   'loongarch' : ['CONFIG_LOONGARCH_DIS'],
2354 if link_language == 'cpp'
2355   disassemblers += {
2356     'aarch64' : [ 'CONFIG_ARM_A64_DIS'],
2357     'arm' : [ 'CONFIG_ARM_DIS', 'CONFIG_ARM_A64_DIS'],
2358     'mips' : [ 'CONFIG_MIPS_DIS', 'CONFIG_NANOMIPS_DIS'],
2359   }
2360 endif
2362 have_ivshmem = config_host_data.get('CONFIG_EVENTFD')
2363 host_kconfig = \
2364   (get_option('fuzzing') ? ['CONFIG_FUZZ=y'] : []) + \
2365   (have_tpm ? ['CONFIG_TPM=y'] : []) + \
2366   (spice.found() ? ['CONFIG_SPICE=y'] : []) + \
2367   (have_ivshmem ? ['CONFIG_IVSHMEM=y'] : []) + \
2368   (opengl.found() ? ['CONFIG_OPENGL=y'] : []) + \
2369   (x11.found() ? ['CONFIG_X11=y'] : []) + \
2370   (have_vhost_user ? ['CONFIG_VHOST_USER=y'] : []) + \
2371   (have_vhost_vdpa ? ['CONFIG_VHOST_VDPA=y'] : []) + \
2372   (have_vhost_kernel ? ['CONFIG_VHOST_KERNEL=y'] : []) + \
2373   (have_virtfs ? ['CONFIG_VIRTFS=y'] : []) + \
2374   ('CONFIG_LINUX' in config_host ? ['CONFIG_LINUX=y'] : []) + \
2375   (have_pvrdma ? ['CONFIG_PVRDMA=y'] : []) + \
2376   (multiprocess_allowed ? ['CONFIG_MULTIPROCESS_ALLOWED=y'] : [])
2378 ignored = [ 'TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_ARCH' ]
2380 default_targets = 'CONFIG_DEFAULT_TARGETS' in config_host
2381 actual_target_dirs = []
2382 fdt_required = []
2383 foreach target : target_dirs
2384   config_target = { 'TARGET_NAME': target.split('-')[0] }
2385   if target.endswith('linux-user')
2386     if targetos != 'linux'
2387       if default_targets
2388         continue
2389       endif
2390       error('Target @0@ is only available on a Linux host'.format(target))
2391     endif
2392     config_target += { 'CONFIG_LINUX_USER': 'y' }
2393   elif target.endswith('bsd-user')
2394     if 'CONFIG_BSD' not in config_host
2395       if default_targets
2396         continue
2397       endif
2398       error('Target @0@ is only available on a BSD host'.format(target))
2399     endif
2400     config_target += { 'CONFIG_BSD_USER': 'y' }
2401   elif target.endswith('softmmu')
2402     config_target += { 'CONFIG_SOFTMMU': 'y' }
2403   endif
2404   if target.endswith('-user')
2405     config_target += {
2406       'CONFIG_USER_ONLY': 'y',
2407       'CONFIG_QEMU_INTERP_PREFIX':
2408         get_option('interp_prefix').replace('%M', config_target['TARGET_NAME'])
2409     }
2410   endif
2412   accel_kconfig = []
2413   foreach sym: accelerators
2414     if sym == 'CONFIG_TCG' or target in accelerator_targets.get(sym, [])
2415       config_target += { sym: 'y' }
2416       config_all += { sym: 'y' }
2417       if sym == 'CONFIG_TCG' and tcg_arch == 'tci'
2418         config_target += { 'CONFIG_TCG_INTERPRETER': 'y' }
2419       endif
2420       if target in modular_tcg
2421         config_target += { 'CONFIG_TCG_MODULAR': 'y' }
2422       else
2423         config_target += { 'CONFIG_TCG_BUILTIN': 'y' }
2424       endif
2425       accel_kconfig += [ sym + '=y' ]
2426     endif
2427   endforeach
2428   if accel_kconfig.length() == 0
2429     if default_targets
2430       continue
2431     endif
2432     error('No accelerator available for target @0@'.format(target))
2433   endif
2435   actual_target_dirs += target
2436   config_target += keyval.load('configs/targets' / target + '.mak')
2437   config_target += { 'TARGET_' + config_target['TARGET_ARCH'].to_upper(): 'y' }
2439   if 'TARGET_NEED_FDT' in config_target
2440     fdt_required += target
2441   endif
2443   # Add default keys
2444   if 'TARGET_BASE_ARCH' not in config_target
2445     config_target += {'TARGET_BASE_ARCH': config_target['TARGET_ARCH']}
2446   endif
2447   if 'TARGET_ABI_DIR' not in config_target
2448     config_target += {'TARGET_ABI_DIR': config_target['TARGET_ARCH']}
2449   endif
2450   if 'TARGET_BIG_ENDIAN' not in config_target
2451     config_target += {'TARGET_BIG_ENDIAN': 'n'}
2452   endif
2454   foreach k, v: disassemblers
2455     if host_arch.startswith(k) or config_target['TARGET_BASE_ARCH'].startswith(k)
2456       foreach sym: v
2457         config_target += { sym: 'y' }
2458         config_all_disas += { sym: 'y' }
2459       endforeach
2460     endif
2461   endforeach
2463   config_target_data = configuration_data()
2464   foreach k, v: config_target
2465     if not k.startswith('TARGET_') and not k.startswith('CONFIG_')
2466       # do nothing
2467     elif ignored.contains(k)
2468       # do nothing
2469     elif k == 'TARGET_BASE_ARCH'
2470       # Note that TARGET_BASE_ARCH ends up in config-target.h but it is
2471       # not used to select files from sourcesets.
2472       config_target_data.set('TARGET_' + v.to_upper(), 1)
2473     elif k == 'TARGET_NAME' or k == 'CONFIG_QEMU_INTERP_PREFIX'
2474       config_target_data.set_quoted(k, v)
2475     elif v == 'y'
2476       config_target_data.set(k, 1)
2477     elif v == 'n'
2478       config_target_data.set(k, 0)
2479     else
2480       config_target_data.set(k, v)
2481     endif
2482   endforeach
2483   config_target_data.set('QEMU_ARCH',
2484                          'QEMU_ARCH_' + config_target['TARGET_BASE_ARCH'].to_upper())
2485   config_target_h += {target: configure_file(output: target + '-config-target.h',
2486                                                configuration: config_target_data)}
2488   if target.endswith('-softmmu')
2489     config_input = meson.get_external_property(target, 'default')
2490     config_devices_mak = target + '-config-devices.mak'
2491     config_devices_mak = configure_file(
2492       input: ['configs/devices' / target / config_input + '.mak', 'Kconfig'],
2493       output: config_devices_mak,
2494       depfile: config_devices_mak + '.d',
2495       capture: true,
2496       command: [minikconf,
2497                 get_option('default_devices') ? '--defconfig' : '--allnoconfig',
2498                 config_devices_mak, '@DEPFILE@', '@INPUT@',
2499                 host_kconfig, accel_kconfig,
2500                 'CONFIG_' + config_target['TARGET_ARCH'].to_upper() + '=y'])
2502     config_devices_data = configuration_data()
2503     config_devices = keyval.load(config_devices_mak)
2504     foreach k, v: config_devices
2505       config_devices_data.set(k, 1)
2506     endforeach
2507     config_devices_mak_list += config_devices_mak
2508     config_devices_h += {target: configure_file(output: target + '-config-devices.h',
2509                                                 configuration: config_devices_data)}
2510     config_target += config_devices
2511     config_all_devices += config_devices
2512   endif
2513   config_target_mak += {target: config_target}
2514 endforeach
2515 target_dirs = actual_target_dirs
2517 # This configuration is used to build files that are shared by
2518 # multiple binaries, and then extracted out of the "common"
2519 # static_library target.
2521 # We do not use all_sources()/all_dependencies(), because it would
2522 # build literally all source files, including devices only used by
2523 # targets that are not built for this compilation.  The CONFIG_ALL
2524 # pseudo symbol replaces it.
2526 config_all += config_all_devices
2527 config_all += config_host
2528 config_all += config_all_disas
2529 config_all += {
2530   'CONFIG_XEN': xen.found(),
2531   'CONFIG_SOFTMMU': have_system,
2532   'CONFIG_USER_ONLY': have_user,
2533   'CONFIG_ALL': true,
2536 target_configs_h = []
2537 foreach target: target_dirs
2538   target_configs_h += config_target_h[target]
2539   target_configs_h += config_devices_h.get(target, [])
2540 endforeach
2541 genh += custom_target('config-poison.h',
2542                       input: [target_configs_h],
2543                       output: 'config-poison.h',
2544                       capture: true,
2545                       command: [find_program('scripts/make-config-poison.sh'),
2546                                 target_configs_h])
2548 ##############
2549 # Submodules #
2550 ##############
2552 capstone = not_found
2553 if not get_option('capstone').auto() or have_system or have_user
2554   capstone = dependency('capstone', version: '>=3.0.5',
2555                         kwargs: static_kwargs, method: 'pkg-config',
2556                         required: get_option('capstone'))
2558   # Some versions of capstone have broken pkg-config file
2559   # that reports a wrong -I path, causing the #include to
2560   # fail later. If the system has such a broken version
2561   # do not use it.
2562   if capstone.found() and not cc.compiles('#include <capstone.h>',
2563                                           dependencies: [capstone])
2564     capstone = not_found
2565     if get_option('capstone').enabled()
2566       error('capstone requested, but it does not appear to work')
2567     endif
2568   endif
2569 endif
2571 slirp = not_found
2572 slirp_opt = 'disabled'
2573 if have_system
2574   slirp_opt = get_option('slirp')
2575   if slirp_opt in ['enabled', 'auto', 'system']
2576     have_internal = fs.exists(meson.current_source_dir() / 'slirp/meson.build')
2577     slirp_dep_required = (slirp_opt == 'system' or
2578                           slirp_opt == 'enabled' and not have_internal)
2579     slirp = dependency('slirp', kwargs: static_kwargs,
2580                        method: 'pkg-config', version: '>=4.1.0',
2581                        required: slirp_dep_required)
2582     # slirp <4.7 is incompatible with CFI support in QEMU.  This is because
2583     # it passes function pointers within libslirp as callbacks for timers.
2584     # When using a system-wide shared libslirp, the type information for the
2585     # callback is missing and the timer call produces a false positive with CFI.
2586     # Do not use the "version" keyword argument to produce a better error.
2587     # with control-flow integrity.
2588     if get_option('cfi') and slirp.found() and slirp.version().version_compare('<4.7')
2589       if slirp_dep_required
2590         error('Control-Flow Integrity requires libslirp 4.7.')
2591       else
2592         warning('Control-Flow Integrity requires libslirp 4.7, not using system-wide libslirp.')
2593         slirp = not_found
2594       endif
2595     endif
2596     if slirp.found()
2597       slirp_opt = 'system'
2598     elif have_internal
2599       slirp_opt = 'internal'
2600     else
2601       slirp_opt = 'disabled'
2602     endif
2603   endif
2604   if slirp_opt == 'internal'
2605     slirp_deps = []
2606     if targetos == 'windows'
2607       slirp_deps = cc.find_library('iphlpapi')
2608     elif targetos == 'darwin'
2609       slirp_deps = cc.find_library('resolv')
2610     endif
2611     slirp_conf = configuration_data()
2612     slirp_conf.set('SLIRP_MAJOR_VERSION', meson.project_version().split('.')[0])
2613     slirp_conf.set('SLIRP_MINOR_VERSION', meson.project_version().split('.')[1])
2614     slirp_conf.set('SLIRP_MICRO_VERSION', meson.project_version().split('.')[2])
2615     slirp_conf.set_quoted('SLIRP_VERSION_STRING', meson.project_version())
2616     slirp_cargs = ['-DG_LOG_DOMAIN="Slirp"']
2617     slirp_files = [
2618       'slirp/src/arp_table.c',
2619       'slirp/src/bootp.c',
2620       'slirp/src/cksum.c',
2621       'slirp/src/dhcpv6.c',
2622       'slirp/src/dnssearch.c',
2623       'slirp/src/if.c',
2624       'slirp/src/ip6_icmp.c',
2625       'slirp/src/ip6_input.c',
2626       'slirp/src/ip6_output.c',
2627       'slirp/src/ip_icmp.c',
2628       'slirp/src/ip_input.c',
2629       'slirp/src/ip_output.c',
2630       'slirp/src/mbuf.c',
2631       'slirp/src/misc.c',
2632       'slirp/src/ncsi.c',
2633       'slirp/src/ndp_table.c',
2634       'slirp/src/sbuf.c',
2635       'slirp/src/slirp.c',
2636       'slirp/src/socket.c',
2637       'slirp/src/state.c',
2638       'slirp/src/stream.c',
2639       'slirp/src/tcp_input.c',
2640       'slirp/src/tcp_output.c',
2641       'slirp/src/tcp_subr.c',
2642       'slirp/src/tcp_timer.c',
2643       'slirp/src/tftp.c',
2644       'slirp/src/udp.c',
2645       'slirp/src/udp6.c',
2646       'slirp/src/util.c',
2647       'slirp/src/version.c',
2648       'slirp/src/vmstate.c',
2649     ]
2651     configure_file(
2652       input : 'slirp/src/libslirp-version.h.in',
2653       output : 'libslirp-version.h',
2654       configuration: slirp_conf)
2656     slirp_inc = include_directories('slirp', 'slirp/src')
2657     libslirp = static_library('slirp',
2658                               build_by_default: false,
2659                               sources: slirp_files,
2660                               c_args: slirp_cargs,
2661                               include_directories: slirp_inc)
2662     slirp = declare_dependency(link_with: libslirp,
2663                                dependencies: slirp_deps,
2664                                include_directories: slirp_inc)
2665   endif
2666 endif
2668 fdt = not_found
2669 if have_system
2670   fdt_opt = get_option('fdt')
2671   if fdt_opt in ['enabled', 'auto', 'system']
2672     have_internal = fs.exists(meson.current_source_dir() / 'dtc/libfdt/Makefile.libfdt')
2673     fdt = cc.find_library('fdt', kwargs: static_kwargs,
2674                           required: fdt_opt == 'system' or
2675                                     fdt_opt == 'enabled' and not have_internal)
2676     if fdt.found() and cc.links('''
2677        #include <libfdt.h>
2678        #include <libfdt_env.h>
2679        int main(void) { fdt_find_max_phandle(NULL, NULL); return 0; }''',
2680          dependencies: fdt)
2681       fdt_opt = 'system'
2682     elif fdt_opt == 'system'
2683        error('system libfdt requested, but it is too old (1.5.1 or newer required)')
2684     elif have_internal
2685       fdt_opt = 'internal'
2686     else
2687       fdt_opt = 'disabled'
2688       fdt = not_found
2689     endif
2690   endif
2691   if fdt_opt == 'internal'
2692     fdt_files = files(
2693       'dtc/libfdt/fdt.c',
2694       'dtc/libfdt/fdt_ro.c',
2695       'dtc/libfdt/fdt_wip.c',
2696       'dtc/libfdt/fdt_sw.c',
2697       'dtc/libfdt/fdt_rw.c',
2698       'dtc/libfdt/fdt_strerror.c',
2699       'dtc/libfdt/fdt_empty_tree.c',
2700       'dtc/libfdt/fdt_addresses.c',
2701       'dtc/libfdt/fdt_overlay.c',
2702       'dtc/libfdt/fdt_check.c',
2703     )
2705     fdt_inc = include_directories('dtc/libfdt')
2706     libfdt = static_library('fdt',
2707                             build_by_default: false,
2708                             sources: fdt_files,
2709                             include_directories: fdt_inc)
2710     fdt = declare_dependency(link_with: libfdt,
2711                              include_directories: fdt_inc)
2712   endif
2713 else
2714   fdt_opt = 'disabled'
2715 endif
2716 if not fdt.found() and fdt_required.length() > 0
2717   error('fdt not available but required by targets ' + ', '.join(fdt_required))
2718 endif
2720 config_host_data.set('CONFIG_CAPSTONE', capstone.found())
2721 config_host_data.set('CONFIG_FDT', fdt.found())
2722 config_host_data.set('CONFIG_SLIRP', slirp.found())
2724 #####################
2725 # Generated sources #
2726 #####################
2728 genh += configure_file(output: 'config-host.h', configuration: config_host_data)
2730 hxtool = find_program('scripts/hxtool')
2731 shaderinclude = find_program('scripts/shaderinclude.pl')
2732 qapi_gen = find_program('scripts/qapi-gen.py')
2733 qapi_gen_depends = [ meson.current_source_dir() / 'scripts/qapi/__init__.py',
2734                      meson.current_source_dir() / 'scripts/qapi/commands.py',
2735                      meson.current_source_dir() / 'scripts/qapi/common.py',
2736                      meson.current_source_dir() / 'scripts/qapi/error.py',
2737                      meson.current_source_dir() / 'scripts/qapi/events.py',
2738                      meson.current_source_dir() / 'scripts/qapi/expr.py',
2739                      meson.current_source_dir() / 'scripts/qapi/gen.py',
2740                      meson.current_source_dir() / 'scripts/qapi/introspect.py',
2741                      meson.current_source_dir() / 'scripts/qapi/parser.py',
2742                      meson.current_source_dir() / 'scripts/qapi/schema.py',
2743                      meson.current_source_dir() / 'scripts/qapi/source.py',
2744                      meson.current_source_dir() / 'scripts/qapi/types.py',
2745                      meson.current_source_dir() / 'scripts/qapi/visit.py',
2746                      meson.current_source_dir() / 'scripts/qapi/common.py',
2747                      meson.current_source_dir() / 'scripts/qapi-gen.py'
2750 tracetool = [
2751   python, files('scripts/tracetool.py'),
2752    '--backend=' + ','.join(get_option('trace_backends'))
2754 tracetool_depends = files(
2755   'scripts/tracetool/backend/log.py',
2756   'scripts/tracetool/backend/__init__.py',
2757   'scripts/tracetool/backend/dtrace.py',
2758   'scripts/tracetool/backend/ftrace.py',
2759   'scripts/tracetool/backend/simple.py',
2760   'scripts/tracetool/backend/syslog.py',
2761   'scripts/tracetool/backend/ust.py',
2762   'scripts/tracetool/format/ust_events_c.py',
2763   'scripts/tracetool/format/ust_events_h.py',
2764   'scripts/tracetool/format/__init__.py',
2765   'scripts/tracetool/format/d.py',
2766   'scripts/tracetool/format/simpletrace_stap.py',
2767   'scripts/tracetool/format/c.py',
2768   'scripts/tracetool/format/h.py',
2769   'scripts/tracetool/format/log_stap.py',
2770   'scripts/tracetool/format/stap.py',
2771   'scripts/tracetool/__init__.py',
2772   'scripts/tracetool/transform.py',
2773   'scripts/tracetool/vcpu.py'
2776 qemu_version_cmd = [find_program('scripts/qemu-version.sh'),
2777                     meson.current_source_dir(),
2778                     get_option('pkgversion'), meson.project_version()]
2779 qemu_version = custom_target('qemu-version.h',
2780                              output: 'qemu-version.h',
2781                              command: qemu_version_cmd,
2782                              capture: true,
2783                              build_by_default: true,
2784                              build_always_stale: true)
2785 genh += qemu_version
2787 hxdep = []
2788 hx_headers = [
2789   ['qemu-options.hx', 'qemu-options.def'],
2790   ['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
2792 if have_system
2793   hx_headers += [
2794     ['hmp-commands.hx', 'hmp-commands.h'],
2795     ['hmp-commands-info.hx', 'hmp-commands-info.h'],
2796   ]
2797 endif
2798 foreach d : hx_headers
2799   hxdep += custom_target(d[1],
2800                 input: files(d[0]),
2801                 output: d[1],
2802                 capture: true,
2803                 build_by_default: true, # to be removed when added to a target
2804                 command: [hxtool, '-h', '@INPUT0@'])
2805 endforeach
2806 genh += hxdep
2808 ###################
2809 # Collect sources #
2810 ###################
2812 authz_ss = ss.source_set()
2813 blockdev_ss = ss.source_set()
2814 block_ss = ss.source_set()
2815 chardev_ss = ss.source_set()
2816 common_ss = ss.source_set()
2817 crypto_ss = ss.source_set()
2818 hwcore_ss = ss.source_set()
2819 io_ss = ss.source_set()
2820 qmp_ss = ss.source_set()
2821 qom_ss = ss.source_set()
2822 softmmu_ss = ss.source_set()
2823 specific_fuzz_ss = ss.source_set()
2824 specific_ss = ss.source_set()
2825 stub_ss = ss.source_set()
2826 trace_ss = ss.source_set()
2827 user_ss = ss.source_set()
2828 util_ss = ss.source_set()
2830 # accel modules
2831 qtest_module_ss = ss.source_set()
2832 tcg_module_ss = ss.source_set()
2834 modules = {}
2835 target_modules = {}
2836 hw_arch = {}
2837 target_arch = {}
2838 target_softmmu_arch = {}
2839 target_user_arch = {}
2841 ###############
2842 # Trace files #
2843 ###############
2845 # TODO: add each directory to the subdirs from its own meson.build, once
2846 # we have those
2847 trace_events_subdirs = [
2848   'crypto',
2849   'qapi',
2850   'qom',
2851   'monitor',
2852   'util',
2854 if have_linux_user
2855   trace_events_subdirs += [ 'linux-user' ]
2856 endif
2857 if have_bsd_user
2858   trace_events_subdirs += [ 'bsd-user' ]
2859 endif
2860 if have_block
2861   trace_events_subdirs += [
2862     'authz',
2863     'block',
2864     'io',
2865     'nbd',
2866     'scsi',
2867   ]
2868 endif
2869 if have_system
2870   trace_events_subdirs += [
2871     'accel/kvm',
2872     'audio',
2873     'backends',
2874     'backends/tpm',
2875     'chardev',
2876     'ebpf',
2877     'hw/9pfs',
2878     'hw/acpi',
2879     'hw/adc',
2880     'hw/alpha',
2881     'hw/arm',
2882     'hw/audio',
2883     'hw/block',
2884     'hw/block/dataplane',
2885     'hw/char',
2886     'hw/display',
2887     'hw/dma',
2888     'hw/hyperv',
2889     'hw/i2c',
2890     'hw/i386',
2891     'hw/i386/xen',
2892     'hw/ide',
2893     'hw/input',
2894     'hw/intc',
2895     'hw/isa',
2896     'hw/mem',
2897     'hw/mips',
2898     'hw/misc',
2899     'hw/misc/macio',
2900     'hw/net',
2901     'hw/net/can',
2902     'hw/nubus',
2903     'hw/nvme',
2904     'hw/nvram',
2905     'hw/pci',
2906     'hw/pci-host',
2907     'hw/ppc',
2908     'hw/rdma',
2909     'hw/rdma/vmw',
2910     'hw/rtc',
2911     'hw/s390x',
2912     'hw/scsi',
2913     'hw/sd',
2914     'hw/sh4',
2915     'hw/sparc',
2916     'hw/sparc64',
2917     'hw/ssi',
2918     'hw/timer',
2919     'hw/tpm',
2920     'hw/usb',
2921     'hw/vfio',
2922     'hw/virtio',
2923     'hw/watchdog',
2924     'hw/xen',
2925     'hw/gpio',
2926     'migration',
2927     'net',
2928     'softmmu',
2929     'ui',
2930     'hw/remote',
2931   ]
2932 endif
2933 if have_system or have_user
2934   trace_events_subdirs += [
2935     'accel/tcg',
2936     'hw/core',
2937     'target/arm',
2938     'target/arm/hvf',
2939     'target/hppa',
2940     'target/i386',
2941     'target/i386/kvm',
2942     'target/mips/tcg',
2943     'target/nios2',
2944     'target/ppc',
2945     'target/riscv',
2946     'target/s390x',
2947     'target/s390x/kvm',
2948     'target/sparc',
2949   ]
2950 endif
2952 vhost_user = not_found
2953 if targetos == 'linux' and have_vhost_user
2954   libvhost_user = subproject('libvhost-user')
2955   vhost_user = libvhost_user.get_variable('vhost_user_dep')
2956 endif
2958 # NOTE: the trace/ subdirectory needs the qapi_trace_events variable
2959 # that is filled in by qapi/.
2960 subdir('qapi')
2961 subdir('qobject')
2962 subdir('stubs')
2963 subdir('trace')
2964 subdir('util')
2965 subdir('qom')
2966 subdir('authz')
2967 subdir('crypto')
2968 subdir('ui')
2969 subdir('hw')
2972 if enable_modules
2973   libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
2974   modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
2975 endif
2977 qom_ss = qom_ss.apply(config_host, strict: false)
2978 libqom = static_library('qom', qom_ss.sources() + genh,
2979                         dependencies: [qom_ss.dependencies()],
2980                         name_suffix: 'fa')
2981 qom = declare_dependency(link_whole: libqom)
2983 event_loop_base = files('event-loop-base.c')
2984 event_loop_base = static_library('event-loop-base', sources: event_loop_base + genh,
2985                                  build_by_default: true)
2986 event_loop_base = declare_dependency(link_whole: event_loop_base,
2987                                      dependencies: [qom])
2989 stub_ss = stub_ss.apply(config_all, strict: false)
2991 util_ss.add_all(trace_ss)
2992 util_ss = util_ss.apply(config_all, strict: false)
2993 libqemuutil = static_library('qemuutil',
2994                              sources: util_ss.sources() + stub_ss.sources() + genh,
2995                              dependencies: [util_ss.dependencies(), libm, threads, glib, socket, malloc, pixman])
2996 qemuutil = declare_dependency(link_with: libqemuutil,
2997                               sources: genh + version_res,
2998                               dependencies: [event_loop_base])
3000 if have_system or have_user
3001   decodetree = generator(find_program('scripts/decodetree.py'),
3002                          output: 'decode-@BASENAME@.c.inc',
3003                          arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
3004   subdir('libdecnumber')
3005   subdir('target')
3006 endif
3008 subdir('audio')
3009 subdir('io')
3010 subdir('chardev')
3011 subdir('fsdev')
3012 subdir('dump')
3014 if have_block
3015   block_ss.add(files(
3016     'block.c',
3017     'blockjob.c',
3018     'job.c',
3019     'qemu-io-cmds.c',
3020   ))
3021   if config_host_data.get('CONFIG_REPLICATION')
3022     block_ss.add(files('replication.c'))
3023   endif
3025   subdir('nbd')
3026   subdir('scsi')
3027   subdir('block')
3029   blockdev_ss.add(files(
3030     'blockdev.c',
3031     'blockdev-nbd.c',
3032     'iothread.c',
3033     'job-qmp.c',
3034   ), gnutls)
3036   # os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
3037   # os-win32.c does not
3038   blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c'))
3039   softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')])
3040 endif
3042 common_ss.add(files('cpus-common.c'))
3044 subdir('softmmu')
3046 common_ss.add(capstone)
3047 specific_ss.add(files('cpu.c', 'disas.c', 'gdbstub.c'), capstone)
3049 # Work around a gcc bug/misfeature wherein constant propagation looks
3050 # through an alias:
3051 #   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99696
3052 # to guess that a const variable is always zero.  Without lto, this is
3053 # impossible, as the alias is restricted to page-vary-common.c.  Indeed,
3054 # without lto, not even the alias is required -- we simply use different
3055 # declarations in different compilation units.
3056 pagevary = files('page-vary-common.c')
3057 if get_option('b_lto')
3058   pagevary_flags = ['-fno-lto']
3059   if get_option('cfi')
3060     pagevary_flags += '-fno-sanitize=cfi-icall'
3061   endif
3062   pagevary = static_library('page-vary-common', sources: pagevary + genh,
3063                             c_args: pagevary_flags)
3064   pagevary = declare_dependency(link_with: pagevary)
3065 endif
3066 common_ss.add(pagevary)
3067 specific_ss.add(files('page-vary.c'))
3069 subdir('backends')
3070 subdir('disas')
3071 subdir('migration')
3072 subdir('monitor')
3073 subdir('net')
3074 subdir('replay')
3075 subdir('semihosting')
3076 subdir('tcg')
3077 subdir('fpu')
3078 subdir('accel')
3079 subdir('plugins')
3080 subdir('ebpf')
3082 common_user_inc = []
3084 subdir('common-user')
3085 subdir('bsd-user')
3086 subdir('linux-user')
3088 # needed for fuzzing binaries
3089 subdir('tests/qtest/libqos')
3090 subdir('tests/qtest/fuzz')
3092 # accel modules
3093 tcg_real_module_ss = ss.source_set()
3094 tcg_real_module_ss.add_all(when: 'CONFIG_TCG_MODULAR', if_true: tcg_module_ss)
3095 specific_ss.add_all(when: 'CONFIG_TCG_BUILTIN', if_true: tcg_module_ss)
3096 target_modules += { 'accel' : { 'qtest': qtest_module_ss,
3097                                 'tcg': tcg_real_module_ss }}
3099 ########################
3100 # Library dependencies #
3101 ########################
3103 modinfo_collect = find_program('scripts/modinfo-collect.py')
3104 modinfo_generate = find_program('scripts/modinfo-generate.py')
3105 modinfo_files = []
3107 block_mods = []
3108 softmmu_mods = []
3109 foreach d, list : modules
3110   foreach m, module_ss : list
3111     if enable_modules and targetos != 'windows'
3112       module_ss = module_ss.apply(config_all, strict: false)
3113       sl = static_library(d + '-' + m, [genh, module_ss.sources()],
3114                           dependencies: [modulecommon, module_ss.dependencies()], pic: true)
3115       if d == 'block'
3116         block_mods += sl
3117       else
3118         softmmu_mods += sl
3119       endif
3120       if module_ss.sources() != []
3121         # FIXME: Should use sl.extract_all_objects(recursive: true) as
3122         # input. Sources can be used multiple times but objects are
3123         # unique when it comes to lookup in compile_commands.json.
3124         # Depnds on a mesion version with
3125         # https://github.com/mesonbuild/meson/pull/8900
3126         modinfo_files += custom_target(d + '-' + m + '.modinfo',
3127                                        output: d + '-' + m + '.modinfo',
3128                                        input: module_ss.sources() + genh,
3129                                        capture: true,
3130                                        command: [modinfo_collect, module_ss.sources()])
3131       endif
3132     else
3133       if d == 'block'
3134         block_ss.add_all(module_ss)
3135       else
3136         softmmu_ss.add_all(module_ss)
3137       endif
3138     endif
3139   endforeach
3140 endforeach
3142 foreach d, list : target_modules
3143   foreach m, module_ss : list
3144     if enable_modules and targetos != 'windows'
3145       foreach target : target_dirs
3146         if target.endswith('-softmmu')
3147           config_target = config_target_mak[target]
3148           config_target += config_host
3149           target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
3150           c_args = ['-DNEED_CPU_H',
3151                     '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
3152                     '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
3153           target_module_ss = module_ss.apply(config_target, strict: false)
3154           if target_module_ss.sources() != []
3155             module_name = d + '-' + m + '-' + config_target['TARGET_NAME']
3156             sl = static_library(module_name,
3157                                 [genh, target_module_ss.sources()],
3158                                 dependencies: [modulecommon, target_module_ss.dependencies()],
3159                                 include_directories: target_inc,
3160                                 c_args: c_args,
3161                                 pic: true)
3162             softmmu_mods += sl
3163             # FIXME: Should use sl.extract_all_objects(recursive: true) too.
3164             modinfo_files += custom_target(module_name + '.modinfo',
3165                                            output: module_name + '.modinfo',
3166                                            input: target_module_ss.sources() + genh,
3167                                            capture: true,
3168                                            command: [modinfo_collect, '--target', target, target_module_ss.sources()])
3169           endif
3170         endif
3171       endforeach
3172     else
3173       specific_ss.add_all(module_ss)
3174     endif
3175   endforeach
3176 endforeach
3178 if enable_modules
3179   foreach target : target_dirs
3180     if target.endswith('-softmmu')
3181       config_target = config_target_mak[target]
3182       config_devices_mak = target + '-config-devices.mak'
3183       modinfo_src = custom_target('modinfo-' + target + '.c',
3184                                   output: 'modinfo-' + target + '.c',
3185                                   input: modinfo_files,
3186                                   command: [modinfo_generate, '--devices', config_devices_mak, '@INPUT@'],
3187                                   capture: true)
3189       modinfo_lib = static_library('modinfo-' + target + '.c', modinfo_src)
3190       modinfo_dep = declare_dependency(link_with: modinfo_lib)
3192       arch = config_target['TARGET_NAME'] == 'sparc64' ? 'sparc64' : config_target['TARGET_BASE_ARCH']
3193       hw_arch[arch].add(modinfo_dep)
3194     endif
3195   endforeach
3196 endif
3198 nm = find_program('nm')
3199 undefsym = find_program('scripts/undefsym.py')
3200 block_syms = custom_target('block.syms', output: 'block.syms',
3201                              input: [libqemuutil, block_mods],
3202                              capture: true,
3203                              command: [undefsym, nm, '@INPUT@'])
3204 qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
3205                              input: [libqemuutil, softmmu_mods],
3206                              capture: true,
3207                              command: [undefsym, nm, '@INPUT@'])
3209 authz_ss = authz_ss.apply(config_host, strict: false)
3210 libauthz = static_library('authz', authz_ss.sources() + genh,
3211                           dependencies: [authz_ss.dependencies()],
3212                           name_suffix: 'fa',
3213                           build_by_default: false)
3215 authz = declare_dependency(link_whole: libauthz,
3216                            dependencies: qom)
3218 crypto_ss = crypto_ss.apply(config_host, strict: false)
3219 libcrypto = static_library('crypto', crypto_ss.sources() + genh,
3220                            dependencies: [crypto_ss.dependencies()],
3221                            name_suffix: 'fa',
3222                            build_by_default: false)
3224 crypto = declare_dependency(link_whole: libcrypto,
3225                             dependencies: [authz, qom])
3227 io_ss = io_ss.apply(config_host, strict: false)
3228 libio = static_library('io', io_ss.sources() + genh,
3229                        dependencies: [io_ss.dependencies()],
3230                        link_with: libqemuutil,
3231                        name_suffix: 'fa',
3232                        build_by_default: false)
3234 io = declare_dependency(link_whole: libio, dependencies: [crypto, qom])
3236 libmigration = static_library('migration', sources: migration_files + genh,
3237                               name_suffix: 'fa',
3238                               build_by_default: false)
3239 migration = declare_dependency(link_with: libmigration,
3240                                dependencies: [zlib, qom, io])
3241 softmmu_ss.add(migration)
3243 block_ss = block_ss.apply(config_host, strict: false)
3244 libblock = static_library('block', block_ss.sources() + genh,
3245                           dependencies: block_ss.dependencies(),
3246                           link_depends: block_syms,
3247                           name_suffix: 'fa',
3248                           build_by_default: false)
3250 block = declare_dependency(link_whole: [libblock],
3251                            link_args: '@block.syms',
3252                            dependencies: [crypto, io])
3254 blockdev_ss = blockdev_ss.apply(config_host, strict: false)
3255 libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
3256                              dependencies: blockdev_ss.dependencies(),
3257                              name_suffix: 'fa',
3258                              build_by_default: false)
3260 blockdev = declare_dependency(link_whole: [libblockdev],
3261                               dependencies: [block, event_loop_base])
3263 qmp_ss = qmp_ss.apply(config_host, strict: false)
3264 libqmp = static_library('qmp', qmp_ss.sources() + genh,
3265                         dependencies: qmp_ss.dependencies(),
3266                         name_suffix: 'fa',
3267                         build_by_default: false)
3269 qmp = declare_dependency(link_whole: [libqmp])
3271 libchardev = static_library('chardev', chardev_ss.sources() + genh,
3272                             name_suffix: 'fa',
3273                             dependencies: chardev_ss.dependencies(),
3274                             build_by_default: false)
3276 chardev = declare_dependency(link_whole: libchardev)
3278 hwcore_ss = hwcore_ss.apply(config_host, strict: false)
3279 libhwcore = static_library('hwcore', sources: hwcore_ss.sources() + genh,
3280                            name_suffix: 'fa',
3281                            build_by_default: false)
3282 hwcore = declare_dependency(link_whole: libhwcore)
3283 common_ss.add(hwcore)
3285 ###########
3286 # Targets #
3287 ###########
3289 emulator_modules = []
3290 foreach m : block_mods + softmmu_mods
3291   emulator_modules += shared_module(m.name(),
3292                 build_by_default: true,
3293                 name_prefix: '',
3294                 link_whole: m,
3295                 install: true,
3296                 install_dir: qemu_moddir)
3297 endforeach
3298 if emulator_modules.length() > 0
3299   alias_target('modules', emulator_modules)
3300 endif
3302 softmmu_ss.add(authz, blockdev, chardev, crypto, io, qmp)
3303 common_ss.add(qom, qemuutil)
3305 common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss])
3306 common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
3308 common_all = common_ss.apply(config_all, strict: false)
3309 common_all = static_library('common',
3310                             build_by_default: false,
3311                             sources: common_all.sources() + genh,
3312                             include_directories: common_user_inc,
3313                             implicit_include_directories: false,
3314                             dependencies: common_all.dependencies(),
3315                             name_suffix: 'fa')
3317 feature_to_c = find_program('scripts/feature_to_c.sh')
3319 if targetos == 'darwin'
3320   entitlement = find_program('scripts/entitlement.sh')
3321 endif
3323 emulators = {}
3324 foreach target : target_dirs
3325   config_target = config_target_mak[target]
3326   target_name = config_target['TARGET_NAME']
3327   target_base_arch = config_target['TARGET_BASE_ARCH']
3328   arch_srcs = [config_target_h[target]]
3329   arch_deps = []
3330   c_args = ['-DNEED_CPU_H',
3331             '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
3332             '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
3333   link_args = emulator_link_args
3335   config_target += config_host
3336   target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
3337   if targetos == 'linux'
3338     target_inc += include_directories('linux-headers', is_system: true)
3339   endif
3340   if target.endswith('-softmmu')
3341     qemu_target_name = 'qemu-system-' + target_name
3342     target_type='system'
3343     t = target_softmmu_arch[target_base_arch].apply(config_target, strict: false)
3344     arch_srcs += t.sources()
3345     arch_deps += t.dependencies()
3347     hw_dir = target_name == 'sparc64' ? 'sparc64' : target_base_arch
3348     hw = hw_arch[hw_dir].apply(config_target, strict: false)
3349     arch_srcs += hw.sources()
3350     arch_deps += hw.dependencies()
3352     arch_srcs += config_devices_h[target]
3353     link_args += ['@block.syms', '@qemu.syms']
3354   else
3355     abi = config_target['TARGET_ABI_DIR']
3356     target_type='user'
3357     target_inc += common_user_inc
3358     qemu_target_name = 'qemu-' + target_name
3359     if target_base_arch in target_user_arch
3360       t = target_user_arch[target_base_arch].apply(config_target, strict: false)
3361       arch_srcs += t.sources()
3362       arch_deps += t.dependencies()
3363     endif
3364     if 'CONFIG_LINUX_USER' in config_target
3365       base_dir = 'linux-user'
3366     endif
3367     if 'CONFIG_BSD_USER' in config_target
3368       base_dir = 'bsd-user'
3369       target_inc += include_directories('bsd-user/' / targetos)
3370       target_inc += include_directories('bsd-user/host/' / host_arch)
3371       dir = base_dir / abi
3372       arch_srcs += files(dir / 'signal.c', dir / 'target_arch_cpu.c')
3373     endif
3374     target_inc += include_directories(
3375       base_dir,
3376       base_dir / abi,
3377     )
3378     if 'CONFIG_LINUX_USER' in config_target
3379       dir = base_dir / abi
3380       arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
3381       if config_target.has_key('TARGET_SYSTBL_ABI')
3382         arch_srcs += \
3383           syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
3384                                              extra_args : config_target['TARGET_SYSTBL_ABI'])
3385       endif
3386     endif
3387   endif
3389   if 'TARGET_XML_FILES' in config_target
3390     gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
3391                                 output: target + '-gdbstub-xml.c',
3392                                 input: files(config_target['TARGET_XML_FILES'].split()),
3393                                 command: [feature_to_c, '@INPUT@'],
3394                                 capture: true)
3395     arch_srcs += gdbstub_xml
3396   endif
3398   t = target_arch[target_base_arch].apply(config_target, strict: false)
3399   arch_srcs += t.sources()
3400   arch_deps += t.dependencies()
3402   target_common = common_ss.apply(config_target, strict: false)
3403   objects = common_all.extract_objects(target_common.sources())
3404   deps = target_common.dependencies()
3406   target_specific = specific_ss.apply(config_target, strict: false)
3407   arch_srcs += target_specific.sources()
3408   arch_deps += target_specific.dependencies()
3410   lib = static_library('qemu-' + target,
3411                  sources: arch_srcs + genh,
3412                  dependencies: arch_deps,
3413                  objects: objects,
3414                  include_directories: target_inc,
3415                  c_args: c_args,
3416                  build_by_default: false,
3417                  name_suffix: 'fa')
3419   if target.endswith('-softmmu')
3420     execs = [{
3421       'name': 'qemu-system-' + target_name,
3422       'win_subsystem': 'console',
3423       'sources': files('softmmu/main.c'),
3424       'dependencies': []
3425     }]
3426     if targetos == 'windows' and (sdl.found() or gtk.found())
3427       execs += [{
3428         'name': 'qemu-system-' + target_name + 'w',
3429         'win_subsystem': 'windows',
3430         'sources': files('softmmu/main.c'),
3431         'dependencies': []
3432       }]
3433     endif
3434     if get_option('fuzzing')
3435       specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
3436       execs += [{
3437         'name': 'qemu-fuzz-' + target_name,
3438         'win_subsystem': 'console',
3439         'sources': specific_fuzz.sources(),
3440         'dependencies': specific_fuzz.dependencies(),
3441       }]
3442     endif
3443   else
3444     execs = [{
3445       'name': 'qemu-' + target_name,
3446       'win_subsystem': 'console',
3447       'sources': [],
3448       'dependencies': []
3449     }]
3450   endif
3451   foreach exe: execs
3452     exe_name = exe['name']
3453     if targetos == 'darwin'
3454       exe_name += '-unsigned'
3455     endif
3457     emulator = executable(exe_name, exe['sources'],
3458                install: true,
3459                c_args: c_args,
3460                dependencies: arch_deps + deps + exe['dependencies'],
3461                objects: lib.extract_all_objects(recursive: true),
3462                link_language: link_language,
3463                link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
3464                link_args: link_args,
3465                win_subsystem: exe['win_subsystem'])
3467     if targetos == 'darwin'
3468       icon = 'pc-bios/qemu.rsrc'
3469       build_input = [emulator, files(icon)]
3470       install_input = [
3471         get_option('bindir') / exe_name,
3472         meson.current_source_dir() / icon
3473       ]
3474       if 'CONFIG_HVF' in config_target
3475         entitlements = 'accel/hvf/entitlements.plist'
3476         build_input += files(entitlements)
3477         install_input += meson.current_source_dir() / entitlements
3478       endif
3480       emulators += {exe['name'] : custom_target(exe['name'],
3481                    input: build_input,
3482                    output: exe['name'],
3483                    command: [entitlement, '@OUTPUT@', '@INPUT@'])
3484       }
3486       meson.add_install_script(entitlement, '--install',
3487                                get_option('bindir') / exe['name'],
3488                                install_input)
3489     else
3490       emulators += {exe['name']: emulator}
3491     endif
3493     if stap.found()
3494       foreach stp: [
3495         {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
3496         {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
3497         {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
3498         {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
3499       ]
3500         custom_target(exe['name'] + stp['ext'],
3501                       input: trace_events_all,
3502                       output: exe['name'] + stp['ext'],
3503                       install: stp['install'],
3504                       install_dir: get_option('datadir') / 'systemtap/tapset',
3505                       command: [
3506                         tracetool, '--group=all', '--format=' + stp['fmt'],
3507                         '--binary=' + stp['bin'],
3508                         '--target-name=' + target_name,
3509                         '--target-type=' + target_type,
3510                         '--probe-prefix=qemu.' + target_type + '.' + target_name,
3511                         '@INPUT@', '@OUTPUT@'
3512                       ],
3513                       depend_files: tracetool_depends)
3514       endforeach
3515     endif
3516   endforeach
3517 endforeach
3519 # Other build targets
3521 if 'CONFIG_PLUGIN' in config_host
3522   install_headers('include/qemu/qemu-plugin.h')
3523 endif
3525 subdir('qga')
3527 # Don't build qemu-keymap if xkbcommon is not explicitly enabled
3528 # when we don't build tools or system
3529 if xkbcommon.found()
3530   # used for the update-keymaps target, so include rules even if !have_tools
3531   qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
3532                            dependencies: [qemuutil, xkbcommon], install: have_tools)
3533 endif
3535 if have_tools
3536   qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
3537              dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
3538   qemu_io = executable('qemu-io', files('qemu-io.c'),
3539              dependencies: [block, qemuutil], install: true)
3540   qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
3541                dependencies: [blockdev, qemuutil, gnutls, selinux],
3542                install: true)
3544   subdir('storage-daemon')
3545   subdir('contrib/rdmacm-mux')
3546   subdir('contrib/elf2dmp')
3548   executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
3549              dependencies: qemuutil,
3550              install: true)
3552   if have_vhost_user
3553     subdir('contrib/vhost-user-blk')
3554     subdir('contrib/vhost-user-gpu')
3555     subdir('contrib/vhost-user-input')
3556     subdir('contrib/vhost-user-scsi')
3557   endif
3559   if targetos == 'linux'
3560     executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
3561                dependencies: [qemuutil, libcap_ng],
3562                install: true,
3563                install_dir: get_option('libexecdir'))
3565     executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
3566                dependencies: [authz, crypto, io, qom, qemuutil,
3567                               libcap_ng, mpathpersist],
3568                install: true)
3569   endif
3571   if have_ivshmem
3572     subdir('contrib/ivshmem-client')
3573     subdir('contrib/ivshmem-server')
3574   endif
3575 endif
3577 subdir('scripts')
3578 subdir('tools')
3579 subdir('pc-bios')
3580 subdir('docs')
3581 subdir('tests')
3582 if gtk.found()
3583   subdir('po')
3584 endif
3586 if host_machine.system() == 'windows'
3587   nsis_cmd = [
3588     find_program('scripts/nsis.py'),
3589     '@OUTPUT@',
3590     get_option('prefix'),
3591     meson.current_source_dir(),
3592     host_machine.cpu(),
3593     '--',
3594     '-DDISPLAYVERSION=' + meson.project_version(),
3595   ]
3596   if build_docs
3597     nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
3598   endif
3599   if gtk.found()
3600     nsis_cmd += '-DCONFIG_GTK=y'
3601   endif
3603   nsis = custom_target('nsis',
3604                        output: 'qemu-setup-' + meson.project_version() + '.exe',
3605                        input: files('qemu.nsi'),
3606                        build_always_stale: true,
3607                        command: nsis_cmd + ['@INPUT@'])
3608   alias_target('installer', nsis)
3609 endif
3611 #########################
3612 # Configuration summary #
3613 #########################
3615 # Directories
3616 summary_info = {}
3617 summary_info += {'Install prefix':    get_option('prefix')}
3618 summary_info += {'BIOS directory':    qemu_datadir}
3619 summary_info += {'firmware path':     get_option('prefix') / get_option('qemu_firmwarepath')}
3620 summary_info += {'binary directory':  get_option('prefix') / get_option('bindir')}
3621 summary_info += {'library directory': get_option('prefix') / get_option('libdir')}
3622 summary_info += {'module directory':  qemu_moddir}
3623 summary_info += {'libexec directory': get_option('prefix') / get_option('libexecdir')}
3624 summary_info += {'include directory': get_option('prefix') / get_option('includedir')}
3625 summary_info += {'config directory':  get_option('prefix') / get_option('sysconfdir')}
3626 if targetos != 'windows'
3627   summary_info += {'local state directory': get_option('prefix') / get_option('localstatedir')}
3628   summary_info += {'Manual directory':      get_option('prefix') / get_option('mandir')}
3629 else
3630   summary_info += {'local state directory': 'queried at runtime'}
3631 endif
3632 summary_info += {'Doc directory':     get_option('prefix') / get_option('docdir')}
3633 summary_info += {'Build directory':   meson.current_build_dir()}
3634 summary_info += {'Source path':       meson.current_source_dir()}
3635 summary_info += {'GIT submodules':    config_host['GIT_SUBMODULES']}
3636 summary(summary_info, bool_yn: true, section: 'Directories')
3638 # Host binaries
3639 summary_info = {}
3640 summary_info += {'git':               config_host['GIT']}
3641 summary_info += {'make':              config_host['MAKE']}
3642 summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
3643 summary_info += {'sphinx-build':      sphinx_build}
3644 if config_host.has_key('HAVE_GDB_BIN')
3645   summary_info += {'gdb':             config_host['HAVE_GDB_BIN']}
3646 endif
3647 summary_info += {'iasl':              iasl}
3648 summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
3649 if targetos == 'windows' and have_ga
3650   summary_info += {'wixl':            wixl}
3651 endif
3652 if slirp_opt != 'disabled' and have_system
3653   summary_info += {'smbd':            have_slirp_smbd ? smbd_path : false}
3654 endif
3655 summary(summary_info, bool_yn: true, section: 'Host binaries')
3657 # Configurable features
3658 summary_info = {}
3659 summary_info += {'Documentation':     build_docs}
3660 summary_info += {'system-mode emulation': have_system}
3661 summary_info += {'user-mode emulation': have_user}
3662 summary_info += {'block layer':       have_block}
3663 summary_info += {'Install blobs':     get_option('install_blobs')}
3664 summary_info += {'module support':    config_host.has_key('CONFIG_MODULES')}
3665 if config_host.has_key('CONFIG_MODULES')
3666   summary_info += {'alternative module path': get_option('module_upgrades')}
3667 endif
3668 summary_info += {'fuzzing support':   get_option('fuzzing')}
3669 if have_system
3670   summary_info += {'Audio drivers':     ' '.join(audio_drivers_selected)}
3671 endif
3672 summary_info += {'Trace backends':    ','.join(get_option('trace_backends'))}
3673 if 'simple' in get_option('trace_backends')
3674   summary_info += {'Trace output file': get_option('trace_file') + '-<pid>'}
3675 endif
3676 summary_info += {'D-Bus display':     dbus_display}
3677 summary_info += {'QOM debugging':     get_option('qom_cast_debug')}
3678 summary_info += {'vhost-kernel support': have_vhost_kernel}
3679 summary_info += {'vhost-net support': have_vhost_net}
3680 summary_info += {'vhost-user support': have_vhost_user}
3681 summary_info += {'vhost-user-crypto support': have_vhost_user_crypto}
3682 summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
3683 summary_info += {'vhost-vdpa support': have_vhost_vdpa}
3684 summary_info += {'build guest agent': have_ga}
3685 summary(summary_info, bool_yn: true, section: 'Configurable features')
3687 # Compilation information
3688 summary_info = {}
3689 summary_info += {'host CPU':          cpu}
3690 summary_info += {'host endianness':   build_machine.endian()}
3691 summary_info += {'C compiler':        ' '.join(meson.get_compiler('c').cmd_array())}
3692 summary_info += {'Host C compiler':   ' '.join(meson.get_compiler('c', native: true).cmd_array())}
3693 if link_language == 'cpp'
3694   summary_info += {'C++ compiler':    ' '.join(meson.get_compiler('cpp').cmd_array())}
3695 else
3696   summary_info += {'C++ compiler':      false}
3697 endif
3698 if targetos == 'darwin'
3699   summary_info += {'Objective-C compiler': ' '.join(meson.get_compiler('objc').cmd_array())}
3700 endif
3701 summary_info += {'CFLAGS':            ' '.join(get_option('c_args')
3702                                                + ['-O' + get_option('optimization')]
3703                                                + (get_option('debug') ? ['-g'] : []))}
3704 if link_language == 'cpp'
3705   summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args')
3706                                                + ['-O' + get_option('optimization')]
3707                                                + (get_option('debug') ? ['-g'] : []))}
3708 endif
3709 if targetos == 'darwin'
3710   summary_info += {'OBJCFLAGS':       ' '.join(get_option('objc_args')
3711                                                + ['-O' + get_option('optimization')]
3712                                                + (get_option('debug') ? ['-g'] : []))}
3713 endif
3714 link_args = get_option(link_language + '_link_args')
3715 if link_args.length() > 0
3716   summary_info += {'LDFLAGS':         ' '.join(link_args)}
3717 endif
3718 summary_info += {'QEMU_CFLAGS':       ' '.join(qemu_cflags)}
3719 summary_info += {'QEMU_CXXFLAGS':     ' '.join(qemu_cxxflags)}
3720 summary_info += {'QEMU_OBJCFLAGS':    ' '.join(qemu_objcflags)}
3721 summary_info += {'QEMU_LDFLAGS':      ' '.join(qemu_ldflags)}
3722 summary_info += {'profiler':          get_option('profiler')}
3723 summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
3724 summary_info += {'PIE':               get_option('b_pie')}
3725 summary_info += {'static build':      config_host.has_key('CONFIG_STATIC')}
3726 summary_info += {'malloc trim support': has_malloc_trim}
3727 summary_info += {'membarrier':        have_membarrier}
3728 summary_info += {'debug stack usage': get_option('debug_stack_usage')}
3729 summary_info += {'mutex debugging':   get_option('debug_mutex')}
3730 summary_info += {'memory allocator':  get_option('malloc')}
3731 summary_info += {'avx2 optimization': config_host_data.get('CONFIG_AVX2_OPT')}
3732 summary_info += {'avx512f optimization': config_host_data.get('CONFIG_AVX512F_OPT')}
3733 summary_info += {'gprof enabled':     get_option('gprof')}
3734 summary_info += {'gcov':              get_option('b_coverage')}
3735 summary_info += {'thread sanitizer':  config_host.has_key('CONFIG_TSAN')}
3736 summary_info += {'CFI support':       get_option('cfi')}
3737 if get_option('cfi')
3738   summary_info += {'CFI debug support': get_option('cfi_debug')}
3739 endif
3740 summary_info += {'strip binaries':    get_option('strip')}
3741 summary_info += {'sparse':            sparse}
3742 summary_info += {'mingw32 support':   targetos == 'windows'}
3744 # snarf the cross-compilation information for tests
3745 foreach target: target_dirs
3746   tcg_mak = meson.current_build_dir() / 'tests/tcg' / 'config-' + target + '.mak'
3747   if fs.exists(tcg_mak)
3748     config_cross_tcg = keyval.load(tcg_mak)
3749     target = config_cross_tcg['TARGET_NAME']
3750     compiler = ''
3751     if 'CC' in config_cross_tcg
3752       summary_info += {target + ' tests': config_cross_tcg['CC']}
3753     endif
3754    endif
3755 endforeach
3757 summary(summary_info, bool_yn: true, section: 'Compilation')
3759 # Targets and accelerators
3760 summary_info = {}
3761 if have_system
3762   summary_info += {'KVM support':       config_all.has_key('CONFIG_KVM')}
3763   summary_info += {'HAX support':       config_all.has_key('CONFIG_HAX')}
3764   summary_info += {'HVF support':       config_all.has_key('CONFIG_HVF')}
3765   summary_info += {'WHPX support':      config_all.has_key('CONFIG_WHPX')}
3766   summary_info += {'NVMM support':      config_all.has_key('CONFIG_NVMM')}
3767   summary_info += {'Xen support':       xen.found()}
3768   if xen.found()
3769     summary_info += {'xen ctrl version':  xen.version()}
3770   endif
3771 endif
3772 summary_info += {'TCG support':       config_all.has_key('CONFIG_TCG')}
3773 if config_all.has_key('CONFIG_TCG')
3774   if get_option('tcg_interpreter')
3775     summary_info += {'TCG backend':   'TCI (TCG with bytecode interpreter, slow)'}
3776   else
3777     summary_info += {'TCG backend':   'native (@0@)'.format(cpu)}
3778   endif
3779   summary_info += {'TCG plugins': config_host.has_key('CONFIG_PLUGIN')}
3780   summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')}
3781 endif
3782 summary_info += {'target list':       ' '.join(target_dirs)}
3783 if have_system
3784   summary_info += {'default devices':   get_option('default_devices')}
3785   summary_info += {'out of process emulation': multiprocess_allowed}
3786 endif
3787 summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
3789 # Block layer
3790 summary_info = {}
3791 summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']}
3792 summary_info += {'coroutine pool':    have_coroutine_pool}
3793 if have_block
3794   summary_info += {'Block whitelist (rw)': get_option('block_drv_rw_whitelist')}
3795   summary_info += {'Block whitelist (ro)': get_option('block_drv_ro_whitelist')}
3796   summary_info += {'Use block whitelist in tools': get_option('block_drv_whitelist_in_tools')}
3797   summary_info += {'VirtFS support':    have_virtfs}
3798   summary_info += {'build virtiofs daemon': have_virtiofsd}
3799   summary_info += {'Live block migration': config_host_data.get('CONFIG_LIVE_BLOCK_MIGRATION')}
3800   summary_info += {'replication support': config_host_data.get('CONFIG_REPLICATION')}
3801   summary_info += {'bochs support':     get_option('bochs').allowed()}
3802   summary_info += {'cloop support':     get_option('cloop').allowed()}
3803   summary_info += {'dmg support':       get_option('dmg').allowed()}
3804   summary_info += {'qcow v1 support':   get_option('qcow1').allowed()}
3805   summary_info += {'vdi support':       get_option('vdi').allowed()}
3806   summary_info += {'vvfat support':     get_option('vvfat').allowed()}
3807   summary_info += {'qed support':       get_option('qed').allowed()}
3808   summary_info += {'parallels support': get_option('parallels').allowed()}
3809   summary_info += {'FUSE exports':      fuse}
3810 endif
3811 summary(summary_info, bool_yn: true, section: 'Block layer support')
3813 # Crypto
3814 summary_info = {}
3815 summary_info += {'TLS priority':      get_option('tls_priority')}
3816 summary_info += {'GNUTLS support':    gnutls}
3817 if gnutls.found()
3818   summary_info += {'  GNUTLS crypto':   gnutls_crypto.found()}
3819 endif
3820 summary_info += {'libgcrypt':         gcrypt}
3821 summary_info += {'nettle':            nettle}
3822 if nettle.found()
3823    summary_info += {'  XTS':             xts != 'private'}
3824 endif
3825 summary_info += {'AF_ALG support':    have_afalg}
3826 summary_info += {'rng-none':          get_option('rng_none')}
3827 summary_info += {'Linux keyring':     have_keyring}
3828 summary(summary_info, bool_yn: true, section: 'Crypto')
3830 # Libraries
3831 summary_info = {}
3832 if targetos == 'darwin'
3833   summary_info += {'Cocoa support':           cocoa}
3834   summary_info += {'vmnet.framework support': vmnet}
3835 endif
3836 summary_info += {'SDL support':       sdl}
3837 summary_info += {'SDL image support': sdl_image}
3838 summary_info += {'GTK support':       gtk}
3839 summary_info += {'pixman':            pixman}
3840 summary_info += {'VTE support':       vte}
3841 summary_info += {'slirp support':     slirp_opt == 'internal' ? slirp_opt : slirp}
3842 summary_info += {'libtasn1':          tasn1}
3843 summary_info += {'PAM':               pam}
3844 summary_info += {'iconv support':     iconv}
3845 summary_info += {'curses support':    curses}
3846 summary_info += {'virgl support':     virgl}
3847 summary_info += {'curl support':      curl}
3848 summary_info += {'Multipath support': mpathpersist}
3849 summary_info += {'PNG support':       png}
3850 summary_info += {'VNC support':       vnc}
3851 if vnc.found()
3852   summary_info += {'VNC SASL support':  sasl}
3853   summary_info += {'VNC JPEG support':  jpeg}
3854 endif
3855 if targetos not in ['darwin', 'haiku', 'windows']
3856   summary_info += {'OSS support':     oss}
3857 elif targetos == 'darwin'
3858   summary_info += {'CoreAudio support': coreaudio}
3859 elif targetos == 'windows'
3860   summary_info += {'DirectSound support': dsound}
3861 endif
3862 if targetos == 'linux'
3863   summary_info += {'ALSA support':    alsa}
3864   summary_info += {'PulseAudio support': pulse}
3865 endif
3866 summary_info += {'JACK support':      jack}
3867 summary_info += {'brlapi support':    brlapi}
3868 summary_info += {'vde support':       vde}
3869 summary_info += {'netmap support':    have_netmap}
3870 summary_info += {'l2tpv3 support':    have_l2tpv3}
3871 summary_info += {'Linux AIO support': libaio}
3872 summary_info += {'Linux io_uring support': linux_io_uring}
3873 summary_info += {'ATTR/XATTR support': libattr}
3874 summary_info += {'RDMA support':      rdma}
3875 summary_info += {'PVRDMA support':    have_pvrdma}
3876 summary_info += {'fdt support':       fdt_opt == 'disabled' ? false : fdt_opt}
3877 summary_info += {'libcap-ng support': libcap_ng}
3878 summary_info += {'bpf support':       libbpf}
3879 summary_info += {'spice protocol support': spice_protocol}
3880 if spice_protocol.found()
3881   summary_info += {'  spice server support': spice}
3882 endif
3883 summary_info += {'rbd support':       rbd}
3884 summary_info += {'smartcard support': cacard}
3885 summary_info += {'U2F support':       u2f}
3886 summary_info += {'libusb':            libusb}
3887 summary_info += {'usb net redir':     usbredir}
3888 summary_info += {'OpenGL support (epoxy)': opengl}
3889 summary_info += {'GBM':               gbm}
3890 summary_info += {'libiscsi support':  libiscsi}
3891 summary_info += {'libnfs support':    libnfs}
3892 if targetos == 'windows'
3893   if have_ga
3894     summary_info += {'QGA VSS support':   have_qga_vss}
3895   endif
3896 endif
3897 summary_info += {'seccomp support':   seccomp}
3898 summary_info += {'GlusterFS support': glusterfs}
3899 summary_info += {'TPM support':       have_tpm}
3900 summary_info += {'libssh support':    libssh}
3901 summary_info += {'lzo support':       lzo}
3902 summary_info += {'snappy support':    snappy}
3903 summary_info += {'bzip2 support':     libbzip2}
3904 summary_info += {'lzfse support':     liblzfse}
3905 summary_info += {'zstd support':      zstd}
3906 summary_info += {'NUMA host support': numa}
3907 summary_info += {'capstone':          capstone}
3908 summary_info += {'libpmem support':   libpmem}
3909 summary_info += {'libdaxctl support': libdaxctl}
3910 summary_info += {'libudev':           libudev}
3911 # Dummy dependency, keep .found()
3912 summary_info += {'FUSE lseek':        fuse_lseek.found()}
3913 summary_info += {'selinux':           selinux}
3914 summary(summary_info, bool_yn: true, section: 'Dependencies')
3916 if not supported_cpus.contains(cpu)
3917   message()
3918   warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!')
3919   message()
3920   message('CPU host architecture ' + cpu + ' support is not currently maintained.')
3921   message('The QEMU project intends to remove support for this host CPU in')
3922   message('a future release if nobody volunteers to maintain it and to')
3923   message('provide a build host for our continuous integration setup.')
3924   message('configure has succeeded and you can continue to build, but')
3925   message('if you care about QEMU on this platform you should contact')
3926   message('us upstream at qemu-devel@nongnu.org.')
3927 endif
3929 if not supported_oses.contains(targetos)
3930   message()
3931   warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!')
3932   message()
3933   message('Host OS ' + targetos + 'support is not currently maintained.')
3934   message('The QEMU project intends to remove support for this host OS in')
3935   message('a future release if nobody volunteers to maintain it and to')
3936   message('provide a build host for our continuous integration setup.')
3937   message('configure has succeeded and you can continue to build, but')
3938   message('if you care about QEMU on this platform you should contact')
3939   message('us upstream at qemu-devel@nongnu.org.')
3940 endif