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