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