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