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