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