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