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