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