target/i386: Introduce Icelake-Server-v7 to enable TSX
[qemu/armbru.git] / meson.build
blob84e59dcbb49ab977bca4bc971c391cd6a103711d
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_LIVE_BLOCK_MIGRATION', get_option('live_block_migration').allowed())
2354 config_host_data.set('CONFIG_QOM_CAST_DEBUG', get_option('qom_cast_debug'))
2355 config_host_data.set('CONFIG_REPLICATION', get_option('replication').allowed())
2357 # has_header
2358 config_host_data.set('CONFIG_EPOLL', cc.has_header('sys/epoll.h'))
2359 config_host_data.set('CONFIG_LINUX_MAGIC_H', cc.has_header('linux/magic.h'))
2360 config_host_data.set('CONFIG_VALGRIND_H', cc.has_header('valgrind/valgrind.h'))
2361 config_host_data.set('HAVE_BTRFS_H', cc.has_header('linux/btrfs.h'))
2362 config_host_data.set('HAVE_DRM_H', cc.has_header('libdrm/drm.h'))
2363 config_host_data.set('HAVE_PTY_H', cc.has_header('pty.h'))
2364 config_host_data.set('HAVE_SYS_DISK_H', cc.has_header('sys/disk.h'))
2365 config_host_data.set('HAVE_SYS_IOCCOM_H', cc.has_header('sys/ioccom.h'))
2366 config_host_data.set('HAVE_SYS_KCOV_H', cc.has_header('sys/kcov.h'))
2367 if host_os == 'windows'
2368   config_host_data.set('HAVE_AFUNIX_H', cc.has_header('afunix.h'))
2369 endif
2371 # has_function
2372 config_host_data.set('CONFIG_CLOSE_RANGE', cc.has_function('close_range'))
2373 config_host_data.set('CONFIG_ACCEPT4', cc.has_function('accept4'))
2374 config_host_data.set('CONFIG_CLOCK_ADJTIME', cc.has_function('clock_adjtime'))
2375 config_host_data.set('CONFIG_DUP3', cc.has_function('dup3'))
2376 config_host_data.set('CONFIG_FALLOCATE', cc.has_function('fallocate'))
2377 config_host_data.set('CONFIG_POSIX_FALLOCATE', cc.has_function('posix_fallocate'))
2378 config_host_data.set('CONFIG_GETCPU', cc.has_function('getcpu', prefix: gnu_source_prefix))
2379 config_host_data.set('CONFIG_SCHED_GETCPU', cc.has_function('sched_getcpu', prefix: '#include <sched.h>'))
2380 # Note that we need to specify prefix: here to avoid incorrectly
2381 # thinking that Windows has posix_memalign()
2382 config_host_data.set('CONFIG_POSIX_MEMALIGN', cc.has_function('posix_memalign', prefix: '#include <stdlib.h>'))
2383 config_host_data.set('CONFIG_ALIGNED_MALLOC', cc.has_function('_aligned_malloc'))
2384 config_host_data.set('CONFIG_VALLOC', cc.has_function('valloc'))
2385 config_host_data.set('CONFIG_MEMALIGN', cc.has_function('memalign'))
2386 config_host_data.set('CONFIG_PPOLL', cc.has_function('ppoll'))
2387 config_host_data.set('CONFIG_PREADV', cc.has_function('preadv', prefix: '#include <sys/uio.h>'))
2388 config_host_data.set('CONFIG_PTHREAD_FCHDIR_NP', cc.has_function('pthread_fchdir_np'))
2389 config_host_data.set('CONFIG_SENDFILE', cc.has_function('sendfile'))
2390 config_host_data.set('CONFIG_SETNS', cc.has_function('setns') and cc.has_function('unshare'))
2391 config_host_data.set('CONFIG_SYNCFS', cc.has_function('syncfs'))
2392 config_host_data.set('CONFIG_SYNC_FILE_RANGE', cc.has_function('sync_file_range'))
2393 config_host_data.set('CONFIG_TIMERFD', cc.has_function('timerfd_create'))
2394 config_host_data.set('HAVE_COPY_FILE_RANGE', cc.has_function('copy_file_range'))
2395 config_host_data.set('HAVE_GETIFADDRS', cc.has_function('getifaddrs'))
2396 config_host_data.set('HAVE_GLIB_WITH_SLICE_ALLOCATOR', glib_has_gslice)
2397 config_host_data.set('HAVE_OPENPTY', cc.has_function('openpty', dependencies: util))
2398 config_host_data.set('HAVE_STRCHRNUL', cc.has_function('strchrnul'))
2399 config_host_data.set('HAVE_SYSTEM_FUNCTION', cc.has_function('system', prefix: '#include <stdlib.h>'))
2400 if rbd.found()
2401   config_host_data.set('HAVE_RBD_NAMESPACE_EXISTS',
2402                        cc.has_function('rbd_namespace_exists',
2403                                        dependencies: rbd,
2404                                        prefix: '#include <rbd/librbd.h>'))
2405 endif
2406 if rdma.found()
2407   config_host_data.set('HAVE_IBV_ADVISE_MR',
2408                        cc.has_function('ibv_advise_mr',
2409                                        dependencies: rdma,
2410                                        prefix: '#include <infiniband/verbs.h>'))
2411 endif
2413 have_asan_fiber = false
2414 if get_option('sanitizers') and \
2415    not cc.has_function('__sanitizer_start_switch_fiber',
2416                          args: '-fsanitize=address',
2417                          prefix: '#include <sanitizer/asan_interface.h>')
2418   warning('Missing ASAN due to missing fiber annotation interface')
2419   warning('Without code annotation, the report may be inferior.')
2420 else
2421   have_asan_fiber = true
2422 endif
2423 config_host_data.set('CONFIG_ASAN_IFACE_FIBER', have_asan_fiber)
2425 have_inotify_init = cc.has_header_symbol('sys/inotify.h', 'inotify_init')
2426 have_inotify_init1 = cc.has_header_symbol('sys/inotify.h', 'inotify_init1')
2427 inotify = not_found
2428 if (have_inotify_init or have_inotify_init1) and host_os == 'freebsd'
2429   # libinotify-kqueue
2430   inotify = cc.find_library('inotify')
2431   if have_inotify_init
2432     have_inotify_init = inotify.found()
2433   endif
2434   if have_inotify_init1
2435     have_inotify_init1 = inotify.found()
2436   endif
2437 endif
2438 config_host_data.set('CONFIG_INOTIFY', have_inotify_init)
2439 config_host_data.set('CONFIG_INOTIFY1', have_inotify_init1)
2441 # has_header_symbol
2442 config_host_data.set('CONFIG_BLKZONED',
2443                      cc.has_header_symbol('linux/blkzoned.h', 'BLKOPENZONE'))
2444 config_host_data.set('CONFIG_EPOLL_CREATE1',
2445                      cc.has_header_symbol('sys/epoll.h', 'epoll_create1'))
2446 config_host_data.set('CONFIG_FALLOCATE_PUNCH_HOLE',
2447                      cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_PUNCH_HOLE') and
2448                      cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_KEEP_SIZE'))
2449 config_host_data.set('CONFIG_FALLOCATE_ZERO_RANGE',
2450                      cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_ZERO_RANGE'))
2451 config_host_data.set('CONFIG_FIEMAP',
2452                      cc.has_header('linux/fiemap.h') and
2453                      cc.has_header_symbol('linux/fs.h', 'FS_IOC_FIEMAP'))
2454 config_host_data.set('CONFIG_GETRANDOM',
2455                      cc.has_function('getrandom') and
2456                      cc.has_header_symbol('sys/random.h', 'GRND_NONBLOCK'))
2457 config_host_data.set('CONFIG_PRCTL_PR_SET_TIMERSLACK',
2458                      cc.has_header_symbol('sys/prctl.h', 'PR_SET_TIMERSLACK'))
2459 config_host_data.set('CONFIG_RTNETLINK',
2460                      cc.has_header_symbol('linux/rtnetlink.h', 'IFLA_PROTO_DOWN'))
2461 config_host_data.set('CONFIG_SYSMACROS',
2462                      cc.has_header_symbol('sys/sysmacros.h', 'makedev'))
2463 config_host_data.set('HAVE_OPTRESET',
2464                      cc.has_header_symbol('getopt.h', 'optreset'))
2465 config_host_data.set('HAVE_IPPROTO_MPTCP',
2466                      cc.has_header_symbol('netinet/in.h', 'IPPROTO_MPTCP'))
2468 # has_member
2469 config_host_data.set('HAVE_SIGEV_NOTIFY_THREAD_ID',
2470                      cc.has_member('struct sigevent', 'sigev_notify_thread_id',
2471                                    prefix: '#include <signal.h>'))
2472 config_host_data.set('HAVE_STRUCT_STAT_ST_ATIM',
2473                      cc.has_member('struct stat', 'st_atim',
2474                                    prefix: '#include <sys/stat.h>'))
2475 config_host_data.set('HAVE_BLK_ZONE_REP_CAPACITY',
2476                      cc.has_member('struct blk_zone', 'capacity',
2477                                    prefix: '#include <linux/blkzoned.h>'))
2479 # has_type
2480 config_host_data.set('CONFIG_IOVEC',
2481                      cc.has_type('struct iovec',
2482                                  prefix: '#include <sys/uio.h>'))
2483 config_host_data.set('HAVE_UTMPX',
2484                      cc.has_type('struct utmpx',
2485                                  prefix: '#include <utmpx.h>'))
2487 config_host_data.set('CONFIG_EVENTFD', cc.links('''
2488   #include <sys/eventfd.h>
2489   int main(void) { return eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); }'''))
2490 config_host_data.set('CONFIG_FDATASYNC', cc.links(gnu_source_prefix + '''
2491   #include <unistd.h>
2492   int main(void) {
2493   #if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
2494   return fdatasync(0);
2495   #else
2496   #error Not supported
2497   #endif
2498   }'''))
2500 has_madvise = cc.links(gnu_source_prefix + '''
2501   #include <sys/types.h>
2502   #include <sys/mman.h>
2503   #include <stddef.h>
2504   int main(void) { return madvise(NULL, 0, MADV_DONTNEED); }''')
2505 missing_madvise_proto = false
2506 if has_madvise
2507   # Some platforms (illumos and Solaris before Solaris 11) provide madvise()
2508   # but forget to prototype it. In this case, has_madvise will be true (the
2509   # test program links despite a compile warning). To detect the
2510   # missing-prototype case, we try again with a definitely-bogus prototype.
2511   # This will only compile if the system headers don't provide the prototype;
2512   # otherwise the conflicting prototypes will cause a compiler error.
2513   missing_madvise_proto = cc.links(gnu_source_prefix + '''
2514     #include <sys/types.h>
2515     #include <sys/mman.h>
2516     #include <stddef.h>
2517     extern int madvise(int);
2518     int main(void) { return madvise(0); }''')
2519 endif
2520 config_host_data.set('CONFIG_MADVISE', has_madvise)
2521 config_host_data.set('HAVE_MADVISE_WITHOUT_PROTOTYPE', missing_madvise_proto)
2523 config_host_data.set('CONFIG_MEMFD', cc.links(gnu_source_prefix + '''
2524   #include <sys/mman.h>
2525   int main(void) { return memfd_create("foo", MFD_ALLOW_SEALING); }'''))
2526 config_host_data.set('CONFIG_OPEN_BY_HANDLE', cc.links(gnu_source_prefix + '''
2527   #include <fcntl.h>
2528   #if !defined(AT_EMPTY_PATH)
2529   # error missing definition
2530   #else
2531   int main(void) { struct file_handle fh; return open_by_handle_at(0, &fh, 0); }
2532   #endif'''))
2533 config_host_data.set('CONFIG_POSIX_MADVISE', cc.links(gnu_source_prefix + '''
2534   #include <sys/mman.h>
2535   #include <stddef.h>
2536   int main(void) { return posix_madvise(NULL, 0, POSIX_MADV_DONTNEED); }'''))
2538 config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_W_TID', cc.links(gnu_source_prefix + '''
2539   #include <pthread.h>
2541   static void *f(void *p) { return NULL; }
2542   int main(void)
2543   {
2544     pthread_t thread;
2545     pthread_create(&thread, 0, f, 0);
2546     pthread_setname_np(thread, "QEMU");
2547     return 0;
2548   }''', dependencies: threads))
2549 config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_WO_TID', cc.links(gnu_source_prefix + '''
2550   #include <pthread.h>
2552   static void *f(void *p) { pthread_setname_np("QEMU"); return NULL; }
2553   int main(void)
2554   {
2555     pthread_t thread;
2556     pthread_create(&thread, 0, f, 0);
2557     return 0;
2558   }''', dependencies: threads))
2559 config_host_data.set('CONFIG_PTHREAD_SET_NAME_NP', cc.links(gnu_source_prefix + '''
2560   #include <pthread.h>
2561   #include <pthread_np.h>
2563   static void *f(void *p) { return NULL; }
2564   int main(void)
2565   {
2566     pthread_t thread;
2567     pthread_create(&thread, 0, f, 0);
2568     pthread_set_name_np(thread, "QEMU");
2569     return 0;
2570   }''', dependencies: threads))
2571 config_host_data.set('CONFIG_PTHREAD_CONDATTR_SETCLOCK', cc.links(gnu_source_prefix + '''
2572   #include <pthread.h>
2573   #include <time.h>
2575   int main(void)
2576   {
2577     pthread_condattr_t attr
2578     pthread_condattr_init(&attr);
2579     pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
2580     return 0;
2581   }''', dependencies: threads))
2582 config_host_data.set('CONFIG_PTHREAD_AFFINITY_NP', cc.links(gnu_source_prefix + '''
2583   #include <pthread.h>
2585   static void *f(void *p) { return NULL; }
2586   int main(void)
2587   {
2588     int setsize = CPU_ALLOC_SIZE(64);
2589     pthread_t thread;
2590     cpu_set_t *cpuset;
2591     pthread_create(&thread, 0, f, 0);
2592     cpuset = CPU_ALLOC(64);
2593     CPU_ZERO_S(setsize, cpuset);
2594     pthread_setaffinity_np(thread, setsize, cpuset);
2595     pthread_getaffinity_np(thread, setsize, cpuset);
2596     CPU_FREE(cpuset);
2597     return 0;
2598   }''', dependencies: threads))
2599 config_host_data.set('CONFIG_SIGNALFD', cc.links(gnu_source_prefix + '''
2600   #include <sys/signalfd.h>
2601   #include <stddef.h>
2602   int main(void) { return signalfd(-1, NULL, SFD_CLOEXEC); }'''))
2603 config_host_data.set('CONFIG_SPLICE', cc.links(gnu_source_prefix + '''
2604   #include <unistd.h>
2605   #include <fcntl.h>
2606   #include <limits.h>
2608   int main(void)
2609   {
2610     int len, fd = 0;
2611     len = tee(STDIN_FILENO, STDOUT_FILENO, INT_MAX, SPLICE_F_NONBLOCK);
2612     splice(STDIN_FILENO, NULL, fd, NULL, len, SPLICE_F_MOVE);
2613     return 0;
2614   }'''))
2616 config_host_data.set('HAVE_MLOCKALL', cc.links(gnu_source_prefix + '''
2617   #include <sys/mman.h>
2618   int main(void) {
2619     return mlockall(MCL_FUTURE);
2620   }'''))
2622 have_l2tpv3 = false
2623 if get_option('l2tpv3').allowed() and have_system
2624   have_l2tpv3 = cc.has_type('struct mmsghdr',
2625     prefix: gnu_source_prefix + '''
2626       #include <sys/socket.h>
2627       #include <linux/ip.h>''')
2628 endif
2629 config_host_data.set('CONFIG_L2TPV3', have_l2tpv3)
2631 have_netmap = false
2632 if get_option('netmap').allowed() and have_system
2633   have_netmap = cc.compiles('''
2634     #include <inttypes.h>
2635     #include <net/if.h>
2636     #include <net/netmap.h>
2637     #include <net/netmap_user.h>
2638     #if (NETMAP_API < 11) || (NETMAP_API > 15)
2639     #error
2640     #endif
2641     int main(void) { return 0; }''')
2642   if not have_netmap and get_option('netmap').enabled()
2643     error('Netmap headers not available')
2644   endif
2645 endif
2646 config_host_data.set('CONFIG_NETMAP', have_netmap)
2648 # Work around a system header bug with some kernel/XFS header
2649 # versions where they both try to define 'struct fsxattr':
2650 # xfs headers will not try to redefine structs from linux headers
2651 # if this macro is set.
2652 config_host_data.set('HAVE_FSXATTR', cc.links('''
2653   #include <linux/fs.h>
2654   struct fsxattr foo;
2655   int main(void) {
2656     return 0;
2657   }'''))
2659 # Some versions of Mac OS X incorrectly define SIZE_MAX
2660 config_host_data.set('HAVE_BROKEN_SIZE_MAX', not cc.compiles('''
2661     #include <stdint.h>
2662     #include <stdio.h>
2663     int main(void) {
2664         return printf("%zu", SIZE_MAX);
2665     }''', args: ['-Werror']))
2667 # See if 64-bit atomic operations are supported.
2668 # Note that without __atomic builtins, we can only
2669 # assume atomic loads/stores max at pointer size.
2670 config_host_data.set('CONFIG_ATOMIC64', cc.links('''
2671   #include <stdint.h>
2672   int main(void)
2673   {
2674     uint64_t x = 0, y = 0;
2675     y = __atomic_load_n(&x, __ATOMIC_RELAXED);
2676     __atomic_store_n(&x, y, __ATOMIC_RELAXED);
2677     __atomic_compare_exchange_n(&x, &y, x, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
2678     __atomic_exchange_n(&x, y, __ATOMIC_RELAXED);
2679     __atomic_fetch_add(&x, y, __ATOMIC_RELAXED);
2680     return 0;
2681   }'''))
2683 has_int128_type = cc.compiles('''
2684   __int128_t a;
2685   __uint128_t b;
2686   int main(void) { b = a; }''')
2687 config_host_data.set('CONFIG_INT128_TYPE', has_int128_type)
2689 has_int128 = has_int128_type and cc.links('''
2690   __int128_t a;
2691   __uint128_t b;
2692   int main (void) {
2693     a = a + b;
2694     b = a * b;
2695     a = a * a;
2696     return 0;
2697   }''')
2698 config_host_data.set('CONFIG_INT128', has_int128)
2700 if has_int128_type
2701   # "do we have 128-bit atomics which are handled inline and specifically not
2702   # via libatomic". The reason we can't use libatomic is documented in the
2703   # comment starting "GCC is a house divided" in include/qemu/atomic128.h.
2704   # We only care about these operations on 16-byte aligned pointers, so
2705   # force 16-byte alignment of the pointer, which may be greater than
2706   # __alignof(unsigned __int128) for the host.
2707   atomic_test_128 = '''
2708     int main(int ac, char **av) {
2709       __uint128_t *p = __builtin_assume_aligned(av[ac - 1], 16);
2710       p[1] = __atomic_load_n(&p[0], __ATOMIC_RELAXED);
2711       __atomic_store_n(&p[2], p[3], __ATOMIC_RELAXED);
2712       __atomic_compare_exchange_n(&p[4], &p[5], p[6], 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
2713       return 0;
2714     }'''
2715   has_atomic128 = cc.links(atomic_test_128)
2717   config_host_data.set('CONFIG_ATOMIC128', has_atomic128)
2719   if not has_atomic128
2720     # Even with __builtin_assume_aligned, the above test may have failed
2721     # without optimization enabled.  Try again with optimizations locally
2722     # enabled for the function.  See
2723     #   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107389
2724     has_atomic128_opt = cc.links('__attribute__((optimize("O1")))' + atomic_test_128)
2725     config_host_data.set('CONFIG_ATOMIC128_OPT', has_atomic128_opt)
2727     if not has_atomic128_opt
2728       config_host_data.set('CONFIG_CMPXCHG128', cc.links('''
2729         int main(void)
2730         {
2731           __uint128_t x = 0, y = 0;
2732           __sync_val_compare_and_swap_16(&x, y, x);
2733           return 0;
2734         }
2735       '''))
2736     endif
2737   endif
2738 endif
2740 config_host_data.set('CONFIG_GETAUXVAL', cc.links(gnu_source_prefix + '''
2741   #include <sys/auxv.h>
2742   int main(void) {
2743     return getauxval(AT_HWCAP) == 0;
2744   }'''))
2746 config_host_data.set('CONFIG_USBFS', have_linux_user and cc.compiles('''
2747   #include <linux/usbdevice_fs.h>
2749   #ifndef USBDEVFS_GET_CAPABILITIES
2750   #error "USBDEVFS_GET_CAPABILITIES undefined"
2751   #endif
2753   #ifndef USBDEVFS_DISCONNECT_CLAIM
2754   #error "USBDEVFS_DISCONNECT_CLAIM undefined"
2755   #endif
2757   int main(void) { return 0; }'''))
2759 have_keyring = get_option('keyring') \
2760   .require(host_os == 'linux', error_message: 'keyring is only available on Linux') \
2761   .require(cc.compiles('''
2762     #include <errno.h>
2763     #include <asm/unistd.h>
2764     #include <linux/keyctl.h>
2765     #include <sys/syscall.h>
2766     #include <unistd.h>
2767     int main(void) {
2768         return syscall(__NR_keyctl, KEYCTL_READ, 0, NULL, NULL, 0);
2769     }'''), error_message: 'keyctl syscall not available on this system').allowed()
2770 config_host_data.set('CONFIG_SECRET_KEYRING', have_keyring)
2772 have_cpuid_h = cc.links('''
2773   #include <cpuid.h>
2774   int main(void) {
2775     unsigned a, b, c, d;
2776     unsigned max = __get_cpuid_max(0, 0);
2778     if (max >= 1) {
2779         __cpuid(1, a, b, c, d);
2780     }
2782     if (max >= 7) {
2783         __cpuid_count(7, 0, a, b, c, d);
2784     }
2786     return 0;
2787   }''')
2788 config_host_data.set('CONFIG_CPUID_H', have_cpuid_h)
2790 config_host_data.set('CONFIG_AVX2_OPT', get_option('avx2') \
2791   .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable AVX2') \
2792   .require(cc.links('''
2793     #include <cpuid.h>
2794     #include <immintrin.h>
2795     static int __attribute__((target("avx2"))) bar(void *a) {
2796       __m256i x = *(__m256i *)a;
2797       return _mm256_testz_si256(x, x);
2798     }
2799     int main(int argc, char *argv[]) { return bar(argv[argc - 1]); }
2800   '''), error_message: 'AVX2 not available').allowed())
2802 config_host_data.set('CONFIG_AVX512F_OPT', get_option('avx512f') \
2803   .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable AVX512F') \
2804   .require(cc.links('''
2805     #include <cpuid.h>
2806     #include <immintrin.h>
2807     static int __attribute__((target("avx512f"))) bar(void *a) {
2808       __m512i x = *(__m512i *)a;
2809       return _mm512_test_epi64_mask(x, x);
2810     }
2811     int main(int argc, char *argv[]) { return bar(argv[argc - 1]); }
2812   '''), error_message: 'AVX512F not available').allowed())
2814 config_host_data.set('CONFIG_AVX512BW_OPT', get_option('avx512bw') \
2815   .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable AVX512BW') \
2816   .require(cc.links('''
2817     #include <cpuid.h>
2818     #include <immintrin.h>
2819     static int __attribute__((target("avx512bw"))) bar(void *a) {
2820       __m512i *x = a;
2821       __m512i res= _mm512_abs_epi8(*x);
2822       return res[1];
2823     }
2824     int main(int argc, char *argv[]) { return bar(argv[0]); }
2825   '''), error_message: 'AVX512BW not available').allowed())
2827 # For both AArch64 and AArch32, detect if builtins are available.
2828 config_host_data.set('CONFIG_ARM_AES_BUILTIN', cc.compiles('''
2829     #include <arm_neon.h>
2830     #ifndef __ARM_FEATURE_AES
2831     __attribute__((target("+crypto")))
2832     #endif
2833     void foo(uint8x16_t *p) { *p = vaesmcq_u8(*p); }
2834   '''))
2836 have_pvrdma = get_option('pvrdma') \
2837   .require(rdma.found(), error_message: 'PVRDMA requires OpenFabrics libraries') \
2838   .require(cc.compiles(gnu_source_prefix + '''
2839     #include <sys/mman.h>
2840     int main(void)
2841     {
2842       char buf = 0;
2843       void *addr = &buf;
2844       addr = mremap(addr, 0, 1, MREMAP_MAYMOVE | MREMAP_FIXED);
2846       return 0;
2847     }'''), error_message: 'PVRDMA requires mremap').allowed()
2849 if have_pvrdma
2850   config_host_data.set('LEGACY_RDMA_REG_MR', not cc.links('''
2851     #include <infiniband/verbs.h>
2852     int main(void)
2853     {
2854       struct ibv_mr *mr;
2855       struct ibv_pd *pd = NULL;
2856       size_t length = 10;
2857       uint64_t iova = 0;
2858       int access = 0;
2859       void *addr = NULL;
2861       mr = ibv_reg_mr_iova(pd, addr, length, iova, access);
2862       ibv_dereg_mr(mr);
2863       return 0;
2864     }'''))
2865 endif
2867 if get_option('membarrier').disabled()
2868   have_membarrier = false
2869 elif host_os == 'windows'
2870   have_membarrier = true
2871 elif host_os == 'linux'
2872   have_membarrier = cc.compiles('''
2873     #include <linux/membarrier.h>
2874     #include <sys/syscall.h>
2875     #include <unistd.h>
2876     #include <stdlib.h>
2877     int main(void) {
2878         syscall(__NR_membarrier, MEMBARRIER_CMD_QUERY, 0);
2879         syscall(__NR_membarrier, MEMBARRIER_CMD_SHARED, 0);
2880         exit(0);
2881     }''')
2882 endif
2883 config_host_data.set('CONFIG_MEMBARRIER', get_option('membarrier') \
2884   .require(have_membarrier, error_message: 'membarrier system call not available') \
2885   .allowed())
2887 have_afalg = get_option('crypto_afalg') \
2888   .require(cc.compiles(gnu_source_prefix + '''
2889     #include <errno.h>
2890     #include <sys/types.h>
2891     #include <sys/socket.h>
2892     #include <linux/if_alg.h>
2893     int main(void) {
2894       int sock;
2895       sock = socket(AF_ALG, SOCK_SEQPACKET, 0);
2896       return sock;
2897     }
2898   '''), error_message: 'AF_ALG requested but could not be detected').allowed()
2899 config_host_data.set('CONFIG_AF_ALG', have_afalg)
2901 config_host_data.set('CONFIG_AF_VSOCK', cc.has_header_symbol(
2902   'linux/vm_sockets.h', 'AF_VSOCK',
2903   prefix: '#include <sys/socket.h>',
2906 have_vss = false
2907 have_vss_sdk = false # old xp/2003 SDK
2908 if host_os == 'windows' and 'cpp' in all_languages
2909   have_vss = cxx.compiles('''
2910     #define __MIDL_user_allocate_free_DEFINED__
2911     #include <vss.h>
2912     int main(void) { return VSS_CTX_BACKUP; }''')
2913   have_vss_sdk = cxx.has_header('vscoordint.h')
2914 endif
2915 config_host_data.set('HAVE_VSS_SDK', have_vss_sdk)
2917 # Older versions of MinGW do not import _lock_file and _unlock_file properly.
2918 # This was fixed for v6.0.0 with commit b48e3ac8969d.
2919 if host_os == 'windows'
2920   config_host_data.set('HAVE__LOCK_FILE', cc.links('''
2921     #include <stdio.h>
2922     int main(void) {
2923       _lock_file(NULL);
2924       _unlock_file(NULL);
2925       return 0;
2926     }''', name: '_lock_file and _unlock_file'))
2927 endif
2929 if host_os == 'windows'
2930   mingw_has_setjmp_longjmp = cc.links('''
2931     #include <setjmp.h>
2932     int main(void) {
2933       /*
2934        * These functions are not available in setjmp header, but may be
2935        * available at link time, from libmingwex.a.
2936        */
2937       extern int __mingw_setjmp(jmp_buf);
2938       extern void __attribute__((noreturn)) __mingw_longjmp(jmp_buf, int);
2939       jmp_buf env;
2940       __mingw_setjmp(env);
2941       __mingw_longjmp(env, 0);
2942     }
2943   ''', name: 'mingw setjmp and longjmp')
2945   if cpu == 'aarch64' and not mingw_has_setjmp_longjmp
2946     error('mingw must provide setjmp/longjmp for windows-arm64')
2947   endif
2948 endif
2950 ########################
2951 # Target configuration #
2952 ########################
2954 minikconf = find_program('scripts/minikconf.py')
2956 config_all_accel = {}
2957 config_all_devices = {}
2958 config_devices_mak_list = []
2959 config_devices_h = {}
2960 config_target_h = {}
2961 config_target_mak = {}
2963 disassemblers = {
2964   'alpha' : ['CONFIG_ALPHA_DIS'],
2965   'avr' : ['CONFIG_AVR_DIS'],
2966   'cris' : ['CONFIG_CRIS_DIS'],
2967   'hexagon' : ['CONFIG_HEXAGON_DIS'],
2968   'hppa' : ['CONFIG_HPPA_DIS'],
2969   'i386' : ['CONFIG_I386_DIS'],
2970   'x86_64' : ['CONFIG_I386_DIS'],
2971   'm68k' : ['CONFIG_M68K_DIS'],
2972   'microblaze' : ['CONFIG_MICROBLAZE_DIS'],
2973   'mips' : ['CONFIG_MIPS_DIS'],
2974   'nios2' : ['CONFIG_NIOS2_DIS'],
2975   'or1k' : ['CONFIG_OPENRISC_DIS'],
2976   'ppc' : ['CONFIG_PPC_DIS'],
2977   'riscv' : ['CONFIG_RISCV_DIS'],
2978   'rx' : ['CONFIG_RX_DIS'],
2979   's390' : ['CONFIG_S390_DIS'],
2980   'sh4' : ['CONFIG_SH4_DIS'],
2981   'sparc' : ['CONFIG_SPARC_DIS'],
2982   'xtensa' : ['CONFIG_XTENSA_DIS'],
2983   'loongarch' : ['CONFIG_LOONGARCH_DIS'],
2986 have_ivshmem = config_host_data.get('CONFIG_EVENTFD')
2987 host_kconfig = \
2988   (get_option('fuzzing') ? ['CONFIG_FUZZ=y'] : []) + \
2989   (have_tpm ? ['CONFIG_TPM=y'] : []) + \
2990   (pixman.found() ? ['CONFIG_PIXMAN=y'] : []) + \
2991   (spice.found() ? ['CONFIG_SPICE=y'] : []) + \
2992   (have_ivshmem ? ['CONFIG_IVSHMEM=y'] : []) + \
2993   (opengl.found() ? ['CONFIG_OPENGL=y'] : []) + \
2994   (x11.found() ? ['CONFIG_X11=y'] : []) + \
2995   (have_vhost_user ? ['CONFIG_VHOST_USER=y'] : []) + \
2996   (have_vhost_vdpa ? ['CONFIG_VHOST_VDPA=y'] : []) + \
2997   (have_vhost_kernel ? ['CONFIG_VHOST_KERNEL=y'] : []) + \
2998   (have_virtfs ? ['CONFIG_VIRTFS=y'] : []) + \
2999   (host_os == 'linux' ? ['CONFIG_LINUX=y'] : []) + \
3000   (have_pvrdma ? ['CONFIG_PVRDMA=y'] : []) + \
3001   (multiprocess_allowed ? ['CONFIG_MULTIPROCESS_ALLOWED=y'] : []) + \
3002   (vfio_user_server_allowed ? ['CONFIG_VFIO_USER_SERVER_ALLOWED=y'] : []) + \
3003   (hv_balloon ? ['CONFIG_HV_BALLOON_POSSIBLE=y'] : [])
3005 ignored = [ 'TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_ARCH' ]
3007 default_targets = 'CONFIG_DEFAULT_TARGETS' in config_host
3008 actual_target_dirs = []
3009 fdt_required = []
3010 foreach target : target_dirs
3011   config_target = { 'TARGET_NAME': target.split('-')[0] }
3012   if target.endswith('linux-user')
3013     if host_os != 'linux'
3014       if default_targets
3015         continue
3016       endif
3017       error('Target @0@ is only available on a Linux host'.format(target))
3018     endif
3019     config_target += { 'CONFIG_LINUX_USER': 'y' }
3020   elif target.endswith('bsd-user')
3021     if host_os not in bsd_oses
3022       if default_targets
3023         continue
3024       endif
3025       error('Target @0@ is only available on a BSD host'.format(target))
3026     endif
3027     config_target += { 'CONFIG_BSD_USER': 'y' }
3028   elif target.endswith('softmmu')
3029     config_target += { 'CONFIG_SYSTEM_ONLY': 'y' }
3030     config_target += { 'CONFIG_SOFTMMU': 'y' }
3031   endif
3032   if target.endswith('-user')
3033     config_target += {
3034       'CONFIG_USER_ONLY': 'y',
3035       'CONFIG_QEMU_INTERP_PREFIX':
3036         get_option('interp_prefix').replace('%M', config_target['TARGET_NAME'])
3037     }
3038   endif
3040   accel_kconfig = []
3041   foreach sym: accelerators
3042     if sym == 'CONFIG_TCG' or target in accelerator_targets.get(sym, [])
3043       config_target += { sym: 'y' }
3044       config_all_accel += { sym: 'y' }
3045       if target in modular_tcg
3046         config_target += { 'CONFIG_TCG_MODULAR': 'y' }
3047       else
3048         config_target += { 'CONFIG_TCG_BUILTIN': 'y' }
3049       endif
3050       accel_kconfig += [ sym + '=y' ]
3051     endif
3052   endforeach
3053   if accel_kconfig.length() == 0
3054     if default_targets
3055       continue
3056     endif
3057     error('No accelerator available for target @0@'.format(target))
3058   endif
3060   actual_target_dirs += target
3061   config_target += keyval.load('configs/targets' / target + '.mak')
3062   config_target += { 'TARGET_' + config_target['TARGET_ARCH'].to_upper(): 'y' }
3064   if 'TARGET_NEED_FDT' in config_target
3065     fdt_required += target
3066   endif
3068   # Add default keys
3069   if 'TARGET_BASE_ARCH' not in config_target
3070     config_target += {'TARGET_BASE_ARCH': config_target['TARGET_ARCH']}
3071   endif
3072   if 'TARGET_ABI_DIR' not in config_target
3073     config_target += {'TARGET_ABI_DIR': config_target['TARGET_ARCH']}
3074   endif
3075   if 'TARGET_BIG_ENDIAN' not in config_target
3076     config_target += {'TARGET_BIG_ENDIAN': 'n'}
3077   endif
3079   foreach k, v: disassemblers
3080     if host_arch.startswith(k) or config_target['TARGET_BASE_ARCH'].startswith(k)
3081       foreach sym: v
3082         config_target += { sym: 'y' }
3083       endforeach
3084     endif
3085   endforeach
3087   config_target_data = configuration_data()
3088   foreach k, v: config_target
3089     if not k.startswith('TARGET_') and not k.startswith('CONFIG_')
3090       # do nothing
3091     elif ignored.contains(k)
3092       # do nothing
3093     elif k == 'TARGET_BASE_ARCH'
3094       # Note that TARGET_BASE_ARCH ends up in config-target.h but it is
3095       # not used to select files from sourcesets.
3096       config_target_data.set('TARGET_' + v.to_upper(), 1)
3097     elif k == 'TARGET_NAME' or k == 'CONFIG_QEMU_INTERP_PREFIX'
3098       config_target_data.set_quoted(k, v)
3099     elif v == 'y'
3100       config_target_data.set(k, 1)
3101     elif v == 'n'
3102       config_target_data.set(k, 0)
3103     else
3104       config_target_data.set(k, v)
3105     endif
3106   endforeach
3107   config_target_data.set('QEMU_ARCH',
3108                          'QEMU_ARCH_' + config_target['TARGET_BASE_ARCH'].to_upper())
3109   config_target_h += {target: configure_file(output: target + '-config-target.h',
3110                                                configuration: config_target_data)}
3112   if target.endswith('-softmmu')
3113     config_input = meson.get_external_property(target, 'default')
3114     config_devices_mak = target + '-config-devices.mak'
3115     config_devices_mak = configure_file(
3116       input: ['configs/devices' / target / config_input + '.mak', 'Kconfig'],
3117       output: config_devices_mak,
3118       depfile: config_devices_mak + '.d',
3119       capture: true,
3120       command: [minikconf,
3121                 get_option('default_devices') ? '--defconfig' : '--allnoconfig',
3122                 config_devices_mak, '@DEPFILE@', '@INPUT@',
3123                 host_kconfig, accel_kconfig,
3124                 'CONFIG_' + config_target['TARGET_ARCH'].to_upper() + '=y'])
3126     config_devices_data = configuration_data()
3127     config_devices = keyval.load(config_devices_mak)
3128     foreach k, v: config_devices
3129       config_devices_data.set(k, 1)
3130     endforeach
3131     config_devices_mak_list += config_devices_mak
3132     config_devices_h += {target: configure_file(output: target + '-config-devices.h',
3133                                                 configuration: config_devices_data)}
3134     config_target += config_devices
3135     config_all_devices += config_devices
3136   endif
3137   config_target_mak += {target: config_target}
3138 endforeach
3139 target_dirs = actual_target_dirs
3141 target_configs_h = []
3142 foreach target: target_dirs
3143   target_configs_h += config_target_h[target]
3144   target_configs_h += config_devices_h.get(target, [])
3145 endforeach
3146 genh += custom_target('config-poison.h',
3147                       input: [target_configs_h],
3148                       output: 'config-poison.h',
3149                       capture: true,
3150                       command: [find_program('scripts/make-config-poison.sh'),
3151                                 target_configs_h])
3153 ###############
3154 # Subprojects #
3155 ###############
3157 libvfio_user_dep = not_found
3158 if have_system and vfio_user_server_allowed
3159   libvfio_user_proj = subproject('libvfio-user', required: true)
3160   libvfio_user_dep = libvfio_user_proj.get_variable('libvfio_user_dep')
3161 endif
3163 fdt = not_found
3164 fdt_opt = get_option('fdt')
3165 if fdt_required.length() > 0 or fdt_opt == 'enabled'
3166   if fdt_opt == 'disabled'
3167     error('fdt disabled but required by targets ' + ', '.join(fdt_required))
3168   endif
3170   if fdt_opt in ['enabled', 'auto', 'system']
3171     if get_option('wrap_mode') == 'nodownload'
3172       fdt_opt = 'system'
3173     endif
3174     fdt = cc.find_library('fdt', required: fdt_opt == 'system')
3175     if fdt.found() and cc.links('''
3176        #include <libfdt.h>
3177        #include <libfdt_env.h>
3178        int main(void) { fdt_find_max_phandle(NULL, NULL); return 0; }''',
3179          dependencies: fdt)
3180       fdt_opt = 'system'
3181     elif fdt_opt == 'system'
3182        error('system libfdt requested, but it is too old (1.5.1 or newer required)')
3183     else
3184       fdt_opt = 'internal'
3185       fdt = not_found
3186     endif
3187   endif
3188   if not fdt.found()
3189     assert(fdt_opt == 'internal')
3190     libfdt_proj = subproject('dtc', required: true,
3191                              default_options: ['tools=false',  'yaml=disabled',
3192                                                'python=disabled', 'default_library=static'])
3193     fdt = libfdt_proj.get_variable('libfdt_dep')
3194   endif
3195 else
3196   fdt_opt = 'disabled'
3197 endif
3199 config_host_data.set('CONFIG_FDT', fdt.found())
3201 vhost_user = not_found
3202 if host_os == 'linux' and have_vhost_user
3203   libvhost_user = subproject('libvhost-user')
3204   vhost_user = libvhost_user.get_variable('vhost_user_dep')
3205 endif
3207 libvduse = not_found
3208 if have_libvduse
3209   libvduse_proj = subproject('libvduse')
3210   libvduse = libvduse_proj.get_variable('libvduse_dep')
3211 endif
3213 #####################
3214 # Generated sources #
3215 #####################
3217 genh += configure_file(output: 'config-host.h', configuration: config_host_data)
3219 hxtool = find_program('scripts/hxtool')
3220 shaderinclude = find_program('scripts/shaderinclude.py')
3221 qapi_gen = find_program('scripts/qapi-gen.py')
3222 qapi_gen_depends = [ meson.current_source_dir() / 'scripts/qapi/__init__.py',
3223                      meson.current_source_dir() / 'scripts/qapi/commands.py',
3224                      meson.current_source_dir() / 'scripts/qapi/common.py',
3225                      meson.current_source_dir() / 'scripts/qapi/error.py',
3226                      meson.current_source_dir() / 'scripts/qapi/events.py',
3227                      meson.current_source_dir() / 'scripts/qapi/expr.py',
3228                      meson.current_source_dir() / 'scripts/qapi/gen.py',
3229                      meson.current_source_dir() / 'scripts/qapi/introspect.py',
3230                      meson.current_source_dir() / 'scripts/qapi/main.py',
3231                      meson.current_source_dir() / 'scripts/qapi/parser.py',
3232                      meson.current_source_dir() / 'scripts/qapi/schema.py',
3233                      meson.current_source_dir() / 'scripts/qapi/source.py',
3234                      meson.current_source_dir() / 'scripts/qapi/types.py',
3235                      meson.current_source_dir() / 'scripts/qapi/visit.py',
3236                      meson.current_source_dir() / 'scripts/qapi-gen.py'
3239 tracetool = [
3240   python, files('scripts/tracetool.py'),
3241    '--backend=' + ','.join(get_option('trace_backends'))
3243 tracetool_depends = files(
3244   'scripts/tracetool/backend/log.py',
3245   'scripts/tracetool/backend/__init__.py',
3246   'scripts/tracetool/backend/dtrace.py',
3247   'scripts/tracetool/backend/ftrace.py',
3248   'scripts/tracetool/backend/simple.py',
3249   'scripts/tracetool/backend/syslog.py',
3250   'scripts/tracetool/backend/ust.py',
3251   'scripts/tracetool/format/ust_events_c.py',
3252   'scripts/tracetool/format/ust_events_h.py',
3253   'scripts/tracetool/format/__init__.py',
3254   'scripts/tracetool/format/d.py',
3255   'scripts/tracetool/format/simpletrace_stap.py',
3256   'scripts/tracetool/format/c.py',
3257   'scripts/tracetool/format/h.py',
3258   'scripts/tracetool/format/log_stap.py',
3259   'scripts/tracetool/format/stap.py',
3260   'scripts/tracetool/__init__.py',
3261   'scripts/tracetool/vcpu.py'
3264 qemu_version_cmd = [find_program('scripts/qemu-version.sh'),
3265                     meson.current_source_dir(),
3266                     get_option('pkgversion'), meson.project_version()]
3267 qemu_version = custom_target('qemu-version.h',
3268                              output: 'qemu-version.h',
3269                              command: qemu_version_cmd,
3270                              capture: true,
3271                              build_by_default: true,
3272                              build_always_stale: true)
3273 genh += qemu_version
3275 hxdep = []
3276 hx_headers = [
3277   ['qemu-options.hx', 'qemu-options.def'],
3278   ['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
3280 if have_system
3281   hx_headers += [
3282     ['hmp-commands.hx', 'hmp-commands.h'],
3283     ['hmp-commands-info.hx', 'hmp-commands-info.h'],
3284   ]
3285 endif
3286 foreach d : hx_headers
3287   hxdep += custom_target(d[1],
3288                 input: files(d[0]),
3289                 output: d[1],
3290                 capture: true,
3291                 command: [hxtool, '-h', '@INPUT0@'])
3292 endforeach
3293 genh += hxdep
3295 ###############
3296 # Trace files #
3297 ###############
3299 # TODO: add each directory to the subdirs from its own meson.build, once
3300 # we have those
3301 trace_events_subdirs = [
3302   'crypto',
3303   'qapi',
3304   'qom',
3305   'monitor',
3306   'util',
3307   'gdbstub',
3309 if have_linux_user
3310   trace_events_subdirs += [ 'linux-user' ]
3311 endif
3312 if have_bsd_user
3313   trace_events_subdirs += [ 'bsd-user' ]
3314 endif
3315 if have_block
3316   trace_events_subdirs += [
3317     'authz',
3318     'block',
3319     'io',
3320     'nbd',
3321     'scsi',
3322   ]
3323 endif
3324 if have_system
3325   trace_events_subdirs += [
3326     'accel/kvm',
3327     'audio',
3328     'backends',
3329     'backends/tpm',
3330     'chardev',
3331     'ebpf',
3332     'hw/9pfs',
3333     'hw/acpi',
3334     'hw/adc',
3335     'hw/alpha',
3336     'hw/arm',
3337     'hw/audio',
3338     'hw/block',
3339     'hw/char',
3340     'hw/display',
3341     'hw/dma',
3342     'hw/fsi',
3343     'hw/hyperv',
3344     'hw/i2c',
3345     'hw/i386',
3346     'hw/i386/xen',
3347     'hw/i386/kvm',
3348     'hw/ide',
3349     'hw/input',
3350     'hw/intc',
3351     'hw/isa',
3352     'hw/mem',
3353     'hw/mips',
3354     'hw/misc',
3355     'hw/misc/macio',
3356     'hw/net',
3357     'hw/net/can',
3358     'hw/nubus',
3359     'hw/nvme',
3360     'hw/nvram',
3361     'hw/pci',
3362     'hw/pci-host',
3363     'hw/ppc',
3364     'hw/rdma',
3365     'hw/rdma/vmw',
3366     'hw/rtc',
3367     'hw/s390x',
3368     'hw/scsi',
3369     'hw/sd',
3370     'hw/sh4',
3371     'hw/sparc',
3372     'hw/sparc64',
3373     'hw/ssi',
3374     'hw/timer',
3375     'hw/tpm',
3376     'hw/ufs',
3377     'hw/usb',
3378     'hw/vfio',
3379     'hw/virtio',
3380     'hw/watchdog',
3381     'hw/xen',
3382     'hw/gpio',
3383     'migration',
3384     'net',
3385     'system',
3386     'ui',
3387     'hw/remote',
3388   ]
3389 endif
3390 if have_system or have_user
3391   trace_events_subdirs += [
3392     'accel/tcg',
3393     'hw/core',
3394     'target/arm',
3395     'target/arm/hvf',
3396     'target/hppa',
3397     'target/i386',
3398     'target/i386/kvm',
3399     'target/loongarch',
3400     'target/mips/tcg',
3401     'target/nios2',
3402     'target/ppc',
3403     'target/riscv',
3404     'target/s390x',
3405     'target/s390x/kvm',
3406     'target/sparc',
3407   ]
3408 endif
3410 ###################
3411 # Collect sources #
3412 ###################
3414 authz_ss = ss.source_set()
3415 blockdev_ss = ss.source_set()
3416 block_ss = ss.source_set()
3417 chardev_ss = ss.source_set()
3418 common_ss = ss.source_set()
3419 crypto_ss = ss.source_set()
3420 hwcore_ss = ss.source_set()
3421 io_ss = ss.source_set()
3422 qmp_ss = ss.source_set()
3423 qom_ss = ss.source_set()
3424 system_ss = ss.source_set()
3425 specific_fuzz_ss = ss.source_set()
3426 specific_ss = ss.source_set()
3427 stub_ss = ss.source_set()
3428 trace_ss = ss.source_set()
3429 user_ss = ss.source_set()
3430 util_ss = ss.source_set()
3432 # accel modules
3433 qtest_module_ss = ss.source_set()
3434 tcg_module_ss = ss.source_set()
3436 modules = {}
3437 target_modules = {}
3438 hw_arch = {}
3439 target_arch = {}
3440 target_system_arch = {}
3441 target_user_arch = {}
3443 # NOTE: the trace/ subdirectory needs the qapi_trace_events variable
3444 # that is filled in by qapi/.
3445 subdir('qapi')
3446 subdir('qobject')
3447 subdir('stubs')
3448 subdir('trace')
3449 subdir('util')
3450 subdir('qom')
3451 subdir('authz')
3452 subdir('crypto')
3453 subdir('ui')
3454 subdir('gdbstub')
3455 if have_system
3456   subdir('hw')
3457 else
3458   subdir('hw/core')
3459 endif
3461 if enable_modules
3462   libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
3463   modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
3464 endif
3466 qom_ss = qom_ss.apply({})
3467 libqom = static_library('qom', qom_ss.sources() + genh,
3468                         dependencies: [qom_ss.dependencies()],
3469                         name_suffix: 'fa',
3470                         build_by_default: false)
3471 qom = declare_dependency(link_whole: libqom)
3473 event_loop_base = files('event-loop-base.c')
3474 event_loop_base = static_library('event-loop-base',
3475                                  sources: event_loop_base + genh,
3476                                  name_suffix: 'fa',
3477                                  build_by_default: false)
3478 event_loop_base = declare_dependency(link_whole: event_loop_base,
3479                                      dependencies: [qom])
3481 stub_ss = stub_ss.apply({})
3483 util_ss.add_all(trace_ss)
3484 util_ss = util_ss.apply({})
3485 libqemuutil = static_library('qemuutil',
3486                              build_by_default: false,
3487                              sources: util_ss.sources() + stub_ss.sources() + genh,
3488                              dependencies: [util_ss.dependencies(), libm, threads, glib, socket, malloc])
3489 qemuutil = declare_dependency(link_with: libqemuutil,
3490                               sources: genh + version_res,
3491                               dependencies: [event_loop_base])
3493 if have_system or have_user
3494   decodetree = generator(find_program('scripts/decodetree.py'),
3495                          output: 'decode-@BASENAME@.c.inc',
3496                          arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
3497   subdir('libdecnumber')
3498   subdir('target')
3499 endif
3501 subdir('audio')
3502 subdir('io')
3503 subdir('chardev')
3504 subdir('fsdev')
3505 subdir('dump')
3507 if have_block
3508   block_ss.add(files(
3509     'block.c',
3510     'blockjob.c',
3511     'job.c',
3512     'qemu-io-cmds.c',
3513   ))
3514   if config_host_data.get('CONFIG_REPLICATION')
3515     block_ss.add(files('replication.c'))
3516   endif
3518   subdir('nbd')
3519   subdir('scsi')
3520   subdir('block')
3522   blockdev_ss.add(files(
3523     'blockdev.c',
3524     'blockdev-nbd.c',
3525     'iothread.c',
3526     'job-qmp.c',
3527   ), gnutls)
3529   # os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
3530   # os-win32.c does not
3531   if host_os == 'windows'
3532     system_ss.add(files('os-win32.c'))
3533   else
3534     blockdev_ss.add(files('os-posix.c'))
3535   endif
3536 endif
3538 common_ss.add(files('cpu-common.c'))
3539 specific_ss.add(files('cpu-target.c'))
3541 subdir('system')
3543 # Work around a gcc bug/misfeature wherein constant propagation looks
3544 # through an alias:
3545 #   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99696
3546 # to guess that a const variable is always zero.  Without lto, this is
3547 # impossible, as the alias is restricted to page-vary-common.c.  Indeed,
3548 # without lto, not even the alias is required -- we simply use different
3549 # declarations in different compilation units.
3550 pagevary = files('page-vary-common.c')
3551 if get_option('b_lto')
3552   pagevary_flags = ['-fno-lto']
3553   if get_option('cfi')
3554     pagevary_flags += '-fno-sanitize=cfi-icall'
3555   endif
3556   pagevary = static_library('page-vary-common', sources: pagevary + genh,
3557                             c_args: pagevary_flags)
3558   pagevary = declare_dependency(link_with: pagevary)
3559 endif
3560 common_ss.add(pagevary)
3561 specific_ss.add(files('page-vary-target.c'))
3563 subdir('backends')
3564 subdir('disas')
3565 subdir('migration')
3566 subdir('monitor')
3567 subdir('net')
3568 subdir('replay')
3569 subdir('semihosting')
3570 subdir('stats')
3571 subdir('tcg')
3572 subdir('fpu')
3573 subdir('accel')
3574 subdir('plugins')
3575 subdir('ebpf')
3577 common_user_inc = []
3579 subdir('common-user')
3580 subdir('bsd-user')
3581 subdir('linux-user')
3583 # needed for fuzzing binaries
3584 subdir('tests/qtest/libqos')
3585 subdir('tests/qtest/fuzz')
3587 # accel modules
3588 tcg_real_module_ss = ss.source_set()
3589 tcg_real_module_ss.add_all(when: 'CONFIG_TCG_MODULAR', if_true: tcg_module_ss)
3590 specific_ss.add_all(when: 'CONFIG_TCG_BUILTIN', if_true: tcg_module_ss)
3591 target_modules += { 'accel' : { 'qtest': qtest_module_ss,
3592                                 'tcg': tcg_real_module_ss }}
3594 ##############################################
3595 # Internal static_libraries and dependencies #
3596 ##############################################
3598 modinfo_collect = find_program('scripts/modinfo-collect.py')
3599 modinfo_generate = find_program('scripts/modinfo-generate.py')
3600 modinfo_files = []
3602 block_mods = []
3603 system_mods = []
3604 foreach d, list : modules
3605   if not (d == 'block' ? have_block : have_system)
3606     continue
3607   endif
3609   foreach m, module_ss : list
3610     if enable_modules
3611       module_ss = module_ss.apply(config_all_devices, strict: false)
3612       sl = static_library(d + '-' + m, [genh, module_ss.sources()],
3613                           dependencies: [modulecommon, module_ss.dependencies()], pic: true)
3614       if d == 'block'
3615         block_mods += sl
3616       else
3617         system_mods += sl
3618       endif
3619       if module_ss.sources() != []
3620         # FIXME: Should use sl.extract_all_objects(recursive: true) as
3621         # input. Sources can be used multiple times but objects are
3622         # unique when it comes to lookup in compile_commands.json.
3623         # Depnds on a mesion version with
3624         # https://github.com/mesonbuild/meson/pull/8900
3625         modinfo_files += custom_target(d + '-' + m + '.modinfo',
3626                                        output: d + '-' + m + '.modinfo',
3627                                        input: module_ss.sources() + genh,
3628                                        capture: true,
3629                                        command: [modinfo_collect, module_ss.sources()])
3630       endif
3631     else
3632       if d == 'block'
3633         block_ss.add_all(module_ss)
3634       else
3635         system_ss.add_all(module_ss)
3636       endif
3637     endif
3638   endforeach
3639 endforeach
3641 foreach d, list : target_modules
3642   foreach m, module_ss : list
3643     if enable_modules
3644       foreach target : target_dirs
3645         if target.endswith('-softmmu')
3646           config_target = config_target_mak[target]
3647           target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
3648           c_args = ['-DNEED_CPU_H',
3649                     '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
3650                     '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
3651           target_module_ss = module_ss.apply(config_target, strict: false)
3652           if target_module_ss.sources() != []
3653             module_name = d + '-' + m + '-' + config_target['TARGET_NAME']
3654             sl = static_library(module_name,
3655                                 [genh, target_module_ss.sources()],
3656                                 dependencies: [modulecommon, target_module_ss.dependencies()],
3657                                 include_directories: target_inc,
3658                                 c_args: c_args,
3659                                 pic: true)
3660             system_mods += sl
3661             # FIXME: Should use sl.extract_all_objects(recursive: true) too.
3662             modinfo_files += custom_target(module_name + '.modinfo',
3663                                            output: module_name + '.modinfo',
3664                                            input: target_module_ss.sources() + genh,
3665                                            capture: true,
3666                                            command: [modinfo_collect, '--target', target, target_module_ss.sources()])
3667           endif
3668         endif
3669       endforeach
3670     else
3671       specific_ss.add_all(module_ss)
3672     endif
3673   endforeach
3674 endforeach
3676 if enable_modules
3677   foreach target : target_dirs
3678     if target.endswith('-softmmu')
3679       config_target = config_target_mak[target]
3680       config_devices_mak = target + '-config-devices.mak'
3681       modinfo_src = custom_target('modinfo-' + target + '.c',
3682                                   output: 'modinfo-' + target + '.c',
3683                                   input: modinfo_files,
3684                                   command: [modinfo_generate, '--devices', config_devices_mak, '@INPUT@'],
3685                                   capture: true)
3687       modinfo_lib = static_library('modinfo-' + target + '.c', modinfo_src)
3688       modinfo_dep = declare_dependency(link_with: modinfo_lib)
3690       arch = config_target['TARGET_NAME'] == 'sparc64' ? 'sparc64' : config_target['TARGET_BASE_ARCH']
3691       hw_arch[arch].add(modinfo_dep)
3692     endif
3693   endforeach
3694 endif
3696 nm = find_program('nm')
3697 undefsym = find_program('scripts/undefsym.py')
3698 block_syms = custom_target('block.syms', output: 'block.syms',
3699                              input: [libqemuutil, block_mods],
3700                              capture: true,
3701                              command: [undefsym, nm, '@INPUT@'])
3702 qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
3703                              input: [libqemuutil, system_mods],
3704                              capture: true,
3705                              command: [undefsym, nm, '@INPUT@'])
3707 authz_ss = authz_ss.apply({})
3708 libauthz = static_library('authz', authz_ss.sources() + genh,
3709                           dependencies: [authz_ss.dependencies()],
3710                           name_suffix: 'fa',
3711                           build_by_default: false)
3713 authz = declare_dependency(link_whole: libauthz,
3714                            dependencies: qom)
3716 crypto_ss = crypto_ss.apply({})
3717 libcrypto = static_library('crypto', crypto_ss.sources() + genh,
3718                            dependencies: [crypto_ss.dependencies()],
3719                            name_suffix: 'fa',
3720                            build_by_default: false)
3722 crypto = declare_dependency(link_whole: libcrypto,
3723                             dependencies: [authz, qom])
3725 io_ss = io_ss.apply({})
3726 libio = static_library('io', io_ss.sources() + genh,
3727                        dependencies: [io_ss.dependencies()],
3728                        link_with: libqemuutil,
3729                        name_suffix: 'fa',
3730                        build_by_default: false)
3732 io = declare_dependency(link_whole: libio, dependencies: [crypto, qom])
3734 libmigration = static_library('migration', sources: migration_files + genh,
3735                               name_suffix: 'fa',
3736                               build_by_default: false)
3737 migration = declare_dependency(link_with: libmigration,
3738                                dependencies: [zlib, qom, io])
3739 system_ss.add(migration)
3741 block_ss = block_ss.apply({})
3742 libblock = static_library('block', block_ss.sources() + genh,
3743                           dependencies: block_ss.dependencies(),
3744                           link_depends: block_syms,
3745                           name_suffix: 'fa',
3746                           build_by_default: false)
3748 block = declare_dependency(link_whole: [libblock],
3749                            link_args: '@block.syms',
3750                            dependencies: [crypto, io])
3752 blockdev_ss = blockdev_ss.apply({})
3753 libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
3754                              dependencies: blockdev_ss.dependencies(),
3755                              name_suffix: 'fa',
3756                              build_by_default: false)
3758 blockdev = declare_dependency(link_whole: [libblockdev],
3759                               dependencies: [block, event_loop_base])
3761 qmp_ss = qmp_ss.apply({})
3762 libqmp = static_library('qmp', qmp_ss.sources() + genh,
3763                         dependencies: qmp_ss.dependencies(),
3764                         name_suffix: 'fa',
3765                         build_by_default: false)
3767 qmp = declare_dependency(link_whole: [libqmp])
3769 libchardev = static_library('chardev', chardev_ss.sources() + genh,
3770                             name_suffix: 'fa',
3771                             dependencies: chardev_ss.dependencies(),
3772                             build_by_default: false)
3774 chardev = declare_dependency(link_whole: libchardev)
3776 hwcore_ss = hwcore_ss.apply({})
3777 libhwcore = static_library('hwcore', sources: hwcore_ss.sources() + genh,
3778                            name_suffix: 'fa',
3779                            build_by_default: false)
3780 hwcore = declare_dependency(link_whole: libhwcore)
3781 common_ss.add(hwcore)
3783 ###########
3784 # Targets #
3785 ###########
3787 emulator_modules = []
3788 foreach m : block_mods + system_mods
3789   emulator_modules += shared_module(m.name(),
3790                 build_by_default: true,
3791                 name_prefix: '',
3792                 link_whole: m,
3793                 install: true,
3794                 install_dir: qemu_moddir)
3795 endforeach
3796 if emulator_modules.length() > 0
3797   alias_target('modules', emulator_modules)
3798 endif
3800 system_ss.add(authz, blockdev, chardev, crypto, io, qmp)
3801 common_ss.add(qom, qemuutil)
3803 common_ss.add_all(when: 'CONFIG_SYSTEM_ONLY', if_true: [system_ss])
3804 common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
3806 # Note that this library is never used directly (only through extract_objects)
3807 # and is not built by default; therefore, source files not used by the build
3808 # configuration will be in build.ninja, but are never built by default.
3809 common_all = static_library('common',
3810                             build_by_default: false,
3811                             sources: common_ss.all_sources() + genh,
3812                             include_directories: common_user_inc,
3813                             implicit_include_directories: false,
3814                             dependencies: common_ss.all_dependencies(),
3815                             name_suffix: 'fa')
3817 feature_to_c = find_program('scripts/feature_to_c.py')
3819 if host_os == 'darwin'
3820   entitlement = find_program('scripts/entitlement.sh')
3821 endif
3823 traceable = []
3824 emulators = {}
3825 foreach target : target_dirs
3826   config_target = config_target_mak[target]
3827   target_name = config_target['TARGET_NAME']
3828   target_base_arch = config_target['TARGET_BASE_ARCH']
3829   arch_srcs = [config_target_h[target]]
3830   arch_deps = []
3831   c_args = ['-DNEED_CPU_H',
3832             '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
3833             '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
3834   link_args = emulator_link_args
3836   target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
3837   if host_os == 'linux'
3838     target_inc += include_directories('linux-headers', is_system: true)
3839   endif
3840   if target.endswith('-softmmu')
3841     target_type='system'
3842     t = target_system_arch[target_base_arch].apply(config_target, strict: false)
3843     arch_srcs += t.sources()
3844     arch_deps += t.dependencies()
3846     hw_dir = target_name == 'sparc64' ? 'sparc64' : target_base_arch
3847     if hw_arch.has_key(hw_dir)
3848       hw = hw_arch[hw_dir].apply(config_target, strict: false)
3849       arch_srcs += hw.sources()
3850       arch_deps += hw.dependencies()
3851     endif
3853     arch_srcs += config_devices_h[target]
3854     link_args += ['@block.syms', '@qemu.syms']
3855   else
3856     abi = config_target['TARGET_ABI_DIR']
3857     target_type='user'
3858     target_inc += common_user_inc
3859     if target_base_arch in target_user_arch
3860       t = target_user_arch[target_base_arch].apply(config_target, strict: false)
3861       arch_srcs += t.sources()
3862       arch_deps += t.dependencies()
3863     endif
3864     if 'CONFIG_LINUX_USER' in config_target
3865       base_dir = 'linux-user'
3866     endif
3867     if 'CONFIG_BSD_USER' in config_target
3868       base_dir = 'bsd-user'
3869       target_inc += include_directories('bsd-user/' / host_os)
3870       target_inc += include_directories('bsd-user/host/' / host_arch)
3871       dir = base_dir / abi
3872       arch_srcs += files(dir / 'signal.c', dir / 'target_arch_cpu.c')
3873     endif
3874     target_inc += include_directories(
3875       base_dir,
3876       base_dir / abi,
3877     )
3878     if 'CONFIG_LINUX_USER' in config_target
3879       dir = base_dir / abi
3880       arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
3881       if config_target.has_key('TARGET_SYSTBL_ABI')
3882         arch_srcs += \
3883           syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
3884                                              extra_args : config_target['TARGET_SYSTBL_ABI'])
3885       endif
3886     endif
3887   endif
3889   if 'TARGET_XML_FILES' in config_target
3890     gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
3891                                 output: target + '-gdbstub-xml.c',
3892                                 input: files(config_target['TARGET_XML_FILES'].split()),
3893                                 command: [feature_to_c, '@INPUT@'],
3894                                 capture: true)
3895     arch_srcs += gdbstub_xml
3896   endif
3898   t = target_arch[target_base_arch].apply(config_target, strict: false)
3899   arch_srcs += t.sources()
3900   arch_deps += t.dependencies()
3902   target_common = common_ss.apply(config_target, strict: false)
3903   objects = common_all.extract_objects(target_common.sources())
3904   deps = target_common.dependencies()
3906   target_specific = specific_ss.apply(config_target, strict: false)
3907   arch_srcs += target_specific.sources()
3908   arch_deps += target_specific.dependencies()
3910   lib = static_library('qemu-' + target,
3911                  sources: arch_srcs + genh,
3912                  dependencies: arch_deps,
3913                  objects: objects,
3914                  include_directories: target_inc,
3915                  c_args: c_args,
3916                  build_by_default: false,
3917                  name_suffix: 'fa')
3919   if target.endswith('-softmmu')
3920     execs = [{
3921       'name': 'qemu-system-' + target_name,
3922       'win_subsystem': 'console',
3923       'sources': files('system/main.c'),
3924       'dependencies': []
3925     }]
3926     if host_os == 'windows' and (sdl.found() or gtk.found())
3927       execs += [{
3928         'name': 'qemu-system-' + target_name + 'w',
3929         'win_subsystem': 'windows',
3930         'sources': files('system/main.c'),
3931         'dependencies': []
3932       }]
3933     endif
3934     if get_option('fuzzing')
3935       specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
3936       execs += [{
3937         'name': 'qemu-fuzz-' + target_name,
3938         'win_subsystem': 'console',
3939         'sources': specific_fuzz.sources(),
3940         'dependencies': specific_fuzz.dependencies(),
3941       }]
3942     endif
3943   else
3944     execs = [{
3945       'name': 'qemu-' + target_name,
3946       'win_subsystem': 'console',
3947       'sources': [],
3948       'dependencies': []
3949     }]
3950   endif
3951   foreach exe: execs
3952     exe_name = exe['name']
3953     if host_os == 'darwin'
3954       exe_name += '-unsigned'
3955     endif
3957     emulator = executable(exe_name, exe['sources'],
3958                install: true,
3959                c_args: c_args,
3960                dependencies: arch_deps + deps + exe['dependencies'],
3961                objects: lib.extract_all_objects(recursive: true),
3962                link_depends: [block_syms, qemu_syms],
3963                link_args: link_args,
3964                win_subsystem: exe['win_subsystem'])
3966     if host_os == 'darwin'
3967       icon = 'pc-bios/qemu.rsrc'
3968       build_input = [emulator, files(icon)]
3969       install_input = [
3970         get_option('bindir') / exe_name,
3971         meson.current_source_dir() / icon
3972       ]
3973       if 'CONFIG_HVF' in config_target
3974         entitlements = 'accel/hvf/entitlements.plist'
3975         build_input += files(entitlements)
3976         install_input += meson.current_source_dir() / entitlements
3977       endif
3979       emulators += {exe['name'] : custom_target(exe['name'],
3980                    input: build_input,
3981                    output: exe['name'],
3982                    command: [entitlement, '@OUTPUT@', '@INPUT@'])
3983       }
3985       meson.add_install_script(entitlement, '--install',
3986                                get_option('bindir') / exe['name'],
3987                                install_input)
3988     else
3989       emulators += {exe['name']: emulator}
3990     endif
3992     traceable += [{
3993       'exe': exe['name'],
3994       'probe-prefix': 'qemu.' + target_type + '.' + target_name,
3995     }]
3997   endforeach
3998 endforeach
4000 # Other build targets
4002 if get_option('plugins')
4003   install_headers('include/qemu/qemu-plugin.h')
4004   if host_os == 'windows'
4005     # On windows, we want to deliver the qemu_plugin_api.lib file in the qemu installer,
4006     # so that plugin authors can compile against it.
4007     install_data(win32_qemu_plugin_api_lib, install_dir: 'lib')
4008   endif
4009 endif
4011 subdir('qga')
4013 # Don't build qemu-keymap if xkbcommon is not explicitly enabled
4014 # when we don't build tools or system
4015 if xkbcommon.found()
4016   # used for the update-keymaps target, so include rules even if !have_tools
4017   qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
4018                            dependencies: [qemuutil, xkbcommon], install: have_tools)
4019 endif
4021 if have_tools
4022   qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
4023              dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
4024   qemu_io = executable('qemu-io', files('qemu-io.c'),
4025              dependencies: [block, qemuutil], install: true)
4026   qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
4027                dependencies: [blockdev, qemuutil, gnutls, selinux],
4028                install: true)
4030   subdir('storage-daemon')
4032   foreach exe: [ 'qemu-img', 'qemu-io', 'qemu-nbd', 'qemu-storage-daemon']
4033     traceable += [{
4034       'exe': exe,
4035       'probe-prefix': 'qemu.' + exe.substring(5).replace('-', '_')
4036     }]
4037   endforeach
4039   subdir('contrib/rdmacm-mux')
4040   subdir('contrib/elf2dmp')
4042   executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
4043              dependencies: qemuutil,
4044              install: true)
4046   if have_vhost_user
4047     subdir('contrib/vhost-user-blk')
4048     subdir('contrib/vhost-user-gpu')
4049     subdir('contrib/vhost-user-input')
4050     subdir('contrib/vhost-user-scsi')
4051   endif
4053   if host_os == 'linux'
4054     executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
4055                dependencies: [qemuutil, libcap_ng],
4056                install: true,
4057                install_dir: get_option('libexecdir'))
4059     executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
4060                dependencies: [authz, crypto, io, qom, qemuutil,
4061                               libcap_ng, mpathpersist],
4062                install: true)
4063   endif
4065   if have_ivshmem
4066     subdir('contrib/ivshmem-client')
4067     subdir('contrib/ivshmem-server')
4068   endif
4069 endif
4071 if stap.found()
4072   foreach t: traceable
4073     foreach stp: [
4074       {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / t['exe'], 'install': false},
4075       {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / t['exe'], 'install': true},
4076       {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
4077       {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
4078     ]
4079       cmd = [
4080         tracetool, '--group=all', '--format=' + stp['fmt'],
4081         '--binary=' + stp['bin'],
4082         '--probe-prefix=' + t['probe-prefix'],
4083         '@INPUT@', '@OUTPUT@'
4084       ]
4086       custom_target(t['exe'] + stp['ext'],
4087                     input: trace_events_all,
4088                     output: t['exe'] + stp['ext'],
4089                     install: stp['install'],
4090                     install_dir: get_option('datadir') / 'systemtap/tapset',
4091                     command: cmd,
4092                     depend_files: tracetool_depends)
4093     endforeach
4094   endforeach
4095 endif
4097 subdir('scripts')
4098 subdir('tools')
4099 subdir('pc-bios')
4100 subdir('docs')
4101 subdir('tests')
4102 if gtk.found()
4103   subdir('po')
4104 endif
4106 if host_machine.system() == 'windows'
4107   nsis_cmd = [
4108     find_program('scripts/nsis.py'),
4109     '@OUTPUT@',
4110     get_option('prefix'),
4111     meson.current_source_dir(),
4112     glib_pc.get_variable('bindir'),
4113     host_machine.cpu(),
4114     '--',
4115     '-DDISPLAYVERSION=' + meson.project_version(),
4116   ]
4117   if build_docs
4118     nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
4119   endif
4120   if gtk.found()
4121     nsis_cmd += '-DCONFIG_GTK=y'
4122   endif
4124   nsis = custom_target('nsis',
4125                        output: 'qemu-setup-' + meson.project_version() + '.exe',
4126                        input: files('qemu.nsi'),
4127                        build_always_stale: true,
4128                        command: nsis_cmd + ['@INPUT@'])
4129   alias_target('installer', nsis)
4130 endif
4132 #########################
4133 # Configuration summary #
4134 #########################
4136 # Build environment
4137 summary_info = {}
4138 summary_info += {'Build directory':   meson.current_build_dir()}
4139 summary_info += {'Source path':       meson.current_source_dir()}
4140 summary_info += {'Download dependencies': get_option('wrap_mode') != 'nodownload'}
4141 summary(summary_info, bool_yn: true, section: 'Build environment')
4143 # Directories
4144 summary_info += {'Install prefix':    get_option('prefix')}
4145 summary_info += {'BIOS directory':    qemu_datadir}
4146 pathsep = host_os == 'windows' ? ';' : ':'
4147 summary_info += {'firmware path':     pathsep.join(get_option('qemu_firmwarepath'))}
4148 summary_info += {'binary directory':  get_option('prefix') / get_option('bindir')}
4149 summary_info += {'library directory': get_option('prefix') / get_option('libdir')}
4150 summary_info += {'module directory':  qemu_moddir}
4151 summary_info += {'libexec directory': get_option('prefix') / get_option('libexecdir')}
4152 summary_info += {'include directory': get_option('prefix') / get_option('includedir')}
4153 summary_info += {'config directory':  get_option('prefix') / get_option('sysconfdir')}
4154 if host_os != 'windows'
4155   summary_info += {'local state directory': get_option('prefix') / get_option('localstatedir')}
4156   summary_info += {'Manual directory':      get_option('prefix') / get_option('mandir')}
4157 else
4158   summary_info += {'local state directory': 'queried at runtime'}
4159 endif
4160 summary_info += {'Doc directory':     get_option('prefix') / get_option('docdir')}
4161 summary(summary_info, bool_yn: true, section: 'Directories')
4163 # Host binaries
4164 summary_info = {}
4165 summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
4166 summary_info += {'sphinx-build':      sphinx_build}
4168 # FIXME: the [binaries] section of machine files, which can be probed
4169 # with find_program(), would be great for passing gdb and genisoimage
4170 # paths from configure to Meson.  However, there seems to be no way to
4171 # hide a program (for example if gdb is too old).
4172 if config_host.has_key('GDB')
4173   summary_info += {'gdb':             config_host['GDB']}
4174 endif
4175 summary_info += {'iasl':              iasl}
4176 summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
4177 if host_os == 'windows' and have_ga
4178   summary_info += {'wixl':            wixl}
4179 endif
4180 if slirp.found() and have_system
4181   summary_info += {'smbd':            have_slirp_smbd ? smbd_path : false}
4182 endif
4183 summary(summary_info, bool_yn: true, section: 'Host binaries')
4185 # Configurable features
4186 summary_info = {}
4187 summary_info += {'Documentation':     build_docs}
4188 summary_info += {'system-mode emulation': have_system}
4189 summary_info += {'user-mode emulation': have_user}
4190 summary_info += {'block layer':       have_block}
4191 summary_info += {'Install blobs':     get_option('install_blobs')}
4192 summary_info += {'module support':    enable_modules}
4193 if enable_modules
4194   summary_info += {'alternative module path': get_option('module_upgrades')}
4195 endif
4196 summary_info += {'fuzzing support':   get_option('fuzzing')}
4197 if have_system
4198   summary_info += {'Audio drivers':     ' '.join(audio_drivers_selected)}
4199 endif
4200 summary_info += {'Trace backends':    ','.join(get_option('trace_backends'))}
4201 if 'simple' in get_option('trace_backends')
4202   summary_info += {'Trace output file': get_option('trace_file') + '-<pid>'}
4203 endif
4204 summary_info += {'D-Bus display':     dbus_display}
4205 summary_info += {'QOM debugging':     get_option('qom_cast_debug')}
4206 summary_info += {'Relocatable install': get_option('relocatable')}
4207 summary_info += {'vhost-kernel support': have_vhost_kernel}
4208 summary_info += {'vhost-net support': have_vhost_net}
4209 summary_info += {'vhost-user support': have_vhost_user}
4210 summary_info += {'vhost-user-crypto support': have_vhost_user_crypto}
4211 summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
4212 summary_info += {'vhost-vdpa support': have_vhost_vdpa}
4213 summary_info += {'build guest agent': have_ga}
4214 summary(summary_info, bool_yn: true, section: 'Configurable features')
4216 # Compilation information
4217 summary_info = {}
4218 summary_info += {'host CPU':          cpu}
4219 summary_info += {'host endianness':   build_machine.endian()}
4220 summary_info += {'C compiler':        ' '.join(meson.get_compiler('c').cmd_array())}
4221 summary_info += {'Host C compiler':   ' '.join(meson.get_compiler('c', native: true).cmd_array())}
4222 if 'cpp' in all_languages
4223   summary_info += {'C++ compiler':    ' '.join(meson.get_compiler('cpp').cmd_array())}
4224 else
4225   summary_info += {'C++ compiler':      false}
4226 endif
4227 if 'objc' in all_languages
4228   summary_info += {'Objective-C compiler': ' '.join(meson.get_compiler('objc').cmd_array())}
4229 else
4230   summary_info += {'Objective-C compiler': false}
4231 endif
4232 option_cflags = (get_option('debug') ? ['-g'] : [])
4233 if get_option('optimization') != 'plain'
4234   option_cflags += ['-O' + get_option('optimization')]
4235 endif
4236 summary_info += {'CFLAGS':            ' '.join(get_option('c_args') + option_cflags)}
4237 if 'cpp' in all_languages
4238   summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args') + option_cflags)}
4239 endif
4240 if 'objc' in all_languages
4241   summary_info += {'OBJCFLAGS':       ' '.join(get_option('objc_args') + option_cflags)}
4242 endif
4243 link_args = get_option('c_link_args')
4244 if link_args.length() > 0
4245   summary_info += {'LDFLAGS':         ' '.join(link_args)}
4246 endif
4247 summary_info += {'QEMU_CFLAGS':       ' '.join(qemu_common_flags + qemu_cflags)}
4248 if 'cpp' in all_languages
4249   summary_info += {'QEMU_CXXFLAGS':     ' '.join(qemu_common_flags + qemu_cxxflags)}
4250 endif
4251 if 'objc' in all_languages
4252   summary_info += {'QEMU_OBJCFLAGS':    ' '.join(qemu_common_flags)}
4253 endif
4254 summary_info += {'QEMU_LDFLAGS':      ' '.join(qemu_ldflags)}
4255 summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
4256 summary_info += {'PIE':               get_option('b_pie')}
4257 summary_info += {'static build':      get_option('prefer_static')}
4258 summary_info += {'malloc trim support': has_malloc_trim}
4259 summary_info += {'membarrier':        have_membarrier}
4260 summary_info += {'debug graph lock':  get_option('debug_graph_lock')}
4261 summary_info += {'debug stack usage': get_option('debug_stack_usage')}
4262 summary_info += {'mutex debugging':   get_option('debug_mutex')}
4263 summary_info += {'memory allocator':  get_option('malloc')}
4264 summary_info += {'avx2 optimization': config_host_data.get('CONFIG_AVX2_OPT')}
4265 summary_info += {'avx512bw optimization': config_host_data.get('CONFIG_AVX512BW_OPT')}
4266 summary_info += {'avx512f optimization': config_host_data.get('CONFIG_AVX512F_OPT')}
4267 summary_info += {'gcov':              get_option('b_coverage')}
4268 summary_info += {'thread sanitizer':  get_option('tsan')}
4269 summary_info += {'CFI support':       get_option('cfi')}
4270 if get_option('cfi')
4271   summary_info += {'CFI debug support': get_option('cfi_debug')}
4272 endif
4273 summary_info += {'strip binaries':    get_option('strip')}
4274 summary_info += {'sparse':            sparse}
4275 summary_info += {'mingw32 support':   host_os == 'windows'}
4276 summary(summary_info, bool_yn: true, section: 'Compilation')
4278 # snarf the cross-compilation information for tests
4279 summary_info = {}
4280 have_cross = false
4281 foreach target: target_dirs
4282   tcg_mak = meson.current_build_dir() / 'tests/tcg' / target / 'config-target.mak'
4283   if fs.exists(tcg_mak)
4284     config_cross_tcg = keyval.load(tcg_mak)
4285     if 'CC' in config_cross_tcg
4286       summary_info += {config_cross_tcg['TARGET_NAME']: config_cross_tcg['CC']}
4287       have_cross = true
4288     endif
4289   endif
4290 endforeach
4291 if have_cross
4292   summary(summary_info, bool_yn: true, section: 'Cross compilers')
4293 endif
4295 # Targets and accelerators
4296 summary_info = {}
4297 if have_system
4298   summary_info += {'KVM support':       config_all_accel.has_key('CONFIG_KVM')}
4299   summary_info += {'HVF support':       config_all_accel.has_key('CONFIG_HVF')}
4300   summary_info += {'WHPX support':      config_all_accel.has_key('CONFIG_WHPX')}
4301   summary_info += {'NVMM support':      config_all_accel.has_key('CONFIG_NVMM')}
4302   summary_info += {'Xen support':       xen.found()}
4303   if xen.found()
4304     summary_info += {'xen ctrl version':  xen.version()}
4305   endif
4306   summary_info += {'Xen emulation':     config_all_devices.has_key('CONFIG_XEN_EMU')}
4307 endif
4308 summary_info += {'TCG support':       config_all_accel.has_key('CONFIG_TCG')}
4309 if config_all_accel.has_key('CONFIG_TCG')
4310   if get_option('tcg_interpreter')
4311     summary_info += {'TCG backend':   'TCI (TCG with bytecode interpreter, slow)'}
4312   else
4313     summary_info += {'TCG backend':   'native (@0@)'.format(cpu)}
4314   endif
4315   summary_info += {'TCG plugins':       get_option('plugins')}
4316   summary_info += {'TCG debug enabled': get_option('debug_tcg')}
4317 endif
4318 summary_info += {'target list':       ' '.join(target_dirs)}
4319 if have_system
4320   summary_info += {'default devices':   get_option('default_devices')}
4321   summary_info += {'out of process emulation': multiprocess_allowed}
4322   summary_info += {'vfio-user server': vfio_user_server_allowed}
4323 endif
4324 summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
4326 # Block layer
4327 summary_info = {}
4328 summary_info += {'coroutine backend': coroutine_backend}
4329 summary_info += {'coroutine pool':    have_coroutine_pool}
4330 if have_block
4331   summary_info += {'Block whitelist (rw)': get_option('block_drv_rw_whitelist')}
4332   summary_info += {'Block whitelist (ro)': get_option('block_drv_ro_whitelist')}
4333   summary_info += {'Use block whitelist in tools': get_option('block_drv_whitelist_in_tools')}
4334   summary_info += {'VirtFS (9P) support':    have_virtfs}
4335   summary_info += {'VirtFS (9P) Proxy Helper support (deprecated)': have_virtfs_proxy_helper}
4336   summary_info += {'Live block migration': config_host_data.get('CONFIG_LIVE_BLOCK_MIGRATION')}
4337   summary_info += {'replication support': config_host_data.get('CONFIG_REPLICATION')}
4338   summary_info += {'bochs support':     get_option('bochs').allowed()}
4339   summary_info += {'cloop support':     get_option('cloop').allowed()}
4340   summary_info += {'dmg support':       get_option('dmg').allowed()}
4341   summary_info += {'qcow v1 support':   get_option('qcow1').allowed()}
4342   summary_info += {'vdi support':       get_option('vdi').allowed()}
4343   summary_info += {'vhdx support':      get_option('vhdx').allowed()}
4344   summary_info += {'vmdk support':      get_option('vmdk').allowed()}
4345   summary_info += {'vpc support':       get_option('vpc').allowed()}
4346   summary_info += {'vvfat support':     get_option('vvfat').allowed()}
4347   summary_info += {'qed support':       get_option('qed').allowed()}
4348   summary_info += {'parallels support': get_option('parallels').allowed()}
4349   summary_info += {'FUSE exports':      fuse}
4350   summary_info += {'VDUSE block exports': have_vduse_blk_export}
4351 endif
4352 summary(summary_info, bool_yn: true, section: 'Block layer support')
4354 # Crypto
4355 summary_info = {}
4356 summary_info += {'TLS priority':      get_option('tls_priority')}
4357 summary_info += {'GNUTLS support':    gnutls}
4358 if gnutls.found()
4359   summary_info += {'  GNUTLS crypto':   gnutls_crypto.found()}
4360 endif
4361 summary_info += {'libgcrypt':         gcrypt}
4362 summary_info += {'nettle':            nettle}
4363 if nettle.found()
4364    summary_info += {'  XTS':             xts != 'private'}
4365 endif
4366 summary_info += {'SM4 ALG support':   crypto_sm4}
4367 summary_info += {'AF_ALG support':    have_afalg}
4368 summary_info += {'rng-none':          get_option('rng_none')}
4369 summary_info += {'Linux keyring':     have_keyring}
4370 summary_info += {'Linux keyutils':    keyutils}
4371 summary(summary_info, bool_yn: true, section: 'Crypto')
4373 # UI
4374 summary_info = {}
4375 if host_os == 'darwin'
4376   summary_info += {'Cocoa support':           cocoa}
4377 endif
4378 summary_info += {'SDL support':       sdl}
4379 summary_info += {'SDL image support': sdl_image}
4380 summary_info += {'GTK support':       gtk}
4381 summary_info += {'pixman':            pixman}
4382 summary_info += {'VTE support':       vte}
4383 summary_info += {'PNG support':       png}
4384 summary_info += {'VNC support':       vnc}
4385 if vnc.found()
4386   summary_info += {'VNC SASL support':  sasl}
4387   summary_info += {'VNC JPEG support':  jpeg}
4388 endif
4389 summary_info += {'spice protocol support': spice_protocol}
4390 if spice_protocol.found()
4391   summary_info += {'  spice server support': spice}
4392 endif
4393 summary_info += {'curses support':    curses}
4394 summary_info += {'brlapi support':    brlapi}
4395 summary(summary_info, bool_yn: true, section: 'User interface')
4397 # Graphics backends
4398 summary_info = {}
4399 summary_info += {'VirGL support':     virgl}
4400 summary_info += {'Rutabaga support':  rutabaga}
4401 summary(summary_info, bool_yn: true, section: 'Graphics backends')
4403 # Audio backends
4404 summary_info = {}
4405 if host_os not in ['darwin', 'haiku', 'windows']
4406   summary_info += {'OSS support':     oss}
4407   summary_info += {'sndio support':   sndio}
4408 elif host_os == 'darwin'
4409   summary_info += {'CoreAudio support': coreaudio}
4410 elif host_os == 'windows'
4411   summary_info += {'DirectSound support': dsound}
4412 endif
4413 if host_os == 'linux'
4414   summary_info += {'ALSA support':    alsa}
4415   summary_info += {'PulseAudio support': pulse}
4416 endif
4417 summary_info += {'PipeWire support':  pipewire}
4418 summary_info += {'JACK support':      jack}
4419 summary(summary_info, bool_yn: true, section: 'Audio backends')
4421 # Network backends
4422 summary_info = {}
4423 if host_os == 'darwin'
4424   summary_info += {'vmnet.framework support': vmnet}
4425 endif
4426 summary_info += {'AF_XDP support':    libxdp}
4427 summary_info += {'slirp support':     slirp}
4428 summary_info += {'vde support':       vde}
4429 summary_info += {'netmap support':    have_netmap}
4430 summary_info += {'l2tpv3 support':    have_l2tpv3}
4431 summary(summary_info, bool_yn: true, section: 'Network backends')
4433 # Libraries
4434 summary_info = {}
4435 summary_info += {'libtasn1':          tasn1}
4436 summary_info += {'PAM':               pam}
4437 summary_info += {'iconv support':     iconv}
4438 summary_info += {'blkio support':     blkio}
4439 summary_info += {'curl support':      curl}
4440 summary_info += {'Multipath support': mpathpersist}
4441 summary_info += {'Linux AIO support': libaio}
4442 summary_info += {'Linux io_uring support': linux_io_uring}
4443 summary_info += {'ATTR/XATTR support': libattr}
4444 summary_info += {'RDMA support':      rdma}
4445 summary_info += {'PVRDMA support':    have_pvrdma}
4446 summary_info += {'fdt support':       fdt_opt == 'disabled' ? false : fdt_opt}
4447 summary_info += {'libcap-ng support': libcap_ng}
4448 summary_info += {'bpf support':       libbpf}
4449 summary_info += {'rbd support':       rbd}
4450 summary_info += {'smartcard support': cacard}
4451 summary_info += {'U2F support':       u2f}
4452 summary_info += {'libusb':            libusb}
4453 summary_info += {'usb net redir':     usbredir}
4454 summary_info += {'OpenGL support (epoxy)': opengl}
4455 summary_info += {'GBM':               gbm}
4456 summary_info += {'libiscsi support':  libiscsi}
4457 summary_info += {'libnfs support':    libnfs}
4458 if host_os == 'windows'
4459   if have_ga
4460     summary_info += {'QGA VSS support':   have_qga_vss}
4461   endif
4462 endif
4463 summary_info += {'seccomp support':   seccomp}
4464 summary_info += {'GlusterFS support': glusterfs}
4465 summary_info += {'hv-balloon support': hv_balloon}
4466 summary_info += {'TPM support':       have_tpm}
4467 summary_info += {'libssh support':    libssh}
4468 summary_info += {'lzo support':       lzo}
4469 summary_info += {'snappy support':    snappy}
4470 summary_info += {'bzip2 support':     libbzip2}
4471 summary_info += {'lzfse support':     liblzfse}
4472 summary_info += {'zstd support':      zstd}
4473 summary_info += {'NUMA host support': numa}
4474 summary_info += {'capstone':          capstone}
4475 summary_info += {'libpmem support':   libpmem}
4476 summary_info += {'libdaxctl support': libdaxctl}
4477 summary_info += {'libudev':           libudev}
4478 # Dummy dependency, keep .found()
4479 summary_info += {'FUSE lseek':        fuse_lseek.found()}
4480 summary_info += {'selinux':           selinux}
4481 summary_info += {'libdw':             libdw}
4482 if host_os == 'freebsd'
4483   summary_info += {'libinotify-kqueue': inotify}
4484 endif
4485 summary(summary_info, bool_yn: true, section: 'Dependencies')
4487 if host_arch == 'unknown'
4488   message()
4489   warning('UNSUPPORTED HOST CPU')
4490   message()
4491   message('Support for CPU host architecture ' + cpu + ' is not currently')
4492   message('maintained. The QEMU project does not guarantee that QEMU will')
4493   message('compile or work on this host CPU. You can help by volunteering')
4494   message('to maintain it and providing a build host for our continuous')
4495   message('integration setup.')
4496   if get_option('tcg').allowed() and target_dirs.length() > 0
4497     message()
4498     message('configure has succeeded and you can continue to build, but')
4499     message('QEMU will use a slow interpreter to emulate the target CPU.')
4500   endif
4501 endif
4503 if not supported_oses.contains(host_os)
4504   message()
4505   warning('UNSUPPORTED HOST OS')
4506   message()
4507   message('Support for host OS ' + host_os + 'is not currently maintained.')
4508   message('configure has succeeded and you can continue to build, but')
4509   message('the QEMU project does not guarantee that QEMU will compile or')
4510   message('work on this operating system. You can help by volunteering')
4511   message('to maintain it and providing a build host for our continuous')
4512   message('integration setup. This will ensure that future versions of QEMU')
4513   message('will keep working on ' + host_os + '.')
4514 endif
4516 if host_arch == 'unknown' or not supported_oses.contains(host_os)
4517   message()
4518   message('If you want to help supporting QEMU on this platform, please')
4519   message('contact the developers at qemu-devel@nongnu.org.')
4520 endif
4522 actually_reloc = get_option('relocatable')
4523 # check if get_relocated_path() is actually able to relocate paths
4524 if get_option('relocatable') and \
4525   not (get_option('prefix') / get_option('bindir')).startswith(get_option('prefix') / '')
4526   message()
4527   warning('bindir not included within prefix, the installation will not be relocatable.')
4528   actually_reloc = false
4529 endif
4530 if not actually_reloc and (host_os == 'windows' or get_option('relocatable'))
4531   if host_os == 'windows'
4532     message()
4533     warning('Windows installs should usually be relocatable.')
4534   endif
4535   message()
4536   message('QEMU will have to be installed under ' + get_option('prefix') + '.')
4537   message('Use --disable-relocatable to remove this warning.')
4538 endif