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