qapi/schema: add type narrowing to lookup_type()
[qemu/kevin.git] / meson.build
blob91a0aa64c64057a096ce371625ea02e0dfa309df
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('hw')
3455 subdir('gdbstub')
3457 if enable_modules
3458   libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
3459   modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
3460 endif
3462 qom_ss = qom_ss.apply({})
3463 libqom = static_library('qom', qom_ss.sources() + genh,
3464                         dependencies: [qom_ss.dependencies()],
3465                         name_suffix: 'fa',
3466                         build_by_default: false)
3467 qom = declare_dependency(link_whole: libqom)
3469 event_loop_base = files('event-loop-base.c')
3470 event_loop_base = static_library('event-loop-base',
3471                                  sources: event_loop_base + genh,
3472                                  name_suffix: 'fa',
3473                                  build_by_default: false)
3474 event_loop_base = declare_dependency(link_whole: event_loop_base,
3475                                      dependencies: [qom])
3477 stub_ss = stub_ss.apply({})
3479 util_ss.add_all(trace_ss)
3480 util_ss = util_ss.apply({})
3481 libqemuutil = static_library('qemuutil',
3482                              build_by_default: false,
3483                              sources: util_ss.sources() + stub_ss.sources() + genh,
3484                              dependencies: [util_ss.dependencies(), libm, threads, glib, socket, malloc, pixman])
3485 qemuutil = declare_dependency(link_with: libqemuutil,
3486                               sources: genh + version_res,
3487                               dependencies: [event_loop_base])
3489 if have_system or have_user
3490   decodetree = generator(find_program('scripts/decodetree.py'),
3491                          output: 'decode-@BASENAME@.c.inc',
3492                          arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
3493   subdir('libdecnumber')
3494   subdir('target')
3495 endif
3497 subdir('audio')
3498 subdir('io')
3499 subdir('chardev')
3500 subdir('fsdev')
3501 subdir('dump')
3503 if have_block
3504   block_ss.add(files(
3505     'block.c',
3506     'blockjob.c',
3507     'job.c',
3508     'qemu-io-cmds.c',
3509   ))
3510   if config_host_data.get('CONFIG_REPLICATION')
3511     block_ss.add(files('replication.c'))
3512   endif
3514   subdir('nbd')
3515   subdir('scsi')
3516   subdir('block')
3518   blockdev_ss.add(files(
3519     'blockdev.c',
3520     'blockdev-nbd.c',
3521     'iothread.c',
3522     'job-qmp.c',
3523   ), gnutls)
3525   # os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
3526   # os-win32.c does not
3527   if host_os == 'windows'
3528     system_ss.add(files('os-win32.c'))
3529   else
3530     blockdev_ss.add(files('os-posix.c'))
3531   endif
3532 endif
3534 common_ss.add(files('cpu-common.c'))
3535 specific_ss.add(files('cpu-target.c'))
3537 subdir('system')
3539 # Work around a gcc bug/misfeature wherein constant propagation looks
3540 # through an alias:
3541 #   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99696
3542 # to guess that a const variable is always zero.  Without lto, this is
3543 # impossible, as the alias is restricted to page-vary-common.c.  Indeed,
3544 # without lto, not even the alias is required -- we simply use different
3545 # declarations in different compilation units.
3546 pagevary = files('page-vary-common.c')
3547 if get_option('b_lto')
3548   pagevary_flags = ['-fno-lto']
3549   if get_option('cfi')
3550     pagevary_flags += '-fno-sanitize=cfi-icall'
3551   endif
3552   pagevary = static_library('page-vary-common', sources: pagevary + genh,
3553                             c_args: pagevary_flags)
3554   pagevary = declare_dependency(link_with: pagevary)
3555 endif
3556 common_ss.add(pagevary)
3557 specific_ss.add(files('page-vary-target.c'))
3559 subdir('backends')
3560 subdir('disas')
3561 subdir('migration')
3562 subdir('monitor')
3563 subdir('net')
3564 subdir('replay')
3565 subdir('semihosting')
3566 subdir('stats')
3567 subdir('tcg')
3568 subdir('fpu')
3569 subdir('accel')
3570 subdir('plugins')
3571 subdir('ebpf')
3573 common_user_inc = []
3575 subdir('common-user')
3576 subdir('bsd-user')
3577 subdir('linux-user')
3579 # needed for fuzzing binaries
3580 subdir('tests/qtest/libqos')
3581 subdir('tests/qtest/fuzz')
3583 # accel modules
3584 tcg_real_module_ss = ss.source_set()
3585 tcg_real_module_ss.add_all(when: 'CONFIG_TCG_MODULAR', if_true: tcg_module_ss)
3586 specific_ss.add_all(when: 'CONFIG_TCG_BUILTIN', if_true: tcg_module_ss)
3587 target_modules += { 'accel' : { 'qtest': qtest_module_ss,
3588                                 'tcg': tcg_real_module_ss }}
3590 ##############################################
3591 # Internal static_libraries and dependencies #
3592 ##############################################
3594 modinfo_collect = find_program('scripts/modinfo-collect.py')
3595 modinfo_generate = find_program('scripts/modinfo-generate.py')
3596 modinfo_files = []
3598 block_mods = []
3599 system_mods = []
3600 foreach d, list : modules
3601   if not (d == 'block' ? have_block : have_system)
3602     continue
3603   endif
3605   foreach m, module_ss : list
3606     if enable_modules
3607       module_ss = module_ss.apply(config_all_devices, strict: false)
3608       sl = static_library(d + '-' + m, [genh, module_ss.sources()],
3609                           dependencies: [modulecommon, module_ss.dependencies()], pic: true)
3610       if d == 'block'
3611         block_mods += sl
3612       else
3613         system_mods += sl
3614       endif
3615       if module_ss.sources() != []
3616         # FIXME: Should use sl.extract_all_objects(recursive: true) as
3617         # input. Sources can be used multiple times but objects are
3618         # unique when it comes to lookup in compile_commands.json.
3619         # Depnds on a mesion version with
3620         # https://github.com/mesonbuild/meson/pull/8900
3621         modinfo_files += custom_target(d + '-' + m + '.modinfo',
3622                                        output: d + '-' + m + '.modinfo',
3623                                        input: module_ss.sources() + genh,
3624                                        capture: true,
3625                                        command: [modinfo_collect, module_ss.sources()])
3626       endif
3627     else
3628       if d == 'block'
3629         block_ss.add_all(module_ss)
3630       else
3631         system_ss.add_all(module_ss)
3632       endif
3633     endif
3634   endforeach
3635 endforeach
3637 foreach d, list : target_modules
3638   foreach m, module_ss : list
3639     if enable_modules
3640       foreach target : target_dirs
3641         if target.endswith('-softmmu')
3642           config_target = config_target_mak[target]
3643           target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
3644           c_args = ['-DNEED_CPU_H',
3645                     '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
3646                     '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
3647           target_module_ss = module_ss.apply(config_target, strict: false)
3648           if target_module_ss.sources() != []
3649             module_name = d + '-' + m + '-' + config_target['TARGET_NAME']
3650             sl = static_library(module_name,
3651                                 [genh, target_module_ss.sources()],
3652                                 dependencies: [modulecommon, target_module_ss.dependencies()],
3653                                 include_directories: target_inc,
3654                                 c_args: c_args,
3655                                 pic: true)
3656             system_mods += sl
3657             # FIXME: Should use sl.extract_all_objects(recursive: true) too.
3658             modinfo_files += custom_target(module_name + '.modinfo',
3659                                            output: module_name + '.modinfo',
3660                                            input: target_module_ss.sources() + genh,
3661                                            capture: true,
3662                                            command: [modinfo_collect, '--target', target, target_module_ss.sources()])
3663           endif
3664         endif
3665       endforeach
3666     else
3667       specific_ss.add_all(module_ss)
3668     endif
3669   endforeach
3670 endforeach
3672 if enable_modules
3673   foreach target : target_dirs
3674     if target.endswith('-softmmu')
3675       config_target = config_target_mak[target]
3676       config_devices_mak = target + '-config-devices.mak'
3677       modinfo_src = custom_target('modinfo-' + target + '.c',
3678                                   output: 'modinfo-' + target + '.c',
3679                                   input: modinfo_files,
3680                                   command: [modinfo_generate, '--devices', config_devices_mak, '@INPUT@'],
3681                                   capture: true)
3683       modinfo_lib = static_library('modinfo-' + target + '.c', modinfo_src)
3684       modinfo_dep = declare_dependency(link_with: modinfo_lib)
3686       arch = config_target['TARGET_NAME'] == 'sparc64' ? 'sparc64' : config_target['TARGET_BASE_ARCH']
3687       hw_arch[arch].add(modinfo_dep)
3688     endif
3689   endforeach
3690 endif
3692 nm = find_program('nm')
3693 undefsym = find_program('scripts/undefsym.py')
3694 block_syms = custom_target('block.syms', output: 'block.syms',
3695                              input: [libqemuutil, block_mods],
3696                              capture: true,
3697                              command: [undefsym, nm, '@INPUT@'])
3698 qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
3699                              input: [libqemuutil, system_mods],
3700                              capture: true,
3701                              command: [undefsym, nm, '@INPUT@'])
3703 authz_ss = authz_ss.apply({})
3704 libauthz = static_library('authz', authz_ss.sources() + genh,
3705                           dependencies: [authz_ss.dependencies()],
3706                           name_suffix: 'fa',
3707                           build_by_default: false)
3709 authz = declare_dependency(link_whole: libauthz,
3710                            dependencies: qom)
3712 crypto_ss = crypto_ss.apply({})
3713 libcrypto = static_library('crypto', crypto_ss.sources() + genh,
3714                            dependencies: [crypto_ss.dependencies()],
3715                            name_suffix: 'fa',
3716                            build_by_default: false)
3718 crypto = declare_dependency(link_whole: libcrypto,
3719                             dependencies: [authz, qom])
3721 io_ss = io_ss.apply({})
3722 libio = static_library('io', io_ss.sources() + genh,
3723                        dependencies: [io_ss.dependencies()],
3724                        link_with: libqemuutil,
3725                        name_suffix: 'fa',
3726                        build_by_default: false)
3728 io = declare_dependency(link_whole: libio, dependencies: [crypto, qom])
3730 libmigration = static_library('migration', sources: migration_files + genh,
3731                               name_suffix: 'fa',
3732                               build_by_default: false)
3733 migration = declare_dependency(link_with: libmigration,
3734                                dependencies: [zlib, qom, io])
3735 system_ss.add(migration)
3737 block_ss = block_ss.apply({})
3738 libblock = static_library('block', block_ss.sources() + genh,
3739                           dependencies: block_ss.dependencies(),
3740                           link_depends: block_syms,
3741                           name_suffix: 'fa',
3742                           build_by_default: false)
3744 block = declare_dependency(link_whole: [libblock],
3745                            link_args: '@block.syms',
3746                            dependencies: [crypto, io])
3748 blockdev_ss = blockdev_ss.apply({})
3749 libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
3750                              dependencies: blockdev_ss.dependencies(),
3751                              name_suffix: 'fa',
3752                              build_by_default: false)
3754 blockdev = declare_dependency(link_whole: [libblockdev],
3755                               dependencies: [block, event_loop_base])
3757 qmp_ss = qmp_ss.apply({})
3758 libqmp = static_library('qmp', qmp_ss.sources() + genh,
3759                         dependencies: qmp_ss.dependencies(),
3760                         name_suffix: 'fa',
3761                         build_by_default: false)
3763 qmp = declare_dependency(link_whole: [libqmp])
3765 libchardev = static_library('chardev', chardev_ss.sources() + genh,
3766                             name_suffix: 'fa',
3767                             dependencies: chardev_ss.dependencies(),
3768                             build_by_default: false)
3770 chardev = declare_dependency(link_whole: libchardev)
3772 hwcore_ss = hwcore_ss.apply({})
3773 libhwcore = static_library('hwcore', sources: hwcore_ss.sources() + genh,
3774                            name_suffix: 'fa',
3775                            build_by_default: false)
3776 hwcore = declare_dependency(link_whole: libhwcore)
3777 common_ss.add(hwcore)
3779 ###########
3780 # Targets #
3781 ###########
3783 emulator_modules = []
3784 foreach m : block_mods + system_mods
3785   emulator_modules += shared_module(m.name(),
3786                 build_by_default: true,
3787                 name_prefix: '',
3788                 link_whole: m,
3789                 install: true,
3790                 install_dir: qemu_moddir)
3791 endforeach
3792 if emulator_modules.length() > 0
3793   alias_target('modules', emulator_modules)
3794 endif
3796 system_ss.add(authz, blockdev, chardev, crypto, io, qmp)
3797 common_ss.add(qom, qemuutil)
3799 common_ss.add_all(when: 'CONFIG_SYSTEM_ONLY', if_true: [system_ss])
3800 common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
3802 # Note that this library is never used directly (only through extract_objects)
3803 # and is not built by default; therefore, source files not used by the build
3804 # configuration will be in build.ninja, but are never built by default.
3805 common_all = static_library('common',
3806                             build_by_default: false,
3807                             sources: common_ss.all_sources() + genh,
3808                             include_directories: common_user_inc,
3809                             implicit_include_directories: false,
3810                             dependencies: common_ss.all_dependencies(),
3811                             name_suffix: 'fa')
3813 feature_to_c = find_program('scripts/feature_to_c.py')
3815 if host_os == 'darwin'
3816   entitlement = find_program('scripts/entitlement.sh')
3817 endif
3819 traceable = []
3820 emulators = {}
3821 foreach target : target_dirs
3822   config_target = config_target_mak[target]
3823   target_name = config_target['TARGET_NAME']
3824   target_base_arch = config_target['TARGET_BASE_ARCH']
3825   arch_srcs = [config_target_h[target]]
3826   arch_deps = []
3827   c_args = ['-DNEED_CPU_H',
3828             '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
3829             '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
3830   link_args = emulator_link_args
3832   target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
3833   if host_os == 'linux'
3834     target_inc += include_directories('linux-headers', is_system: true)
3835   endif
3836   if target.endswith('-softmmu')
3837     target_type='system'
3838     t = target_system_arch[target_base_arch].apply(config_target, strict: false)
3839     arch_srcs += t.sources()
3840     arch_deps += t.dependencies()
3842     hw_dir = target_name == 'sparc64' ? 'sparc64' : target_base_arch
3843     if hw_arch.has_key(hw_dir)
3844       hw = hw_arch[hw_dir].apply(config_target, strict: false)
3845       arch_srcs += hw.sources()
3846       arch_deps += hw.dependencies()
3847     endif
3849     arch_srcs += config_devices_h[target]
3850     link_args += ['@block.syms', '@qemu.syms']
3851   else
3852     abi = config_target['TARGET_ABI_DIR']
3853     target_type='user'
3854     target_inc += common_user_inc
3855     if target_base_arch in target_user_arch
3856       t = target_user_arch[target_base_arch].apply(config_target, strict: false)
3857       arch_srcs += t.sources()
3858       arch_deps += t.dependencies()
3859     endif
3860     if 'CONFIG_LINUX_USER' in config_target
3861       base_dir = 'linux-user'
3862     endif
3863     if 'CONFIG_BSD_USER' in config_target
3864       base_dir = 'bsd-user'
3865       target_inc += include_directories('bsd-user/' / host_os)
3866       target_inc += include_directories('bsd-user/host/' / host_arch)
3867       dir = base_dir / abi
3868       arch_srcs += files(dir / 'signal.c', dir / 'target_arch_cpu.c')
3869     endif
3870     target_inc += include_directories(
3871       base_dir,
3872       base_dir / abi,
3873     )
3874     if 'CONFIG_LINUX_USER' in config_target
3875       dir = base_dir / abi
3876       arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
3877       if config_target.has_key('TARGET_SYSTBL_ABI')
3878         arch_srcs += \
3879           syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
3880                                              extra_args : config_target['TARGET_SYSTBL_ABI'])
3881       endif
3882     endif
3883   endif
3885   if 'TARGET_XML_FILES' in config_target
3886     gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
3887                                 output: target + '-gdbstub-xml.c',
3888                                 input: files(config_target['TARGET_XML_FILES'].split()),
3889                                 command: [feature_to_c, '@INPUT@'],
3890                                 capture: true)
3891     arch_srcs += gdbstub_xml
3892   endif
3894   t = target_arch[target_base_arch].apply(config_target, strict: false)
3895   arch_srcs += t.sources()
3896   arch_deps += t.dependencies()
3898   target_common = common_ss.apply(config_target, strict: false)
3899   objects = common_all.extract_objects(target_common.sources())
3900   deps = target_common.dependencies()
3902   target_specific = specific_ss.apply(config_target, strict: false)
3903   arch_srcs += target_specific.sources()
3904   arch_deps += target_specific.dependencies()
3906   lib = static_library('qemu-' + target,
3907                  sources: arch_srcs + genh,
3908                  dependencies: arch_deps,
3909                  objects: objects,
3910                  include_directories: target_inc,
3911                  c_args: c_args,
3912                  build_by_default: false,
3913                  name_suffix: 'fa')
3915   if target.endswith('-softmmu')
3916     execs = [{
3917       'name': 'qemu-system-' + target_name,
3918       'win_subsystem': 'console',
3919       'sources': files('system/main.c'),
3920       'dependencies': []
3921     }]
3922     if host_os == 'windows' and (sdl.found() or gtk.found())
3923       execs += [{
3924         'name': 'qemu-system-' + target_name + 'w',
3925         'win_subsystem': 'windows',
3926         'sources': files('system/main.c'),
3927         'dependencies': []
3928       }]
3929     endif
3930     if get_option('fuzzing')
3931       specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
3932       execs += [{
3933         'name': 'qemu-fuzz-' + target_name,
3934         'win_subsystem': 'console',
3935         'sources': specific_fuzz.sources(),
3936         'dependencies': specific_fuzz.dependencies(),
3937       }]
3938     endif
3939   else
3940     execs = [{
3941       'name': 'qemu-' + target_name,
3942       'win_subsystem': 'console',
3943       'sources': [],
3944       'dependencies': []
3945     }]
3946   endif
3947   foreach exe: execs
3948     exe_name = exe['name']
3949     if host_os == 'darwin'
3950       exe_name += '-unsigned'
3951     endif
3953     emulator = executable(exe_name, exe['sources'],
3954                install: true,
3955                c_args: c_args,
3956                dependencies: arch_deps + deps + exe['dependencies'],
3957                objects: lib.extract_all_objects(recursive: true),
3958                link_depends: [block_syms, qemu_syms],
3959                link_args: link_args,
3960                win_subsystem: exe['win_subsystem'])
3962     if host_os == 'darwin'
3963       icon = 'pc-bios/qemu.rsrc'
3964       build_input = [emulator, files(icon)]
3965       install_input = [
3966         get_option('bindir') / exe_name,
3967         meson.current_source_dir() / icon
3968       ]
3969       if 'CONFIG_HVF' in config_target
3970         entitlements = 'accel/hvf/entitlements.plist'
3971         build_input += files(entitlements)
3972         install_input += meson.current_source_dir() / entitlements
3973       endif
3975       emulators += {exe['name'] : custom_target(exe['name'],
3976                    input: build_input,
3977                    output: exe['name'],
3978                    command: [entitlement, '@OUTPUT@', '@INPUT@'])
3979       }
3981       meson.add_install_script(entitlement, '--install',
3982                                get_option('bindir') / exe['name'],
3983                                install_input)
3984     else
3985       emulators += {exe['name']: emulator}
3986     endif
3988     traceable += [{
3989       'exe': exe['name'],
3990       'probe-prefix': 'qemu.' + target_type + '.' + target_name,
3991     }]
3993   endforeach
3994 endforeach
3996 # Other build targets
3998 if get_option('plugins')
3999   install_headers('include/qemu/qemu-plugin.h')
4000   if host_os == 'windows'
4001     # On windows, we want to deliver the qemu_plugin_api.lib file in the qemu installer,
4002     # so that plugin authors can compile against it.
4003     install_data(win32_qemu_plugin_api_lib, install_dir: 'lib')
4004   endif
4005 endif
4007 subdir('qga')
4009 # Don't build qemu-keymap if xkbcommon is not explicitly enabled
4010 # when we don't build tools or system
4011 if xkbcommon.found()
4012   # used for the update-keymaps target, so include rules even if !have_tools
4013   qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
4014                            dependencies: [qemuutil, xkbcommon], install: have_tools)
4015 endif
4017 if have_tools
4018   qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
4019              dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
4020   qemu_io = executable('qemu-io', files('qemu-io.c'),
4021              dependencies: [block, qemuutil], install: true)
4022   qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
4023                dependencies: [blockdev, qemuutil, gnutls, selinux],
4024                install: true)
4026   subdir('storage-daemon')
4028   foreach exe: [ 'qemu-img', 'qemu-io', 'qemu-nbd', 'qemu-storage-daemon']
4029     traceable += [{
4030       'exe': exe,
4031       'probe-prefix': 'qemu.' + exe.substring(5).replace('-', '_')
4032     }]
4033   endforeach
4035   subdir('contrib/rdmacm-mux')
4036   subdir('contrib/elf2dmp')
4038   executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
4039              dependencies: qemuutil,
4040              install: true)
4042   if have_vhost_user
4043     subdir('contrib/vhost-user-blk')
4044     subdir('contrib/vhost-user-gpu')
4045     subdir('contrib/vhost-user-input')
4046     subdir('contrib/vhost-user-scsi')
4047   endif
4049   if host_os == 'linux'
4050     executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
4051                dependencies: [qemuutil, libcap_ng],
4052                install: true,
4053                install_dir: get_option('libexecdir'))
4055     executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
4056                dependencies: [authz, crypto, io, qom, qemuutil,
4057                               libcap_ng, mpathpersist],
4058                install: true)
4059   endif
4061   if have_ivshmem
4062     subdir('contrib/ivshmem-client')
4063     subdir('contrib/ivshmem-server')
4064   endif
4065 endif
4067 if stap.found()
4068   foreach t: traceable
4069     foreach stp: [
4070       {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / t['exe'], 'install': false},
4071       {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / t['exe'], 'install': true},
4072       {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
4073       {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
4074     ]
4075       cmd = [
4076         tracetool, '--group=all', '--format=' + stp['fmt'],
4077         '--binary=' + stp['bin'],
4078         '--probe-prefix=' + t['probe-prefix'],
4079         '@INPUT@', '@OUTPUT@'
4080       ]
4082       custom_target(t['exe'] + stp['ext'],
4083                     input: trace_events_all,
4084                     output: t['exe'] + stp['ext'],
4085                     install: stp['install'],
4086                     install_dir: get_option('datadir') / 'systemtap/tapset',
4087                     command: cmd,
4088                     depend_files: tracetool_depends)
4089     endforeach
4090   endforeach
4091 endif
4093 subdir('scripts')
4094 subdir('tools')
4095 subdir('pc-bios')
4096 subdir('docs')
4097 subdir('tests')
4098 if gtk.found()
4099   subdir('po')
4100 endif
4102 if host_machine.system() == 'windows'
4103   nsis_cmd = [
4104     find_program('scripts/nsis.py'),
4105     '@OUTPUT@',
4106     get_option('prefix'),
4107     meson.current_source_dir(),
4108     glib_pc.get_variable('bindir'),
4109     host_machine.cpu(),
4110     '--',
4111     '-DDISPLAYVERSION=' + meson.project_version(),
4112   ]
4113   if build_docs
4114     nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
4115   endif
4116   if gtk.found()
4117     nsis_cmd += '-DCONFIG_GTK=y'
4118   endif
4120   nsis = custom_target('nsis',
4121                        output: 'qemu-setup-' + meson.project_version() + '.exe',
4122                        input: files('qemu.nsi'),
4123                        build_always_stale: true,
4124                        command: nsis_cmd + ['@INPUT@'])
4125   alias_target('installer', nsis)
4126 endif
4128 #########################
4129 # Configuration summary #
4130 #########################
4132 # Build environment
4133 summary_info = {}
4134 summary_info += {'Build directory':   meson.current_build_dir()}
4135 summary_info += {'Source path':       meson.current_source_dir()}
4136 summary_info += {'Download dependencies': get_option('wrap_mode') != 'nodownload'}
4137 summary(summary_info, bool_yn: true, section: 'Build environment')
4139 # Directories
4140 summary_info += {'Install prefix':    get_option('prefix')}
4141 summary_info += {'BIOS directory':    qemu_datadir}
4142 pathsep = host_os == 'windows' ? ';' : ':'
4143 summary_info += {'firmware path':     pathsep.join(get_option('qemu_firmwarepath'))}
4144 summary_info += {'binary directory':  get_option('prefix') / get_option('bindir')}
4145 summary_info += {'library directory': get_option('prefix') / get_option('libdir')}
4146 summary_info += {'module directory':  qemu_moddir}
4147 summary_info += {'libexec directory': get_option('prefix') / get_option('libexecdir')}
4148 summary_info += {'include directory': get_option('prefix') / get_option('includedir')}
4149 summary_info += {'config directory':  get_option('prefix') / get_option('sysconfdir')}
4150 if host_os != 'windows'
4151   summary_info += {'local state directory': get_option('prefix') / get_option('localstatedir')}
4152   summary_info += {'Manual directory':      get_option('prefix') / get_option('mandir')}
4153 else
4154   summary_info += {'local state directory': 'queried at runtime'}
4155 endif
4156 summary_info += {'Doc directory':     get_option('prefix') / get_option('docdir')}
4157 summary(summary_info, bool_yn: true, section: 'Directories')
4159 # Host binaries
4160 summary_info = {}
4161 summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
4162 summary_info += {'sphinx-build':      sphinx_build}
4164 # FIXME: the [binaries] section of machine files, which can be probed
4165 # with find_program(), would be great for passing gdb and genisoimage
4166 # paths from configure to Meson.  However, there seems to be no way to
4167 # hide a program (for example if gdb is too old).
4168 if config_host.has_key('GDB')
4169   summary_info += {'gdb':             config_host['GDB']}
4170 endif
4171 summary_info += {'iasl':              iasl}
4172 summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
4173 if host_os == 'windows' and have_ga
4174   summary_info += {'wixl':            wixl}
4175 endif
4176 if slirp.found() and have_system
4177   summary_info += {'smbd':            have_slirp_smbd ? smbd_path : false}
4178 endif
4179 summary(summary_info, bool_yn: true, section: 'Host binaries')
4181 # Configurable features
4182 summary_info = {}
4183 summary_info += {'Documentation':     build_docs}
4184 summary_info += {'system-mode emulation': have_system}
4185 summary_info += {'user-mode emulation': have_user}
4186 summary_info += {'block layer':       have_block}
4187 summary_info += {'Install blobs':     get_option('install_blobs')}
4188 summary_info += {'module support':    enable_modules}
4189 if enable_modules
4190   summary_info += {'alternative module path': get_option('module_upgrades')}
4191 endif
4192 summary_info += {'fuzzing support':   get_option('fuzzing')}
4193 if have_system
4194   summary_info += {'Audio drivers':     ' '.join(audio_drivers_selected)}
4195 endif
4196 summary_info += {'Trace backends':    ','.join(get_option('trace_backends'))}
4197 if 'simple' in get_option('trace_backends')
4198   summary_info += {'Trace output file': get_option('trace_file') + '-<pid>'}
4199 endif
4200 summary_info += {'D-Bus display':     dbus_display}
4201 summary_info += {'QOM debugging':     get_option('qom_cast_debug')}
4202 summary_info += {'Relocatable install': get_option('relocatable')}
4203 summary_info += {'vhost-kernel support': have_vhost_kernel}
4204 summary_info += {'vhost-net support': have_vhost_net}
4205 summary_info += {'vhost-user support': have_vhost_user}
4206 summary_info += {'vhost-user-crypto support': have_vhost_user_crypto}
4207 summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
4208 summary_info += {'vhost-vdpa support': have_vhost_vdpa}
4209 summary_info += {'build guest agent': have_ga}
4210 summary(summary_info, bool_yn: true, section: 'Configurable features')
4212 # Compilation information
4213 summary_info = {}
4214 summary_info += {'host CPU':          cpu}
4215 summary_info += {'host endianness':   build_machine.endian()}
4216 summary_info += {'C compiler':        ' '.join(meson.get_compiler('c').cmd_array())}
4217 summary_info += {'Host C compiler':   ' '.join(meson.get_compiler('c', native: true).cmd_array())}
4218 if 'cpp' in all_languages
4219   summary_info += {'C++ compiler':    ' '.join(meson.get_compiler('cpp').cmd_array())}
4220 else
4221   summary_info += {'C++ compiler':      false}
4222 endif
4223 if 'objc' in all_languages
4224   summary_info += {'Objective-C compiler': ' '.join(meson.get_compiler('objc').cmd_array())}
4225 else
4226   summary_info += {'Objective-C compiler': false}
4227 endif
4228 option_cflags = (get_option('debug') ? ['-g'] : [])
4229 if get_option('optimization') != 'plain'
4230   option_cflags += ['-O' + get_option('optimization')]
4231 endif
4232 summary_info += {'CFLAGS':            ' '.join(get_option('c_args') + option_cflags)}
4233 if 'cpp' in all_languages
4234   summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args') + option_cflags)}
4235 endif
4236 if 'objc' in all_languages
4237   summary_info += {'OBJCFLAGS':       ' '.join(get_option('objc_args') + option_cflags)}
4238 endif
4239 link_args = get_option('c_link_args')
4240 if link_args.length() > 0
4241   summary_info += {'LDFLAGS':         ' '.join(link_args)}
4242 endif
4243 summary_info += {'QEMU_CFLAGS':       ' '.join(qemu_common_flags + qemu_cflags)}
4244 if 'cpp' in all_languages
4245   summary_info += {'QEMU_CXXFLAGS':     ' '.join(qemu_common_flags + qemu_cxxflags)}
4246 endif
4247 if 'objc' in all_languages
4248   summary_info += {'QEMU_OBJCFLAGS':    ' '.join(qemu_common_flags)}
4249 endif
4250 summary_info += {'QEMU_LDFLAGS':      ' '.join(qemu_ldflags)}
4251 summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
4252 summary_info += {'PIE':               get_option('b_pie')}
4253 summary_info += {'static build':      get_option('prefer_static')}
4254 summary_info += {'malloc trim support': has_malloc_trim}
4255 summary_info += {'membarrier':        have_membarrier}
4256 summary_info += {'debug graph lock':  get_option('debug_graph_lock')}
4257 summary_info += {'debug stack usage': get_option('debug_stack_usage')}
4258 summary_info += {'mutex debugging':   get_option('debug_mutex')}
4259 summary_info += {'memory allocator':  get_option('malloc')}
4260 summary_info += {'avx2 optimization': config_host_data.get('CONFIG_AVX2_OPT')}
4261 summary_info += {'avx512bw optimization': config_host_data.get('CONFIG_AVX512BW_OPT')}
4262 summary_info += {'avx512f optimization': config_host_data.get('CONFIG_AVX512F_OPT')}
4263 summary_info += {'gcov':              get_option('b_coverage')}
4264 summary_info += {'thread sanitizer':  get_option('tsan')}
4265 summary_info += {'CFI support':       get_option('cfi')}
4266 if get_option('cfi')
4267   summary_info += {'CFI debug support': get_option('cfi_debug')}
4268 endif
4269 summary_info += {'strip binaries':    get_option('strip')}
4270 summary_info += {'sparse':            sparse}
4271 summary_info += {'mingw32 support':   host_os == 'windows'}
4272 summary(summary_info, bool_yn: true, section: 'Compilation')
4274 # snarf the cross-compilation information for tests
4275 summary_info = {}
4276 have_cross = false
4277 foreach target: target_dirs
4278   tcg_mak = meson.current_build_dir() / 'tests/tcg' / target / 'config-target.mak'
4279   if fs.exists(tcg_mak)
4280     config_cross_tcg = keyval.load(tcg_mak)
4281     if 'CC' in config_cross_tcg
4282       summary_info += {config_cross_tcg['TARGET_NAME']: config_cross_tcg['CC']}
4283       have_cross = true
4284     endif
4285   endif
4286 endforeach
4287 if have_cross
4288   summary(summary_info, bool_yn: true, section: 'Cross compilers')
4289 endif
4291 # Targets and accelerators
4292 summary_info = {}
4293 if have_system
4294   summary_info += {'KVM support':       config_all_accel.has_key('CONFIG_KVM')}
4295   summary_info += {'HVF support':       config_all_accel.has_key('CONFIG_HVF')}
4296   summary_info += {'WHPX support':      config_all_accel.has_key('CONFIG_WHPX')}
4297   summary_info += {'NVMM support':      config_all_accel.has_key('CONFIG_NVMM')}
4298   summary_info += {'Xen support':       xen.found()}
4299   if xen.found()
4300     summary_info += {'xen ctrl version':  xen.version()}
4301   endif
4302   summary_info += {'Xen emulation':     config_all_devices.has_key('CONFIG_XEN_EMU')}
4303 endif
4304 summary_info += {'TCG support':       config_all_accel.has_key('CONFIG_TCG')}
4305 if config_all_accel.has_key('CONFIG_TCG')
4306   if get_option('tcg_interpreter')
4307     summary_info += {'TCG backend':   'TCI (TCG with bytecode interpreter, slow)'}
4308   else
4309     summary_info += {'TCG backend':   'native (@0@)'.format(cpu)}
4310   endif
4311   summary_info += {'TCG plugins':       get_option('plugins')}
4312   summary_info += {'TCG debug enabled': get_option('debug_tcg')}
4313 endif
4314 summary_info += {'target list':       ' '.join(target_dirs)}
4315 if have_system
4316   summary_info += {'default devices':   get_option('default_devices')}
4317   summary_info += {'out of process emulation': multiprocess_allowed}
4318   summary_info += {'vfio-user server': vfio_user_server_allowed}
4319 endif
4320 summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
4322 # Block layer
4323 summary_info = {}
4324 summary_info += {'coroutine backend': coroutine_backend}
4325 summary_info += {'coroutine pool':    have_coroutine_pool}
4326 if have_block
4327   summary_info += {'Block whitelist (rw)': get_option('block_drv_rw_whitelist')}
4328   summary_info += {'Block whitelist (ro)': get_option('block_drv_ro_whitelist')}
4329   summary_info += {'Use block whitelist in tools': get_option('block_drv_whitelist_in_tools')}
4330   summary_info += {'VirtFS (9P) support':    have_virtfs}
4331   summary_info += {'VirtFS (9P) Proxy Helper support (deprecated)': have_virtfs_proxy_helper}
4332   summary_info += {'Live block migration': config_host_data.get('CONFIG_LIVE_BLOCK_MIGRATION')}
4333   summary_info += {'replication support': config_host_data.get('CONFIG_REPLICATION')}
4334   summary_info += {'bochs support':     get_option('bochs').allowed()}
4335   summary_info += {'cloop support':     get_option('cloop').allowed()}
4336   summary_info += {'dmg support':       get_option('dmg').allowed()}
4337   summary_info += {'qcow v1 support':   get_option('qcow1').allowed()}
4338   summary_info += {'vdi support':       get_option('vdi').allowed()}
4339   summary_info += {'vhdx support':      get_option('vhdx').allowed()}
4340   summary_info += {'vmdk support':      get_option('vmdk').allowed()}
4341   summary_info += {'vpc support':       get_option('vpc').allowed()}
4342   summary_info += {'vvfat support':     get_option('vvfat').allowed()}
4343   summary_info += {'qed support':       get_option('qed').allowed()}
4344   summary_info += {'parallels support': get_option('parallels').allowed()}
4345   summary_info += {'FUSE exports':      fuse}
4346   summary_info += {'VDUSE block exports': have_vduse_blk_export}
4347 endif
4348 summary(summary_info, bool_yn: true, section: 'Block layer support')
4350 # Crypto
4351 summary_info = {}
4352 summary_info += {'TLS priority':      get_option('tls_priority')}
4353 summary_info += {'GNUTLS support':    gnutls}
4354 if gnutls.found()
4355   summary_info += {'  GNUTLS crypto':   gnutls_crypto.found()}
4356 endif
4357 summary_info += {'libgcrypt':         gcrypt}
4358 summary_info += {'nettle':            nettle}
4359 if nettle.found()
4360    summary_info += {'  XTS':             xts != 'private'}
4361 endif
4362 summary_info += {'SM4 ALG support':   crypto_sm4}
4363 summary_info += {'AF_ALG support':    have_afalg}
4364 summary_info += {'rng-none':          get_option('rng_none')}
4365 summary_info += {'Linux keyring':     have_keyring}
4366 summary_info += {'Linux keyutils':    keyutils}
4367 summary(summary_info, bool_yn: true, section: 'Crypto')
4369 # UI
4370 summary_info = {}
4371 if host_os == 'darwin'
4372   summary_info += {'Cocoa support':           cocoa}
4373 endif
4374 summary_info += {'SDL support':       sdl}
4375 summary_info += {'SDL image support': sdl_image}
4376 summary_info += {'GTK support':       gtk}
4377 summary_info += {'pixman':            pixman}
4378 summary_info += {'VTE support':       vte}
4379 summary_info += {'PNG support':       png}
4380 summary_info += {'VNC support':       vnc}
4381 if vnc.found()
4382   summary_info += {'VNC SASL support':  sasl}
4383   summary_info += {'VNC JPEG support':  jpeg}
4384 endif
4385 summary_info += {'spice protocol support': spice_protocol}
4386 if spice_protocol.found()
4387   summary_info += {'  spice server support': spice}
4388 endif
4389 summary_info += {'curses support':    curses}
4390 summary_info += {'brlapi support':    brlapi}
4391 summary(summary_info, bool_yn: true, section: 'User interface')
4393 # Graphics backends
4394 summary_info = {}
4395 summary_info += {'VirGL support':     virgl}
4396 summary_info += {'Rutabaga support':  rutabaga}
4397 summary(summary_info, bool_yn: true, section: 'Graphics backends')
4399 # Audio backends
4400 summary_info = {}
4401 if host_os not in ['darwin', 'haiku', 'windows']
4402   summary_info += {'OSS support':     oss}
4403   summary_info += {'sndio support':   sndio}
4404 elif host_os == 'darwin'
4405   summary_info += {'CoreAudio support': coreaudio}
4406 elif host_os == 'windows'
4407   summary_info += {'DirectSound support': dsound}
4408 endif
4409 if host_os == 'linux'
4410   summary_info += {'ALSA support':    alsa}
4411   summary_info += {'PulseAudio support': pulse}
4412 endif
4413 summary_info += {'PipeWire support':  pipewire}
4414 summary_info += {'JACK support':      jack}
4415 summary(summary_info, bool_yn: true, section: 'Audio backends')
4417 # Network backends
4418 summary_info = {}
4419 if host_os == 'darwin'
4420   summary_info += {'vmnet.framework support': vmnet}
4421 endif
4422 summary_info += {'AF_XDP support':    libxdp}
4423 summary_info += {'slirp support':     slirp}
4424 summary_info += {'vde support':       vde}
4425 summary_info += {'netmap support':    have_netmap}
4426 summary_info += {'l2tpv3 support':    have_l2tpv3}
4427 summary(summary_info, bool_yn: true, section: 'Network backends')
4429 # Libraries
4430 summary_info = {}
4431 summary_info += {'libtasn1':          tasn1}
4432 summary_info += {'PAM':               pam}
4433 summary_info += {'iconv support':     iconv}
4434 summary_info += {'blkio support':     blkio}
4435 summary_info += {'curl support':      curl}
4436 summary_info += {'Multipath support': mpathpersist}
4437 summary_info += {'Linux AIO support': libaio}
4438 summary_info += {'Linux io_uring support': linux_io_uring}
4439 summary_info += {'ATTR/XATTR support': libattr}
4440 summary_info += {'RDMA support':      rdma}
4441 summary_info += {'PVRDMA support':    have_pvrdma}
4442 summary_info += {'fdt support':       fdt_opt == 'disabled' ? false : fdt_opt}
4443 summary_info += {'libcap-ng support': libcap_ng}
4444 summary_info += {'bpf support':       libbpf}
4445 summary_info += {'rbd support':       rbd}
4446 summary_info += {'smartcard support': cacard}
4447 summary_info += {'U2F support':       u2f}
4448 summary_info += {'libusb':            libusb}
4449 summary_info += {'usb net redir':     usbredir}
4450 summary_info += {'OpenGL support (epoxy)': opengl}
4451 summary_info += {'GBM':               gbm}
4452 summary_info += {'libiscsi support':  libiscsi}
4453 summary_info += {'libnfs support':    libnfs}
4454 if host_os == 'windows'
4455   if have_ga
4456     summary_info += {'QGA VSS support':   have_qga_vss}
4457   endif
4458 endif
4459 summary_info += {'seccomp support':   seccomp}
4460 summary_info += {'GlusterFS support': glusterfs}
4461 summary_info += {'hv-balloon support': hv_balloon}
4462 summary_info += {'TPM support':       have_tpm}
4463 summary_info += {'libssh support':    libssh}
4464 summary_info += {'lzo support':       lzo}
4465 summary_info += {'snappy support':    snappy}
4466 summary_info += {'bzip2 support':     libbzip2}
4467 summary_info += {'lzfse support':     liblzfse}
4468 summary_info += {'zstd support':      zstd}
4469 summary_info += {'NUMA host support': numa}
4470 summary_info += {'capstone':          capstone}
4471 summary_info += {'libpmem support':   libpmem}
4472 summary_info += {'libdaxctl support': libdaxctl}
4473 summary_info += {'libudev':           libudev}
4474 # Dummy dependency, keep .found()
4475 summary_info += {'FUSE lseek':        fuse_lseek.found()}
4476 summary_info += {'selinux':           selinux}
4477 summary_info += {'libdw':             libdw}
4478 if host_os == 'freebsd'
4479   summary_info += {'libinotify-kqueue': inotify}
4480 endif
4481 summary(summary_info, bool_yn: true, section: 'Dependencies')
4483 if host_arch == 'unknown'
4484   message()
4485   warning('UNSUPPORTED HOST CPU')
4486   message()
4487   message('Support for CPU host architecture ' + cpu + ' is not currently')
4488   message('maintained. The QEMU project does not guarantee that QEMU will')
4489   message('compile or work on this host CPU. You can help by volunteering')
4490   message('to maintain it and providing a build host for our continuous')
4491   message('integration setup.')
4492   if get_option('tcg').allowed() and target_dirs.length() > 0
4493     message()
4494     message('configure has succeeded and you can continue to build, but')
4495     message('QEMU will use a slow interpreter to emulate the target CPU.')
4496   endif
4497 endif
4499 if not supported_oses.contains(host_os)
4500   message()
4501   warning('UNSUPPORTED HOST OS')
4502   message()
4503   message('Support for host OS ' + host_os + 'is not currently maintained.')
4504   message('configure has succeeded and you can continue to build, but')
4505   message('the QEMU project does not guarantee that QEMU will compile or')
4506   message('work on this operating system. You can help by volunteering')
4507   message('to maintain it and providing a build host for our continuous')
4508   message('integration setup. This will ensure that future versions of QEMU')
4509   message('will keep working on ' + host_os + '.')
4510 endif
4512 if host_arch == 'unknown' or not supported_oses.contains(host_os)
4513   message()
4514   message('If you want to help supporting QEMU on this platform, please')
4515   message('contact the developers at qemu-devel@nongnu.org.')
4516 endif
4518 actually_reloc = get_option('relocatable')
4519 # check if get_relocated_path() is actually able to relocate paths
4520 if get_option('relocatable') and \
4521   not (get_option('prefix') / get_option('bindir')).startswith(get_option('prefix') / '')
4522   message()
4523   warning('bindir not included within prefix, the installation will not be relocatable.')
4524   actually_reloc = false
4525 endif
4526 if not actually_reloc and (host_os == 'windows' or get_option('relocatable'))
4527   if host_os == 'windows'
4528     message()
4529     warning('Windows installs should usually be relocatable.')
4530   endif
4531   message()
4532   message('QEMU will have to be installed under ' + get_option('prefix') + '.')
4533   message('Use --disable-relocatable to remove this warning.')
4534 endif