OSDN Git Service

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