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