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