xref: /openbmc/qemu/meson.build (revision 174952080806fe45e836760a550d844559bd68c0)
1 project('qemu', ['c'], meson_version: '>=1.5.0',
2         default_options: ['warning_level=1', 'c_std=gnu11', 'cpp_std=gnu++11', 'b_colorout=auto',
3                           'b_staticpic=false', 'stdsplit=false', 'optimization=2', 'b_pie=true'],
4         version: files('VERSION'))
5 
6 add_test_setup('quick', exclude_suites: ['slow', 'thorough'], is_default: true)
7 add_test_setup('slow', exclude_suites: ['thorough'], env: ['G_TEST_SLOW=1', 'SPEED=slow'])
8 add_test_setup('thorough', env: ['G_TEST_SLOW=1', 'SPEED=thorough'])
9 
10 meson.add_postconf_script(find_program('scripts/symlink-install-tree.py'))
11 
12 ####################
13 # Global variables #
14 ####################
15 
16 not_found = dependency('', required: false)
17 keyval = import('keyval')
18 rust = import('rust')
19 ss = import('sourceset')
20 fs = import('fs')
21 
22 host_os = host_machine.system()
23 config_host = keyval.load(meson.current_build_dir() / 'config-host.mak')
24 
25 # Temporary directory used for files created while
26 # configure runs. Since it is in the build directory
27 # we can safely blow away any previous version of it
28 # (and we need not jump through hoops to try to delete
29 # it when configure exits.)
30 tmpdir = meson.current_build_dir() / 'meson-private/temp'
31 
32 if get_option('qemu_suffix').startswith('/')
33   error('qemu_suffix cannot start with a /')
34 endif
35 
36 qemu_confdir = get_option('sysconfdir') / get_option('qemu_suffix')
37 qemu_datadir = get_option('datadir') / get_option('qemu_suffix')
38 qemu_docdir = get_option('docdir') / get_option('qemu_suffix')
39 qemu_moddir = get_option('libdir') / get_option('qemu_suffix')
40 
41 qemu_desktopdir = get_option('datadir') / 'applications'
42 qemu_icondir = get_option('datadir') / 'icons'
43 
44 genh = []
45 qapi_trace_events = []
46 
47 bsd_oses = ['gnu/kfreebsd', 'freebsd', 'netbsd', 'openbsd', 'dragonfly', 'darwin']
48 supported_oses = ['windows', 'freebsd', 'netbsd', 'openbsd', 'darwin', 'sunos', 'linux']
49 supported_cpus = ['ppc', 'ppc64', 's390x', 'riscv32', 'riscv64', 'x86', 'x86_64',
50   'arm', 'aarch64', 'loongarch64', 'mips', 'mips64', 'sparc64']
51 
52 cpu = host_machine.cpu_family()
53 
54 target_dirs = config_host['TARGET_DIRS'].split()
55 
56 # type of binaries to build
57 have_linux_user = false
58 have_bsd_user = false
59 have_system = false
60 foreach target : target_dirs
61   have_linux_user = have_linux_user or target.endswith('linux-user')
62   have_bsd_user = have_bsd_user or target.endswith('bsd-user')
63   have_system = have_system or target.endswith('-softmmu')
64 endforeach
65 have_user = have_linux_user or have_bsd_user
66 
67 ############
68 # Programs #
69 ############
70 
71 sh = find_program('sh')
72 python = import('python').find_installation()
73 
74 cc = meson.get_compiler('c')
75 all_languages = ['c']
76 if host_os == 'windows' and add_languages('cpp', required: false, native: false)
77   all_languages += ['cpp']
78   cxx = meson.get_compiler('cpp')
79 endif
80 if host_os == 'darwin' and \
81    add_languages('objc', required: true, native: false)
82   all_languages += ['objc']
83   objc = meson.get_compiler('objc')
84 endif
85 
86 have_rust = add_languages('rust', native: false,
87     required: get_option('rust').disable_auto_if(not have_system))
88 have_rust = have_rust and add_languages('rust', native: true,
89     required: get_option('rust').disable_auto_if(not have_system))
90 if have_rust
91   rustc = meson.get_compiler('rust')
92   if rustc.version().version_compare('<1.63.0')
93     if get_option('rust').enabled()
94       error('rustc version ' + rustc.version() + ' is unsupported. Please upgrade to at least 1.63.0')
95     else
96       warning('rustc version ' + rustc.version() + ' is unsupported, disabling Rust compilation.')
97       message('Please upgrade to at least 1.63.0 to use Rust.')
98       have_rust = false
99     endif
100   endif
101 endif
102 
103 if have_rust
104   bindgen = find_program('bindgen', required: get_option('rust'))
105   if not bindgen.found() or bindgen.version().version_compare('<0.60.0')
106     if get_option('rust').enabled()
107       error('bindgen version ' + bindgen.version() + ' is unsupported. You can install a new version with "cargo install bindgen-cli"')
108     else
109       if bindgen.found()
110         warning('bindgen version ' + bindgen.version() + ' is unsupported, disabling Rust compilation.')
111       else
112         warning('bindgen not found, disabling Rust compilation.')
113       endif
114       message('To use Rust you can install a new version with "cargo install bindgen-cli"')
115       have_rust = false
116     endif
117   endif
118 endif
119 
120 if have_rust
121   rustfmt = find_program('rustfmt', required: false)
122 endif
123 
124 dtrace = not_found
125 stap = not_found
126 if 'dtrace' in get_option('trace_backends')
127   dtrace = find_program('dtrace', required: true)
128   stap = find_program('stap', required: false)
129   if stap.found()
130     # Workaround to avoid dtrace(1) producing a file with 'hidden' symbol
131     # visibility. Define STAP_SDT_V2 to produce 'default' symbol visibility
132     # instead. QEMU --enable-modules depends on this because the SystemTap
133     # semaphores are linked into the main binary and not the module's shared
134     # object.
135     add_global_arguments('-DSTAP_SDT_V2',
136                          native: false, language: all_languages)
137   endif
138 endif
139 
140 if get_option('iasl') == ''
141   iasl = find_program('iasl', required: false)
142 else
143   iasl = find_program(get_option('iasl'), required: true)
144 endif
145 
146 edk2_targets = [ 'arm-softmmu', 'aarch64-softmmu', 'i386-softmmu', 'x86_64-softmmu', 'riscv64-softmmu', 'loongarch64-softmmu' ]
147 unpack_edk2_blobs = false
148 foreach target : edk2_targets
149   if target in target_dirs
150     bzip2 = find_program('bzip2', required: get_option('install_blobs'))
151     unpack_edk2_blobs = bzip2.found()
152     break
153   endif
154 endforeach
155 
156 #####################
157 # Option validation #
158 #####################
159 
160 # Fuzzing
161 if get_option('fuzzing') and get_option('fuzzing_engine') == '' and \
162     not cc.links('''
163           #include <stdint.h>
164           #include <sys/types.h>
165           int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
166           int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { return 0; }
167         ''',
168         args: ['-Werror', '-fsanitize=fuzzer'])
169   error('Your compiler does not support -fsanitize=fuzzer')
170 endif
171 
172 # Tracing backends
173 if 'ftrace' in get_option('trace_backends') and host_os != 'linux'
174   error('ftrace is supported only on Linux')
175 endif
176 if 'syslog' in get_option('trace_backends') and not cc.compiles('''
177     #include <syslog.h>
178     int main(void) {
179         openlog("qemu", LOG_PID, LOG_DAEMON);
180         syslog(LOG_INFO, "configure");
181         return 0;
182     }''')
183   error('syslog is not supported on this system')
184 endif
185 
186 # Miscellaneous Linux-only features
187 get_option('mpath') \
188   .require(host_os == 'linux', error_message: 'Multipath is supported only on Linux')
189 
190 multiprocess_allowed = get_option('multiprocess') \
191   .require(host_os == 'linux', error_message: 'Multiprocess QEMU is supported only on Linux') \
192   .allowed()
193 
194 vfio_user_server_allowed = get_option('vfio_user_server') \
195   .require(host_os == 'linux', error_message: 'vfio-user server is supported only on Linux') \
196   .allowed()
197 
198 have_tpm = get_option('tpm') \
199   .require(host_os != 'windows', error_message: 'TPM emulation only available on POSIX systems') \
200   .allowed()
201 
202 # vhost
203 have_vhost_user = get_option('vhost_user') \
204   .disable_auto_if(host_os != 'linux') \
205   .require(host_os != 'windows',
206            error_message: 'vhost-user is not available on Windows').allowed()
207 have_vhost_vdpa = get_option('vhost_vdpa') \
208   .require(host_os == 'linux',
209            error_message: 'vhost-vdpa is only available on Linux').allowed()
210 have_vhost_kernel = get_option('vhost_kernel') \
211   .require(host_os == 'linux',
212            error_message: 'vhost-kernel is only available on Linux').allowed()
213 have_vhost_user_crypto = get_option('vhost_crypto') \
214   .require(have_vhost_user,
215            error_message: 'vhost-crypto requires vhost-user to be enabled').allowed()
216 
217 have_vhost = have_vhost_user or have_vhost_vdpa or have_vhost_kernel
218 
219 have_vhost_net_user = have_vhost_user and get_option('vhost_net').allowed()
220 have_vhost_net_vdpa = have_vhost_vdpa and get_option('vhost_net').allowed()
221 have_vhost_net_kernel = have_vhost_kernel and get_option('vhost_net').allowed()
222 have_vhost_net = have_vhost_net_kernel or have_vhost_net_user or have_vhost_net_vdpa
223 
224 have_tools = get_option('tools') \
225   .disable_auto_if(not have_system) \
226   .allowed()
227 have_ga = get_option('guest_agent') \
228   .disable_auto_if(not have_system and not have_tools) \
229   .require(host_os in ['sunos', 'linux', 'windows', 'freebsd', 'netbsd', 'openbsd'],
230            error_message: 'unsupported OS for QEMU guest agent') \
231   .allowed()
232 have_block = have_system or have_tools
233 
234 enable_modules = get_option('modules') \
235   .require(host_os != 'windows',
236            error_message: 'Modules are not available for Windows') \
237   .require(not get_option('prefer_static'),
238            error_message: 'Modules are incompatible with static linking') \
239   .allowed()
240 
241 #######################################
242 # Variables for host and accelerators #
243 #######################################
244 
245 if cpu not in supported_cpus
246   host_arch = 'unknown'
247 elif cpu == 'x86'
248   host_arch = 'i386'
249 elif cpu == 'mips64'
250   host_arch = 'mips'
251 elif cpu in ['riscv32', 'riscv64']
252   host_arch = 'riscv'
253 else
254   host_arch = cpu
255 endif
256 
257 if cpu in ['x86', 'x86_64']
258   kvm_targets = ['i386-softmmu', 'x86_64-softmmu']
259 elif cpu == 'aarch64'
260   kvm_targets = ['aarch64-softmmu']
261 elif cpu == 's390x'
262   kvm_targets = ['s390x-softmmu']
263 elif cpu in ['ppc', 'ppc64']
264   kvm_targets = ['ppc-softmmu', 'ppc64-softmmu']
265 elif cpu in ['mips', 'mips64']
266   kvm_targets = ['mips-softmmu', 'mipsel-softmmu', 'mips64-softmmu', 'mips64el-softmmu']
267 elif cpu in ['riscv32']
268   kvm_targets = ['riscv32-softmmu']
269 elif cpu in ['riscv64']
270   kvm_targets = ['riscv64-softmmu']
271 elif cpu in ['loongarch64']
272   kvm_targets = ['loongarch64-softmmu']
273 else
274   kvm_targets = []
275 endif
276 accelerator_targets = { 'CONFIG_KVM': kvm_targets }
277 
278 if cpu in ['x86', 'x86_64']
279   xen_targets = ['i386-softmmu', 'x86_64-softmmu']
280 elif cpu in ['arm', 'aarch64']
281   # i386 emulator provides xenpv machine type for multiple architectures
282   xen_targets = ['i386-softmmu', 'x86_64-softmmu', 'aarch64-softmmu']
283 else
284   xen_targets = []
285 endif
286 accelerator_targets += { 'CONFIG_XEN': xen_targets }
287 
288 if cpu in ['aarch64']
289   accelerator_targets += {
290     'CONFIG_HVF': ['aarch64-softmmu']
291   }
292 endif
293 
294 if cpu in ['x86', 'x86_64']
295   accelerator_targets += {
296     'CONFIG_HVF': ['x86_64-softmmu'],
297     'CONFIG_NVMM': ['i386-softmmu', 'x86_64-softmmu'],
298     'CONFIG_WHPX': ['i386-softmmu', 'x86_64-softmmu'],
299   }
300 endif
301 
302 modular_tcg = []
303 # Darwin does not support references to thread-local variables in modules
304 if host_os != 'darwin'
305   modular_tcg = ['i386-softmmu', 'x86_64-softmmu']
306 endif
307 
308 ##################
309 # Compiler flags #
310 ##################
311 
312 foreach lang : all_languages
313   compiler = meson.get_compiler(lang)
314   if compiler.get_id() == 'gcc' and compiler.version().version_compare('>=7.4')
315     # ok
316   elif compiler.get_id() == 'clang' and compiler.compiles('''
317       #ifdef __apple_build_version__
318       # if __clang_major__ < 15 || (__clang_major__ == 15 && __clang_minor__ < 0)
319       #  error You need at least XCode Clang v15.0 to compile QEMU
320       # endif
321       #else
322       # if __clang_major__ < 10 || (__clang_major__ == 10 && __clang_minor__ < 0)
323       #  error You need at least Clang v10.0 to compile QEMU
324       # endif
325       #endif''')
326     # ok
327   else
328     error('You either need GCC v7.4 or Clang v10.0 (or XCode Clang v15.0) to compile QEMU')
329   endif
330 endforeach
331 
332 # default flags for all hosts
333 # We use -fwrapv to tell the compiler that we require a C dialect where
334 # left shift of signed integers is well defined and has the expected
335 # 2s-complement style results. (Both clang and gcc agree that it
336 # provides these semantics.)
337 
338 qemu_common_flags = [
339   '-D_GNU_SOURCE', '-D_FILE_OFFSET_BITS=64', '-D_LARGEFILE_SOURCE',
340   '-fno-strict-aliasing', '-fno-common', '-fwrapv' ]
341 qemu_cflags = []
342 qemu_ldflags = []
343 
344 if host_os == 'darwin'
345   # Disable attempts to use ObjectiveC features in os/object.h since they
346   # won't work when we're compiling with gcc as a C compiler.
347   if compiler.get_id() == 'gcc'
348     qemu_common_flags += '-DOS_OBJECT_USE_OBJC=0'
349   endif
350 elif host_os == 'sunos'
351   # needed for CMSG_ macros in sys/socket.h
352   qemu_common_flags += '-D_XOPEN_SOURCE=600'
353   # needed for TIOCWIN* defines in termios.h
354   qemu_common_flags += '-D__EXTENSIONS__'
355 elif host_os == 'haiku'
356   qemu_common_flags += ['-DB_USE_POSITIVE_POSIX_ERRORS', '-D_BSD_SOURCE', '-fPIC']
357 elif host_os == 'windows'
358   if not compiler.compiles('struct x { int y; } __attribute__((gcc_struct));',
359                            args: '-Werror')
360     error('Your compiler does not support __attribute__((gcc_struct)) - please use GCC instead of Clang')
361   endif
362 endif
363 
364 # Choose instruction set (currently x86-only)
365 
366 qemu_isa_flags = []
367 
368 # __sync_fetch_and_and requires at least -march=i486. Many toolchains
369 # use i686 as default anyway, but for those that don't, an explicit
370 # specification is necessary
371 if host_arch == 'i386' and not cc.links('''
372   static int sfaa(int *ptr)
373   {
374     return __sync_fetch_and_and(ptr, 0);
375   }
376 
377   int main(void)
378   {
379     int val = 42;
380     val = __sync_val_compare_and_swap(&val, 0, 1);
381     sfaa(&val);
382     return val;
383   }''')
384   qemu_isa_flags += ['-march=i486']
385 endif
386 
387 # Pick x86-64 baseline version
388 if host_arch in ['i386', 'x86_64']
389   if get_option('x86_version') == '0' and host_arch == 'x86_64'
390     error('x86_64-v1 required for x86-64 hosts')
391   endif
392 
393   # add flags for individual instruction set extensions
394   if get_option('x86_version') >= '1'
395     if host_arch == 'i386'
396       qemu_common_flags = ['-mfpmath=sse'] + qemu_common_flags
397     else
398       # present on basically all processors but technically not part of
399       # x86-64-v1, so only include -mneeded for x86-64 version 2 and above
400       qemu_isa_flags += ['-mcx16']
401     endif
402   endif
403   if get_option('x86_version') >= '2'
404     qemu_isa_flags += ['-mpopcnt']
405     qemu_isa_flags += cc.get_supported_arguments('-mneeded')
406   endif
407   if get_option('x86_version') >= '3'
408     qemu_isa_flags += ['-mmovbe', '-mabm', '-mbmi', '-mbmi2', '-mfma', '-mf16c']
409   endif
410 
411   # add required vector instruction set (each level implies those below)
412   if get_option('x86_version') == '1'
413     qemu_isa_flags += ['-msse2']
414   elif get_option('x86_version') == '2'
415     qemu_isa_flags += ['-msse4.2']
416   elif get_option('x86_version') == '3'
417     qemu_isa_flags += ['-mavx2']
418   elif get_option('x86_version') == '4'
419     qemu_isa_flags += ['-mavx512f', '-mavx512bw', '-mavx512cd', '-mavx512dq', '-mavx512vl']
420   endif
421 endif
422 
423 qemu_common_flags = qemu_isa_flags + qemu_common_flags
424 
425 if get_option('prefer_static')
426   qemu_ldflags += get_option('b_pie') ? '-static-pie' : '-static'
427 endif
428 
429 # Meson currently only handles pie as a boolean for now, so if the user
430 # has explicitly disabled PIE we need to extend our cflags.
431 #
432 # -no-pie is supposedly a linker flag that has no effect on the compiler
433 # command line, but some distros, that didn't quite know what they were
434 # doing, made local changes to gcc's specs file that turned it into
435 # a compiler command-line flag.
436 #
437 # What about linker flags?  For a static build, no PIE is implied by -static
438 # which we added above (and if it's not because of the same specs patching,
439 # there's nothing we can do: compilation will fail, report a bug to your
440 # distro and do not use --disable-pie in the meanwhile).  For dynamic linking,
441 # instead, we can't add -no-pie because it overrides -shared: the linker then
442 # tries to build an executable instead of a shared library and fails.  So
443 # don't add -no-pie anywhere and cross fingers. :(
444 if not get_option('b_pie')
445   qemu_common_flags += cc.get_supported_arguments('-fno-pie', '-no-pie')
446 endif
447 
448 if not get_option('stack_protector').disabled()
449   stack_protector_probe = '''
450     int main(int argc, char *argv[])
451     {
452       char arr[64], *p = arr, *c = argv[argc - 1];
453       while (*c) {
454           *p++ = *c++;
455       }
456       return 0;
457     }'''
458   have_stack_protector = false
459   foreach arg : ['-fstack-protector-strong', '-fstack-protector-all']
460     # We need to check both a compile and a link, since some compiler
461     # setups fail only on a .c->.o compile and some only at link time
462     if cc.compiles(stack_protector_probe, args: ['-Werror', arg]) and \
463        cc.links(stack_protector_probe, args: ['-Werror', arg])
464       have_stack_protector = true
465       qemu_cflags += arg
466       qemu_ldflags += arg
467       break
468     endif
469   endforeach
470   get_option('stack_protector') \
471     .require(have_stack_protector, error_message: 'Stack protector not supported')
472 endif
473 
474 coroutine_backend = get_option('coroutine_backend')
475 ucontext_probe = '''
476   #include <ucontext.h>
477   #ifdef __stub_makecontext
478   #error Ignoring glibc stub makecontext which will always fail
479   #endif
480   int main(void) { makecontext(0, 0, 0); return 0; }'''
481 
482 # On Windows the only valid backend is the Windows specific one.
483 # For POSIX prefer ucontext, but it's not always possible. The fallback
484 # is sigcontext.
485 supported_backends = []
486 if host_os == 'windows'
487   supported_backends += ['windows']
488 else
489   if host_os != 'darwin' and cc.links(ucontext_probe)
490     supported_backends += ['ucontext']
491   endif
492   supported_backends += ['sigaltstack']
493 endif
494 
495 if coroutine_backend == 'auto'
496   coroutine_backend = supported_backends[0]
497 elif coroutine_backend not in supported_backends
498   error('"@0@" backend requested but not available.  Available backends: @1@' \
499         .format(coroutine_backend, ', '.join(supported_backends)))
500 endif
501 
502 # Compiles if SafeStack *not* enabled
503 safe_stack_probe = '''
504   int main(void)
505   {
506   #if defined(__has_feature)
507   #if __has_feature(safe_stack)
508   #error SafeStack Enabled
509   #endif
510   #endif
511       return 0;
512   }'''
513 if get_option('safe_stack') != not cc.compiles(safe_stack_probe)
514   safe_stack_arg = get_option('safe_stack') ? '-fsanitize=safe-stack' : '-fno-sanitize=safe-stack'
515   if get_option('safe_stack') != not cc.compiles(safe_stack_probe, args: safe_stack_arg)
516     error(get_option('safe_stack') \
517           ? 'SafeStack not supported by your compiler' \
518           : 'Cannot disable SafeStack')
519   endif
520   qemu_cflags += safe_stack_arg
521   qemu_ldflags += safe_stack_arg
522 endif
523 if get_option('safe_stack') and coroutine_backend != 'ucontext'
524   error('SafeStack is only supported with the ucontext coroutine backend')
525 endif
526 
527 if get_option('asan')
528   if cc.has_argument('-fsanitize=address')
529     qemu_cflags = ['-fsanitize=address'] + qemu_cflags
530     qemu_ldflags = ['-fsanitize=address'] + qemu_ldflags
531   else
532     error('Your compiler does not support -fsanitize=address')
533   endif
534 endif
535 
536 if get_option('ubsan')
537   # Detect static linking issue with ubsan:
538   # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84285
539   if cc.links('int main(int argc, char **argv) { return argc + 1; }',
540               args: [qemu_ldflags, '-fsanitize=undefined'])
541     qemu_cflags += ['-fsanitize=undefined']
542     qemu_ldflags += ['-fsanitize=undefined']
543 
544     # Suppress undefined behaviour from function call to mismatched type.
545     # In addition, tcg prologue does not emit function type prefix
546     # required by function call sanitizer.
547     if cc.has_argument('-fno-sanitize=function')
548       qemu_cflags += ['-fno-sanitize=function']
549     endif
550   else
551     error('Your compiler does not support -fsanitize=undefined')
552   endif
553 endif
554 
555 # Thread sanitizer is, for now, much noisier than the other sanitizers;
556 # keep it separate until that is not the case.
557 if get_option('tsan')
558   if get_option('asan') or get_option('ubsan')
559     error('TSAN is not supported with other sanitizers')
560   endif
561   if not cc.has_function('__tsan_create_fiber',
562                          args: '-fsanitize=thread',
563                          prefix: '#include <sanitizer/tsan_interface.h>')
564     error('Cannot enable TSAN due to missing fiber annotation interface')
565   endif
566   tsan_warn_suppress = []
567   # gcc (>=11) will report constructions not supported by tsan:
568   # "error: ‘atomic_thread_fence’ is not supported with ‘-fsanitize=thread’"
569   # https://gcc.gnu.org/gcc-11/changes.html
570   # However, clang does not support this warning and this triggers an error.
571   if cc.has_argument('-Wno-tsan')
572     tsan_warn_suppress = ['-Wno-tsan']
573   endif
574   qemu_cflags = ['-fsanitize=thread'] + tsan_warn_suppress + qemu_cflags
575   qemu_ldflags = ['-fsanitize=thread'] + qemu_ldflags
576 endif
577 
578 # Detect support for PT_GNU_RELRO + DT_BIND_NOW.
579 # The combination is known as "full relro", because .got.plt is read-only too.
580 qemu_ldflags += cc.get_supported_link_arguments('-Wl,-z,relro', '-Wl,-z,now')
581 
582 if host_os == 'windows'
583   qemu_ldflags += cc.get_supported_link_arguments('-Wl,--no-seh', '-Wl,--nxcompat')
584   qemu_ldflags += cc.get_supported_link_arguments('-Wl,--dynamicbase', '-Wl,--high-entropy-va')
585 endif
586 
587 if get_option('fuzzing')
588   # Specify a filter to only instrument code that is directly related to
589   # virtual-devices.
590   configure_file(output: 'instrumentation-filter',
591                  input: 'scripts/oss-fuzz/instrumentation-filter-template',
592                  copy: true)
593 
594   if cc.compiles('int main () { return 0; }',
595                   name: '-fsanitize-coverage-allowlist=/dev/null',
596                  args: ['-fsanitize-coverage-allowlist=/dev/null',
597                         '-fsanitize-coverage=trace-pc'] )
598     qemu_common_flags += ['-fsanitize-coverage-allowlist=instrumentation-filter']
599   endif
600 
601   if get_option('fuzzing_engine') == ''
602     # Add CFLAGS to tell clang to add fuzzer-related instrumentation to all the
603     # compiled code.  To build non-fuzzer binaries with --enable-fuzzing, link
604     # everything with fsanitize=fuzzer-no-link. Otherwise, the linker will be
605     # unable to bind the fuzzer-related callbacks added by instrumentation.
606     qemu_common_flags += ['-fsanitize=fuzzer-no-link']
607     qemu_ldflags += ['-fsanitize=fuzzer-no-link']
608     # For the actual fuzzer binaries, we need to link against the libfuzzer
609     # library. They need to be configurable, to support OSS-Fuzz
610     fuzz_exe_ldflags = ['-fsanitize=fuzzer']
611   else
612     # LIB_FUZZING_ENGINE was set; assume we are running on OSS-Fuzz, and
613     # the needed CFLAGS have already been provided
614     fuzz_exe_ldflags = get_option('fuzzing_engine').split()
615   endif
616 endif
617 
618 if get_option('cfi')
619   cfi_flags=[]
620   # Check for dependency on LTO
621   if not get_option('b_lto')
622     error('Selected Control-Flow Integrity but LTO is disabled')
623   endif
624   if enable_modules
625     error('Selected Control-Flow Integrity is not compatible with modules')
626   endif
627   # Check for cfi flags. CFI requires LTO so we can't use
628   # get_supported_arguments, but need a more complex "compiles" which allows
629   # custom arguments
630   if cc.compiles('int main () { return 0; }', name: '-fsanitize=cfi-icall',
631                  args: ['-flto', '-fsanitize=cfi-icall'] )
632     cfi_flags += '-fsanitize=cfi-icall'
633   else
634     error('-fsanitize=cfi-icall is not supported by the compiler')
635   endif
636   if cc.compiles('int main () { return 0; }',
637                  name: '-fsanitize-cfi-icall-generalize-pointers',
638                  args: ['-flto', '-fsanitize=cfi-icall',
639                         '-fsanitize-cfi-icall-generalize-pointers'] )
640     cfi_flags += '-fsanitize-cfi-icall-generalize-pointers'
641   else
642     error('-fsanitize-cfi-icall-generalize-pointers is not supported by the compiler')
643   endif
644   if get_option('cfi_debug')
645     if cc.compiles('int main () { return 0; }',
646                    name: '-fno-sanitize-trap=cfi-icall',
647                    args: ['-flto', '-fsanitize=cfi-icall',
648                           '-fno-sanitize-trap=cfi-icall'] )
649       cfi_flags += '-fno-sanitize-trap=cfi-icall'
650     else
651       error('-fno-sanitize-trap=cfi-icall is not supported by the compiler')
652     endif
653   endif
654   add_global_arguments(cfi_flags, native: false, language: all_languages)
655   add_global_link_arguments(cfi_flags, native: false, language: all_languages)
656 endif
657 
658 # Check further flags that make QEMU more robust against malicious parties
659 
660 hardening_flags = [
661     # Initialize all stack variables to zero. This makes
662     # it harder to take advantage of uninitialized stack
663     # data to drive exploits
664     '-ftrivial-auto-var-init=zero',
665 ]
666 
667 # Zero out registers used during a function call
668 # upon its return. This makes it harder to assemble
669 # ROP gadgets into something usable
670 #
671 # NB: Clang 17 is broken and SEGVs
672 # https://github.com/llvm/llvm-project/issues/75168
673 #
674 # NB2: This clashes with the "retguard" extension of OpenBSD's Clang
675 # https://gitlab.com/qemu-project/qemu/-/issues/2278
676 if host_os != 'openbsd' and \
677    cc.compiles('extern struct { void (*cb)(void); } s; void f(void) { s.cb(); }',
678                name: '-fzero-call-used-regs=used-gpr',
679                args: ['-O2', '-fzero-call-used-regs=used-gpr'])
680     hardening_flags += '-fzero-call-used-regs=used-gpr'
681 endif
682 
683 qemu_common_flags += cc.get_supported_arguments(hardening_flags)
684 
685 add_global_arguments(qemu_common_flags, native: false, language: all_languages)
686 add_global_link_arguments(qemu_ldflags, native: false, language: all_languages)
687 
688 # Collect warning flags we want to set, sorted alphabetically
689 warn_flags = [
690   # First enable interesting warnings
691   '-Wempty-body',
692   '-Wendif-labels',
693   '-Wexpansion-to-defined',
694   '-Wformat-security',
695   '-Wformat-y2k',
696   '-Wignored-qualifiers',
697   '-Wimplicit-fallthrough=2',
698   '-Winit-self',
699   '-Wmissing-format-attribute',
700   '-Wmissing-prototypes',
701   '-Wnested-externs',
702   '-Wold-style-declaration',
703   '-Wold-style-definition',
704   '-Wredundant-decls',
705   '-Wshadow=local',
706   '-Wstrict-prototypes',
707   '-Wtype-limits',
708   '-Wundef',
709   '-Wvla',
710   '-Wwrite-strings',
711 
712   # Then disable some undesirable warnings
713   '-Wno-gnu-variable-sized-type-not-at-end',
714   '-Wno-initializer-overrides',
715   '-Wno-missing-include-dirs',
716   '-Wno-psabi',
717   '-Wno-shift-negative-value',
718   '-Wno-string-plus-int',
719   '-Wno-tautological-type-limit-compare',
720   '-Wno-typedef-redefinition',
721 ]
722 
723 if host_os != 'darwin'
724   tsa_has_cleanup = cc.compiles('''
725     struct __attribute__((capability("mutex"))) mutex {};
726     void lock(struct mutex *m) __attribute__((acquire_capability(m)));
727     void unlock(struct mutex *m) __attribute__((release_capability(m)));
728 
729     void test(void) {
730       struct mutex __attribute__((cleanup(unlock))) m;
731       lock(&m);
732     }
733   ''', args: ['-Wthread-safety', '-Werror'])
734   if tsa_has_cleanup
735     warn_flags += ['-Wthread-safety']
736   endif
737 endif
738 
739 # Set up C++ compiler flags
740 qemu_cxxflags = []
741 if 'cpp' in all_languages
742   qemu_cxxflags = ['-D__STDC_LIMIT_MACROS', '-D__STDC_CONSTANT_MACROS', '-D__STDC_FORMAT_MACROS'] + qemu_cflags
743 endif
744 
745 add_project_arguments(qemu_cflags, native: false, language: 'c')
746 add_project_arguments(cc.get_supported_arguments(warn_flags), native: false, language: 'c')
747 if 'cpp' in all_languages
748   add_project_arguments(qemu_cxxflags, native: false, language: 'cpp')
749   add_project_arguments(cxx.get_supported_arguments(warn_flags), native: false, language: 'cpp')
750 endif
751 if 'objc' in all_languages
752   # Note sanitizer flags are not applied to Objective-C sources!
753   add_project_arguments(objc.get_supported_arguments(warn_flags), native: false, language: 'objc')
754 endif
755 if host_os == 'linux'
756   add_project_arguments('-isystem', meson.current_source_dir() / 'linux-headers',
757                         '-isystem', 'linux-headers',
758                         language: all_languages)
759 endif
760 
761 add_project_arguments('-iquote', '.',
762                       '-iquote', meson.current_source_dir(),
763                       '-iquote', meson.current_source_dir() / 'include',
764                       language: all_languages)
765 
766 # If a host-specific include directory exists, list that first...
767 host_include = meson.current_source_dir() / 'host/include/'
768 if fs.is_dir(host_include / host_arch)
769   add_project_arguments('-iquote', host_include / host_arch,
770                         language: all_languages)
771 endif
772 # ... followed by the generic fallback.
773 add_project_arguments('-iquote', host_include / 'generic',
774                       language: all_languages)
775 
776 sparse = find_program('cgcc', required: get_option('sparse'))
777 if sparse.found()
778   run_target('sparse',
779              command: [find_program('scripts/check_sparse.py'),
780                        'compile_commands.json', sparse.full_path(), '-Wbitwise',
781                        '-Wno-transparent-union', '-Wno-old-initializer',
782                        '-Wno-non-pointer-null'])
783 endif
784 
785 #####################################
786 # Host-specific libraries and flags #
787 #####################################
788 
789 libm = cc.find_library('m', required: false)
790 threads = dependency('threads')
791 util = cc.find_library('util', required: false)
792 winmm = []
793 socket = []
794 version_res = []
795 coref = []
796 iokit = []
797 emulator_link_args = []
798 midl = not_found
799 widl = not_found
800 pathcch = not_found
801 host_dsosuf = '.so'
802 if host_os == 'windows'
803   midl = find_program('midl', required: false)
804   widl = find_program('widl', required: false)
805   pathcch = cc.find_library('pathcch')
806   socket = cc.find_library('ws2_32')
807   winmm = cc.find_library('winmm')
808 
809   win = import('windows')
810   version_res = win.compile_resources('version.rc',
811                                       depend_files: files('pc-bios/qemu-nsis.ico'),
812                                       include_directories: include_directories('.'))
813   host_dsosuf = '.dll'
814 elif host_os == 'darwin'
815   coref = dependency('appleframeworks', modules: 'CoreFoundation')
816   iokit = dependency('appleframeworks', modules: 'IOKit', required: false)
817   host_dsosuf = '.dylib'
818 elif host_os == 'sunos'
819   socket = [cc.find_library('socket'),
820             cc.find_library('nsl'),
821             cc.find_library('resolv')]
822 elif host_os == 'haiku'
823   socket = [cc.find_library('posix_error_mapper'),
824             cc.find_library('network'),
825             cc.find_library('bsd')]
826 elif host_os == 'openbsd'
827   if get_option('tcg').allowed() and target_dirs.length() > 0
828     # Disable OpenBSD W^X if available
829     emulator_link_args = cc.get_supported_link_arguments('-Wl,-z,wxneeded')
830   endif
831 endif
832 
833 ###############################################
834 # Host-specific configuration of accelerators #
835 ###############################################
836 
837 accelerators = []
838 if get_option('kvm').allowed() and host_os == 'linux'
839   accelerators += 'CONFIG_KVM'
840 endif
841 if get_option('whpx').allowed() and host_os == 'windows'
842   if get_option('whpx').enabled() and host_machine.cpu() != 'x86_64'
843     error('WHPX requires 64-bit host')
844   elif cc.has_header('winhvplatform.h', required: get_option('whpx')) and \
845        cc.has_header('winhvemulation.h', required: get_option('whpx'))
846     accelerators += 'CONFIG_WHPX'
847   endif
848 endif
849 
850 hvf = not_found
851 if get_option('hvf').allowed()
852   hvf = dependency('appleframeworks', modules: 'Hypervisor',
853                    required: get_option('hvf'))
854   if hvf.found()
855     accelerators += 'CONFIG_HVF'
856   endif
857 endif
858 
859 nvmm = not_found
860 if host_os == 'netbsd'
861   nvmm = cc.find_library('nvmm', required: get_option('nvmm'))
862   if nvmm.found()
863     accelerators += 'CONFIG_NVMM'
864   endif
865 endif
866 
867 tcg_arch = host_arch
868 if get_option('tcg').allowed()
869   if host_arch == 'unknown'
870     if not get_option('tcg_interpreter')
871       error('Unsupported CPU @0@, try --enable-tcg-interpreter'.format(cpu))
872     endif
873   elif get_option('tcg_interpreter')
874     warning('Use of the TCG interpreter is not recommended on this host')
875     warning('architecture. There is a native TCG execution backend available')
876     warning('which provides substantially better performance and reliability.')
877     warning('It is strongly recommended to remove the --enable-tcg-interpreter')
878     warning('configuration option on this architecture to use the native')
879     warning('backend.')
880   endif
881   if get_option('tcg_interpreter')
882     tcg_arch = 'tci'
883   elif host_arch == 'x86_64'
884     tcg_arch = 'i386'
885   elif host_arch == 'ppc64'
886     tcg_arch = 'ppc'
887   endif
888   add_project_arguments('-iquote', meson.current_source_dir() / 'tcg' / tcg_arch,
889                         language: all_languages)
890 
891   accelerators += 'CONFIG_TCG'
892 endif
893 
894 if 'CONFIG_KVM' not in accelerators and get_option('kvm').enabled()
895   error('KVM not available on this platform')
896 endif
897 if 'CONFIG_HVF' not in accelerators and get_option('hvf').enabled()
898   error('HVF not available on this platform')
899 endif
900 if 'CONFIG_NVMM' not in accelerators and get_option('nvmm').enabled()
901   error('NVMM not available on this platform')
902 endif
903 if 'CONFIG_WHPX' not in accelerators and get_option('whpx').enabled()
904   error('WHPX not available on this platform')
905 endif
906 
907 xen = not_found
908 if get_option('xen').enabled() or (get_option('xen').auto() and have_system)
909   xencontrol = dependency('xencontrol', required: false,
910                           method: 'pkg-config')
911   if xencontrol.found()
912     xen_pc = declare_dependency(version: xencontrol.version(),
913       dependencies: [
914         xencontrol,
915         # disabler: true makes xen_pc.found() return false if any is not found
916         dependency('xenstore', required: false,
917                    method: 'pkg-config',
918                    disabler: true),
919         dependency('xenforeignmemory', required: false,
920                    method: 'pkg-config',
921                    disabler: true),
922         dependency('xengnttab', required: false,
923                    method: 'pkg-config',
924                    disabler: true),
925         dependency('xenevtchn', required: false,
926                    method: 'pkg-config',
927                    disabler: true),
928         dependency('xendevicemodel', required: false,
929                    method: 'pkg-config',
930                    disabler: true),
931         # optional, no "disabler: true"
932         dependency('xentoolcore', required: false,
933                    method: 'pkg-config')])
934     if xen_pc.found()
935       xen = xen_pc
936     endif
937   endif
938   if not xen.found()
939     xen_tests = [ '4.11.0', '4.10.0', '4.9.0', '4.8.0', '4.7.1' ]
940     xen_libs = {
941       '4.11.0': [ 'xenstore', 'xenctrl', 'xendevicemodel', 'xenforeignmemory', 'xengnttab', 'xenevtchn', 'xentoolcore' ],
942       '4.10.0': [ 'xenstore', 'xenctrl', 'xendevicemodel', 'xenforeignmemory', 'xengnttab', 'xenevtchn', 'xentoolcore' ],
943       '4.9.0': [ 'xenstore', 'xenctrl', 'xendevicemodel', 'xenforeignmemory', 'xengnttab', 'xenevtchn' ],
944       '4.8.0': [ 'xenstore', 'xenctrl', 'xenforeignmemory', 'xengnttab', 'xenevtchn' ],
945       '4.7.1': [ 'xenstore', 'xenctrl', 'xenforeignmemory', 'xengnttab', 'xenevtchn' ],
946     }
947     xen_deps = {}
948     foreach ver: xen_tests
949       # cache the various library tests to avoid polluting the logs
950       xen_test_deps = []
951       foreach l: xen_libs[ver]
952         if l not in xen_deps
953           xen_deps += { l: cc.find_library(l, required: false) }
954         endif
955         xen_test_deps += xen_deps[l]
956       endforeach
957 
958       # Use -D to pick just one of the test programs in scripts/xen-detect.c
959       xen_version = ver.split('.')
960       xen_ctrl_version = xen_version[0] + \
961         ('0' + xen_version[1]).substring(-2) + \
962         ('0' + xen_version[2]).substring(-2)
963       if cc.links(files('scripts/xen-detect.c'),
964                   args: '-DCONFIG_XEN_CTRL_INTERFACE_VERSION=' + xen_ctrl_version,
965                   dependencies: xen_test_deps)
966         xen = declare_dependency(version: ver, dependencies: xen_test_deps)
967         break
968       endif
969     endforeach
970   endif
971   if xen.found()
972     accelerators += 'CONFIG_XEN'
973   elif get_option('xen').enabled()
974     error('could not compile and link Xen test program')
975   endif
976 endif
977 have_xen_pci_passthrough = get_option('xen_pci_passthrough') \
978   .require(xen.found(),
979            error_message: 'Xen PCI passthrough requested but Xen not enabled') \
980   .require(host_os == 'linux',
981            error_message: 'Xen PCI passthrough not available on this platform') \
982   .require(cpu == 'x86'  or cpu == 'x86_64',
983            error_message: 'Xen PCI passthrough not available on this platform') \
984   .allowed()
985 
986 ################
987 # Dependencies #
988 ################
989 
990 # When bumping glib minimum version, please check also whether to increase
991 # the _WIN32_WINNT setting in osdep.h according to the value from glib.
992 # You should also check if any of the glib.version() checks
993 # below can also be removed.
994 glib_req_ver = '>=2.66.0'
995 glib_pc = dependency('glib-2.0', version: glib_req_ver, required: true,
996                     method: 'pkg-config')
997 glib_cflags = []
998 if enable_modules
999   gmodule = dependency('gmodule-export-2.0', version: glib_req_ver, required: true,
1000                        method: 'pkg-config')
1001 elif get_option('plugins')
1002   gmodule = dependency('gmodule-no-export-2.0', version: glib_req_ver, required: true,
1003                        method: 'pkg-config')
1004 else
1005   gmodule = not_found
1006 endif
1007 
1008 # This workaround is required due to a bug in pkg-config file for glib as it
1009 # doesn't define GLIB_STATIC_COMPILATION for pkg-config --static
1010 if host_os == 'windows' and get_option('prefer_static')
1011   glib_cflags += ['-DGLIB_STATIC_COMPILATION']
1012 endif
1013 
1014 # Sanity check that the current size_t matches the
1015 # size that glib thinks it should be. This catches
1016 # problems on multi-arch where people try to build
1017 # 32-bit QEMU while pointing at 64-bit glib headers
1018 
1019 if not cc.compiles('''
1020   #include <glib.h>
1021   #include <unistd.h>
1022 
1023   #define QEMU_BUILD_BUG_ON(x) \
1024   typedef char qemu_build_bug_on[(x)?-1:1] __attribute__((unused));
1025 
1026   int main(void) {
1027      QEMU_BUILD_BUG_ON(sizeof(size_t) != GLIB_SIZEOF_SIZE_T);
1028      return 0;
1029   }''', dependencies: glib_pc, args: glib_cflags)
1030   error('''sizeof(size_t) doesn't match GLIB_SIZEOF_SIZE_T.
1031         You probably need to set PKG_CONFIG_LIBDIR" to point
1032         to the right pkg-config files for your build target.''')
1033 endif
1034 
1035 glib = declare_dependency(dependencies: [glib_pc, gmodule],
1036                           compile_args: glib_cflags,
1037                           version: glib_pc.version())
1038 
1039 # Check whether glib has gslice, which we have to avoid for correctness.
1040 # TODO: remove this check and the corresponding workaround (qtree) when
1041 # the minimum supported glib is >= 2.75.3
1042 glib_has_gslice = glib.version().version_compare('<2.75.3')
1043 # Check whether glib has the aligned_alloc family of functions.
1044 # <https://docs.gtk.org/glib/func.aligned_alloc.html>
1045 glib_has_aligned_alloc = glib.version().version_compare('>=2.72.0')
1046 
1047 # override glib dep to include the above refinements
1048 meson.override_dependency('glib-2.0', glib)
1049 
1050 # The path to glib.h is added to all compilation commands.
1051 add_project_dependencies(glib.partial_dependency(compile_args: true, includes: true),
1052                          native: false, language: all_languages)
1053 
1054 gio = not_found
1055 gdbus_codegen = not_found
1056 gdbus_codegen_error = '@0@ requires gdbus-codegen, please install libgio'
1057 if not get_option('gio').auto() or have_system
1058   gio = dependency('gio-2.0', required: get_option('gio'),
1059                    method: 'pkg-config')
1060   if gio.found() and not cc.links('''
1061     #include <gio/gio.h>
1062     int main(void)
1063     {
1064       g_dbus_proxy_new_sync(0, 0, 0, 0, 0, 0, 0, 0);
1065       return 0;
1066     }''', dependencies: [glib, gio])
1067     if get_option('gio').enabled()
1068       error('The installed libgio is broken for static linking')
1069     endif
1070     gio = not_found
1071   endif
1072   if gio.found()
1073     gdbus_codegen = find_program('gdbus-codegen',
1074                                  required: get_option('gio'))
1075     gio_unix = dependency('gio-unix-2.0', required: get_option('gio'),
1076                           method: 'pkg-config')
1077     gio = declare_dependency(dependencies: [gio, gio_unix],
1078                              version: gio.version())
1079   endif
1080 endif
1081 if gdbus_codegen.found() and get_option('cfi')
1082   gdbus_codegen = not_found
1083   gdbus_codegen_error = '@0@ uses gdbus-codegen, which does not support control flow integrity'
1084 endif
1085 
1086 xml_pp = find_program('scripts/xml-preprocess.py')
1087 
1088 lttng = not_found
1089 if 'ust' in get_option('trace_backends')
1090   lttng = dependency('lttng-ust', required: true, version: '>= 2.1',
1091                      method: 'pkg-config')
1092 endif
1093 pixman = not_found
1094 if not get_option('pixman').auto() or have_system or have_tools
1095   pixman = dependency('pixman-1', required: get_option('pixman'), version:'>=0.21.8',
1096                       method: 'pkg-config')
1097 endif
1098 
1099 zlib = dependency('zlib', required: true)
1100 
1101 libaio = not_found
1102 if not get_option('linux_aio').auto() or have_block
1103   libaio = cc.find_library('aio', has_headers: ['libaio.h'],
1104                            required: get_option('linux_aio'))
1105 endif
1106 
1107 linux_io_uring_test = '''
1108   #include <liburing.h>
1109   #include <linux/errqueue.h>
1110 
1111   int main(void) { return 0; }'''
1112 
1113 linux_io_uring = not_found
1114 if not get_option('linux_io_uring').auto() or have_block
1115   linux_io_uring = dependency('liburing', version: '>=0.3',
1116                               required: get_option('linux_io_uring'),
1117                               method: 'pkg-config')
1118   if not cc.links(linux_io_uring_test)
1119     linux_io_uring = not_found
1120   endif
1121 endif
1122 
1123 libnfs = not_found
1124 if not get_option('libnfs').auto() or have_block
1125   libnfs = dependency('libnfs', version: ['>=1.9.3', '<6.0.0'],
1126                       required: get_option('libnfs'),
1127                       method: 'pkg-config')
1128 endif
1129 
1130 libattr_test = '''
1131   #include <stddef.h>
1132   #include <sys/types.h>
1133   #ifdef CONFIG_LIBATTR
1134   #include <attr/xattr.h>
1135   #else
1136   #include <sys/xattr.h>
1137   #endif
1138   int main(void) { getxattr(NULL, NULL, NULL, 0); setxattr(NULL, NULL, NULL, 0, 0); return 0; }'''
1139 
1140 libattr = not_found
1141 have_old_libattr = false
1142 if get_option('attr').allowed()
1143   if cc.links(libattr_test)
1144     libattr = declare_dependency()
1145   else
1146     libattr = cc.find_library('attr', has_headers: ['attr/xattr.h'],
1147                               required: get_option('attr'))
1148     if libattr.found() and not \
1149       cc.links(libattr_test, dependencies: libattr, args: '-DCONFIG_LIBATTR')
1150       libattr = not_found
1151       if get_option('attr').enabled()
1152         error('could not link libattr')
1153       else
1154         warning('could not link libattr, disabling')
1155       endif
1156     else
1157       have_old_libattr = libattr.found()
1158     endif
1159   endif
1160 endif
1161 
1162 cocoa = dependency('appleframeworks',
1163                    modules: ['Cocoa', 'CoreVideo', 'QuartzCore'],
1164                    required: get_option('cocoa'))
1165 
1166 vmnet = dependency('appleframeworks', modules: 'vmnet', required: get_option('vmnet'))
1167 if vmnet.found() and not cc.has_header_symbol('vmnet/vmnet.h',
1168                                               'VMNET_BRIDGED_MODE',
1169                                               dependencies: vmnet)
1170   vmnet = not_found
1171   if get_option('vmnet').enabled()
1172     error('vmnet.framework API is outdated')
1173   else
1174     warning('vmnet.framework API is outdated, disabling')
1175   endif
1176 endif
1177 
1178 seccomp = not_found
1179 seccomp_has_sysrawrc = false
1180 if not get_option('seccomp').auto() or have_system or have_tools
1181   seccomp = dependency('libseccomp', version: '>=2.3.0',
1182                        required: get_option('seccomp'),
1183                        method: 'pkg-config')
1184   if seccomp.found()
1185     seccomp_has_sysrawrc = cc.has_header_symbol('seccomp.h',
1186                                                 'SCMP_FLTATR_API_SYSRAWRC',
1187                                                 dependencies: seccomp)
1188   endif
1189 endif
1190 
1191 libcap_ng = not_found
1192 if not get_option('cap_ng').auto() or have_system or have_tools
1193   libcap_ng = cc.find_library('cap-ng', has_headers: ['cap-ng.h'],
1194                               required: get_option('cap_ng'))
1195 endif
1196 if libcap_ng.found() and not cc.links('''
1197    #include <cap-ng.h>
1198    int main(void)
1199    {
1200      capng_capability_to_name(CAPNG_EFFECTIVE);
1201      return 0;
1202    }''', dependencies: libcap_ng)
1203   libcap_ng = not_found
1204   if get_option('cap_ng').enabled()
1205     error('could not link libcap-ng')
1206   else
1207     warning('could not link libcap-ng, disabling')
1208   endif
1209 endif
1210 
1211 if get_option('xkbcommon').auto() and not have_system and not have_tools
1212   xkbcommon = not_found
1213 else
1214   xkbcommon = dependency('xkbcommon', required: get_option('xkbcommon'),
1215                          method: 'pkg-config')
1216 endif
1217 
1218 slirp = not_found
1219 if not get_option('slirp').auto() or have_system
1220   slirp = dependency('slirp', required: get_option('slirp'),
1221                      method: 'pkg-config')
1222   # slirp < 4.7 is incompatible with CFI support in QEMU.  This is because
1223   # it passes function pointers within libslirp as callbacks for timers.
1224   # When using a system-wide shared libslirp, the type information for the
1225   # callback is missing and the timer call produces a false positive with CFI.
1226   # Do not use the "version" keyword argument to produce a better error.
1227   # with control-flow integrity.
1228   if get_option('cfi') and slirp.found() and slirp.version().version_compare('<4.7')
1229     if get_option('slirp').enabled()
1230       error('Control-Flow Integrity requires libslirp 4.7.')
1231     else
1232       warning('Cannot use libslirp since Control-Flow Integrity requires libslirp >= 4.7.')
1233       slirp = not_found
1234     endif
1235   endif
1236 endif
1237 
1238 vde = not_found
1239 if not get_option('vde').auto() or have_system or have_tools
1240   vde = cc.find_library('vdeplug', has_headers: ['libvdeplug.h'],
1241                            required: get_option('vde'))
1242 endif
1243 if vde.found() and not cc.links('''
1244    #include <libvdeplug.h>
1245    int main(void)
1246    {
1247      struct vde_open_args a = {0, 0, 0};
1248      char s[] = "";
1249      vde_open(s, s, &a);
1250      return 0;
1251    }''', dependencies: vde)
1252   vde = not_found
1253   if get_option('cap_ng').enabled()
1254     error('could not link libvdeplug')
1255   else
1256     warning('could not link libvdeplug, disabling')
1257   endif
1258 endif
1259 
1260 pulse = not_found
1261 if not get_option('pa').auto() or (host_os == 'linux' and have_system)
1262   pulse = dependency('libpulse', required: get_option('pa'),
1263                      method: 'pkg-config')
1264 endif
1265 alsa = not_found
1266 if not get_option('alsa').auto() or (host_os == 'linux' and have_system)
1267   alsa = dependency('alsa', required: get_option('alsa'),
1268                     method: 'pkg-config')
1269 endif
1270 jack = not_found
1271 if not get_option('jack').auto() or have_system
1272   jack = dependency('jack', required: get_option('jack'),
1273                     method: 'pkg-config')
1274 endif
1275 pipewire = not_found
1276 if not get_option('pipewire').auto() or (host_os == 'linux' and have_system)
1277   pipewire = dependency('libpipewire-0.3', version: '>=0.3.60',
1278                     required: get_option('pipewire'),
1279                     method: 'pkg-config')
1280 endif
1281 sndio = not_found
1282 if not get_option('sndio').auto() or have_system
1283   sndio = dependency('sndio', required: get_option('sndio'),
1284                     method: 'pkg-config')
1285 endif
1286 
1287 spice_protocol = not_found
1288 if not get_option('spice_protocol').auto() or have_system
1289   spice_protocol = dependency('spice-protocol', version: '>=0.14.0',
1290                               required: get_option('spice_protocol'),
1291                               method: 'pkg-config')
1292 endif
1293 spice = not_found
1294 if get_option('spice') \
1295              .disable_auto_if(not have_system) \
1296              .require(pixman.found(),
1297                       error_message: 'cannot enable SPICE if pixman is not available') \
1298              .allowed()
1299   spice = dependency('spice-server', version: '>=0.14.0',
1300                      required: get_option('spice'),
1301                      method: 'pkg-config')
1302 endif
1303 spice_headers = spice.partial_dependency(compile_args: true, includes: true)
1304 
1305 rt = cc.find_library('rt', required: false)
1306 
1307 libiscsi = not_found
1308 if not get_option('libiscsi').auto() or have_block
1309   libiscsi = dependency('libiscsi', version: '>=1.9.0',
1310                          required: get_option('libiscsi'),
1311                          method: 'pkg-config')
1312 endif
1313 zstd = not_found
1314 if not get_option('zstd').auto() or have_block
1315   zstd = dependency('libzstd', version: '>=1.4.0',
1316                     required: get_option('zstd'),
1317                     method: 'pkg-config')
1318 endif
1319 qpl = not_found
1320 if not get_option('qpl').auto() or have_system
1321   qpl = dependency('qpl', version: '>=1.5.0',
1322                     required: get_option('qpl'),
1323                     method: 'pkg-config')
1324 endif
1325 uadk = not_found
1326 if not get_option('uadk').auto() or have_system
1327   libwd = dependency('libwd', version: '>=2.6',
1328                       required: get_option('uadk'),
1329                       method: 'pkg-config')
1330   libwd_comp = dependency('libwd_comp', version: '>=2.6',
1331                            required: get_option('uadk'),
1332                            method: 'pkg-config')
1333   if libwd.found() and libwd_comp.found()
1334      uadk = declare_dependency(dependencies: [libwd, libwd_comp])
1335   endif
1336 endif
1337 
1338 qatzip = not_found
1339 if not get_option('qatzip').auto() or have_system
1340   qatzip = dependency('qatzip', version: '>=1.1.2',
1341                       required: get_option('qatzip'),
1342                       method: 'pkg-config')
1343 endif
1344 
1345 virgl = not_found
1346 
1347 have_vhost_user_gpu = have_tools and host_os == 'linux' and pixman.found()
1348 if not get_option('virglrenderer').auto() or have_system or have_vhost_user_gpu
1349   virgl = dependency('virglrenderer',
1350                      method: 'pkg-config',
1351                      required: get_option('virglrenderer'))
1352 endif
1353 rutabaga = not_found
1354 if not get_option('rutabaga_gfx').auto() or have_system or have_vhost_user_gpu
1355   rutabaga = dependency('rutabaga_gfx_ffi',
1356                          method: 'pkg-config',
1357                          required: get_option('rutabaga_gfx'))
1358 endif
1359 blkio = not_found
1360 if not get_option('blkio').auto() or have_block
1361   blkio = dependency('blkio',
1362                      method: 'pkg-config',
1363                      required: get_option('blkio'))
1364 endif
1365 curl = not_found
1366 if not get_option('curl').auto() or have_block
1367   curl = dependency('libcurl', version: '>=7.29.0',
1368                     method: 'pkg-config',
1369                     required: get_option('curl'))
1370 endif
1371 libudev = not_found
1372 if host_os == 'linux' and (have_system or have_tools)
1373   libudev = dependency('libudev',
1374                        method: 'pkg-config',
1375                        required: get_option('libudev'))
1376 endif
1377 
1378 mpathlibs = [libudev]
1379 mpathpersist = not_found
1380 if host_os == 'linux' and have_tools and get_option('mpath').allowed()
1381   mpath_test_source = '''
1382     #include <libudev.h>
1383     #include <mpath_persist.h>
1384     unsigned mpath_mx_alloc_len = 1024;
1385     int logsink;
1386     static struct config *multipath_conf;
1387     extern struct udev *udev;
1388     extern struct config *get_multipath_config(void);
1389     extern void put_multipath_config(struct config *conf);
1390     struct udev *udev;
1391     struct config *get_multipath_config(void) { return multipath_conf; }
1392     void put_multipath_config(struct config *conf) { }
1393     int main(void) {
1394         udev = udev_new();
1395         multipath_conf = mpath_lib_init();
1396         return 0;
1397     }'''
1398   libmpathpersist = cc.find_library('mpathpersist',
1399                                     required: get_option('mpath'))
1400   if libmpathpersist.found()
1401     mpathlibs += libmpathpersist
1402     if get_option('prefer_static')
1403       mpathlibs += cc.find_library('devmapper',
1404                                      required: get_option('mpath'))
1405     endif
1406     mpathlibs += cc.find_library('multipath',
1407                                  required: get_option('mpath'))
1408     foreach lib: mpathlibs
1409       if not lib.found()
1410         mpathlibs = []
1411         break
1412       endif
1413     endforeach
1414     if mpathlibs.length() == 0
1415       msg = 'Dependencies missing for libmpathpersist'
1416     elif cc.links(mpath_test_source, dependencies: mpathlibs)
1417       mpathpersist = declare_dependency(dependencies: mpathlibs)
1418     else
1419       msg = 'Cannot detect libmpathpersist API'
1420     endif
1421     if not mpathpersist.found()
1422       if get_option('mpath').enabled()
1423         error(msg)
1424       else
1425         warning(msg + ', disabling')
1426       endif
1427     endif
1428   endif
1429 endif
1430 
1431 iconv = not_found
1432 curses = not_found
1433 if have_system and get_option('curses').allowed()
1434   curses_test = '''
1435     #ifdef __APPLE__
1436     #define _XOPEN_SOURCE_EXTENDED 1
1437     #endif
1438     #include <locale.h>
1439     #include <curses.h>
1440     #include <wchar.h>
1441     int main(void) {
1442       wchar_t wch = L'w';
1443       setlocale(LC_ALL, "");
1444       resize_term(0, 0);
1445       addwstr(L"wide chars\n");
1446       addnwstr(&wch, 1);
1447       add_wch(WACS_DEGREE);
1448       return 0;
1449     }'''
1450 
1451   curses_dep_list = host_os == 'windows' ? ['ncurses', 'ncursesw'] : ['ncursesw']
1452   curses = dependency(curses_dep_list,
1453                       required: false,
1454                       method: 'pkg-config')
1455   msg = get_option('curses').enabled() ? 'curses library not found' : ''
1456   curses_compile_args = ['-DNCURSES_WIDECHAR=1']
1457   if curses.found()
1458     if cc.links(curses_test, args: curses_compile_args, dependencies: [curses])
1459       curses = declare_dependency(compile_args: curses_compile_args, dependencies: [curses],
1460                                   version: curses.version())
1461     else
1462       msg = 'curses package not usable'
1463       curses = not_found
1464     endif
1465   endif
1466   if not curses.found()
1467     has_curses_h = cc.has_header('curses.h', args: curses_compile_args)
1468     if host_os != 'windows' and not has_curses_h
1469       message('Trying with /usr/include/ncursesw')
1470       curses_compile_args += ['-I/usr/include/ncursesw']
1471       has_curses_h = cc.has_header('curses.h', args: curses_compile_args)
1472     endif
1473     if has_curses_h
1474       curses_libname_list = (host_os == 'windows' ? ['pdcurses'] : ['ncursesw', 'cursesw'])
1475       foreach curses_libname : curses_libname_list
1476         libcurses = cc.find_library(curses_libname,
1477                                     required: false)
1478         if libcurses.found()
1479           if cc.links(curses_test, args: curses_compile_args, dependencies: libcurses)
1480             curses = declare_dependency(compile_args: curses_compile_args,
1481                                         dependencies: [libcurses])
1482             break
1483           else
1484             msg = 'curses library not usable'
1485           endif
1486         endif
1487       endforeach
1488     endif
1489   endif
1490   if get_option('iconv').allowed()
1491     foreach link_args : [ ['-liconv'], [] ]
1492       # Programs will be linked with glib and this will bring in libiconv on FreeBSD.
1493       # We need to use libiconv if available because mixing libiconv's headers with
1494       # the system libc does not work.
1495       # However, without adding glib to the dependencies -L/usr/local/lib will not be
1496       # included in the command line and libiconv will not be found.
1497       if cc.links('''
1498         #include <iconv.h>
1499         int main(void) {
1500           iconv_t conv = iconv_open("WCHAR_T", "UCS-2");
1501           return conv != (iconv_t) -1;
1502         }''', args: link_args, dependencies: glib)
1503         iconv = declare_dependency(link_args: link_args, dependencies: glib)
1504         break
1505       endif
1506     endforeach
1507   endif
1508   if curses.found() and not iconv.found()
1509     if get_option('iconv').enabled()
1510       error('iconv not available')
1511     endif
1512     msg = 'iconv required for curses UI but not available'
1513     curses = not_found
1514   endif
1515   if not curses.found() and msg != ''
1516     if get_option('curses').enabled()
1517       error(msg)
1518     else
1519       warning(msg + ', disabling')
1520     endif
1521   endif
1522 endif
1523 
1524 brlapi = not_found
1525 if not get_option('brlapi').auto() or have_system
1526   brlapi = cc.find_library('brlapi', has_headers: ['brlapi.h'],
1527                          required: get_option('brlapi'))
1528   if brlapi.found() and not cc.links('''
1529      #include <brlapi.h>
1530      #include <stddef.h>
1531      int main(void) { return brlapi__openConnection (NULL, NULL, NULL); }''', dependencies: brlapi)
1532     brlapi = not_found
1533     if get_option('brlapi').enabled()
1534       error('could not link brlapi')
1535     else
1536       warning('could not link brlapi, disabling')
1537     endif
1538   endif
1539 endif
1540 
1541 sdl = not_found
1542 if not get_option('sdl').auto() or have_system
1543   sdl = dependency('sdl2', required: get_option('sdl'))
1544   sdl_image = not_found
1545 endif
1546 if sdl.found()
1547   # Some versions of SDL have problems with -Wundef
1548   if not cc.compiles('''
1549                      #include <SDL.h>
1550                      #include <SDL_syswm.h>
1551                      int main(int argc, char *argv[]) { return 0; }
1552                      ''', dependencies: sdl, args: '-Werror=undef')
1553     sdl = declare_dependency(compile_args: '-Wno-undef',
1554                              dependencies: sdl,
1555                              version: sdl.version())
1556   endif
1557   sdl_image = dependency('SDL2_image', required: get_option('sdl_image'),
1558                          method: 'pkg-config')
1559 else
1560   if get_option('sdl_image').enabled()
1561     error('sdl-image required, but SDL was @0@'.format(
1562           get_option('sdl').disabled() ? 'disabled' : 'not found'))
1563   endif
1564   sdl_image = not_found
1565 endif
1566 
1567 rbd = not_found
1568 if not get_option('rbd').auto() or have_block
1569   librados = cc.find_library('rados', required: get_option('rbd'))
1570   librbd = cc.find_library('rbd', has_headers: ['rbd/librbd.h'],
1571                            required: get_option('rbd'))
1572   if librados.found() and librbd.found()
1573     if cc.links('''
1574       #include <stdio.h>
1575       #include <rbd/librbd.h>
1576       int main(void) {
1577         rados_t cluster;
1578         rados_create(&cluster, NULL);
1579         #if LIBRBD_VERSION_CODE < LIBRBD_VERSION(1, 12, 0)
1580         #error
1581         #endif
1582         return 0;
1583       }''', dependencies: [librbd, librados])
1584       rbd = declare_dependency(dependencies: [librbd, librados])
1585     elif get_option('rbd').enabled()
1586       error('librbd >= 1.12.0 required')
1587     else
1588       warning('librbd >= 1.12.0 not found, disabling')
1589     endif
1590   endif
1591 endif
1592 
1593 glusterfs = not_found
1594 glusterfs_ftruncate_has_stat = false
1595 glusterfs_iocb_has_stat = false
1596 if not get_option('glusterfs').auto() or have_block
1597   glusterfs = dependency('glusterfs-api', version: '>=3',
1598                          required: get_option('glusterfs'),
1599                          method: 'pkg-config')
1600   if glusterfs.found()
1601     glusterfs_ftruncate_has_stat = cc.links('''
1602       #include <glusterfs/api/glfs.h>
1603 
1604       int
1605       main(void)
1606       {
1607           /* new glfs_ftruncate() passes two additional args */
1608           return glfs_ftruncate(NULL, 0, NULL, NULL);
1609       }
1610     ''', dependencies: glusterfs)
1611     glusterfs_iocb_has_stat = cc.links('''
1612       #include <glusterfs/api/glfs.h>
1613 
1614       /* new glfs_io_cbk() passes two additional glfs_stat structs */
1615       static void
1616       glusterfs_iocb(glfs_fd_t *fd, ssize_t ret, struct glfs_stat *prestat, struct glfs_stat *poststat, void *data)
1617       {}
1618 
1619       int
1620       main(void)
1621       {
1622           glfs_io_cbk iocb = &glusterfs_iocb;
1623           iocb(NULL, 0 , NULL, NULL, NULL);
1624           return 0;
1625       }
1626     ''', dependencies: glusterfs)
1627   endif
1628 endif
1629 
1630 hv_balloon = false
1631 if get_option('hv_balloon').allowed() and have_system
1632   if cc.links('''
1633     #include <string.h>
1634     #include <gmodule.h>
1635     int main(void) {
1636         GTree *tree;
1637 
1638         tree = g_tree_new((GCompareFunc)strcmp);
1639         (void)g_tree_node_first(tree);
1640         g_tree_destroy(tree);
1641         return 0;
1642     }
1643   ''', dependencies: glib)
1644     hv_balloon = true
1645   else
1646     if get_option('hv_balloon').enabled()
1647       error('could not enable hv-balloon, update your glib')
1648     else
1649       warning('could not find glib support for hv-balloon, disabling')
1650     endif
1651   endif
1652 endif
1653 
1654 libssh = not_found
1655 if not get_option('libssh').auto() or have_block
1656   libssh = dependency('libssh', version: '>=0.8.7',
1657                     method: 'pkg-config',
1658                     required: get_option('libssh'))
1659 endif
1660 
1661 libbzip2 = not_found
1662 if not get_option('bzip2').auto() or have_block
1663   libbzip2 = cc.find_library('bz2', has_headers: ['bzlib.h'],
1664                              required: get_option('bzip2'))
1665   if libbzip2.found() and not cc.links('''
1666      #include <bzlib.h>
1667      int main(void) { BZ2_bzlibVersion(); return 0; }''', dependencies: libbzip2)
1668     libbzip2 = not_found
1669     if get_option('bzip2').enabled()
1670       error('could not link libbzip2')
1671     else
1672       warning('could not link libbzip2, disabling')
1673     endif
1674   endif
1675 endif
1676 
1677 liblzfse = not_found
1678 if not get_option('lzfse').auto() or have_block
1679   liblzfse = cc.find_library('lzfse', has_headers: ['lzfse.h'],
1680                              required: get_option('lzfse'))
1681 endif
1682 if liblzfse.found() and not cc.links('''
1683    #include <lzfse.h>
1684    int main(void) { lzfse_decode_scratch_size(); return 0; }''', dependencies: liblzfse)
1685   liblzfse = not_found
1686   if get_option('lzfse').enabled()
1687     error('could not link liblzfse')
1688   else
1689     warning('could not link liblzfse, disabling')
1690   endif
1691 endif
1692 
1693 oss = not_found
1694 if get_option('oss').allowed() and have_system
1695   if not cc.has_header('sys/soundcard.h')
1696     # not found
1697   elif host_os == 'netbsd'
1698     oss = cc.find_library('ossaudio', required: get_option('oss'))
1699   else
1700     oss = declare_dependency()
1701   endif
1702 
1703   if not oss.found()
1704     if get_option('oss').enabled()
1705       error('OSS not found')
1706     endif
1707   endif
1708 endif
1709 dsound = not_found
1710 if not get_option('dsound').auto() or (host_os == 'windows' and have_system)
1711   if cc.has_header('dsound.h')
1712     dsound = declare_dependency(link_args: ['-lole32', '-ldxguid'])
1713   endif
1714 
1715   if not dsound.found()
1716     if get_option('dsound').enabled()
1717       error('DirectSound not found')
1718     endif
1719   endif
1720 endif
1721 
1722 coreaudio = not_found
1723 if not get_option('coreaudio').auto() or (host_os == 'darwin' and have_system)
1724   coreaudio = dependency('appleframeworks', modules: 'CoreAudio',
1725                          required: get_option('coreaudio'))
1726 endif
1727 
1728 opengl = not_found
1729 if not get_option('opengl').auto() or have_system or have_vhost_user_gpu
1730   epoxy = dependency('epoxy', method: 'pkg-config',
1731                       required: get_option('opengl'))
1732   if cc.has_header('epoxy/egl.h', dependencies: epoxy)
1733     opengl = epoxy
1734   elif get_option('opengl').enabled()
1735     error('epoxy/egl.h not found')
1736   endif
1737 endif
1738 gbm = not_found
1739 if (have_system or have_tools) and (virgl.found() or opengl.found())
1740   gbm = dependency('gbm', method: 'pkg-config', required: false)
1741 endif
1742 have_vhost_user_gpu = have_vhost_user_gpu and virgl.found() and opengl.found() and gbm.found()
1743 
1744 libcbor = not_found
1745 if not get_option('libcbor').auto() or have_system
1746   libcbor = dependency('libcbor', version: '>=0.7.0',
1747                        required: get_option('libcbor'))
1748 endif
1749 
1750 gnutls = not_found
1751 gnutls_crypto = not_found
1752 if get_option('gnutls').enabled() or (get_option('gnutls').auto() and have_system)
1753   # For general TLS support our min gnutls matches
1754   # that implied by our platform support matrix
1755   #
1756   # For the crypto backends, we look for a newer
1757   # gnutls:
1758   #
1759   #   Version 3.6.8  is needed to get XTS
1760   #   Version 3.6.13 is needed to get PBKDF
1761   #   Version 3.6.14 is needed to get HW accelerated XTS
1762   #
1763   # If newer enough gnutls isn't available, we can
1764   # still use a different crypto backend to satisfy
1765   # the platform support requirements
1766   gnutls_crypto = dependency('gnutls', version: '>=3.6.14',
1767                              method: 'pkg-config',
1768                              required: false)
1769   if gnutls_crypto.found()
1770     gnutls = gnutls_crypto
1771   else
1772     # Our min version if all we need is TLS
1773     gnutls = dependency('gnutls', version: '>=3.5.18',
1774                         method: 'pkg-config',
1775                         required: get_option('gnutls'))
1776   endif
1777 endif
1778 
1779 # We prefer use of gnutls for crypto, unless the options
1780 # explicitly asked for nettle or gcrypt.
1781 #
1782 # If gnutls isn't available for crypto, then we'll prefer
1783 # gcrypt over nettle for performance reasons.
1784 gcrypt = not_found
1785 nettle = not_found
1786 hogweed = not_found
1787 crypto_sm4 = not_found
1788 crypto_sm3 = not_found
1789 xts = 'none'
1790 
1791 if get_option('nettle').enabled() and get_option('gcrypt').enabled()
1792   error('Only one of gcrypt & nettle can be enabled')
1793 endif
1794 
1795 # Explicit nettle/gcrypt request, so ignore gnutls for crypto
1796 if get_option('nettle').enabled() or get_option('gcrypt').enabled()
1797   gnutls_crypto = not_found
1798 endif
1799 
1800 if not gnutls_crypto.found()
1801   if (not get_option('gcrypt').auto() or have_system) and not get_option('nettle').enabled()
1802     gcrypt = dependency('libgcrypt', version: '>=1.8',
1803                         required: get_option('gcrypt'))
1804     # Debian has removed -lgpg-error from libgcrypt-config
1805     # as it "spreads unnecessary dependencies" which in
1806     # turn breaks static builds...
1807     if gcrypt.found() and get_option('prefer_static')
1808       gcrypt = declare_dependency(dependencies:
1809         [gcrypt,
1810          cc.find_library('gpg-error', required: true)],
1811         version: gcrypt.version())
1812     endif
1813     crypto_sm4 = gcrypt
1814     # SM4 ALG is available in libgcrypt >= 1.9
1815     if gcrypt.found() and not cc.links('''
1816       #include <gcrypt.h>
1817       int main(void) {
1818         gcry_cipher_hd_t handler;
1819         gcry_cipher_open(&handler, GCRY_CIPHER_SM4, GCRY_CIPHER_MODE_ECB, 0);
1820         return 0;
1821       }''', dependencies: gcrypt)
1822       crypto_sm4 = not_found
1823     endif
1824     crypto_sm3 = gcrypt
1825     # SM3 ALG is available in libgcrypt >= 1.9
1826     if gcrypt.found() and not cc.links('''
1827       #include <gcrypt.h>
1828       int main(void) {
1829         gcry_md_hd_t handler;
1830         gcry_md_open(&handler, GCRY_MD_SM3, 0);
1831         return 0;
1832       }''', dependencies: gcrypt)
1833       crypto_sm3 = not_found
1834     endif
1835   endif
1836   if (not get_option('nettle').auto() or have_system) and not gcrypt.found()
1837     nettle = dependency('nettle', version: '>=3.4',
1838                         method: 'pkg-config',
1839                         required: get_option('nettle'))
1840     if nettle.found() and not cc.has_header('nettle/xts.h', dependencies: nettle)
1841       xts = 'private'
1842     endif
1843     crypto_sm4 = nettle
1844     # SM4 ALG is available in nettle >= 3.9
1845     if nettle.found() and not cc.links('''
1846       #include <nettle/sm4.h>
1847       int main(void) {
1848         struct sm4_ctx ctx;
1849         unsigned char key[16] = {0};
1850         sm4_set_encrypt_key(&ctx, key);
1851         return 0;
1852       }''', dependencies: nettle)
1853       crypto_sm4 = not_found
1854     endif
1855     crypto_sm3 = nettle
1856     # SM3 ALG is available in nettle >= 3.8
1857     if nettle.found() and not cc.links('''
1858       #include <nettle/sm3.h>
1859       #include <nettle/hmac.h>
1860       int main(void) {
1861       struct sm3_ctx ctx;
1862       struct hmac_sm3_ctx hmac_ctx;
1863       unsigned char data[64] = {0};
1864       unsigned char output[32];
1865 
1866       // SM3 hash function test
1867       sm3_init(&ctx);
1868       sm3_update(&ctx, 64, data);
1869       sm3_digest(&ctx, 32, data);
1870 
1871       // HMAC-SM3 test
1872       hmac_sm3_set_key(&hmac_ctx, 32, data);
1873       hmac_sm3_update(&hmac_ctx, 64, data);
1874       hmac_sm3_digest(&hmac_ctx, 32, output);
1875 
1876       return 0;
1877       }''', dependencies: nettle)
1878       crypto_sm3 = not_found
1879     endif
1880   endif
1881 endif
1882 
1883 capstone = not_found
1884 if not get_option('capstone').auto() or have_system or have_user
1885   capstone = dependency('capstone', version: '>=3.0.5',
1886                         method: 'pkg-config',
1887                         required: get_option('capstone'))
1888 
1889   # Some versions of capstone have broken pkg-config file
1890   # that reports a wrong -I path, causing the #include to
1891   # fail later. If the system has such a broken version
1892   # do not use it.
1893   if capstone.found() and not cc.compiles('#include <capstone.h>',
1894                                           dependencies: [capstone])
1895     capstone = not_found
1896     if get_option('capstone').enabled()
1897       error('capstone requested, but it does not appear to work')
1898     endif
1899   endif
1900 endif
1901 
1902 gmp = dependency('gmp', required: false, method: 'pkg-config')
1903 if nettle.found() and gmp.found()
1904   hogweed = dependency('hogweed', version: '>=3.4',
1905                        method: 'pkg-config',
1906                        required: get_option('nettle'))
1907 endif
1908 
1909 
1910 gtk = not_found
1911 gtkx11 = not_found
1912 vte = not_found
1913 have_gtk_clipboard = get_option('gtk_clipboard').enabled()
1914 
1915 if get_option('gtk') \
1916              .disable_auto_if(not have_system) \
1917              .require(pixman.found(),
1918                       error_message: 'cannot enable GTK if pixman is not available') \
1919              .allowed()
1920   gtk = dependency('gtk+-3.0', version: '>=3.22.0',
1921                    method: 'pkg-config',
1922                    required: get_option('gtk'))
1923   if gtk.found()
1924     gtkx11 = dependency('gtk+-x11-3.0', version: '>=3.22.0',
1925                         method: 'pkg-config',
1926                         required: false)
1927     gtk = declare_dependency(dependencies: [gtk, gtkx11],
1928                              version: gtk.version())
1929 
1930     if not get_option('vte').auto() or have_system
1931       vte = dependency('vte-2.91',
1932                        method: 'pkg-config',
1933                        required: get_option('vte'))
1934     endif
1935   elif have_gtk_clipboard
1936     error('GTK clipboard requested, but GTK not found')
1937   endif
1938 endif
1939 
1940 x11 = not_found
1941 if gtkx11.found()
1942   x11 = dependency('x11', method: 'pkg-config', required: gtkx11.found())
1943 endif
1944 png = not_found
1945 if get_option('png').allowed() and have_system
1946    png = dependency('libpng', version: '>=1.6.34', required: get_option('png'),
1947                     method: 'pkg-config')
1948 endif
1949 vnc = not_found
1950 jpeg = not_found
1951 sasl = not_found
1952 if get_option('vnc') \
1953              .disable_auto_if(not have_system) \
1954              .require(pixman.found(),
1955                       error_message: 'cannot enable VNC if pixman is not available') \
1956              .allowed()
1957   vnc = declare_dependency() # dummy dependency
1958   jpeg = dependency('libjpeg', required: get_option('vnc_jpeg'),
1959                     method: 'pkg-config')
1960   sasl = cc.find_library('sasl2', has_headers: ['sasl/sasl.h'],
1961                          required: get_option('vnc_sasl'))
1962   if sasl.found()
1963     sasl = declare_dependency(dependencies: sasl,
1964                               compile_args: '-DSTRUCT_IOVEC_DEFINED')
1965   endif
1966 endif
1967 
1968 pam = not_found
1969 if not get_option('auth_pam').auto() or have_system
1970   pam = cc.find_library('pam', has_headers: ['security/pam_appl.h'],
1971                         required: get_option('auth_pam'))
1972 endif
1973 if pam.found() and not cc.links('''
1974    #include <stddef.h>
1975    #include <security/pam_appl.h>
1976    int main(void) {
1977      const char *service_name = "qemu";
1978      const char *user = "frank";
1979      const struct pam_conv pam_conv = { 0 };
1980      pam_handle_t *pamh = NULL;
1981      pam_start(service_name, user, &pam_conv, &pamh);
1982      return 0;
1983    }''', dependencies: pam)
1984   pam = not_found
1985   if get_option('auth_pam').enabled()
1986     error('could not link libpam')
1987   else
1988     warning('could not link libpam, disabling')
1989   endif
1990 endif
1991 
1992 snappy = not_found
1993 if not get_option('snappy').auto() or have_system
1994   snappy = cc.find_library('snappy', has_headers: ['snappy-c.h'],
1995                            required: get_option('snappy'))
1996 endif
1997 if snappy.found() and not cc.links('''
1998    #include <snappy-c.h>
1999    int main(void) { snappy_max_compressed_length(4096); return 0; }''', dependencies: snappy)
2000   snappy = not_found
2001   if get_option('snappy').enabled()
2002     error('could not link libsnappy')
2003   else
2004     warning('could not link libsnappy, disabling')
2005   endif
2006 endif
2007 
2008 lzo = not_found
2009 if not get_option('lzo').auto() or have_system
2010   lzo = cc.find_library('lzo2', has_headers: ['lzo/lzo1x.h'],
2011                         required: get_option('lzo'))
2012 endif
2013 if lzo.found() and not cc.links('''
2014    #include <lzo/lzo1x.h>
2015    int main(void) { lzo_version(); return 0; }''', dependencies: lzo)
2016   lzo = not_found
2017   if get_option('lzo').enabled()
2018     error('could not link liblzo2')
2019   else
2020     warning('could not link liblzo2, disabling')
2021   endif
2022 endif
2023 
2024 numa = not_found
2025 if not get_option('numa').auto() or have_system or have_tools
2026   numa = cc.find_library('numa', has_headers: ['numa.h'],
2027                               required: get_option('numa'))
2028 endif
2029 if numa.found() and not cc.links('''
2030    #include <numa.h>
2031    int main(void) { return numa_available(); }
2032    ''', dependencies: numa)
2033   numa = not_found
2034   if get_option('numa').enabled()
2035     error('could not link numa')
2036   else
2037     warning('could not link numa, disabling')
2038   endif
2039 endif
2040 
2041 fdt = not_found
2042 fdt_opt = get_option('fdt')
2043 if fdt_opt == 'enabled' and get_option('wrap_mode') == 'nodownload'
2044   fdt_opt = 'system'
2045 endif
2046 if fdt_opt in ['enabled', 'system'] or (fdt_opt == 'auto' and have_system)
2047   fdt = cc.find_library('fdt', required: fdt_opt == 'system')
2048   if fdt.found() and cc.links('''
2049      #include <libfdt.h>
2050      #include <libfdt_env.h>
2051      int main(void) { fdt_find_max_phandle(NULL, NULL); return 0; }''',
2052        dependencies: fdt)
2053     fdt_opt = 'system'
2054   elif fdt_opt != 'system'
2055     fdt_opt = get_option('wrap_mode') == 'nodownload' ? 'disabled' : 'internal'
2056     fdt = not_found
2057   else
2058     error('system libfdt is too old (1.5.1 or newer required)')
2059   endif
2060 endif
2061 if fdt_opt == 'internal'
2062   assert(not fdt.found())
2063   libfdt_proj = subproject('dtc', required: true,
2064                            default_options: ['tools=false',  'yaml=disabled',
2065                                              'python=disabled', 'default_library=static'])
2066   fdt = libfdt_proj.get_variable('libfdt_dep')
2067 endif
2068 
2069 rdma = not_found
2070 if not get_option('rdma').auto() or have_system
2071   rdma_libs = [cc.find_library('rdmacm', has_headers: ['rdma/rdma_cma.h'],
2072                                required: get_option('rdma')),
2073                cc.find_library('ibverbs', required: get_option('rdma'))]
2074   rdma = declare_dependency(dependencies: rdma_libs)
2075   foreach lib: rdma_libs
2076     if not lib.found()
2077       rdma = not_found
2078     endif
2079   endforeach
2080 endif
2081 
2082 cacard = not_found
2083 if not get_option('smartcard').auto() or have_system
2084   cacard = dependency('libcacard', required: get_option('smartcard'),
2085                       version: '>=2.5.1', method: 'pkg-config')
2086 endif
2087 u2f = not_found
2088 if not get_option('u2f').auto() or have_system
2089   u2f = dependency('u2f-emu', required: get_option('u2f'),
2090                    method: 'pkg-config')
2091 endif
2092 canokey = not_found
2093 if not get_option('canokey').auto() or have_system
2094   canokey = dependency('canokey-qemu', required: get_option('canokey'),
2095                    method: 'pkg-config')
2096 endif
2097 usbredir = not_found
2098 if not get_option('usb_redir').auto() or have_system
2099   usbredir = dependency('libusbredirparser-0.5', required: get_option('usb_redir'),
2100                         version: '>=0.6', method: 'pkg-config')
2101 endif
2102 libusb = not_found
2103 if not get_option('libusb').auto() or have_system
2104   libusb = dependency('libusb-1.0', required: get_option('libusb'),
2105                       version: '>=1.0.13', method: 'pkg-config')
2106 endif
2107 
2108 libpmem = not_found
2109 if not get_option('libpmem').auto() or have_system
2110   libpmem = dependency('libpmem', required: get_option('libpmem'),
2111                        method: 'pkg-config')
2112 endif
2113 libdaxctl = not_found
2114 if not get_option('libdaxctl').auto() or have_system
2115   libdaxctl = dependency('libdaxctl', required: get_option('libdaxctl'),
2116                          version: '>=57', method: 'pkg-config')
2117 endif
2118 tasn1 = not_found
2119 if gnutls.found()
2120   tasn1 = dependency('libtasn1',
2121                      required: false,
2122                      method: 'pkg-config')
2123 endif
2124 keyutils = not_found
2125 if not get_option('libkeyutils').auto() or have_block
2126   keyutils = dependency('libkeyutils', required: get_option('libkeyutils'),
2127                         method: 'pkg-config')
2128 endif
2129 
2130 has_gettid = cc.has_function('gettid')
2131 
2132 # libselinux
2133 selinux = dependency('libselinux',
2134                      required: get_option('selinux'),
2135                      method: 'pkg-config')
2136 
2137 # Malloc tests
2138 
2139 malloc = []
2140 if get_option('malloc') == 'system'
2141   has_malloc_trim = \
2142     get_option('malloc_trim').allowed() and \
2143     cc.has_function('malloc_trim', prefix: '#include <malloc.h>')
2144 else
2145   has_malloc_trim = false
2146   malloc = cc.find_library(get_option('malloc'), required: true)
2147 endif
2148 if not has_malloc_trim and get_option('malloc_trim').enabled()
2149   if get_option('malloc') == 'system'
2150     error('malloc_trim not available on this platform.')
2151   else
2152     error('malloc_trim not available with non-libc memory allocator')
2153   endif
2154 endif
2155 
2156 gnu_source_prefix = '''
2157   #ifndef _GNU_SOURCE
2158   #define _GNU_SOURCE
2159   #endif
2160 '''
2161 
2162 # Check whether the glibc provides STATX_BASIC_STATS
2163 
2164 has_statx = cc.has_header_symbol('sys/stat.h', 'STATX_BASIC_STATS', prefix: gnu_source_prefix)
2165 
2166 # Check whether statx() provides mount ID information
2167 
2168 has_statx_mnt_id = cc.has_header_symbol('sys/stat.h', 'STATX_MNT_ID', prefix: gnu_source_prefix)
2169 
2170 have_vhost_user_blk_server = get_option('vhost_user_blk_server') \
2171   .require(host_os == 'linux',
2172            error_message: 'vhost_user_blk_server requires linux') \
2173   .require(have_vhost_user,
2174            error_message: 'vhost_user_blk_server requires vhost-user support') \
2175   .disable_auto_if(not have_tools and not have_system) \
2176   .allowed()
2177 
2178 if get_option('fuse').disabled() and get_option('fuse_lseek').enabled()
2179   error('Cannot enable fuse-lseek while fuse is disabled')
2180 endif
2181 
2182 fuse = dependency('fuse3', required: get_option('fuse'),
2183                   version: '>=3.1', method: 'pkg-config')
2184 
2185 fuse_lseek = not_found
2186 if get_option('fuse_lseek').allowed()
2187   if fuse.version().version_compare('>=3.8')
2188     # Dummy dependency
2189     fuse_lseek = declare_dependency()
2190   elif get_option('fuse_lseek').enabled()
2191     if fuse.found()
2192       error('fuse-lseek requires libfuse >=3.8, found ' + fuse.version())
2193     else
2194       error('fuse-lseek requires libfuse, which was not found')
2195     endif
2196   endif
2197 endif
2198 
2199 have_libvduse = (host_os == 'linux')
2200 if get_option('libvduse').enabled()
2201     if host_os != 'linux'
2202         error('libvduse requires linux')
2203     endif
2204 elif get_option('libvduse').disabled()
2205     have_libvduse = false
2206 endif
2207 
2208 have_vduse_blk_export = (have_libvduse and host_os == 'linux')
2209 if get_option('vduse_blk_export').enabled()
2210     if host_os != 'linux'
2211         error('vduse_blk_export requires linux')
2212     elif not have_libvduse
2213         error('vduse_blk_export requires libvduse support')
2214     endif
2215 elif get_option('vduse_blk_export').disabled()
2216     have_vduse_blk_export = false
2217 endif
2218 
2219 # libbpf
2220 bpf_version = '1.1.0'
2221 libbpf = dependency('libbpf', version: '>=' + bpf_version, required: get_option('bpf'), method: 'pkg-config')
2222 if libbpf.found() and not cc.links('''
2223    #include <bpf/libbpf.h>
2224    #include <linux/bpf.h>
2225    int main(void)
2226    {
2227      // check flag availability
2228      int flag = BPF_F_MMAPABLE;
2229      bpf_object__destroy_skeleton(NULL);
2230      return 0;
2231    }''', dependencies: libbpf)
2232   libbpf = not_found
2233   if get_option('bpf').enabled()
2234     error('libbpf skeleton/mmaping test failed')
2235   else
2236     warning('libbpf skeleton/mmaping test failed, disabling')
2237   endif
2238 endif
2239 
2240 # libxdp
2241 libxdp = not_found
2242 if not get_option('af_xdp').auto() or have_system
2243     if libbpf.found()
2244         libxdp = dependency('libxdp', required: get_option('af_xdp'),
2245                             version: '>=1.4.0', method: 'pkg-config')
2246     else
2247         if get_option('af_xdp').enabled()
2248             error('libxdp requested, but libbpf is not available')
2249         endif
2250     endif
2251 endif
2252 
2253 # libdw
2254 libdw = not_found
2255 if not get_option('libdw').auto() or \
2256         (not get_option('prefer_static') and (have_system or have_user))
2257     libdw = dependency('libdw',
2258                        method: 'pkg-config',
2259                        required: get_option('libdw'))
2260 endif
2261 
2262 #################
2263 # config-host.h #
2264 #################
2265 
2266 config_host_data = configuration_data()
2267 
2268 config_host_data.set('CONFIG_HAVE_RUST', have_rust)
2269 audio_drivers_selected = []
2270 if have_system
2271   audio_drivers_available = {
2272     'alsa': alsa.found(),
2273     'coreaudio': coreaudio.found(),
2274     'dsound': dsound.found(),
2275     'jack': jack.found(),
2276     'oss': oss.found(),
2277     'pa': pulse.found(),
2278     'pipewire': pipewire.found(),
2279     'sdl': sdl.found(),
2280     'sndio': sndio.found(),
2281   }
2282   foreach k, v: audio_drivers_available
2283     config_host_data.set('CONFIG_AUDIO_' + k.to_upper(), v)
2284   endforeach
2285 
2286   # Default to native drivers first, OSS second, SDL third
2287   audio_drivers_priority = \
2288     [ 'pa', 'coreaudio', 'dsound', 'sndio', 'oss' ] + \
2289     (host_os == 'linux' ? [] : [ 'sdl' ])
2290   audio_drivers_default = []
2291   foreach k: audio_drivers_priority
2292     if audio_drivers_available[k]
2293       audio_drivers_default += k
2294     endif
2295   endforeach
2296 
2297   foreach k: get_option('audio_drv_list')
2298     if k == 'default'
2299       audio_drivers_selected += audio_drivers_default
2300     elif not audio_drivers_available[k]
2301       error('Audio driver "@0@" not available.'.format(k))
2302     else
2303       audio_drivers_selected += k
2304     endif
2305   endforeach
2306 endif
2307 config_host_data.set('CONFIG_AUDIO_DRIVERS',
2308                      '"' + '", "'.join(audio_drivers_selected) + '", ')
2309 
2310 have_host_block_device = (host_os != 'darwin' or
2311     cc.has_header('IOKit/storage/IOMedia.h'))
2312 
2313 dbus_display = get_option('dbus_display') \
2314   .require(gio.version().version_compare('>=2.64'),
2315            error_message: '-display dbus requires glib>=2.64') \
2316   .require(gdbus_codegen.found(),
2317            error_message: gdbus_codegen_error.format('-display dbus')) \
2318   .allowed()
2319 
2320 have_virtfs = get_option('virtfs') \
2321     .require(host_os == 'linux' or host_os == 'darwin',
2322              error_message: 'virtio-9p (virtfs) requires Linux or macOS') \
2323     .require(host_os == 'linux' or cc.has_function('pthread_fchdir_np'),
2324              error_message: 'virtio-9p (virtfs) on macOS requires the presence of pthread_fchdir_np') \
2325     .require(host_os == 'darwin' or libattr.found(),
2326              error_message: 'virtio-9p (virtfs) on Linux requires libattr-devel') \
2327     .disable_auto_if(not have_tools and not have_system) \
2328     .allowed()
2329 
2330 qga_fsfreeze = false
2331 qga_fstrim = false
2332 if host_os == 'linux'
2333     if cc.has_header_symbol('linux/fs.h', 'FIFREEZE')
2334         qga_fsfreeze = true
2335     endif
2336     if cc.has_header_symbol('linux/fs.h', 'FITRIM')
2337         qga_fstrim = true
2338     endif
2339 elif host_os == 'freebsd' and cc.has_header_symbol('ufs/ffs/fs.h', 'UFSSUSPEND')
2340     qga_fsfreeze = true
2341 endif
2342 
2343 if get_option('block_drv_ro_whitelist') == ''
2344   config_host_data.set('CONFIG_BDRV_RO_WHITELIST', '')
2345 else
2346   config_host_data.set('CONFIG_BDRV_RO_WHITELIST',
2347         '"' + get_option('block_drv_ro_whitelist').replace(',', '", "') + '", ')
2348 endif
2349 if get_option('block_drv_rw_whitelist') == ''
2350   config_host_data.set('CONFIG_BDRV_RW_WHITELIST', '')
2351 else
2352   config_host_data.set('CONFIG_BDRV_RW_WHITELIST',
2353         '"' + get_option('block_drv_rw_whitelist').replace(',', '", "') + '", ')
2354 endif
2355 
2356 foreach k : get_option('trace_backends')
2357   config_host_data.set('CONFIG_TRACE_' + k.to_upper(), true)
2358 endforeach
2359 config_host_data.set_quoted('CONFIG_TRACE_FILE', get_option('trace_file'))
2360 config_host_data.set_quoted('CONFIG_TLS_PRIORITY', get_option('tls_priority'))
2361 if iasl.found()
2362   config_host_data.set_quoted('CONFIG_IASL', iasl.full_path())
2363 endif
2364 config_host_data.set_quoted('CONFIG_BINDIR', get_option('prefix') / get_option('bindir'))
2365 config_host_data.set_quoted('CONFIG_PREFIX', get_option('prefix'))
2366 config_host_data.set_quoted('CONFIG_QEMU_CONFDIR', get_option('prefix') / qemu_confdir)
2367 config_host_data.set_quoted('CONFIG_QEMU_DATADIR', get_option('prefix') / qemu_datadir)
2368 config_host_data.set_quoted('CONFIG_QEMU_DESKTOPDIR', get_option('prefix') / qemu_desktopdir)
2369 
2370 qemu_firmwarepath = ''
2371 foreach k : get_option('qemu_firmwarepath')
2372   qemu_firmwarepath += '"' + get_option('prefix') / k + '", '
2373 endforeach
2374 config_host_data.set('CONFIG_QEMU_FIRMWAREPATH', qemu_firmwarepath)
2375 
2376 config_host_data.set_quoted('CONFIG_QEMU_HELPERDIR', get_option('prefix') / get_option('libexecdir'))
2377 config_host_data.set_quoted('CONFIG_QEMU_ICONDIR', get_option('prefix') / qemu_icondir)
2378 config_host_data.set_quoted('CONFIG_QEMU_LOCALEDIR', get_option('prefix') / get_option('localedir'))
2379 config_host_data.set_quoted('CONFIG_QEMU_LOCALSTATEDIR', get_option('prefix') / get_option('localstatedir'))
2380 config_host_data.set_quoted('CONFIG_QEMU_MODDIR', get_option('prefix') / qemu_moddir)
2381 config_host_data.set_quoted('CONFIG_SYSCONFDIR', get_option('prefix') / get_option('sysconfdir'))
2382 
2383 if enable_modules
2384   config_host_data.set('CONFIG_STAMP', run_command(
2385       meson.current_source_dir() / 'scripts/qemu-stamp.py',
2386       meson.project_version(), get_option('pkgversion'), '--',
2387       meson.current_source_dir() / 'configure',
2388       capture: true, check: true).stdout().strip())
2389 endif
2390 
2391 have_slirp_smbd = get_option('slirp_smbd') \
2392   .require(host_os != 'windows', error_message: 'Host smbd not supported on this platform.') \
2393   .allowed()
2394 if have_slirp_smbd
2395   smbd_path = get_option('smbd')
2396   if smbd_path == ''
2397     smbd_path = (host_os == 'sunos' ? '/usr/sfw/sbin/smbd' : '/usr/sbin/smbd')
2398   endif
2399   config_host_data.set_quoted('CONFIG_SMBD_COMMAND', smbd_path)
2400 endif
2401 
2402 config_host_data.set('HOST_' + host_arch.to_upper(), 1)
2403 
2404 kvm_targets_c = '""'
2405 if get_option('kvm').allowed() and host_os == 'linux'
2406   kvm_targets_c = '"' + '" ,"'.join(kvm_targets) + '"'
2407 endif
2408 config_host_data.set('CONFIG_KVM_TARGETS', kvm_targets_c)
2409 
2410 if get_option('module_upgrades') and not enable_modules
2411   error('Cannot enable module-upgrades as modules are not enabled')
2412 endif
2413 config_host_data.set('CONFIG_MODULE_UPGRADES', get_option('module_upgrades'))
2414 
2415 config_host_data.set('CONFIG_ATTR', libattr.found())
2416 config_host_data.set('CONFIG_BDRV_WHITELIST_TOOLS', get_option('block_drv_whitelist_in_tools'))
2417 config_host_data.set('CONFIG_BRLAPI', brlapi.found())
2418 config_host_data.set('CONFIG_BSD', host_os in bsd_oses)
2419 config_host_data.set('CONFIG_FREEBSD', host_os == 'freebsd')
2420 config_host_data.set('CONFIG_CAPSTONE', capstone.found())
2421 config_host_data.set('CONFIG_COCOA', cocoa.found())
2422 config_host_data.set('CONFIG_DARWIN', host_os == 'darwin')
2423 config_host_data.set('CONFIG_FDT', fdt.found())
2424 config_host_data.set('CONFIG_FUZZ', get_option('fuzzing'))
2425 config_host_data.set('CONFIG_GCOV', get_option('b_coverage'))
2426 config_host_data.set('CONFIG_LIBUDEV', libudev.found())
2427 config_host_data.set('CONFIG_LINUX', host_os == 'linux')
2428 config_host_data.set('CONFIG_POSIX', host_os != 'windows')
2429 config_host_data.set('CONFIG_WIN32', host_os == 'windows')
2430 config_host_data.set('CONFIG_LZO', lzo.found())
2431 config_host_data.set('CONFIG_MPATH', mpathpersist.found())
2432 config_host_data.set('CONFIG_BLKIO', blkio.found())
2433 if blkio.found()
2434   config_host_data.set('CONFIG_BLKIO_VHOST_VDPA_FD',
2435                        blkio.version().version_compare('>=1.3.0'))
2436   config_host_data.set('CONFIG_BLKIO_WRITE_ZEROS_FUA',
2437                        blkio.version().version_compare('>=1.4.0'))
2438 endif
2439 config_host_data.set('CONFIG_CURL', curl.found())
2440 config_host_data.set('CONFIG_CURSES', curses.found())
2441 config_host_data.set('CONFIG_GBM', gbm.found())
2442 config_host_data.set('CONFIG_GIO', gio.found())
2443 config_host_data.set('CONFIG_GLUSTERFS', glusterfs.found())
2444 if glusterfs.found()
2445   config_host_data.set('CONFIG_GLUSTERFS_XLATOR_OPT', glusterfs.version().version_compare('>=4'))
2446   config_host_data.set('CONFIG_GLUSTERFS_DISCARD', glusterfs.version().version_compare('>=5'))
2447   config_host_data.set('CONFIG_GLUSTERFS_FALLOCATE', glusterfs.version().version_compare('>=6'))
2448   config_host_data.set('CONFIG_GLUSTERFS_ZEROFILL', glusterfs.version().version_compare('>=6'))
2449   config_host_data.set('CONFIG_GLUSTERFS_FTRUNCATE_HAS_STAT', glusterfs_ftruncate_has_stat)
2450   config_host_data.set('CONFIG_GLUSTERFS_IOCB_HAS_STAT', glusterfs_iocb_has_stat)
2451 endif
2452 config_host_data.set('CONFIG_GTK', gtk.found())
2453 config_host_data.set('CONFIG_VTE', vte.found())
2454 config_host_data.set('CONFIG_GTK_CLIPBOARD', have_gtk_clipboard)
2455 config_host_data.set('CONFIG_HEXAGON_IDEF_PARSER', get_option('hexagon_idef_parser'))
2456 config_host_data.set('CONFIG_LIBATTR', have_old_libattr)
2457 config_host_data.set('CONFIG_LIBCAP_NG', libcap_ng.found())
2458 config_host_data.set('CONFIG_EBPF', libbpf.found())
2459 config_host_data.set('CONFIG_AF_XDP', libxdp.found())
2460 config_host_data.set('CONFIG_LIBDAXCTL', libdaxctl.found())
2461 config_host_data.set('CONFIG_LIBISCSI', libiscsi.found())
2462 config_host_data.set('CONFIG_LIBNFS', libnfs.found())
2463 config_host_data.set('CONFIG_LIBSSH', libssh.found())
2464 config_host_data.set('CONFIG_LINUX_AIO', libaio.found())
2465 config_host_data.set('CONFIG_LINUX_IO_URING', linux_io_uring.found())
2466 config_host_data.set('CONFIG_LIBPMEM', libpmem.found())
2467 config_host_data.set('CONFIG_MODULES', enable_modules)
2468 config_host_data.set('CONFIG_NUMA', numa.found())
2469 if numa.found()
2470   config_host_data.set('HAVE_NUMA_HAS_PREFERRED_MANY',
2471                        cc.has_function('numa_has_preferred_many',
2472                                        dependencies: numa))
2473 endif
2474 config_host_data.set('CONFIG_OPENGL', opengl.found())
2475 config_host_data.set('CONFIG_PLUGIN', get_option('plugins'))
2476 config_host_data.set('CONFIG_RBD', rbd.found())
2477 config_host_data.set('CONFIG_RDMA', rdma.found())
2478 config_host_data.set('CONFIG_RELOCATABLE', get_option('relocatable'))
2479 config_host_data.set('CONFIG_SAFESTACK', get_option('safe_stack'))
2480 config_host_data.set('CONFIG_SDL', sdl.found())
2481 config_host_data.set('CONFIG_SDL_IMAGE', sdl_image.found())
2482 config_host_data.set('CONFIG_SECCOMP', seccomp.found())
2483 if seccomp.found()
2484   config_host_data.set('CONFIG_SECCOMP_SYSRAWRC', seccomp_has_sysrawrc)
2485 endif
2486 config_host_data.set('CONFIG_PIXMAN', pixman.found())
2487 config_host_data.set('CONFIG_SLIRP', slirp.found())
2488 config_host_data.set('CONFIG_SNAPPY', snappy.found())
2489 config_host_data.set('CONFIG_SOLARIS', host_os == 'sunos')
2490 if get_option('tcg').allowed()
2491   config_host_data.set('CONFIG_TCG', 1)
2492   config_host_data.set('CONFIG_TCG_INTERPRETER', tcg_arch == 'tci')
2493 endif
2494 config_host_data.set('CONFIG_TPM', have_tpm)
2495 config_host_data.set('CONFIG_TSAN', get_option('tsan'))
2496 config_host_data.set('CONFIG_USB_LIBUSB', libusb.found())
2497 config_host_data.set('CONFIG_VDE', vde.found())
2498 config_host_data.set('CONFIG_VHOST', have_vhost)
2499 config_host_data.set('CONFIG_VHOST_NET', have_vhost_net)
2500 config_host_data.set('CONFIG_VHOST_NET_USER', have_vhost_net_user)
2501 config_host_data.set('CONFIG_VHOST_NET_VDPA', have_vhost_net_vdpa)
2502 config_host_data.set('CONFIG_VHOST_KERNEL', have_vhost_kernel)
2503 config_host_data.set('CONFIG_VHOST_USER', have_vhost_user)
2504 config_host_data.set('CONFIG_VHOST_CRYPTO', have_vhost_user_crypto)
2505 config_host_data.set('CONFIG_VHOST_VDPA', have_vhost_vdpa)
2506 config_host_data.set('CONFIG_VMNET', vmnet.found())
2507 config_host_data.set('CONFIG_VHOST_USER_BLK_SERVER', have_vhost_user_blk_server)
2508 config_host_data.set('CONFIG_VDUSE_BLK_EXPORT', have_vduse_blk_export)
2509 config_host_data.set('CONFIG_PNG', png.found())
2510 config_host_data.set('CONFIG_VNC', vnc.found())
2511 config_host_data.set('CONFIG_VNC_JPEG', jpeg.found())
2512 config_host_data.set('CONFIG_VNC_SASL', sasl.found())
2513 if virgl.found()
2514   config_host_data.set('VIRGL_VERSION_MAJOR', virgl.version().split('.')[0])
2515 endif
2516 config_host_data.set('CONFIG_VIRTFS', have_virtfs)
2517 config_host_data.set('CONFIG_VTE', vte.found())
2518 config_host_data.set('CONFIG_XKBCOMMON', xkbcommon.found())
2519 config_host_data.set('CONFIG_KEYUTILS', keyutils.found())
2520 config_host_data.set('CONFIG_GETTID', has_gettid)
2521 config_host_data.set('CONFIG_GNUTLS', gnutls.found())
2522 config_host_data.set('CONFIG_GNUTLS_CRYPTO', gnutls_crypto.found())
2523 config_host_data.set('CONFIG_TASN1', tasn1.found())
2524 config_host_data.set('CONFIG_GCRYPT', gcrypt.found())
2525 config_host_data.set('CONFIG_NETTLE', nettle.found())
2526 config_host_data.set('CONFIG_CRYPTO_SM4', crypto_sm4.found())
2527 config_host_data.set('CONFIG_CRYPTO_SM3', crypto_sm3.found())
2528 config_host_data.set('CONFIG_HOGWEED', hogweed.found())
2529 config_host_data.set('CONFIG_QEMU_PRIVATE_XTS', xts == 'private')
2530 config_host_data.set('CONFIG_MALLOC_TRIM', has_malloc_trim)
2531 config_host_data.set('CONFIG_STATX', has_statx)
2532 config_host_data.set('CONFIG_STATX_MNT_ID', has_statx_mnt_id)
2533 config_host_data.set('CONFIG_ZSTD', zstd.found())
2534 config_host_data.set('CONFIG_QPL', qpl.found())
2535 config_host_data.set('CONFIG_UADK', uadk.found())
2536 config_host_data.set('CONFIG_QATZIP', qatzip.found())
2537 config_host_data.set('CONFIG_FUSE', fuse.found())
2538 config_host_data.set('CONFIG_FUSE_LSEEK', fuse_lseek.found())
2539 config_host_data.set('CONFIG_SPICE_PROTOCOL', spice_protocol.found())
2540 if spice_protocol.found()
2541 config_host_data.set('CONFIG_SPICE_PROTOCOL_MAJOR', spice_protocol.version().split('.')[0])
2542 config_host_data.set('CONFIG_SPICE_PROTOCOL_MINOR', spice_protocol.version().split('.')[1])
2543 config_host_data.set('CONFIG_SPICE_PROTOCOL_MICRO', spice_protocol.version().split('.')[2])
2544 endif
2545 config_host_data.set('CONFIG_SPICE', spice.found())
2546 config_host_data.set('CONFIG_X11', x11.found())
2547 config_host_data.set('CONFIG_DBUS_DISPLAY', dbus_display)
2548 config_host_data.set('CONFIG_CFI', get_option('cfi'))
2549 config_host_data.set('CONFIG_SELINUX', selinux.found())
2550 config_host_data.set('CONFIG_XEN_BACKEND', xen.found())
2551 config_host_data.set('CONFIG_LIBDW', libdw.found())
2552 if xen.found()
2553   # protect from xen.version() having less than three components
2554   xen_version = xen.version().split('.') + ['0', '0']
2555   xen_ctrl_version = xen_version[0] + \
2556     ('0' + xen_version[1]).substring(-2) + \
2557     ('0' + xen_version[2]).substring(-2)
2558   config_host_data.set('CONFIG_XEN_CTRL_INTERFACE_VERSION', xen_ctrl_version)
2559 endif
2560 config_host_data.set('QEMU_VERSION', '"@0@"'.format(meson.project_version()))
2561 config_host_data.set('QEMU_VERSION_MAJOR', meson.project_version().split('.')[0])
2562 config_host_data.set('QEMU_VERSION_MINOR', meson.project_version().split('.')[1])
2563 config_host_data.set('QEMU_VERSION_MICRO', meson.project_version().split('.')[2])
2564 
2565 config_host_data.set_quoted('CONFIG_HOST_DSOSUF', host_dsosuf)
2566 config_host_data.set('HAVE_HOST_BLOCK_DEVICE', have_host_block_device)
2567 
2568 have_coroutine_pool = get_option('coroutine_pool')
2569 if get_option('debug_stack_usage') and have_coroutine_pool
2570   message('Disabling coroutine pool to measure stack usage')
2571   have_coroutine_pool = false
2572 endif
2573 config_host_data.set('CONFIG_COROUTINE_POOL', have_coroutine_pool)
2574 config_host_data.set('CONFIG_DEBUG_GRAPH_LOCK', get_option('debug_graph_lock'))
2575 config_host_data.set('CONFIG_DEBUG_MUTEX', get_option('debug_mutex'))
2576 config_host_data.set('CONFIG_DEBUG_STACK_USAGE', get_option('debug_stack_usage'))
2577 config_host_data.set('CONFIG_DEBUG_TCG', get_option('debug_tcg'))
2578 config_host_data.set('CONFIG_DEBUG_REMAP', get_option('debug_remap'))
2579 config_host_data.set('CONFIG_QOM_CAST_DEBUG', get_option('qom_cast_debug'))
2580 config_host_data.set('CONFIG_REPLICATION', get_option('replication').allowed())
2581 config_host_data.set('CONFIG_FSFREEZE', qga_fsfreeze)
2582 config_host_data.set('CONFIG_FSTRIM', qga_fstrim)
2583 
2584 # has_header
2585 config_host_data.set('CONFIG_EPOLL', cc.has_header('sys/epoll.h'))
2586 config_host_data.set('CONFIG_LINUX_MAGIC_H', cc.has_header('linux/magic.h'))
2587 config_host_data.set('CONFIG_VALGRIND_H', cc.has_header('valgrind/valgrind.h'))
2588 config_host_data.set('HAVE_BTRFS_H', cc.has_header('linux/btrfs.h'))
2589 config_host_data.set('HAVE_DRM_H', cc.has_header('libdrm/drm.h'))
2590 config_host_data.set('HAVE_OPENAT2_H', cc.has_header('linux/openat2.h'))
2591 config_host_data.set('HAVE_PTY_H', cc.has_header('pty.h'))
2592 config_host_data.set('HAVE_SYS_DISK_H', cc.has_header('sys/disk.h'))
2593 config_host_data.set('HAVE_SYS_IOCCOM_H', cc.has_header('sys/ioccom.h'))
2594 config_host_data.set('HAVE_SYS_KCOV_H', cc.has_header('sys/kcov.h'))
2595 if host_os == 'windows'
2596   config_host_data.set('HAVE_AFUNIX_H', cc.has_header('afunix.h'))
2597 endif
2598 
2599 # has_function
2600 config_host_data.set('CONFIG_CLOSE_RANGE', cc.has_function('close_range'))
2601 config_host_data.set('CONFIG_ACCEPT4', cc.has_function('accept4'))
2602 config_host_data.set('CONFIG_CLOCK_ADJTIME', cc.has_function('clock_adjtime'))
2603 config_host_data.set('CONFIG_DUP3', cc.has_function('dup3'))
2604 config_host_data.set('CONFIG_FALLOCATE', cc.has_function('fallocate'))
2605 config_host_data.set('CONFIG_POSIX_FALLOCATE', cc.has_function('posix_fallocate'))
2606 config_host_data.set('CONFIG_GETCPU', cc.has_function('getcpu', prefix: gnu_source_prefix))
2607 config_host_data.set('CONFIG_SCHED_GETCPU', cc.has_function('sched_getcpu', prefix: '#include <sched.h>'))
2608 # Note that we need to specify prefix: here to avoid incorrectly
2609 # thinking that Windows has posix_memalign()
2610 config_host_data.set('CONFIG_POSIX_MEMALIGN', cc.has_function('posix_memalign', prefix: '#include <stdlib.h>'))
2611 config_host_data.set('CONFIG_ALIGNED_MALLOC', cc.has_function('_aligned_malloc'))
2612 config_host_data.set('CONFIG_VALLOC', cc.has_function('valloc'))
2613 config_host_data.set('CONFIG_MEMALIGN', cc.has_function('memalign'))
2614 config_host_data.set('CONFIG_PPOLL', cc.has_function('ppoll'))
2615 config_host_data.set('CONFIG_PREADV', cc.has_function('preadv', prefix: '#include <sys/uio.h>'))
2616 config_host_data.set('CONFIG_PTHREAD_FCHDIR_NP', cc.has_function('pthread_fchdir_np'))
2617 config_host_data.set('CONFIG_SENDFILE', cc.has_function('sendfile'))
2618 config_host_data.set('CONFIG_SETNS', cc.has_function('setns') and cc.has_function('unshare'))
2619 config_host_data.set('CONFIG_SYNCFS', cc.has_function('syncfs'))
2620 config_host_data.set('CONFIG_SYNC_FILE_RANGE', cc.has_function('sync_file_range'))
2621 config_host_data.set('CONFIG_TIMERFD', cc.has_function('timerfd_create'))
2622 config_host_data.set('HAVE_COPY_FILE_RANGE', cc.has_function('copy_file_range'))
2623 config_host_data.set('HAVE_GETIFADDRS', cc.has_function('getifaddrs'))
2624 config_host_data.set('HAVE_GLIB_WITH_SLICE_ALLOCATOR', glib_has_gslice)
2625 config_host_data.set('HAVE_GLIB_WITH_ALIGNED_ALLOC', glib_has_aligned_alloc)
2626 config_host_data.set('HAVE_OPENPTY', cc.has_function('openpty', dependencies: util))
2627 config_host_data.set('HAVE_STRCHRNUL', cc.has_function('strchrnul'))
2628 config_host_data.set('HAVE_SYSTEM_FUNCTION', cc.has_function('system', prefix: '#include <stdlib.h>'))
2629 if rbd.found()
2630   config_host_data.set('HAVE_RBD_NAMESPACE_EXISTS',
2631                        cc.has_function('rbd_namespace_exists',
2632                                        dependencies: rbd,
2633                                        prefix: '#include <rbd/librbd.h>'))
2634 endif
2635 if rdma.found()
2636   config_host_data.set('HAVE_IBV_ADVISE_MR',
2637                        cc.has_function('ibv_advise_mr',
2638                                        dependencies: rdma,
2639                                        prefix: '#include <infiniband/verbs.h>'))
2640 endif
2641 
2642 have_asan_fiber = false
2643 if get_option('asan') and \
2644    not cc.has_function('__sanitizer_start_switch_fiber',
2645                          args: '-fsanitize=address',
2646                          prefix: '#include <sanitizer/asan_interface.h>')
2647   warning('Missing ASAN due to missing fiber annotation interface')
2648   warning('Without code annotation, the report may be inferior.')
2649 else
2650   have_asan_fiber = true
2651 endif
2652 config_host_data.set('CONFIG_ASAN_IFACE_FIBER', have_asan_fiber)
2653 
2654 have_inotify_init = cc.has_header_symbol('sys/inotify.h', 'inotify_init')
2655 have_inotify_init1 = cc.has_header_symbol('sys/inotify.h', 'inotify_init1')
2656 inotify = not_found
2657 if (have_inotify_init or have_inotify_init1) and host_os == 'freebsd'
2658   # libinotify-kqueue
2659   inotify = cc.find_library('inotify')
2660   if have_inotify_init
2661     have_inotify_init = inotify.found()
2662   endif
2663   if have_inotify_init1
2664     have_inotify_init1 = inotify.found()
2665   endif
2666 endif
2667 config_host_data.set('CONFIG_INOTIFY', have_inotify_init)
2668 config_host_data.set('CONFIG_INOTIFY1', have_inotify_init1)
2669 
2670 # has_header_symbol
2671 config_host_data.set('CONFIG_BLKZONED',
2672                      cc.has_header_symbol('linux/blkzoned.h', 'BLKOPENZONE'))
2673 config_host_data.set('CONFIG_EPOLL_CREATE1',
2674                      cc.has_header_symbol('sys/epoll.h', 'epoll_create1'))
2675 config_host_data.set('CONFIG_FALLOCATE_PUNCH_HOLE',
2676                      cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_PUNCH_HOLE') and
2677                      cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_KEEP_SIZE'))
2678 config_host_data.set('CONFIG_FALLOCATE_ZERO_RANGE',
2679                      cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_ZERO_RANGE'))
2680 config_host_data.set('CONFIG_FIEMAP',
2681                      cc.has_header('linux/fiemap.h') and
2682                      cc.has_header_symbol('linux/fs.h', 'FS_IOC_FIEMAP'))
2683 config_host_data.set('CONFIG_GETRANDOM',
2684                      cc.has_function('getrandom') and
2685                      cc.has_header_symbol('sys/random.h', 'GRND_NONBLOCK'))
2686 config_host_data.set('CONFIG_PRCTL_PR_SET_TIMERSLACK',
2687                      cc.has_header_symbol('sys/prctl.h', 'PR_SET_TIMERSLACK'))
2688 config_host_data.set('CONFIG_RTNETLINK',
2689                      cc.has_header_symbol('linux/rtnetlink.h', 'IFLA_PROTO_DOWN'))
2690 config_host_data.set('CONFIG_SYSMACROS',
2691                      cc.has_header_symbol('sys/sysmacros.h', 'makedev'))
2692 config_host_data.set('HAVE_OPTRESET',
2693                      cc.has_header_symbol('getopt.h', 'optreset'))
2694 config_host_data.set('HAVE_IPPROTO_MPTCP',
2695                      cc.has_header_symbol('netinet/in.h', 'IPPROTO_MPTCP'))
2696 
2697 # has_member
2698 config_host_data.set('HAVE_SIGEV_NOTIFY_THREAD_ID',
2699                      cc.has_member('struct sigevent', 'sigev_notify_thread_id',
2700                                    prefix: '#include <signal.h>'))
2701 config_host_data.set('HAVE_STRUCT_STAT_ST_ATIM',
2702                      cc.has_member('struct stat', 'st_atim',
2703                                    prefix: '#include <sys/stat.h>'))
2704 config_host_data.set('HAVE_BLK_ZONE_REP_CAPACITY',
2705                      cc.has_member('struct blk_zone', 'capacity',
2706                                    prefix: '#include <linux/blkzoned.h>'))
2707 
2708 # has_type
2709 config_host_data.set('CONFIG_IOVEC',
2710                      cc.has_type('struct iovec',
2711                                  prefix: '#include <sys/uio.h>'))
2712 config_host_data.set('HAVE_UTMPX',
2713                      cc.has_type('struct utmpx',
2714                                  prefix: '#include <utmpx.h>'))
2715 
2716 config_host_data.set('CONFIG_EVENTFD', cc.links('''
2717   #include <sys/eventfd.h>
2718   int main(void) { return eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); }'''))
2719 config_host_data.set('CONFIG_FDATASYNC', cc.links(gnu_source_prefix + '''
2720   #include <unistd.h>
2721   int main(void) {
2722   #if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
2723   return fdatasync(0);
2724   #else
2725   #error Not supported
2726   #endif
2727   }'''))
2728 
2729 has_madvise = cc.links(gnu_source_prefix + '''
2730   #include <sys/types.h>
2731   #include <sys/mman.h>
2732   #include <stddef.h>
2733   int main(void) { return madvise(NULL, 0, MADV_DONTNEED); }''')
2734 missing_madvise_proto = false
2735 if has_madvise
2736   # Some platforms (illumos and Solaris before Solaris 11) provide madvise()
2737   # but forget to prototype it. In this case, has_madvise will be true (the
2738   # test program links despite a compile warning). To detect the
2739   # missing-prototype case, we try again with a definitely-bogus prototype.
2740   # This will only compile if the system headers don't provide the prototype;
2741   # otherwise the conflicting prototypes will cause a compiler error.
2742   missing_madvise_proto = cc.links(gnu_source_prefix + '''
2743     #include <sys/types.h>
2744     #include <sys/mman.h>
2745     #include <stddef.h>
2746     extern int madvise(int);
2747     int main(void) { return madvise(0); }''')
2748 endif
2749 config_host_data.set('CONFIG_MADVISE', has_madvise)
2750 config_host_data.set('HAVE_MADVISE_WITHOUT_PROTOTYPE', missing_madvise_proto)
2751 
2752 config_host_data.set('CONFIG_MEMFD', cc.links(gnu_source_prefix + '''
2753   #include <sys/mman.h>
2754   int main(void) { return memfd_create("foo", MFD_ALLOW_SEALING); }'''))
2755 config_host_data.set('CONFIG_OPEN_BY_HANDLE', cc.links(gnu_source_prefix + '''
2756   #include <fcntl.h>
2757   #if !defined(AT_EMPTY_PATH)
2758   # error missing definition
2759   #else
2760   int main(void) { struct file_handle fh; return open_by_handle_at(0, &fh, 0); }
2761   #endif'''))
2762 
2763 # On Darwin posix_madvise() has the same return semantics as plain madvise(),
2764 # i.e. errno is set and -1 is returned. That's not really how POSIX defines the
2765 # function. On the flip side, it has madvise() which is preferred anyways.
2766 if host_os != 'darwin'
2767   config_host_data.set('CONFIG_POSIX_MADVISE', cc.links(gnu_source_prefix + '''
2768     #include <sys/mman.h>
2769     #include <stddef.h>
2770     int main(void) { return posix_madvise(NULL, 0, POSIX_MADV_DONTNEED); }'''))
2771 endif
2772 
2773 config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_W_TID', cc.links(gnu_source_prefix + '''
2774   #include <pthread.h>
2775 
2776   static void *f(void *p) { return NULL; }
2777   int main(void)
2778   {
2779     pthread_t thread;
2780     pthread_create(&thread, 0, f, 0);
2781     pthread_setname_np(thread, "QEMU");
2782     return 0;
2783   }''', dependencies: threads))
2784 config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_WO_TID', cc.links(gnu_source_prefix + '''
2785   #include <pthread.h>
2786 
2787   static void *f(void *p) { pthread_setname_np("QEMU"); return NULL; }
2788   int main(void)
2789   {
2790     pthread_t thread;
2791     pthread_create(&thread, 0, f, 0);
2792     return 0;
2793   }''', dependencies: threads))
2794 config_host_data.set('CONFIG_PTHREAD_SET_NAME_NP', cc.links(gnu_source_prefix + '''
2795   #include <pthread.h>
2796   #include <pthread_np.h>
2797 
2798   static void *f(void *p) { return NULL; }
2799   int main(void)
2800   {
2801     pthread_t thread;
2802     pthread_create(&thread, 0, f, 0);
2803     pthread_set_name_np(thread, "QEMU");
2804     return 0;
2805   }''', dependencies: threads))
2806 config_host_data.set('CONFIG_PTHREAD_CONDATTR_SETCLOCK', cc.links(gnu_source_prefix + '''
2807   #include <pthread.h>
2808   #include <time.h>
2809 
2810   int main(void)
2811   {
2812     pthread_condattr_t attr
2813     pthread_condattr_init(&attr);
2814     pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
2815     return 0;
2816   }''', dependencies: threads))
2817 config_host_data.set('CONFIG_PTHREAD_AFFINITY_NP', cc.links(gnu_source_prefix + '''
2818   #include <pthread.h>
2819 
2820   static void *f(void *p) { return NULL; }
2821   int main(void)
2822   {
2823     int setsize = CPU_ALLOC_SIZE(64);
2824     pthread_t thread;
2825     cpu_set_t *cpuset;
2826     pthread_create(&thread, 0, f, 0);
2827     cpuset = CPU_ALLOC(64);
2828     CPU_ZERO_S(setsize, cpuset);
2829     pthread_setaffinity_np(thread, setsize, cpuset);
2830     pthread_getaffinity_np(thread, setsize, cpuset);
2831     CPU_FREE(cpuset);
2832     return 0;
2833   }''', dependencies: threads))
2834 config_host_data.set('CONFIG_SIGNALFD', cc.links(gnu_source_prefix + '''
2835   #include <sys/signalfd.h>
2836   #include <stddef.h>
2837   int main(void) { return signalfd(-1, NULL, SFD_CLOEXEC); }'''))
2838 config_host_data.set('CONFIG_SPLICE', cc.links(gnu_source_prefix + '''
2839   #include <unistd.h>
2840   #include <fcntl.h>
2841   #include <limits.h>
2842 
2843   int main(void)
2844   {
2845     int len, fd = 0;
2846     len = tee(STDIN_FILENO, STDOUT_FILENO, INT_MAX, SPLICE_F_NONBLOCK);
2847     splice(STDIN_FILENO, NULL, fd, NULL, len, SPLICE_F_MOVE);
2848     return 0;
2849   }'''))
2850 
2851 config_host_data.set('HAVE_MLOCKALL', cc.links(gnu_source_prefix + '''
2852   #include <sys/mman.h>
2853   int main(void) {
2854     return mlockall(MCL_FUTURE);
2855   }'''))
2856 
2857 have_l2tpv3 = false
2858 if get_option('l2tpv3').allowed() and have_system
2859   have_l2tpv3 = cc.has_type('struct mmsghdr',
2860     prefix: gnu_source_prefix + '''
2861       #include <sys/socket.h>
2862       #include <linux/ip.h>''')
2863 endif
2864 config_host_data.set('CONFIG_L2TPV3', have_l2tpv3)
2865 
2866 have_netmap = false
2867 if get_option('netmap').allowed() and have_system
2868   have_netmap = cc.compiles('''
2869     #include <inttypes.h>
2870     #include <net/if.h>
2871     #include <net/netmap.h>
2872     #include <net/netmap_user.h>
2873     #if (NETMAP_API < 11) || (NETMAP_API > 15)
2874     #error
2875     #endif
2876     int main(void) { return 0; }''')
2877   if not have_netmap and get_option('netmap').enabled()
2878     error('Netmap headers not available')
2879   endif
2880 endif
2881 config_host_data.set('CONFIG_NETMAP', have_netmap)
2882 
2883 # Work around a system header bug with some kernel/XFS header
2884 # versions where they both try to define 'struct fsxattr':
2885 # xfs headers will not try to redefine structs from linux headers
2886 # if this macro is set.
2887 config_host_data.set('HAVE_FSXATTR', cc.links('''
2888   #include <linux/fs.h>
2889   struct fsxattr foo;
2890   int main(void) {
2891     return 0;
2892   }'''))
2893 
2894 # Some versions of Mac OS X incorrectly define SIZE_MAX
2895 config_host_data.set('HAVE_BROKEN_SIZE_MAX', not cc.compiles('''
2896     #include <stdint.h>
2897     #include <stdio.h>
2898     int main(void) {
2899         return printf("%zu", SIZE_MAX);
2900     }''', args: ['-Werror']))
2901 
2902 # See if 64-bit atomic operations are supported.
2903 # Note that without __atomic builtins, we can only
2904 # assume atomic loads/stores max at pointer size.
2905 config_host_data.set('CONFIG_ATOMIC64', cc.links('''
2906   #include <stdint.h>
2907   int main(void)
2908   {
2909     uint64_t x = 0, y = 0;
2910     y = __atomic_load_n(&x, __ATOMIC_RELAXED);
2911     __atomic_store_n(&x, y, __ATOMIC_RELAXED);
2912     __atomic_compare_exchange_n(&x, &y, x, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
2913     __atomic_exchange_n(&x, y, __ATOMIC_RELAXED);
2914     __atomic_fetch_add(&x, y, __ATOMIC_RELAXED);
2915     return 0;
2916   }''', args: qemu_isa_flags))
2917 
2918 has_int128_type = cc.compiles('''
2919   __int128_t a;
2920   __uint128_t b;
2921   int main(void) { b = a; }''')
2922 config_host_data.set('CONFIG_INT128_TYPE', has_int128_type)
2923 
2924 has_int128 = has_int128_type and cc.links('''
2925   __int128_t a;
2926   __uint128_t b;
2927   int main (void) {
2928     a = a + b;
2929     b = a * b;
2930     a = a * a;
2931     return 0;
2932   }''')
2933 config_host_data.set('CONFIG_INT128', has_int128)
2934 
2935 if has_int128_type
2936   # "do we have 128-bit atomics which are handled inline and specifically not
2937   # via libatomic". The reason we can't use libatomic is documented in the
2938   # comment starting "GCC is a house divided" in include/qemu/atomic128.h.
2939   # We only care about these operations on 16-byte aligned pointers, so
2940   # force 16-byte alignment of the pointer, which may be greater than
2941   # __alignof(unsigned __int128) for the host.
2942   atomic_test_128 = '''
2943     int main(int ac, char **av) {
2944       __uint128_t *p = __builtin_assume_aligned(av[ac - 1], 16);
2945       p[1] = __atomic_load_n(&p[0], __ATOMIC_RELAXED);
2946       __atomic_store_n(&p[2], p[3], __ATOMIC_RELAXED);
2947       __atomic_compare_exchange_n(&p[4], &p[5], p[6], 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
2948       return 0;
2949     }'''
2950   has_atomic128 = cc.links(atomic_test_128, args: qemu_isa_flags)
2951 
2952   config_host_data.set('CONFIG_ATOMIC128', has_atomic128)
2953 
2954   if not has_atomic128
2955     # Even with __builtin_assume_aligned, the above test may have failed
2956     # without optimization enabled.  Try again with optimizations locally
2957     # enabled for the function.  See
2958     #   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107389
2959     has_atomic128_opt = cc.links('__attribute__((optimize("O1")))' + atomic_test_128,
2960                                  args: qemu_isa_flags)
2961     config_host_data.set('CONFIG_ATOMIC128_OPT', has_atomic128_opt)
2962 
2963     if not has_atomic128_opt
2964       config_host_data.set('CONFIG_CMPXCHG128', cc.links('''
2965         int main(void)
2966         {
2967           __uint128_t x = 0, y = 0;
2968           __sync_val_compare_and_swap_16(&x, y, x);
2969           return 0;
2970         }
2971       ''', args: qemu_isa_flags))
2972     endif
2973   endif
2974 endif
2975 
2976 config_host_data.set('CONFIG_GETAUXVAL', cc.links(gnu_source_prefix + '''
2977   #include <sys/auxv.h>
2978   int main(void) {
2979     return getauxval(AT_HWCAP) == 0;
2980   }'''))
2981 
2982 config_host_data.set('CONFIG_ELF_AUX_INFO', cc.links(gnu_source_prefix + '''
2983   #include <sys/auxv.h>
2984   int main(void) {
2985     unsigned long hwcap = 0;
2986     elf_aux_info(AT_HWCAP, &hwcap, sizeof(hwcap));
2987     return hwcap;
2988   }'''))
2989 
2990 config_host_data.set('CONFIG_USBFS', have_linux_user and cc.compiles('''
2991   #include <linux/usbdevice_fs.h>
2992 
2993   #ifndef USBDEVFS_GET_CAPABILITIES
2994   #error "USBDEVFS_GET_CAPABILITIES undefined"
2995   #endif
2996 
2997   #ifndef USBDEVFS_DISCONNECT_CLAIM
2998   #error "USBDEVFS_DISCONNECT_CLAIM undefined"
2999   #endif
3000 
3001   int main(void) { return 0; }'''))
3002 
3003 have_keyring = get_option('keyring') \
3004   .require(host_os == 'linux', error_message: 'keyring is only available on Linux') \
3005   .require(cc.compiles('''
3006     #include <errno.h>
3007     #include <asm/unistd.h>
3008     #include <linux/keyctl.h>
3009     #include <sys/syscall.h>
3010     #include <unistd.h>
3011     int main(void) {
3012         return syscall(__NR_keyctl, KEYCTL_READ, 0, NULL, NULL, 0);
3013     }'''), error_message: 'keyctl syscall not available on this system').allowed()
3014 config_host_data.set('CONFIG_SECRET_KEYRING', have_keyring)
3015 
3016 have_cpuid_h = cc.links('''
3017   #include <cpuid.h>
3018   int main(void) {
3019     unsigned a, b, c, d;
3020     unsigned max = __get_cpuid_max(0, 0);
3021 
3022     if (max >= 1) {
3023         __cpuid(1, a, b, c, d);
3024     }
3025 
3026     if (max >= 7) {
3027         __cpuid_count(7, 0, a, b, c, d);
3028     }
3029 
3030     return 0;
3031   }''')
3032 config_host_data.set('CONFIG_CPUID_H', have_cpuid_h)
3033 
3034 # Don't bother to advertise asm/hwprobe.h for old versions that do
3035 # not contain RISCV_HWPROBE_EXT_ZBA.
3036 config_host_data.set('CONFIG_ASM_HWPROBE_H',
3037                      cc.has_header_symbol('asm/hwprobe.h',
3038                                           'RISCV_HWPROBE_EXT_ZBA'))
3039 
3040 config_host_data.set('CONFIG_AVX2_OPT', get_option('avx2') \
3041   .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable AVX2') \
3042   .require(cc.links('''
3043     #include <cpuid.h>
3044     #include <immintrin.h>
3045     static int __attribute__((target("avx2"))) bar(void *a) {
3046       __m256i x = *(__m256i *)a;
3047       return _mm256_testz_si256(x, x);
3048     }
3049     int main(int argc, char *argv[]) { return bar(argv[argc - 1]); }
3050   '''), error_message: 'AVX2 not available').allowed())
3051 
3052 config_host_data.set('CONFIG_AVX512BW_OPT', get_option('avx512bw') \
3053   .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable AVX512BW') \
3054   .require(cc.links('''
3055     #include <cpuid.h>
3056     #include <immintrin.h>
3057     static int __attribute__((target("avx512bw"))) bar(void *a) {
3058       __m512i *x = a;
3059       __m512i res= _mm512_abs_epi8(*x);
3060       return res[1];
3061     }
3062     int main(int argc, char *argv[]) { return bar(argv[0]); }
3063   '''), error_message: 'AVX512BW not available').allowed())
3064 
3065 # For both AArch64 and AArch32, detect if builtins are available.
3066 config_host_data.set('CONFIG_ARM_AES_BUILTIN', cc.compiles('''
3067     #include <arm_neon.h>
3068     #ifndef __ARM_FEATURE_AES
3069     __attribute__((target("+crypto")))
3070     #endif
3071     void foo(uint8x16_t *p) { *p = vaesmcq_u8(*p); }
3072   '''))
3073 
3074 if get_option('membarrier').disabled()
3075   have_membarrier = false
3076 elif host_os == 'windows'
3077   have_membarrier = true
3078 elif host_os == 'linux'
3079   have_membarrier = cc.compiles('''
3080     #include <linux/membarrier.h>
3081     #include <sys/syscall.h>
3082     #include <unistd.h>
3083     #include <stdlib.h>
3084     int main(void) {
3085         syscall(__NR_membarrier, MEMBARRIER_CMD_QUERY, 0);
3086         syscall(__NR_membarrier, MEMBARRIER_CMD_SHARED, 0);
3087         exit(0);
3088     }''')
3089 endif
3090 config_host_data.set('CONFIG_MEMBARRIER', get_option('membarrier') \
3091   .require(have_membarrier, error_message: 'membarrier system call not available') \
3092   .allowed())
3093 
3094 have_afalg = get_option('crypto_afalg') \
3095   .require(cc.compiles(gnu_source_prefix + '''
3096     #include <errno.h>
3097     #include <sys/types.h>
3098     #include <sys/socket.h>
3099     #include <linux/if_alg.h>
3100     int main(void) {
3101       int sock;
3102       sock = socket(AF_ALG, SOCK_SEQPACKET, 0);
3103       return sock;
3104     }
3105   '''), error_message: 'AF_ALG requested but could not be detected').allowed()
3106 config_host_data.set('CONFIG_AF_ALG', have_afalg)
3107 
3108 config_host_data.set('CONFIG_AF_VSOCK', cc.has_header_symbol(
3109   'linux/vm_sockets.h', 'AF_VSOCK',
3110   prefix: '#include <sys/socket.h>',
3111 ))
3112 
3113 have_vss = false
3114 have_vss_sdk = false # old xp/2003 SDK
3115 if host_os == 'windows' and 'cpp' in all_languages
3116   have_vss = cxx.compiles('''
3117     #define __MIDL_user_allocate_free_DEFINED__
3118     #include <vss.h>
3119     int main(void) { return VSS_CTX_BACKUP; }''')
3120   have_vss_sdk = cxx.has_header('vscoordint.h')
3121 endif
3122 config_host_data.set('HAVE_VSS_SDK', have_vss_sdk)
3123 
3124 # Older versions of MinGW do not import _lock_file and _unlock_file properly.
3125 # This was fixed for v6.0.0 with commit b48e3ac8969d.
3126 if host_os == 'windows'
3127   config_host_data.set('HAVE__LOCK_FILE', cc.links('''
3128     #include <stdio.h>
3129     int main(void) {
3130       _lock_file(NULL);
3131       _unlock_file(NULL);
3132       return 0;
3133     }''', name: '_lock_file and _unlock_file'))
3134 endif
3135 
3136 if host_os == 'windows'
3137   mingw_has_setjmp_longjmp = cc.links('''
3138     #include <setjmp.h>
3139     int main(void) {
3140       /*
3141        * These functions are not available in setjmp header, but may be
3142        * available at link time, from libmingwex.a.
3143        */
3144       extern int __mingw_setjmp(jmp_buf);
3145       extern void __attribute__((noreturn)) __mingw_longjmp(jmp_buf, int);
3146       jmp_buf env;
3147       __mingw_setjmp(env);
3148       __mingw_longjmp(env, 0);
3149     }
3150   ''', name: 'mingw setjmp and longjmp')
3151 
3152   if cpu == 'aarch64' and not mingw_has_setjmp_longjmp
3153     error('mingw must provide setjmp/longjmp for windows-arm64')
3154   endif
3155 endif
3156 
3157 ########################
3158 # Target configuration #
3159 ########################
3160 
3161 minikconf = find_program('scripts/minikconf.py')
3162 
3163 config_all_accel = {}
3164 config_all_devices = {}
3165 config_devices_mak_list = []
3166 config_devices_h = {}
3167 config_target_h = {}
3168 config_target_mak = {}
3169 
3170 disassemblers = {
3171   'alpha' : ['CONFIG_ALPHA_DIS'],
3172   'avr' : ['CONFIG_AVR_DIS'],
3173   'hexagon' : ['CONFIG_HEXAGON_DIS'],
3174   'hppa' : ['CONFIG_HPPA_DIS'],
3175   'i386' : ['CONFIG_I386_DIS'],
3176   'x86_64' : ['CONFIG_I386_DIS'],
3177   'm68k' : ['CONFIG_M68K_DIS'],
3178   'microblaze' : ['CONFIG_MICROBLAZE_DIS'],
3179   'mips' : ['CONFIG_MIPS_DIS'],
3180   'or1k' : ['CONFIG_OPENRISC_DIS'],
3181   'ppc' : ['CONFIG_PPC_DIS'],
3182   'riscv' : ['CONFIG_RISCV_DIS'],
3183   'rx' : ['CONFIG_RX_DIS'],
3184   's390' : ['CONFIG_S390_DIS'],
3185   'sh4' : ['CONFIG_SH4_DIS'],
3186   'sparc' : ['CONFIG_SPARC_DIS'],
3187   'xtensa' : ['CONFIG_XTENSA_DIS'],
3188   'loongarch' : ['CONFIG_LOONGARCH_DIS'],
3189 }
3190 
3191 have_ivshmem = config_host_data.get('CONFIG_EVENTFD')
3192 host_kconfig = \
3193   (get_option('fuzzing') ? ['CONFIG_FUZZ=y'] : []) + \
3194   (have_tpm ? ['CONFIG_TPM=y'] : []) + \
3195   (pixman.found() ? ['CONFIG_PIXMAN=y'] : []) + \
3196   (spice.found() ? ['CONFIG_SPICE=y'] : []) + \
3197   (have_ivshmem ? ['CONFIG_IVSHMEM=y'] : []) + \
3198   (opengl.found() ? ['CONFIG_OPENGL=y'] : []) + \
3199   (libcbor.found() ? ['CONFIG_LIBCBOR=y'] : []) + \
3200   (gnutls.found() ? ['CONFIG_GNUTLS=y'] : []) + \
3201   (x11.found() ? ['CONFIG_X11=y'] : []) + \
3202   (fdt.found() ? ['CONFIG_FDT=y'] : []) + \
3203   (have_vhost_user ? ['CONFIG_VHOST_USER=y'] : []) + \
3204   (have_vhost_vdpa ? ['CONFIG_VHOST_VDPA=y'] : []) + \
3205   (have_vhost_kernel ? ['CONFIG_VHOST_KERNEL=y'] : []) + \
3206   (have_virtfs ? ['CONFIG_VIRTFS=y'] : []) + \
3207   (host_os == 'linux' ? ['CONFIG_LINUX=y'] : []) + \
3208   (multiprocess_allowed ? ['CONFIG_MULTIPROCESS_ALLOWED=y'] : []) + \
3209   (vfio_user_server_allowed ? ['CONFIG_VFIO_USER_SERVER_ALLOWED=y'] : []) + \
3210   (hv_balloon ? ['CONFIG_HV_BALLOON_POSSIBLE=y'] : []) + \
3211   (have_rust ? ['CONFIG_HAVE_RUST=y'] : [])
3212 
3213 ignored = [ 'TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_ARCH' ]
3214 
3215 default_targets = 'CONFIG_DEFAULT_TARGETS' in config_host
3216 actual_target_dirs = []
3217 fdt_required = []
3218 foreach target : target_dirs
3219   config_target = { 'TARGET_NAME': target.split('-')[0] }
3220   if target.endswith('linux-user')
3221     if host_os != 'linux'
3222       if default_targets
3223         continue
3224       endif
3225       error('Target @0@ is only available on a Linux host'.format(target))
3226     endif
3227     config_target += { 'CONFIG_LINUX_USER': 'y' }
3228   elif target.endswith('bsd-user')
3229     if host_os not in bsd_oses
3230       if default_targets
3231         continue
3232       endif
3233       error('Target @0@ is only available on a BSD host'.format(target))
3234     endif
3235     config_target += { 'CONFIG_BSD_USER': 'y' }
3236   elif target.endswith('softmmu')
3237     config_target += { 'CONFIG_SYSTEM_ONLY': 'y' }
3238     config_target += { 'CONFIG_SOFTMMU': 'y' }
3239   endif
3240   if target.endswith('-user')
3241     config_target += {
3242       'CONFIG_USER_ONLY': 'y',
3243       'CONFIG_QEMU_INTERP_PREFIX':
3244         get_option('interp_prefix').replace('%M', config_target['TARGET_NAME']),
3245       'CONFIG_QEMU_RTSIG_MAP': get_option('rtsig_map'),
3246     }
3247   endif
3248 
3249   target_kconfig = []
3250   foreach sym: accelerators
3251     if sym == 'CONFIG_TCG' or target in accelerator_targets.get(sym, [])
3252       config_target += { sym: 'y' }
3253       config_all_accel += { sym: 'y' }
3254       if target in modular_tcg
3255         config_target += { 'CONFIG_TCG_MODULAR': 'y' }
3256       else
3257         config_target += { 'CONFIG_TCG_BUILTIN': 'y' }
3258       endif
3259       target_kconfig += [ sym + '=y' ]
3260     endif
3261   endforeach
3262   if target_kconfig.length() == 0
3263     if default_targets
3264       continue
3265     endif
3266     error('No accelerator available for target @0@'.format(target))
3267   endif
3268 
3269   config_target += keyval.load('configs/targets' / target + '.mak')
3270   config_target += { 'TARGET_' + config_target['TARGET_ARCH'].to_upper(): 'y' }
3271 
3272   if 'TARGET_NEED_FDT' in config_target and not fdt.found()
3273     if default_targets
3274       warning('Disabling ' + target + ' due to missing libfdt')
3275     else
3276       fdt_required += target
3277     endif
3278     continue
3279   endif
3280 
3281   actual_target_dirs += target
3282 
3283   # Add default keys
3284   if 'TARGET_BASE_ARCH' not in config_target
3285     config_target += {'TARGET_BASE_ARCH': config_target['TARGET_ARCH']}
3286   endif
3287   if 'TARGET_ABI_DIR' not in config_target
3288     config_target += {'TARGET_ABI_DIR': config_target['TARGET_ARCH']}
3289   endif
3290   if 'TARGET_BIG_ENDIAN' not in config_target
3291     config_target += {'TARGET_BIG_ENDIAN': 'n'}
3292   endif
3293 
3294   foreach k, v: disassemblers
3295     if host_arch.startswith(k) or config_target['TARGET_BASE_ARCH'].startswith(k)
3296       foreach sym: v
3297         config_target += { sym: 'y' }
3298       endforeach
3299     endif
3300   endforeach
3301 
3302   config_target_data = configuration_data()
3303   foreach k, v: config_target
3304     if not k.startswith('TARGET_') and not k.startswith('CONFIG_')
3305       # do nothing
3306     elif ignored.contains(k)
3307       # do nothing
3308     elif k == 'TARGET_BASE_ARCH'
3309       # Note that TARGET_BASE_ARCH ends up in config-target.h but it is
3310       # not used to select files from sourcesets.
3311       config_target_data.set('TARGET_' + v.to_upper(), 1)
3312     elif k == 'TARGET_NAME' or k == 'CONFIG_QEMU_INTERP_PREFIX'
3313       config_target_data.set_quoted(k, v)
3314     elif v == 'y'
3315       config_target_data.set(k, 1)
3316     elif v == 'n'
3317       config_target_data.set(k, 0)
3318     else
3319       config_target_data.set(k, v)
3320     endif
3321   endforeach
3322   config_target_data.set('QEMU_ARCH',
3323                          'QEMU_ARCH_' + config_target['TARGET_BASE_ARCH'].to_upper())
3324   config_target_h += {target: configure_file(output: target + '-config-target.h',
3325                                                configuration: config_target_data)}
3326 
3327   if target.endswith('-softmmu')
3328     target_kconfig += 'CONFIG_' + config_target['TARGET_ARCH'].to_upper() + '=y'
3329     target_kconfig += 'CONFIG_TARGET_BIG_ENDIAN=' + config_target['TARGET_BIG_ENDIAN']
3330 
3331     config_input = meson.get_external_property(target, 'default')
3332     config_devices_mak = target + '-config-devices.mak'
3333     config_devices_mak = configure_file(
3334       input: ['configs/devices' / target / config_input + '.mak', 'Kconfig'],
3335       output: config_devices_mak,
3336       depfile: config_devices_mak + '.d',
3337       capture: true,
3338       command: [minikconf,
3339                 get_option('default_devices') ? '--defconfig' : '--allnoconfig',
3340                 config_devices_mak, '@DEPFILE@', '@INPUT@',
3341                 host_kconfig, target_kconfig])
3342 
3343     config_devices_data = configuration_data()
3344     config_devices = keyval.load(config_devices_mak)
3345     foreach k, v: config_devices
3346       config_devices_data.set(k, 1)
3347     endforeach
3348     config_devices_mak_list += config_devices_mak
3349     config_devices_h += {target: configure_file(output: target + '-config-devices.h',
3350                                                 configuration: config_devices_data)}
3351     config_target += config_devices
3352     config_all_devices += config_devices
3353   endif
3354   config_target_mak += {target: config_target}
3355 endforeach
3356 target_dirs = actual_target_dirs
3357 
3358 target_configs_h = []
3359 foreach target: target_dirs
3360   target_configs_h += config_target_h[target]
3361   target_configs_h += config_devices_h.get(target, [])
3362 endforeach
3363 genh += custom_target('config-poison.h',
3364                       input: [target_configs_h],
3365                       output: 'config-poison.h',
3366                       capture: true,
3367                       command: [find_program('scripts/make-config-poison.sh'),
3368                                 target_configs_h])
3369 
3370 if fdt_required.length() > 0
3371   error('fdt disabled but required by targets ' + ', '.join(fdt_required))
3372 endif
3373 
3374 ###############
3375 # Subprojects #
3376 ###############
3377 
3378 libvfio_user_dep = not_found
3379 if have_system and vfio_user_server_allowed
3380   libvfio_user_proj = subproject('libvfio-user', required: true)
3381   libvfio_user_dep = libvfio_user_proj.get_variable('libvfio_user_dep')
3382 endif
3383 
3384 vhost_user = not_found
3385 if host_os == 'linux' and have_vhost_user
3386   libvhost_user = subproject('libvhost-user')
3387   vhost_user = libvhost_user.get_variable('vhost_user_dep')
3388 endif
3389 
3390 libvduse = not_found
3391 if have_libvduse
3392   libvduse_proj = subproject('libvduse')
3393   libvduse = libvduse_proj.get_variable('libvduse_dep')
3394 endif
3395 
3396 #####################
3397 # Generated sources #
3398 #####################
3399 
3400 genh += configure_file(output: 'config-host.h', configuration: config_host_data)
3401 
3402 if have_rust
3403   rustc_args = run_command(
3404     find_program('scripts/rust/rustc_args.py'),
3405     '--config-headers', meson.project_build_root() / 'config-host.h',
3406     capture : true,
3407     check: true).stdout().strip().split()
3408 
3409   # Prohibit code that is forbidden in Rust 2024
3410   rustc_args += ['-D', 'unsafe_op_in_unsafe_fn']
3411 
3412   # Occasionally, we may need to silence warnings and clippy lints that
3413   # were only introduced in newer Rust compiler versions.  Do not croak
3414   # in that case; a CI job with rust_strict_lints == true ensures that
3415   # we do not have misspelled allow() attributes.
3416   if not get_option('strict_rust_lints')
3417     rustc_args += ['-A', 'unknown_lints']
3418   endif
3419 
3420   # Apart from procedural macros, our Rust executables will often link
3421   # with C code, so include all the libraries that C code needs.  This
3422   # is safe; https://github.com/rust-lang/rust/pull/54675 says that
3423   # passing -nodefaultlibs to the linker "was more ideological to
3424   # start with than anything".
3425   add_project_arguments(rustc_args + ['-C', 'default-linker-libraries'],
3426       native: false, language: 'rust')
3427 
3428   add_project_arguments(rustc_args, native: true, language: 'rust')
3429 endif
3430 
3431 hxtool = find_program('scripts/hxtool')
3432 shaderinclude = find_program('scripts/shaderinclude.py')
3433 qapi_gen = find_program('scripts/qapi-gen.py')
3434 qapi_gen_depends = [ meson.current_source_dir() / 'scripts/qapi/__init__.py',
3435                      meson.current_source_dir() / 'scripts/qapi/commands.py',
3436                      meson.current_source_dir() / 'scripts/qapi/common.py',
3437                      meson.current_source_dir() / 'scripts/qapi/error.py',
3438                      meson.current_source_dir() / 'scripts/qapi/events.py',
3439                      meson.current_source_dir() / 'scripts/qapi/expr.py',
3440                      meson.current_source_dir() / 'scripts/qapi/gen.py',
3441                      meson.current_source_dir() / 'scripts/qapi/introspect.py',
3442                      meson.current_source_dir() / 'scripts/qapi/main.py',
3443                      meson.current_source_dir() / 'scripts/qapi/parser.py',
3444                      meson.current_source_dir() / 'scripts/qapi/schema.py',
3445                      meson.current_source_dir() / 'scripts/qapi/source.py',
3446                      meson.current_source_dir() / 'scripts/qapi/types.py',
3447                      meson.current_source_dir() / 'scripts/qapi/visit.py',
3448                      meson.current_source_dir() / 'scripts/qapi-gen.py'
3449 ]
3450 
3451 tracetool = [
3452   python, files('scripts/tracetool.py'),
3453    '--backend=' + ','.join(get_option('trace_backends'))
3454 ]
3455 tracetool_depends = files(
3456   'scripts/tracetool/backend/log.py',
3457   'scripts/tracetool/backend/__init__.py',
3458   'scripts/tracetool/backend/dtrace.py',
3459   'scripts/tracetool/backend/ftrace.py',
3460   'scripts/tracetool/backend/simple.py',
3461   'scripts/tracetool/backend/syslog.py',
3462   'scripts/tracetool/backend/ust.py',
3463   'scripts/tracetool/format/ust_events_c.py',
3464   'scripts/tracetool/format/ust_events_h.py',
3465   'scripts/tracetool/format/__init__.py',
3466   'scripts/tracetool/format/d.py',
3467   'scripts/tracetool/format/simpletrace_stap.py',
3468   'scripts/tracetool/format/c.py',
3469   'scripts/tracetool/format/h.py',
3470   'scripts/tracetool/format/log_stap.py',
3471   'scripts/tracetool/format/stap.py',
3472   'scripts/tracetool/__init__.py',
3473 )
3474 
3475 qemu_version_cmd = [find_program('scripts/qemu-version.sh'),
3476                     meson.current_source_dir(),
3477                     get_option('pkgversion'), meson.project_version()]
3478 qemu_version = custom_target('qemu-version.h',
3479                              output: 'qemu-version.h',
3480                              command: qemu_version_cmd,
3481                              capture: true,
3482                              build_by_default: true,
3483                              build_always_stale: true)
3484 genh += qemu_version
3485 
3486 hxdep = []
3487 hx_headers = [
3488   ['qemu-options.hx', 'qemu-options.def'],
3489   ['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
3490 ]
3491 if have_system
3492   hx_headers += [
3493     ['hmp-commands.hx', 'hmp-commands.h'],
3494     ['hmp-commands-info.hx', 'hmp-commands-info.h'],
3495   ]
3496 endif
3497 foreach d : hx_headers
3498   hxdep += custom_target(d[1],
3499                 input: files(d[0]),
3500                 output: d[1],
3501                 capture: true,
3502                 command: [hxtool, '-h', '@INPUT0@'])
3503 endforeach
3504 genh += hxdep
3505 
3506 ###############
3507 # Trace files #
3508 ###############
3509 
3510 # TODO: add each directory to the subdirs from its own meson.build, once
3511 # we have those
3512 trace_events_subdirs = [
3513   'crypto',
3514   'qapi',
3515   'qom',
3516   'monitor',
3517   'util',
3518   'gdbstub',
3519 ]
3520 if have_linux_user
3521   trace_events_subdirs += [ 'linux-user' ]
3522 endif
3523 if have_bsd_user
3524   trace_events_subdirs += [ 'bsd-user' ]
3525 endif
3526 if have_block
3527   trace_events_subdirs += [
3528     'authz',
3529     'block',
3530     'chardev',
3531     'io',
3532     'nbd',
3533     'scsi',
3534   ]
3535 endif
3536 if have_system
3537   trace_events_subdirs += [
3538     'accel/kvm',
3539     'audio',
3540     'backends',
3541     'backends/tpm',
3542     'ebpf',
3543     'hw/9pfs',
3544     'hw/acpi',
3545     'hw/adc',
3546     'hw/alpha',
3547     'hw/arm',
3548     'hw/audio',
3549     'hw/block',
3550     'hw/char',
3551     'hw/display',
3552     'hw/dma',
3553     'hw/fsi',
3554     'hw/hyperv',
3555     'hw/i2c',
3556     'hw/i3c',
3557     'hw/i386',
3558     'hw/i386/xen',
3559     'hw/i386/kvm',
3560     'hw/ide',
3561     'hw/input',
3562     'hw/intc',
3563     'hw/isa',
3564     'hw/mem',
3565     'hw/mips',
3566     'hw/misc',
3567     'hw/misc/macio',
3568     'hw/net',
3569     'hw/net/can',
3570     'hw/nubus',
3571     'hw/nvme',
3572     'hw/nvram',
3573     'hw/pci',
3574     'hw/pci-host',
3575     'hw/ppc',
3576     'hw/rtc',
3577     'hw/riscv',
3578     'hw/s390x',
3579     'hw/scsi',
3580     'hw/sd',
3581     'hw/sensor',
3582     'hw/sh4',
3583     'hw/sparc',
3584     'hw/sparc64',
3585     'hw/ssi',
3586     'hw/timer',
3587     'hw/tpm',
3588     'hw/ufs',
3589     'hw/usb',
3590     'hw/vfio',
3591     'hw/virtio',
3592     'hw/watchdog',
3593     'hw/xen',
3594     'hw/gpio',
3595     'migration',
3596     'net',
3597     'system',
3598     'ui',
3599     'hw/remote',
3600   ]
3601 endif
3602 if have_system or have_user
3603   trace_events_subdirs += [
3604     'accel/tcg',
3605     'hw/core',
3606     'target/arm',
3607     'target/arm/hvf',
3608     'target/hppa',
3609     'target/i386',
3610     'target/i386/kvm',
3611     'target/loongarch',
3612     'target/mips/tcg',
3613     'target/ppc',
3614     'target/riscv',
3615     'target/s390x',
3616     'target/s390x/kvm',
3617     'target/sparc',
3618   ]
3619 endif
3620 
3621 ###################
3622 # Collect sources #
3623 ###################
3624 
3625 authz_ss = ss.source_set()
3626 blockdev_ss = ss.source_set()
3627 block_ss = ss.source_set()
3628 chardev_ss = ss.source_set()
3629 common_ss = ss.source_set()
3630 crypto_ss = ss.source_set()
3631 hwcore_ss = ss.source_set()
3632 io_ss = ss.source_set()
3633 qmp_ss = ss.source_set()
3634 qom_ss = ss.source_set()
3635 system_ss = ss.source_set()
3636 specific_fuzz_ss = ss.source_set()
3637 specific_ss = ss.source_set()
3638 rust_devices_ss = ss.source_set()
3639 stub_ss = ss.source_set()
3640 trace_ss = ss.source_set()
3641 user_ss = ss.source_set()
3642 util_ss = ss.source_set()
3643 
3644 # accel modules
3645 qtest_module_ss = ss.source_set()
3646 tcg_module_ss = ss.source_set()
3647 
3648 modules = {}
3649 target_modules = {}
3650 hw_arch = {}
3651 target_arch = {}
3652 target_system_arch = {}
3653 target_user_arch = {}
3654 
3655 # NOTE: the trace/ subdirectory needs the qapi_trace_events variable
3656 # that is filled in by qapi/.
3657 subdir('qapi')
3658 subdir('qobject')
3659 subdir('stubs')
3660 subdir('trace')
3661 subdir('util')
3662 subdir('qom')
3663 subdir('authz')
3664 subdir('crypto')
3665 subdir('ui')
3666 subdir('gdbstub')
3667 if have_system
3668   subdir('hw')
3669 else
3670   subdir('hw/core')
3671 endif
3672 
3673 if enable_modules
3674   libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
3675   modulecommon = declare_dependency(objects: libmodulecommon.extract_all_objects(recursive: false), compile_args: '-DBUILD_DSO')
3676 endif
3677 
3678 qom_ss = qom_ss.apply({})
3679 libqom = static_library('qom', qom_ss.sources() + genh,
3680                         dependencies: [qom_ss.dependencies()],
3681                         build_by_default: false)
3682 qom = declare_dependency(objects: libqom.extract_all_objects(recursive: false),
3683                          dependencies: qom_ss.dependencies())
3684 
3685 event_loop_base = files('event-loop-base.c')
3686 event_loop_base = static_library('event-loop-base',
3687                                  sources: event_loop_base + genh,
3688                                  build_by_default: false)
3689 event_loop_base = declare_dependency(objects: event_loop_base.extract_all_objects(recursive: false),
3690                                      dependencies: [qom])
3691 
3692 stub_ss = stub_ss.apply({})
3693 
3694 util_ss.add_all(trace_ss)
3695 util_ss = util_ss.apply({})
3696 libqemuutil = static_library('qemuutil',
3697                              build_by_default: false,
3698                              sources: util_ss.sources() + stub_ss.sources() + genh,
3699                              dependencies: [util_ss.dependencies(), libm, threads, glib, socket, malloc])
3700 qemuutil = declare_dependency(link_with: libqemuutil,
3701                               sources: genh + version_res,
3702                               dependencies: [event_loop_base])
3703 
3704 if have_system or have_user
3705   decodetree = generator(find_program('scripts/decodetree.py'),
3706                          output: 'decode-@BASENAME@.c.inc',
3707                          arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
3708   subdir('libdecnumber')
3709   subdir('target')
3710 endif
3711 
3712 subdir('audio')
3713 subdir('io')
3714 subdir('chardev')
3715 subdir('fsdev')
3716 subdir('dump')
3717 
3718 if have_block
3719   block_ss.add(files(
3720     'block.c',
3721     'blockjob.c',
3722     'job.c',
3723     'qemu-io-cmds.c',
3724   ))
3725   if config_host_data.get('CONFIG_REPLICATION')
3726     block_ss.add(files('replication.c'))
3727   endif
3728 
3729   subdir('nbd')
3730   subdir('scsi')
3731   subdir('block')
3732 
3733   blockdev_ss.add(files(
3734     'blockdev.c',
3735     'blockdev-nbd.c',
3736     'iothread.c',
3737     'job-qmp.c',
3738   ))
3739 
3740   # os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
3741   # os-win32.c does not
3742   if host_os == 'windows'
3743     system_ss.add(files('os-win32.c'))
3744   else
3745     blockdev_ss.add(files('os-posix.c'))
3746   endif
3747 endif
3748 
3749 common_ss.add(files('cpu-common.c'))
3750 specific_ss.add(files('cpu-target.c'))
3751 
3752 subdir('system')
3753 
3754 # Work around a gcc bug/misfeature wherein constant propagation looks
3755 # through an alias:
3756 #   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99696
3757 # to guess that a const variable is always zero.  Without lto, this is
3758 # impossible, as the alias is restricted to page-vary-common.c.  Indeed,
3759 # without lto, not even the alias is required -- we simply use different
3760 # declarations in different compilation units.
3761 pagevary = files('page-vary-common.c')
3762 if get_option('b_lto')
3763   pagevary_flags = ['-fno-lto']
3764   if get_option('cfi')
3765     pagevary_flags += '-fno-sanitize=cfi-icall'
3766   endif
3767   pagevary = static_library('page-vary-common', sources: pagevary + genh,
3768                             c_args: pagevary_flags)
3769   pagevary = declare_dependency(link_with: pagevary)
3770 endif
3771 common_ss.add(pagevary)
3772 specific_ss.add(files('page-target.c', 'page-vary-target.c'))
3773 
3774 subdir('backends')
3775 subdir('disas')
3776 subdir('migration')
3777 subdir('monitor')
3778 subdir('net')
3779 subdir('replay')
3780 subdir('semihosting')
3781 subdir('stats')
3782 subdir('tcg')
3783 subdir('fpu')
3784 subdir('accel')
3785 subdir('plugins')
3786 subdir('ebpf')
3787 
3788 if 'CONFIG_TCG' in config_all_accel
3789   subdir('contrib/plugins')
3790 endif
3791 
3792 common_user_inc = []
3793 
3794 subdir('common-user')
3795 subdir('bsd-user')
3796 subdir('linux-user')
3797 
3798 # needed for fuzzing binaries
3799 subdir('tests/qtest/libqos')
3800 subdir('tests/qtest/fuzz')
3801 
3802 # accel modules
3803 tcg_real_module_ss = ss.source_set()
3804 tcg_real_module_ss.add_all(when: 'CONFIG_TCG_MODULAR', if_true: tcg_module_ss)
3805 specific_ss.add_all(when: 'CONFIG_TCG_BUILTIN', if_true: tcg_module_ss)
3806 target_modules += { 'accel' : { 'qtest': qtest_module_ss,
3807                                 'tcg': tcg_real_module_ss }}
3808 
3809 ##############################################
3810 # Internal static_libraries and dependencies #
3811 ##############################################
3812 
3813 modinfo_collect = find_program('scripts/modinfo-collect.py')
3814 modinfo_generate = find_program('scripts/modinfo-generate.py')
3815 modinfo_files = []
3816 
3817 block_mods = []
3818 system_mods = []
3819 emulator_modules = []
3820 foreach d, list : modules
3821   if not (d == 'block' ? have_block : have_system)
3822     continue
3823   endif
3824 
3825   foreach m, module_ss : list
3826     if enable_modules
3827       module_ss.add(modulecommon)
3828       module_ss = module_ss.apply(config_all_devices, strict: false)
3829       sl = static_library(d + '-' + m, [genh, module_ss.sources()],
3830                           dependencies: module_ss.dependencies(), pic: true)
3831       if d == 'block'
3832         block_mods += sl
3833       else
3834         system_mods += sl
3835       endif
3836       emulator_modules += shared_module(sl.name(),
3837                     name_prefix: '',
3838                     objects: sl.extract_all_objects(recursive: false),
3839                     dependencies: module_ss.dependencies(),
3840                     install: true,
3841                     install_dir: qemu_moddir)
3842       if module_ss.sources() != []
3843         # FIXME: Should use sl.extract_all_objects(recursive: true) as
3844         # input. Sources can be used multiple times but objects are
3845         # unique when it comes to lookup in compile_commands.json.
3846         # Depnds on a mesion version with
3847         # https://github.com/mesonbuild/meson/pull/8900
3848         modinfo_files += custom_target(d + '-' + m + '.modinfo',
3849                                        output: d + '-' + m + '.modinfo',
3850                                        input: module_ss.sources() + genh,
3851                                        capture: true,
3852                                        command: [modinfo_collect, module_ss.sources()])
3853       endif
3854     else
3855       if d == 'block'
3856         block_ss.add_all(module_ss)
3857       else
3858         system_ss.add_all(module_ss)
3859       endif
3860     endif
3861   endforeach
3862 endforeach
3863 
3864 foreach d, list : target_modules
3865   foreach m, module_ss : list
3866     if enable_modules
3867       module_ss.add(modulecommon)
3868       foreach target : target_dirs
3869         if target.endswith('-softmmu')
3870           config_target = config_target_mak[target]
3871           target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
3872           c_args = ['-DCOMPILING_PER_TARGET',
3873                     '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
3874                     '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
3875           target_module_ss = module_ss.apply(config_target, strict: false)
3876           if target_module_ss.sources() != []
3877             module_name = d + '-' + m + '-' + config_target['TARGET_NAME']
3878             sl = static_library(module_name,
3879                                 [genh, target_module_ss.sources()],
3880                                 dependencies: target_module_ss.dependencies(),
3881                                 include_directories: target_inc,
3882                                 c_args: c_args,
3883                                 pic: true)
3884             system_mods += sl
3885             emulator_modules += shared_module(sl.name(),
3886                     name_prefix: '',
3887                     objects: sl.extract_all_objects(recursive: false),
3888                     dependencies: target_module_ss.dependencies(),
3889                     install: true,
3890                     install_dir: qemu_moddir)
3891             # FIXME: Should use sl.extract_all_objects(recursive: true) too.
3892             modinfo_files += custom_target(module_name + '.modinfo',
3893                                            output: module_name + '.modinfo',
3894                                            input: target_module_ss.sources() + genh,
3895                                            capture: true,
3896                                            command: [modinfo_collect, '--target', target, target_module_ss.sources()])
3897           endif
3898         endif
3899       endforeach
3900     else
3901       specific_ss.add_all(module_ss)
3902     endif
3903   endforeach
3904 endforeach
3905 
3906 if enable_modules
3907   foreach target : target_dirs
3908     if target.endswith('-softmmu')
3909       config_target = config_target_mak[target]
3910       config_devices_mak = target + '-config-devices.mak'
3911       modinfo_src = custom_target('modinfo-' + target + '.c',
3912                                   output: 'modinfo-' + target + '.c',
3913                                   input: modinfo_files,
3914                                   command: [modinfo_generate, '--devices', config_devices_mak, '@INPUT@'],
3915                                   capture: true)
3916 
3917       modinfo_lib = static_library('modinfo-' + target + '.c', modinfo_src)
3918       modinfo_dep = declare_dependency(link_with: modinfo_lib)
3919 
3920       arch = config_target['TARGET_NAME'] == 'sparc64' ? 'sparc64' : config_target['TARGET_BASE_ARCH']
3921       hw_arch[arch].add(modinfo_dep)
3922     endif
3923   endforeach
3924 
3925   if emulator_modules.length() > 0
3926     alias_target('modules', emulator_modules)
3927   endif
3928 endif
3929 
3930 nm = find_program('nm')
3931 undefsym = find_program('scripts/undefsym.py')
3932 block_syms = custom_target('block.syms', output: 'block.syms',
3933                              input: [libqemuutil, block_mods],
3934                              capture: true,
3935                              command: [undefsym, nm, '@INPUT@'])
3936 qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
3937                              input: [libqemuutil, system_mods],
3938                              capture: true,
3939                              command: [undefsym, nm, '@INPUT@'])
3940 
3941 authz_ss = authz_ss.apply({})
3942 libauthz = static_library('authz', authz_ss.sources() + genh,
3943                           dependencies: [authz_ss.dependencies()],
3944                           build_by_default: false)
3945 
3946 authz = declare_dependency(objects: libauthz.extract_all_objects(recursive: false),
3947                            dependencies: [authz_ss.dependencies(), qom])
3948 
3949 crypto_ss = crypto_ss.apply({})
3950 libcrypto = static_library('crypto', crypto_ss.sources() + genh,
3951                            dependencies: [crypto_ss.dependencies()],
3952                            build_by_default: false)
3953 
3954 crypto = declare_dependency(objects: libcrypto.extract_all_objects(recursive: false),
3955                             dependencies: [crypto_ss.dependencies(), authz, qom])
3956 
3957 io_ss = io_ss.apply({})
3958 libio = static_library('io', io_ss.sources() + genh,
3959                        dependencies: [io_ss.dependencies()],
3960                        link_with: libqemuutil,
3961                        build_by_default: false)
3962 
3963 io = declare_dependency(objects: libio.extract_all_objects(recursive: false),
3964                         dependencies: [io_ss.dependencies(), crypto, qom])
3965 
3966 libmigration = static_library('migration', sources: migration_files + genh,
3967                               build_by_default: false)
3968 migration = declare_dependency(objects: libmigration.extract_all_objects(recursive: false),
3969                                dependencies: [qom, io])
3970 system_ss.add(migration)
3971 
3972 block_ss = block_ss.apply({})
3973 libblock = static_library('block', block_ss.sources() + genh,
3974                           dependencies: block_ss.dependencies(),
3975                           build_by_default: false)
3976 
3977 block = declare_dependency(objects: libblock.extract_all_objects(recursive: false),
3978                            dependencies: [block_ss.dependencies(), crypto, io])
3979 
3980 blockdev_ss = blockdev_ss.apply({})
3981 libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
3982                              dependencies: blockdev_ss.dependencies(),
3983                              build_by_default: false)
3984 
3985 blockdev = declare_dependency(objects: libblockdev.extract_all_objects(recursive: false),
3986                               dependencies: [blockdev_ss.dependencies(), block, event_loop_base])
3987 
3988 qmp_ss = qmp_ss.apply({})
3989 libqmp = static_library('qmp', qmp_ss.sources() + genh,
3990                         dependencies: qmp_ss.dependencies(),
3991                         build_by_default: false)
3992 
3993 qmp = declare_dependency(objects: libqmp.extract_all_objects(recursive: false),
3994                          dependencies: qmp_ss.dependencies())
3995 
3996 libchardev = static_library('chardev', chardev_ss.sources() + genh,
3997                             dependencies: chardev_ss.dependencies(),
3998                             build_by_default: false)
3999 
4000 chardev = declare_dependency(objects: libchardev.extract_all_objects(recursive: false),
4001                              dependencies: chardev_ss.dependencies())
4002 
4003 hwcore_ss = hwcore_ss.apply({})
4004 libhwcore = static_library('hwcore', sources: hwcore_ss.sources() + genh,
4005                            build_by_default: false)
4006 hwcore = declare_dependency(objects: libhwcore.extract_all_objects(recursive: false))
4007 common_ss.add(hwcore)
4008 
4009 ###########
4010 # Targets #
4011 ###########
4012 
4013 system_ss.add(authz, blockdev, chardev, crypto, io, qmp)
4014 common_ss.add(qom, qemuutil)
4015 
4016 common_ss.add_all(when: 'CONFIG_SYSTEM_ONLY', if_true: [system_ss])
4017 common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
4018 
4019 # Note that this library is never used directly (only through extract_objects)
4020 # and is not built by default; therefore, source files not used by the build
4021 # configuration will be in build.ninja, but are never built by default.
4022 common_all = static_library('common',
4023                             build_by_default: false,
4024                             sources: common_ss.all_sources() + genh,
4025                             include_directories: common_user_inc,
4026                             implicit_include_directories: false,
4027                             dependencies: common_ss.all_dependencies())
4028 
4029 if have_rust
4030   # We would like to use --generate-cstr, but it is only available
4031   # starting with bindgen 0.66.0.  The oldest supported versions
4032   # is 0.60.x (Debian 12 has 0.60.1) which introduces --allowlist-file.
4033   bindgen_args = [
4034     '--disable-header-comment',
4035     '--raw-line', '// @generated',
4036     '--ctypes-prefix', 'std::os::raw',
4037     '--generate-block',
4038     '--impl-debug',
4039     '--no-doc-comments',
4040     '--with-derive-default',
4041     '--no-layout-tests',
4042     '--no-prepend-enum-name',
4043     '--allowlist-file', meson.project_source_root() + '/include/.*',
4044     '--allowlist-file', meson.project_source_root() + '/.*',
4045     '--allowlist-file', meson.project_build_root() + '/.*'
4046     ]
4047   if not rustfmt.found()
4048     if bindgen.version().version_compare('<0.65.0')
4049       bindgen_args += ['--no-rustfmt-bindings']
4050     else
4051       bindgen_args += ['--formatter', 'none']
4052     endif
4053   endif
4054   if bindgen.version().version_compare('>=0.66.0')
4055     bindgen_args += ['--rust-target', '1.59']
4056   endif
4057   if bindgen.version().version_compare('<0.61.0')
4058     # default in 0.61+
4059     bindgen_args += ['--size_t-is-usize']
4060   else
4061     bindgen_args += ['--merge-extern-blocks']
4062   endif
4063   c_enums = [
4064     'DeviceCategory',
4065     'GpioPolarity',
4066     'MachineInitPhase',
4067     'MemoryDeviceInfoKind',
4068     'MigrationPolicy',
4069     'MigrationPriority',
4070     'QEMUChrEvent',
4071     'QEMUClockType',
4072     'device_endian',
4073     'module_init_type',
4074   ]
4075   foreach enum : c_enums
4076     bindgen_args += ['--rustified-enum', enum]
4077   endforeach
4078   c_bitfields = [
4079     'ClockEvent',
4080     'VMStateFlags',
4081   ]
4082   foreach enum : c_bitfields
4083     bindgen_args += ['--bitfield-enum', enum]
4084   endforeach
4085 
4086   # TODO: Remove this comment when the clang/libclang mismatch issue is solved.
4087   #
4088   # Rust bindings generation with `bindgen` might fail in some cases where the
4089   # detected `libclang` does not match the expected `clang` version/target. In
4090   # this case you must pass the path to `clang` and `libclang` to your build
4091   # command invocation using the environment variables CLANG_PATH and
4092   # LIBCLANG_PATH
4093   bindings_rs = rust.bindgen(
4094     input: 'rust/wrapper.h',
4095     dependencies: common_ss.all_dependencies(),
4096     output: 'bindings.rs',
4097     include_directories: include_directories('.', 'include'),
4098     bindgen_version: ['>=0.60.0'],
4099     args: bindgen_args,
4100     )
4101   subdir('rust')
4102 endif
4103 
4104 
4105 feature_to_c = find_program('scripts/feature_to_c.py')
4106 rust_root_crate = find_program('scripts/rust/rust_root_crate.sh')
4107 
4108 if host_os == 'darwin'
4109   entitlement = find_program('scripts/entitlement.sh')
4110 endif
4111 
4112 traceable = []
4113 emulators = {}
4114 foreach target : target_dirs
4115   config_target = config_target_mak[target]
4116   target_name = config_target['TARGET_NAME']
4117   target_base_arch = config_target['TARGET_BASE_ARCH']
4118   arch_srcs = [config_target_h[target]]
4119   arch_deps = []
4120   c_args = ['-DCOMPILING_PER_TARGET',
4121             '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
4122             '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
4123   link_args = emulator_link_args
4124 
4125   target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
4126   if host_os == 'linux'
4127     target_inc += include_directories('linux-headers', is_system: true)
4128   endif
4129   if target.endswith('-softmmu')
4130     target_type='system'
4131     t = target_system_arch[target_base_arch].apply(config_target, strict: false)
4132     arch_srcs += t.sources()
4133     arch_deps += t.dependencies()
4134 
4135     hw_dir = target_name == 'sparc64' ? 'sparc64' : target_base_arch
4136     if hw_arch.has_key(hw_dir)
4137       hw = hw_arch[hw_dir].apply(config_target, strict: false)
4138       arch_srcs += hw.sources()
4139       arch_deps += hw.dependencies()
4140     endif
4141 
4142     arch_srcs += config_devices_h[target]
4143     link_args += ['@block.syms', '@qemu.syms']
4144   else
4145     abi = config_target['TARGET_ABI_DIR']
4146     target_type='user'
4147     target_inc += common_user_inc
4148     if target_base_arch in target_user_arch
4149       t = target_user_arch[target_base_arch].apply(config_target, strict: false)
4150       arch_srcs += t.sources()
4151       arch_deps += t.dependencies()
4152     endif
4153     if 'CONFIG_LINUX_USER' in config_target
4154       base_dir = 'linux-user'
4155     endif
4156     if 'CONFIG_BSD_USER' in config_target
4157       base_dir = 'bsd-user'
4158       target_inc += include_directories('bsd-user/' / host_os)
4159       target_inc += include_directories('bsd-user/host/' / host_arch)
4160       dir = base_dir / abi
4161       arch_srcs += files(dir / 'signal.c', dir / 'target_arch_cpu.c')
4162     endif
4163     target_inc += include_directories(
4164       base_dir,
4165       base_dir / abi,
4166     )
4167     if 'CONFIG_LINUX_USER' in config_target
4168       dir = base_dir / abi
4169       arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
4170       if config_target.has_key('TARGET_SYSTBL_ABI')
4171         arch_srcs += \
4172           syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
4173                                              extra_args : config_target['TARGET_SYSTBL_ABI'])
4174       endif
4175     endif
4176   endif
4177 
4178   if 'TARGET_XML_FILES' in config_target
4179     gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
4180                                 output: target + '-gdbstub-xml.c',
4181                                 input: files(config_target['TARGET_XML_FILES'].split()),
4182                                 command: [feature_to_c, '@INPUT@'],
4183                                 capture: true)
4184     arch_srcs += gdbstub_xml
4185   endif
4186 
4187   t = target_arch[target_base_arch].apply(config_target, strict: false)
4188   arch_srcs += t.sources()
4189   arch_deps += t.dependencies()
4190 
4191   target_common = common_ss.apply(config_target, strict: false)
4192   objects = common_all.extract_objects(target_common.sources())
4193   arch_deps += target_common.dependencies()
4194 
4195   target_specific = specific_ss.apply(config_target, strict: false)
4196   arch_srcs += target_specific.sources()
4197   arch_deps += target_specific.dependencies()
4198 
4199   if have_rust and target_type == 'system'
4200     target_rust = rust_devices_ss.apply(config_target, strict: false)
4201     crates = []
4202     foreach dep : target_rust.dependencies()
4203       crates += dep.get_variable('crate')
4204     endforeach
4205     if crates.length() > 0
4206       rlib_rs = custom_target('rust_' + target.underscorify() + '.rs',
4207                               output: 'rust_' + target.underscorify() + '.rs',
4208                               command: [rust_root_crate, crates],
4209                               capture: true,
4210                               build_by_default: true,
4211                               build_always_stale: true)
4212       rlib = static_library('rust_' + target.underscorify(),
4213                             rlib_rs,
4214                             dependencies: target_rust.dependencies(),
4215                             override_options: ['rust_std=2021', 'build.rust_std=2021'],
4216                             rust_abi: 'c')
4217       arch_deps += declare_dependency(link_whole: [rlib])
4218     endif
4219   endif
4220 
4221   # allow using headers from the dependencies but do not include the sources,
4222   # because this emulator only needs those in "objects".  For external
4223   # dependencies, the full dependency is included below in the executable.
4224   lib_deps = []
4225   foreach dep : arch_deps
4226     lib_deps += dep.partial_dependency(compile_args: true, includes: true)
4227   endforeach
4228 
4229   lib = static_library('qemu-' + target,
4230                  sources: arch_srcs + genh,
4231                  dependencies: lib_deps,
4232                  objects: objects,
4233                  include_directories: target_inc,
4234                  c_args: c_args,
4235                  build_by_default: false)
4236 
4237   if target.endswith('-softmmu')
4238     execs = [{
4239       'name': 'qemu-system-' + target_name,
4240       'win_subsystem': 'console',
4241       'sources': files('system/main.c'),
4242       'dependencies': [sdl]
4243     }]
4244     if host_os == 'windows' and (sdl.found() or gtk.found())
4245       execs += [{
4246         'name': 'qemu-system-' + target_name + 'w',
4247         'win_subsystem': 'windows',
4248         'sources': files('system/main.c'),
4249         'dependencies': [sdl]
4250       }]
4251     endif
4252     if get_option('fuzzing')
4253       specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
4254       execs += [{
4255         'name': 'qemu-fuzz-' + target_name,
4256         'win_subsystem': 'console',
4257         'sources': specific_fuzz.sources(),
4258         'dependencies': specific_fuzz.dependencies(),
4259       }]
4260     endif
4261   else
4262     execs = [{
4263       'name': 'qemu-' + target_name,
4264       'win_subsystem': 'console',
4265       'sources': [],
4266       'dependencies': []
4267     }]
4268   endif
4269   foreach exe: execs
4270     exe_name = exe['name']
4271     if host_os == 'darwin'
4272       exe_name += '-unsigned'
4273     endif
4274 
4275     emulator = executable(exe_name, exe['sources'],
4276                install: true,
4277                c_args: c_args,
4278                dependencies: arch_deps + exe['dependencies'],
4279                objects: lib.extract_all_objects(recursive: true),
4280                link_depends: [block_syms, qemu_syms],
4281                link_args: link_args,
4282                win_subsystem: exe['win_subsystem'])
4283 
4284     if host_os == 'darwin'
4285       icon = 'pc-bios/qemu.rsrc'
4286       build_input = [emulator, files(icon)]
4287       install_input = [
4288         get_option('bindir') / exe_name,
4289         meson.current_source_dir() / icon
4290       ]
4291       if 'CONFIG_HVF' in config_target
4292         entitlements = 'accel/hvf/entitlements.plist'
4293         build_input += files(entitlements)
4294         install_input += meson.current_source_dir() / entitlements
4295       endif
4296 
4297       emulators += {exe['name'] : custom_target(exe['name'],
4298                    input: build_input,
4299                    output: exe['name'],
4300                    command: [entitlement, '@OUTPUT@', '@INPUT@'])
4301       }
4302 
4303       meson.add_install_script(entitlement, '--install',
4304                                get_option('bindir') / exe['name'],
4305                                install_input)
4306     else
4307       emulators += {exe['name']: emulator}
4308     endif
4309 
4310     traceable += [{
4311       'exe': exe['name'],
4312       'probe-prefix': 'qemu.' + target_type + '.' + target_name,
4313     }]
4314 
4315   endforeach
4316 endforeach
4317 
4318 # Other build targets
4319 
4320 if get_option('plugins')
4321   install_headers('include/qemu/qemu-plugin.h')
4322   if host_os == 'windows'
4323     # On windows, we want to deliver the qemu_plugin_api.lib file in the qemu installer,
4324     # so that plugin authors can compile against it.
4325     install_data(win32_qemu_plugin_api_lib, install_dir: 'lib')
4326   endif
4327 endif
4328 
4329 subdir('qga')
4330 
4331 # Don't build qemu-keymap if xkbcommon is not explicitly enabled
4332 # when we don't build tools or system
4333 if xkbcommon.found()
4334   # used for the update-keymaps target, so include rules even if !have_tools
4335   qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
4336                            dependencies: [qemuutil, xkbcommon], install: have_tools)
4337 endif
4338 
4339 if have_tools
4340   qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
4341              link_args: '@block.syms', link_depends: block_syms,
4342              dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
4343   qemu_io = executable('qemu-io', files('qemu-io.c'),
4344              link_args: '@block.syms', link_depends: block_syms,
4345              dependencies: [block, qemuutil], install: true)
4346   qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
4347                link_args: '@block.syms', link_depends: block_syms,
4348                dependencies: [blockdev, qemuutil, selinux],
4349                install: true)
4350 
4351   subdir('storage-daemon')
4352 
4353   foreach exe: [ 'qemu-img', 'qemu-io', 'qemu-nbd', 'qemu-storage-daemon']
4354     traceable += [{
4355       'exe': exe,
4356       'probe-prefix': 'qemu.' + exe.substring(5).replace('-', '_')
4357     }]
4358   endforeach
4359 
4360   subdir('contrib/elf2dmp')
4361 
4362   executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
4363              dependencies: qemuutil,
4364              install: true)
4365 
4366   if have_vhost_user
4367     subdir('contrib/vhost-user-blk')
4368     subdir('contrib/vhost-user-gpu')
4369     subdir('contrib/vhost-user-input')
4370     subdir('contrib/vhost-user-scsi')
4371   endif
4372 
4373   if host_os == 'linux'
4374     executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
4375                dependencies: [qemuutil, libcap_ng],
4376                install: true,
4377                install_dir: get_option('libexecdir'))
4378 
4379     executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
4380                dependencies: [authz, crypto, io, qom, qemuutil,
4381                               libcap_ng, mpathpersist],
4382                install: true)
4383 
4384     if cpu in ['x86', 'x86_64']
4385       executable('qemu-vmsr-helper', files('tools/i386/qemu-vmsr-helper.c'),
4386                dependencies: [authz, crypto, io, qom, qemuutil,
4387                               libcap_ng, mpathpersist],
4388                install: true)
4389     endif
4390   endif
4391 
4392   if have_ivshmem
4393     subdir('contrib/ivshmem-client')
4394     subdir('contrib/ivshmem-server')
4395   endif
4396 endif
4397 
4398 if stap.found()
4399   foreach t: traceable
4400     foreach stp: [
4401       {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / t['exe'], 'install': false},
4402       {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / t['exe'], 'install': true},
4403       {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
4404       {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
4405     ]
4406       cmd = [
4407         tracetool, '--group=all', '--format=' + stp['fmt'],
4408         '--binary=' + stp['bin'],
4409         '--probe-prefix=' + t['probe-prefix'],
4410         '@INPUT@', '@OUTPUT@'
4411       ]
4412 
4413       custom_target(t['exe'] + stp['ext'],
4414                     input: trace_events_all,
4415                     output: t['exe'] + stp['ext'],
4416                     install: stp['install'],
4417                     install_dir: get_option('datadir') / 'systemtap/tapset',
4418                     command: cmd,
4419                     depend_files: tracetool_depends)
4420     endforeach
4421   endforeach
4422 endif
4423 
4424 subdir('scripts')
4425 subdir('tools')
4426 subdir('pc-bios')
4427 subdir('docs')
4428 subdir('tests')
4429 if gtk.found()
4430   subdir('po')
4431 endif
4432 
4433 if host_machine.system() == 'windows'
4434   nsis_cmd = [
4435     find_program('scripts/nsis.py'),
4436     '@OUTPUT@',
4437     get_option('prefix'),
4438     meson.current_source_dir(),
4439     glib_pc.get_variable('bindir'),
4440     host_machine.cpu(),
4441     '--',
4442     '-DDISPLAYVERSION=' + meson.project_version(),
4443   ]
4444   if build_docs
4445     nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
4446   endif
4447   if gtk.found()
4448     nsis_cmd += '-DCONFIG_GTK=y'
4449   endif
4450 
4451   nsis = custom_target('nsis',
4452                        output: 'qemu-setup-' + meson.project_version() + '.exe',
4453                        input: files('qemu.nsi'),
4454                        build_always_stale: true,
4455                        command: nsis_cmd + ['@INPUT@'])
4456   alias_target('installer', nsis)
4457 endif
4458 
4459 #########################
4460 # Configuration summary #
4461 #########################
4462 
4463 # Build environment
4464 summary_info = {}
4465 summary_info += {'Build directory':   meson.current_build_dir()}
4466 summary_info += {'Source path':       meson.current_source_dir()}
4467 summary_info += {'Download dependencies': get_option('wrap_mode') != 'nodownload'}
4468 summary(summary_info, bool_yn: true, section: 'Build environment')
4469 
4470 # Directories
4471 summary_info += {'Install prefix':    get_option('prefix')}
4472 summary_info += {'BIOS directory':    qemu_datadir}
4473 pathsep = host_os == 'windows' ? ';' : ':'
4474 summary_info += {'firmware path':     pathsep.join(get_option('qemu_firmwarepath'))}
4475 summary_info += {'binary directory':  get_option('prefix') / get_option('bindir')}
4476 summary_info += {'library directory': get_option('prefix') / get_option('libdir')}
4477 summary_info += {'module directory':  qemu_moddir}
4478 summary_info += {'libexec directory': get_option('prefix') / get_option('libexecdir')}
4479 summary_info += {'include directory': get_option('prefix') / get_option('includedir')}
4480 summary_info += {'config directory':  get_option('prefix') / get_option('sysconfdir')}
4481 if host_os != 'windows'
4482   summary_info += {'local state directory': get_option('prefix') / get_option('localstatedir')}
4483   summary_info += {'Manual directory':      get_option('prefix') / get_option('mandir')}
4484 else
4485   summary_info += {'local state directory': 'queried at runtime'}
4486 endif
4487 summary_info += {'Doc directory':     get_option('prefix') / get_option('docdir')}
4488 summary(summary_info, bool_yn: true, section: 'Directories')
4489 
4490 # Host binaries
4491 summary_info = {}
4492 summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
4493 summary_info += {'sphinx-build':      sphinx_build}
4494 
4495 # FIXME: the [binaries] section of machine files, which can be probed
4496 # with find_program(), would be great for passing gdb and genisoimage
4497 # paths from configure to Meson.  However, there seems to be no way to
4498 # hide a program (for example if gdb is too old).
4499 if config_host.has_key('GDB')
4500   summary_info += {'gdb':             config_host['GDB']}
4501 endif
4502 summary_info += {'iasl':              iasl}
4503 summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
4504 if host_os == 'windows' and have_ga
4505   summary_info += {'wixl':            wixl}
4506 endif
4507 if slirp.found() and have_system
4508   summary_info += {'smbd':            have_slirp_smbd ? smbd_path : false}
4509 endif
4510 summary(summary_info, bool_yn: true, section: 'Host binaries')
4511 
4512 # Configurable features
4513 summary_info = {}
4514 summary_info += {'Documentation':     build_docs}
4515 summary_info += {'system-mode emulation': have_system}
4516 summary_info += {'user-mode emulation': have_user}
4517 summary_info += {'block layer':       have_block}
4518 summary_info += {'Install blobs':     get_option('install_blobs')}
4519 summary_info += {'module support':    enable_modules}
4520 if enable_modules
4521   summary_info += {'alternative module path': get_option('module_upgrades')}
4522 endif
4523 summary_info += {'fuzzing support':   get_option('fuzzing')}
4524 if have_system
4525   summary_info += {'Audio drivers':     ' '.join(audio_drivers_selected)}
4526 endif
4527 summary_info += {'Trace backends':    ','.join(get_option('trace_backends'))}
4528 if 'simple' in get_option('trace_backends')
4529   summary_info += {'Trace output file': get_option('trace_file') + '-<pid>'}
4530 endif
4531 summary_info += {'D-Bus display':     dbus_display}
4532 summary_info += {'QOM debugging':     get_option('qom_cast_debug')}
4533 summary_info += {'Relocatable install': get_option('relocatable')}
4534 summary_info += {'vhost-kernel support': have_vhost_kernel}
4535 summary_info += {'vhost-net support': have_vhost_net}
4536 summary_info += {'vhost-user support': have_vhost_user}
4537 summary_info += {'vhost-user-crypto support': have_vhost_user_crypto}
4538 summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
4539 summary_info += {'vhost-vdpa support': have_vhost_vdpa}
4540 summary_info += {'build guest agent': have_ga}
4541 summary(summary_info, bool_yn: true, section: 'Configurable features')
4542 
4543 # Compilation information
4544 summary_info = {}
4545 summary_info += {'host CPU':          cpu}
4546 summary_info += {'host endianness':   build_machine.endian()}
4547 summary_info += {'C compiler':        ' '.join(meson.get_compiler('c').cmd_array())}
4548 summary_info += {'Host C compiler':   ' '.join(meson.get_compiler('c', native: true).cmd_array())}
4549 if 'cpp' in all_languages
4550   summary_info += {'C++ compiler':    ' '.join(meson.get_compiler('cpp').cmd_array())}
4551 else
4552   summary_info += {'C++ compiler':      false}
4553 endif
4554 if 'objc' in all_languages
4555   summary_info += {'Objective-C compiler': ' '.join(meson.get_compiler('objc').cmd_array())}
4556 else
4557   summary_info += {'Objective-C compiler': false}
4558 endif
4559 summary_info += {'Rust support':      have_rust}
4560 if have_rust
4561   summary_info += {'Rust target':     config_host['RUST_TARGET_TRIPLE']}
4562   summary_info += {'rustc':           ' '.join(rustc.cmd_array())}
4563   summary_info += {'rustc version':   rustc.version()}
4564   summary_info += {'bindgen':         bindgen.full_path()}
4565   summary_info += {'bindgen version': bindgen.version()}
4566 endif
4567 option_cflags = (get_option('debug') ? ['-g'] : [])
4568 if get_option('optimization') != 'plain'
4569   option_cflags += ['-O' + get_option('optimization')]
4570 endif
4571 summary_info += {'CFLAGS':            ' '.join(get_option('c_args') + option_cflags)}
4572 if 'cpp' in all_languages
4573   summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args') + option_cflags)}
4574 endif
4575 if 'objc' in all_languages
4576   summary_info += {'OBJCFLAGS':       ' '.join(get_option('objc_args') + option_cflags)}
4577 endif
4578 link_args = get_option('c_link_args')
4579 if link_args.length() > 0
4580   summary_info += {'LDFLAGS':         ' '.join(link_args)}
4581 endif
4582 summary_info += {'QEMU_CFLAGS':       ' '.join(qemu_common_flags + qemu_cflags)}
4583 if 'cpp' in all_languages
4584   summary_info += {'QEMU_CXXFLAGS':     ' '.join(qemu_common_flags + qemu_cxxflags)}
4585 endif
4586 if 'objc' in all_languages
4587   summary_info += {'QEMU_OBJCFLAGS':    ' '.join(qemu_common_flags)}
4588 endif
4589 summary_info += {'QEMU_LDFLAGS':      ' '.join(qemu_ldflags)}
4590 summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
4591 summary_info += {'PIE':               get_option('b_pie')}
4592 summary_info += {'static build':      get_option('prefer_static')}
4593 summary_info += {'malloc trim support': has_malloc_trim}
4594 summary_info += {'membarrier':        have_membarrier}
4595 summary_info += {'debug graph lock':  get_option('debug_graph_lock')}
4596 summary_info += {'debug stack usage': get_option('debug_stack_usage')}
4597 summary_info += {'mutex debugging':   get_option('debug_mutex')}
4598 summary_info += {'memory allocator':  get_option('malloc')}
4599 summary_info += {'avx2 optimization': config_host_data.get('CONFIG_AVX2_OPT')}
4600 summary_info += {'avx512bw optimization': config_host_data.get('CONFIG_AVX512BW_OPT')}
4601 summary_info += {'gcov':              get_option('b_coverage')}
4602 summary_info += {'thread sanitizer':  get_option('tsan')}
4603 summary_info += {'CFI support':       get_option('cfi')}
4604 if get_option('cfi')
4605   summary_info += {'CFI debug support': get_option('cfi_debug')}
4606 endif
4607 summary_info += {'strip binaries':    get_option('strip')}
4608 summary_info += {'sparse':            sparse}
4609 summary_info += {'mingw32 support':   host_os == 'windows'}
4610 summary(summary_info, bool_yn: true, section: 'Compilation')
4611 
4612 # snarf the cross-compilation information for tests
4613 summary_info = {}
4614 have_cross = false
4615 foreach target: target_dirs
4616   tcg_mak = meson.current_build_dir() / 'tests/tcg' / target / 'config-target.mak'
4617   if fs.exists(tcg_mak)
4618     config_cross_tcg = keyval.load(tcg_mak)
4619     if 'CC' in config_cross_tcg
4620       summary_info += {config_cross_tcg['TARGET_NAME']: config_cross_tcg['CC']}
4621       have_cross = true
4622     endif
4623   endif
4624 endforeach
4625 if have_cross
4626   summary(summary_info, bool_yn: true, section: 'Cross compilers')
4627 endif
4628 
4629 # Targets and accelerators
4630 summary_info = {}
4631 if have_system
4632   summary_info += {'KVM support':       config_all_accel.has_key('CONFIG_KVM')}
4633   summary_info += {'HVF support':       config_all_accel.has_key('CONFIG_HVF')}
4634   summary_info += {'WHPX support':      config_all_accel.has_key('CONFIG_WHPX')}
4635   summary_info += {'NVMM support':      config_all_accel.has_key('CONFIG_NVMM')}
4636   summary_info += {'Xen support':       xen.found()}
4637   if xen.found()
4638     summary_info += {'xen ctrl version':  xen.version()}
4639   endif
4640   summary_info += {'Xen emulation':     config_all_devices.has_key('CONFIG_XEN_EMU')}
4641 endif
4642 summary_info += {'TCG support':       config_all_accel.has_key('CONFIG_TCG')}
4643 if config_all_accel.has_key('CONFIG_TCG')
4644   if get_option('tcg_interpreter')
4645     summary_info += {'TCG backend':   'TCI (TCG with bytecode interpreter, slow)'}
4646   else
4647     summary_info += {'TCG backend':   'native (@0@)'.format(cpu)}
4648   endif
4649   summary_info += {'TCG plugins':       get_option('plugins')}
4650   summary_info += {'TCG debug enabled': get_option('debug_tcg')}
4651   if have_linux_user or have_bsd_user
4652     summary_info += {'syscall buffer debugging support': get_option('debug_remap')}
4653   endif
4654 endif
4655 summary_info += {'target list':       ' '.join(target_dirs)}
4656 if have_system
4657   summary_info += {'default devices':   get_option('default_devices')}
4658   summary_info += {'out of process emulation': multiprocess_allowed}
4659   summary_info += {'vfio-user server': vfio_user_server_allowed}
4660 endif
4661 summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
4662 
4663 # Block layer
4664 summary_info = {}
4665 summary_info += {'coroutine backend': coroutine_backend}
4666 summary_info += {'coroutine pool':    have_coroutine_pool}
4667 if have_block
4668   summary_info += {'Block whitelist (rw)': get_option('block_drv_rw_whitelist')}
4669   summary_info += {'Block whitelist (ro)': get_option('block_drv_ro_whitelist')}
4670   summary_info += {'Use block whitelist in tools': get_option('block_drv_whitelist_in_tools')}
4671   summary_info += {'VirtFS (9P) support':    have_virtfs}
4672   summary_info += {'replication support': config_host_data.get('CONFIG_REPLICATION')}
4673   summary_info += {'bochs support':     get_option('bochs').allowed()}
4674   summary_info += {'cloop support':     get_option('cloop').allowed()}
4675   summary_info += {'dmg support':       get_option('dmg').allowed()}
4676   summary_info += {'qcow v1 support':   get_option('qcow1').allowed()}
4677   summary_info += {'vdi support':       get_option('vdi').allowed()}
4678   summary_info += {'vhdx support':      get_option('vhdx').allowed()}
4679   summary_info += {'vmdk support':      get_option('vmdk').allowed()}
4680   summary_info += {'vpc support':       get_option('vpc').allowed()}
4681   summary_info += {'vvfat support':     get_option('vvfat').allowed()}
4682   summary_info += {'qed support':       get_option('qed').allowed()}
4683   summary_info += {'parallels support': get_option('parallels').allowed()}
4684   summary_info += {'FUSE exports':      fuse}
4685   summary_info += {'VDUSE block exports': have_vduse_blk_export}
4686 endif
4687 summary(summary_info, bool_yn: true, section: 'Block layer support')
4688 
4689 # Crypto
4690 summary_info = {}
4691 summary_info += {'TLS priority':      get_option('tls_priority')}
4692 summary_info += {'GNUTLS support':    gnutls}
4693 if gnutls.found()
4694   summary_info += {'  GNUTLS crypto':   gnutls_crypto.found()}
4695 endif
4696 summary_info += {'libgcrypt':         gcrypt}
4697 summary_info += {'nettle':            nettle}
4698 if nettle.found()
4699    summary_info += {'  XTS':             xts != 'private'}
4700 endif
4701 summary_info += {'SM4 ALG support':   crypto_sm4}
4702 summary_info += {'SM3 ALG support':   crypto_sm3}
4703 summary_info += {'AF_ALG support':    have_afalg}
4704 summary_info += {'rng-none':          get_option('rng_none')}
4705 summary_info += {'Linux keyring':     have_keyring}
4706 summary_info += {'Linux keyutils':    keyutils}
4707 summary(summary_info, bool_yn: true, section: 'Crypto')
4708 
4709 # UI
4710 summary_info = {}
4711 if host_os == 'darwin'
4712   summary_info += {'Cocoa support':           cocoa}
4713 endif
4714 summary_info += {'SDL support':       sdl}
4715 summary_info += {'SDL image support': sdl_image}
4716 summary_info += {'GTK support':       gtk}
4717 summary_info += {'pixman':            pixman}
4718 summary_info += {'VTE support':       vte}
4719 summary_info += {'PNG support':       png}
4720 summary_info += {'VNC support':       vnc}
4721 if vnc.found()
4722   summary_info += {'VNC SASL support':  sasl}
4723   summary_info += {'VNC JPEG support':  jpeg}
4724 endif
4725 summary_info += {'spice protocol support': spice_protocol}
4726 if spice_protocol.found()
4727   summary_info += {'  spice server support': spice}
4728 endif
4729 summary_info += {'curses support':    curses}
4730 summary_info += {'brlapi support':    brlapi}
4731 summary(summary_info, bool_yn: true, section: 'User interface')
4732 
4733 # Graphics backends
4734 summary_info = {}
4735 summary_info += {'VirGL support':     virgl}
4736 summary_info += {'Rutabaga support':  rutabaga}
4737 summary(summary_info, bool_yn: true, section: 'Graphics backends')
4738 
4739 # Audio backends
4740 summary_info = {}
4741 if host_os not in ['darwin', 'haiku', 'windows']
4742   summary_info += {'OSS support':     oss}
4743   summary_info += {'sndio support':   sndio}
4744 elif host_os == 'darwin'
4745   summary_info += {'CoreAudio support': coreaudio}
4746 elif host_os == 'windows'
4747   summary_info += {'DirectSound support': dsound}
4748 endif
4749 if host_os == 'linux'
4750   summary_info += {'ALSA support':    alsa}
4751   summary_info += {'PulseAudio support': pulse}
4752 endif
4753 summary_info += {'PipeWire support':  pipewire}
4754 summary_info += {'JACK support':      jack}
4755 summary(summary_info, bool_yn: true, section: 'Audio backends')
4756 
4757 # Network backends
4758 summary_info = {}
4759 if host_os == 'darwin'
4760   summary_info += {'vmnet.framework support': vmnet}
4761 endif
4762 summary_info += {'AF_XDP support':    libxdp}
4763 summary_info += {'slirp support':     slirp}
4764 summary_info += {'vde support':       vde}
4765 summary_info += {'netmap support':    have_netmap}
4766 summary_info += {'l2tpv3 support':    have_l2tpv3}
4767 summary(summary_info, bool_yn: true, section: 'Network backends')
4768 
4769 # Libraries
4770 summary_info = {}
4771 summary_info += {'libtasn1':          tasn1}
4772 summary_info += {'PAM':               pam}
4773 summary_info += {'iconv support':     iconv}
4774 summary_info += {'blkio support':     blkio}
4775 summary_info += {'curl support':      curl}
4776 summary_info += {'Multipath support': mpathpersist}
4777 summary_info += {'Linux AIO support': libaio}
4778 summary_info += {'Linux io_uring support': linux_io_uring}
4779 summary_info += {'ATTR/XATTR support': libattr}
4780 summary_info += {'RDMA support':      rdma}
4781 summary_info += {'fdt support':       fdt_opt == 'internal' ? 'internal' : fdt}
4782 summary_info += {'libcap-ng support': libcap_ng}
4783 summary_info += {'bpf support':       libbpf}
4784 summary_info += {'rbd support':       rbd}
4785 summary_info += {'smartcard support': cacard}
4786 summary_info += {'U2F support':       u2f}
4787 summary_info += {'libusb':            libusb}
4788 summary_info += {'usb net redir':     usbredir}
4789 summary_info += {'OpenGL support (epoxy)': opengl}
4790 summary_info += {'GBM':               gbm}
4791 summary_info += {'libiscsi support':  libiscsi}
4792 summary_info += {'libnfs support':    libnfs}
4793 if host_os == 'windows'
4794   if have_ga
4795     summary_info += {'QGA VSS support':   have_qga_vss}
4796   endif
4797 endif
4798 summary_info += {'seccomp support':   seccomp}
4799 summary_info += {'GlusterFS support': glusterfs}
4800 summary_info += {'hv-balloon support': hv_balloon}
4801 summary_info += {'TPM support':       have_tpm}
4802 summary_info += {'libssh support':    libssh}
4803 summary_info += {'lzo support':       lzo}
4804 summary_info += {'snappy support':    snappy}
4805 summary_info += {'bzip2 support':     libbzip2}
4806 summary_info += {'lzfse support':     liblzfse}
4807 summary_info += {'zstd support':      zstd}
4808 summary_info += {'Query Processing Library support': qpl}
4809 summary_info += {'UADK Library support': uadk}
4810 summary_info += {'qatzip support':    qatzip}
4811 summary_info += {'NUMA host support': numa}
4812 summary_info += {'capstone':          capstone}
4813 summary_info += {'libpmem support':   libpmem}
4814 summary_info += {'libdaxctl support': libdaxctl}
4815 summary_info += {'libcbor support':   libcbor}
4816 summary_info += {'libudev':           libudev}
4817 # Dummy dependency, keep .found()
4818 summary_info += {'FUSE lseek':        fuse_lseek.found()}
4819 summary_info += {'selinux':           selinux}
4820 summary_info += {'libdw':             libdw}
4821 if host_os == 'freebsd'
4822   summary_info += {'libinotify-kqueue': inotify}
4823 endif
4824 summary(summary_info, bool_yn: true, section: 'Dependencies')
4825 
4826 if host_arch == 'unknown'
4827   message()
4828   warning('UNSUPPORTED HOST CPU')
4829   message()
4830   message('Support for CPU host architecture ' + cpu + ' is not currently')
4831   message('maintained. The QEMU project does not guarantee that QEMU will')
4832   message('compile or work on this host CPU. You can help by volunteering')
4833   message('to maintain it and providing a build host for our continuous')
4834   message('integration setup.')
4835   if get_option('tcg').allowed() and target_dirs.length() > 0
4836     message()
4837     message('configure has succeeded and you can continue to build, but')
4838     message('QEMU will use a slow interpreter to emulate the target CPU.')
4839   endif
4840 elif host_arch == 'mips'
4841   message()
4842   warning('DEPRECATED HOST CPU')
4843   message()
4844   message('Support for CPU host architecture ' + cpu + ' is going to be')
4845   message('dropped as soon as the QEMU project stops supporting Debian 12')
4846   message('("Bookworm"). Going forward, the QEMU project will not guarantee')
4847   message('that QEMU will compile or work on this host CPU.')
4848 endif
4849 
4850 if not supported_oses.contains(host_os)
4851   message()
4852   warning('UNSUPPORTED HOST OS')
4853   message()
4854   message('Support for host OS ' + host_os + 'is not currently maintained.')
4855   message('configure has succeeded and you can continue to build, but')
4856   message('the QEMU project does not guarantee that QEMU will compile or')
4857   message('work on this operating system. You can help by volunteering')
4858   message('to maintain it and providing a build host for our continuous')
4859   message('integration setup. This will ensure that future versions of QEMU')
4860   message('will keep working on ' + host_os + '.')
4861 endif
4862 
4863 if host_arch == 'unknown' or not supported_oses.contains(host_os)
4864   message()
4865   message('If you want to help supporting QEMU on this platform, please')
4866   message('contact the developers at qemu-devel@nongnu.org.')
4867 endif
4868 
4869 actually_reloc = get_option('relocatable')
4870 # check if get_relocated_path() is actually able to relocate paths
4871 if get_option('relocatable') and \
4872   not (get_option('prefix') / get_option('bindir')).startswith(get_option('prefix') / '')
4873   message()
4874   warning('bindir not included within prefix, the installation will not be relocatable.')
4875   actually_reloc = false
4876 endif
4877 if not actually_reloc and (host_os == 'windows' or get_option('relocatable'))
4878   if host_os == 'windows'
4879     message()
4880     warning('Windows installs should usually be relocatable.')
4881   endif
4882   message()
4883   message('QEMU will have to be installed under ' + get_option('prefix') + '.')
4884   message('Use --disable-relocatable to remove this warning.')
4885 endif
4886