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