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