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