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