OSDN Git Service

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