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