target/loongarch/gdbstub: Add vector registers support
[qemu/ar7.git] / meson.build
bloba1e51277b093f2cae8c181de159b367c8278e065
1 project('qemu', ['c'], meson_version: '>=1.1.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', 'riscv64-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',
1074                    modules: ['Cocoa', 'CoreVideo', 'QuartzCore'],
1075                    required: get_option('cocoa'))
1077 vmnet = dependency('appleframeworks', modules: 'vmnet', required: get_option('vmnet'))
1078 if vmnet.found() and not cc.has_header_symbol('vmnet/vmnet.h',
1079                                               'VMNET_BRIDGED_MODE',
1080                                               dependencies: vmnet)
1081   vmnet = not_found
1082   if get_option('vmnet').enabled()
1083     error('vmnet.framework API is outdated')
1084   else
1085     warning('vmnet.framework API is outdated, disabling')
1086   endif
1087 endif
1089 seccomp = not_found
1090 seccomp_has_sysrawrc = false
1091 if not get_option('seccomp').auto() or have_system or have_tools
1092   seccomp = dependency('libseccomp', version: '>=2.3.0',
1093                        required: get_option('seccomp'),
1094                        method: 'pkg-config')
1095   if seccomp.found()
1096     seccomp_has_sysrawrc = cc.has_header_symbol('seccomp.h',
1097                                                 'SCMP_FLTATR_API_SYSRAWRC',
1098                                                 dependencies: seccomp)
1099   endif
1100 endif
1102 libcap_ng = not_found
1103 if not get_option('cap_ng').auto() or have_system or have_tools
1104   libcap_ng = cc.find_library('cap-ng', has_headers: ['cap-ng.h'],
1105                               required: get_option('cap_ng'))
1106 endif
1107 if libcap_ng.found() and not cc.links('''
1108    #include <cap-ng.h>
1109    int main(void)
1110    {
1111      capng_capability_to_name(CAPNG_EFFECTIVE);
1112      return 0;
1113    }''', dependencies: libcap_ng)
1114   libcap_ng = not_found
1115   if get_option('cap_ng').enabled()
1116     error('could not link libcap-ng')
1117   else
1118     warning('could not link libcap-ng, disabling')
1119   endif
1120 endif
1122 if get_option('xkbcommon').auto() and not have_system and not have_tools
1123   xkbcommon = not_found
1124 else
1125   xkbcommon = dependency('xkbcommon', required: get_option('xkbcommon'),
1126                          method: 'pkg-config')
1127 endif
1129 slirp = not_found
1130 if not get_option('slirp').auto() or have_system
1131   slirp = dependency('slirp', required: get_option('slirp'),
1132                      method: 'pkg-config')
1133   # slirp < 4.7 is incompatible with CFI support in QEMU.  This is because
1134   # it passes function pointers within libslirp as callbacks for timers.
1135   # When using a system-wide shared libslirp, the type information for the
1136   # callback is missing and the timer call produces a false positive with CFI.
1137   # Do not use the "version" keyword argument to produce a better error.
1138   # with control-flow integrity.
1139   if get_option('cfi') and slirp.found() and slirp.version().version_compare('<4.7')
1140     if get_option('slirp').enabled()
1141       error('Control-Flow Integrity requires libslirp 4.7.')
1142     else
1143       warning('Cannot use libslirp since Control-Flow Integrity requires libslirp >= 4.7.')
1144       slirp = not_found
1145     endif
1146   endif
1147 endif
1149 vde = not_found
1150 if not get_option('vde').auto() or have_system or have_tools
1151   vde = cc.find_library('vdeplug', has_headers: ['libvdeplug.h'],
1152                            required: get_option('vde'))
1153 endif
1154 if vde.found() and not cc.links('''
1155    #include <libvdeplug.h>
1156    int main(void)
1157    {
1158      struct vde_open_args a = {0, 0, 0};
1159      char s[] = "";
1160      vde_open(s, s, &a);
1161      return 0;
1162    }''', dependencies: vde)
1163   vde = not_found
1164   if get_option('cap_ng').enabled()
1165     error('could not link libvdeplug')
1166   else
1167     warning('could not link libvdeplug, disabling')
1168   endif
1169 endif
1171 pulse = not_found
1172 if not get_option('pa').auto() or (host_os == 'linux' and have_system)
1173   pulse = dependency('libpulse', required: get_option('pa'),
1174                      method: 'pkg-config')
1175 endif
1176 alsa = not_found
1177 if not get_option('alsa').auto() or (host_os == 'linux' and have_system)
1178   alsa = dependency('alsa', required: get_option('alsa'),
1179                     method: 'pkg-config')
1180 endif
1181 jack = not_found
1182 if not get_option('jack').auto() or have_system
1183   jack = dependency('jack', required: get_option('jack'),
1184                     method: 'pkg-config')
1185 endif
1186 pipewire = not_found
1187 if not get_option('pipewire').auto() or (host_os == 'linux' and have_system)
1188   pipewire = dependency('libpipewire-0.3', version: '>=0.3.60',
1189                     required: get_option('pipewire'),
1190                     method: 'pkg-config')
1191 endif
1192 sndio = not_found
1193 if not get_option('sndio').auto() or have_system
1194   sndio = dependency('sndio', required: get_option('sndio'),
1195                     method: 'pkg-config')
1196 endif
1198 spice_protocol = not_found
1199 if not get_option('spice_protocol').auto() or have_system
1200   spice_protocol = dependency('spice-protocol', version: '>=0.14.0',
1201                               required: get_option('spice_protocol'),
1202                               method: 'pkg-config')
1203 endif
1204 spice = not_found
1205 if get_option('spice') \
1206              .disable_auto_if(not have_system) \
1207              .require(pixman.found(),
1208                       error_message: 'cannot enable SPICE if pixman is not available') \
1209              .allowed()
1210   spice = dependency('spice-server', version: '>=0.14.0',
1211                      required: get_option('spice'),
1212                      method: 'pkg-config')
1213 endif
1214 spice_headers = spice.partial_dependency(compile_args: true, includes: true)
1216 rt = cc.find_library('rt', required: false)
1218 libiscsi = not_found
1219 if not get_option('libiscsi').auto() or have_block
1220   libiscsi = dependency('libiscsi', version: '>=1.9.0',
1221                          required: get_option('libiscsi'),
1222                          method: 'pkg-config')
1223 endif
1224 zstd = not_found
1225 if not get_option('zstd').auto() or have_block
1226   zstd = dependency('libzstd', version: '>=1.4.0',
1227                     required: get_option('zstd'),
1228                     method: 'pkg-config')
1229 endif
1230 qpl = not_found
1231 if not get_option('qpl').auto() or have_system
1232   qpl = dependency('qpl', version: '>=1.5.0',
1233                     required: get_option('qpl'),
1234                     method: 'pkg-config')
1235 endif
1236 uadk = not_found
1237 if not get_option('uadk').auto() or have_system
1238   libwd = dependency('libwd', version: '>=2.6',
1239                       required: get_option('uadk'),
1240                       method: 'pkg-config')
1241   libwd_comp = dependency('libwd_comp', version: '>=2.6',
1242                            required: get_option('uadk'),
1243                            method: 'pkg-config')
1244   if libwd.found() and libwd_comp.found()
1245      uadk = declare_dependency(dependencies: [libwd, libwd_comp])
1246   endif
1247 endif
1248 virgl = not_found
1250 have_vhost_user_gpu = have_tools and host_os == 'linux' and pixman.found()
1251 if not get_option('virglrenderer').auto() or have_system or have_vhost_user_gpu
1252   virgl = dependency('virglrenderer',
1253                      method: 'pkg-config',
1254                      required: get_option('virglrenderer'))
1255 endif
1256 rutabaga = not_found
1257 if not get_option('rutabaga_gfx').auto() or have_system or have_vhost_user_gpu
1258   rutabaga = dependency('rutabaga_gfx_ffi',
1259                          method: 'pkg-config',
1260                          required: get_option('rutabaga_gfx'))
1261 endif
1262 blkio = not_found
1263 if not get_option('blkio').auto() or have_block
1264   blkio = dependency('blkio',
1265                      method: 'pkg-config',
1266                      required: get_option('blkio'))
1267 endif
1268 curl = not_found
1269 if not get_option('curl').auto() or have_block
1270   curl = dependency('libcurl', version: '>=7.29.0',
1271                     method: 'pkg-config',
1272                     required: get_option('curl'))
1273 endif
1274 libudev = not_found
1275 if host_os == 'linux' and (have_system or have_tools)
1276   libudev = dependency('libudev',
1277                        method: 'pkg-config',
1278                        required: get_option('libudev'))
1279 endif
1281 mpathlibs = [libudev]
1282 mpathpersist = not_found
1283 if host_os == 'linux' and have_tools and get_option('mpath').allowed()
1284   mpath_test_source = '''
1285     #include <libudev.h>
1286     #include <mpath_persist.h>
1287     unsigned mpath_mx_alloc_len = 1024;
1288     int logsink;
1289     static struct config *multipath_conf;
1290     extern struct udev *udev;
1291     extern struct config *get_multipath_config(void);
1292     extern void put_multipath_config(struct config *conf);
1293     struct udev *udev;
1294     struct config *get_multipath_config(void) { return multipath_conf; }
1295     void put_multipath_config(struct config *conf) { }
1296     int main(void) {
1297         udev = udev_new();
1298         multipath_conf = mpath_lib_init();
1299         return 0;
1300     }'''
1301   libmpathpersist = cc.find_library('mpathpersist',
1302                                     required: get_option('mpath'))
1303   if libmpathpersist.found()
1304     mpathlibs += libmpathpersist
1305     if get_option('prefer_static')
1306       mpathlibs += cc.find_library('devmapper',
1307                                      required: get_option('mpath'))
1308     endif
1309     mpathlibs += cc.find_library('multipath',
1310                                  required: get_option('mpath'))
1311     foreach lib: mpathlibs
1312       if not lib.found()
1313         mpathlibs = []
1314         break
1315       endif
1316     endforeach
1317     if mpathlibs.length() == 0
1318       msg = 'Dependencies missing for libmpathpersist'
1319     elif cc.links(mpath_test_source, dependencies: mpathlibs)
1320       mpathpersist = declare_dependency(dependencies: mpathlibs)
1321     else
1322       msg = 'Cannot detect libmpathpersist API'
1323     endif
1324     if not mpathpersist.found()
1325       if get_option('mpath').enabled()
1326         error(msg)
1327       else
1328         warning(msg + ', disabling')
1329       endif
1330     endif
1331   endif
1332 endif
1334 iconv = not_found
1335 curses = not_found
1336 if have_system and get_option('curses').allowed()
1337   curses_test = '''
1338     #if defined(__APPLE__) || defined(__OpenBSD__)
1339     #define _XOPEN_SOURCE_EXTENDED 1
1340     #endif
1341     #include <locale.h>
1342     #include <curses.h>
1343     #include <wchar.h>
1344     int main(void) {
1345       wchar_t wch = L'w';
1346       setlocale(LC_ALL, "");
1347       resize_term(0, 0);
1348       addwstr(L"wide chars\n");
1349       addnwstr(&wch, 1);
1350       add_wch(WACS_DEGREE);
1351       return 0;
1352     }'''
1354   curses_dep_list = host_os == 'windows' ? ['ncurses', 'ncursesw'] : ['ncursesw']
1355   curses = dependency(curses_dep_list,
1356                       required: false,
1357                       method: 'pkg-config')
1358   msg = get_option('curses').enabled() ? 'curses library not found' : ''
1359   curses_compile_args = ['-DNCURSES_WIDECHAR=1']
1360   if curses.found()
1361     if cc.links(curses_test, args: curses_compile_args, dependencies: [curses])
1362       curses = declare_dependency(compile_args: curses_compile_args, dependencies: [curses],
1363                                   version: curses.version())
1364     else
1365       msg = 'curses package not usable'
1366       curses = not_found
1367     endif
1368   endif
1369   if not curses.found()
1370     has_curses_h = cc.has_header('curses.h', args: curses_compile_args)
1371     if host_os != 'windows' and not has_curses_h
1372       message('Trying with /usr/include/ncursesw')
1373       curses_compile_args += ['-I/usr/include/ncursesw']
1374       has_curses_h = cc.has_header('curses.h', args: curses_compile_args)
1375     endif
1376     if has_curses_h
1377       curses_libname_list = (host_os == 'windows' ? ['pdcurses'] : ['ncursesw', 'cursesw'])
1378       foreach curses_libname : curses_libname_list
1379         libcurses = cc.find_library(curses_libname,
1380                                     required: false)
1381         if libcurses.found()
1382           if cc.links(curses_test, args: curses_compile_args, dependencies: libcurses)
1383             curses = declare_dependency(compile_args: curses_compile_args,
1384                                         dependencies: [libcurses])
1385             break
1386           else
1387             msg = 'curses library not usable'
1388           endif
1389         endif
1390       endforeach
1391     endif
1392   endif
1393   if get_option('iconv').allowed()
1394     foreach link_args : [ ['-liconv'], [] ]
1395       # Programs will be linked with glib and this will bring in libiconv on FreeBSD.
1396       # We need to use libiconv if available because mixing libiconv's headers with
1397       # the system libc does not work.
1398       # However, without adding glib to the dependencies -L/usr/local/lib will not be
1399       # included in the command line and libiconv will not be found.
1400       if cc.links('''
1401         #include <iconv.h>
1402         int main(void) {
1403           iconv_t conv = iconv_open("WCHAR_T", "UCS-2");
1404           return conv != (iconv_t) -1;
1405         }''', args: link_args, dependencies: glib)
1406         iconv = declare_dependency(link_args: link_args, dependencies: glib)
1407         break
1408       endif
1409     endforeach
1410   endif
1411   if curses.found() and not iconv.found()
1412     if get_option('iconv').enabled()
1413       error('iconv not available')
1414     endif
1415     msg = 'iconv required for curses UI but not available'
1416     curses = not_found
1417   endif
1418   if not curses.found() and msg != ''
1419     if get_option('curses').enabled()
1420       error(msg)
1421     else
1422       warning(msg + ', disabling')
1423     endif
1424   endif
1425 endif
1427 brlapi = not_found
1428 if not get_option('brlapi').auto() or have_system
1429   brlapi = cc.find_library('brlapi', has_headers: ['brlapi.h'],
1430                          required: get_option('brlapi'))
1431   if brlapi.found() and not cc.links('''
1432      #include <brlapi.h>
1433      #include <stddef.h>
1434      int main(void) { return brlapi__openConnection (NULL, NULL, NULL); }''', dependencies: brlapi)
1435     brlapi = not_found
1436     if get_option('brlapi').enabled()
1437       error('could not link brlapi')
1438     else
1439       warning('could not link brlapi, disabling')
1440     endif
1441   endif
1442 endif
1444 sdl = not_found
1445 if not get_option('sdl').auto() or have_system
1446   sdl = dependency('sdl2', required: get_option('sdl'))
1447   sdl_image = not_found
1448 endif
1449 if sdl.found()
1450   # Some versions of SDL have problems with -Wundef
1451   if not cc.compiles('''
1452                      #include <SDL.h>
1453                      #include <SDL_syswm.h>
1454                      int main(int argc, char *argv[]) { return 0; }
1455                      ''', dependencies: sdl, args: '-Werror=undef')
1456     sdl = declare_dependency(compile_args: '-Wno-undef',
1457                              dependencies: sdl,
1458                              version: sdl.version())
1459   endif
1460   sdl_image = dependency('SDL2_image', required: get_option('sdl_image'),
1461                          method: 'pkg-config')
1462 else
1463   if get_option('sdl_image').enabled()
1464     error('sdl-image required, but SDL was @0@'.format(
1465           get_option('sdl').disabled() ? 'disabled' : 'not found'))
1466   endif
1467   sdl_image = not_found
1468 endif
1470 rbd = not_found
1471 if not get_option('rbd').auto() or have_block
1472   librados = cc.find_library('rados', required: get_option('rbd'))
1473   librbd = cc.find_library('rbd', has_headers: ['rbd/librbd.h'],
1474                            required: get_option('rbd'))
1475   if librados.found() and librbd.found()
1476     if cc.links('''
1477       #include <stdio.h>
1478       #include <rbd/librbd.h>
1479       int main(void) {
1480         rados_t cluster;
1481         rados_create(&cluster, NULL);
1482         #if LIBRBD_VERSION_CODE < LIBRBD_VERSION(1, 12, 0)
1483         #error
1484         #endif
1485         return 0;
1486       }''', dependencies: [librbd, librados])
1487       rbd = declare_dependency(dependencies: [librbd, librados])
1488     elif get_option('rbd').enabled()
1489       error('librbd >= 1.12.0 required')
1490     else
1491       warning('librbd >= 1.12.0 not found, disabling')
1492     endif
1493   endif
1494 endif
1496 glusterfs = not_found
1497 glusterfs_ftruncate_has_stat = false
1498 glusterfs_iocb_has_stat = false
1499 if not get_option('glusterfs').auto() or have_block
1500   glusterfs = dependency('glusterfs-api', version: '>=3',
1501                          required: get_option('glusterfs'),
1502                          method: 'pkg-config')
1503   if glusterfs.found()
1504     glusterfs_ftruncate_has_stat = cc.links('''
1505       #include <glusterfs/api/glfs.h>
1507       int
1508       main(void)
1509       {
1510           /* new glfs_ftruncate() passes two additional args */
1511           return glfs_ftruncate(NULL, 0, NULL, NULL);
1512       }
1513     ''', dependencies: glusterfs)
1514     glusterfs_iocb_has_stat = cc.links('''
1515       #include <glusterfs/api/glfs.h>
1517       /* new glfs_io_cbk() passes two additional glfs_stat structs */
1518       static void
1519       glusterfs_iocb(glfs_fd_t *fd, ssize_t ret, struct glfs_stat *prestat, struct glfs_stat *poststat, void *data)
1520       {}
1522       int
1523       main(void)
1524       {
1525           glfs_io_cbk iocb = &glusterfs_iocb;
1526           iocb(NULL, 0 , NULL, NULL, NULL);
1527           return 0;
1528       }
1529     ''', dependencies: glusterfs)
1530   endif
1531 endif
1533 hv_balloon = false
1534 if get_option('hv_balloon').allowed() and have_system
1535   if cc.links('''
1536     #include <string.h>
1537     #include <gmodule.h>
1538     int main(void) {
1539         GTree *tree;
1541         tree = g_tree_new((GCompareFunc)strcmp);
1542         (void)g_tree_node_first(tree);
1543         g_tree_destroy(tree);
1544         return 0;
1545     }
1546   ''', dependencies: glib)
1547     hv_balloon = true
1548   else
1549     if get_option('hv_balloon').enabled()
1550       error('could not enable hv-balloon, update your glib')
1551     else
1552       warning('could not find glib support for hv-balloon, disabling')
1553     endif
1554   endif
1555 endif
1557 libssh = not_found
1558 if not get_option('libssh').auto() or have_block
1559   libssh = dependency('libssh', version: '>=0.8.7',
1560                     method: 'pkg-config',
1561                     required: get_option('libssh'))
1562 endif
1564 libbzip2 = not_found
1565 if not get_option('bzip2').auto() or have_block
1566   libbzip2 = cc.find_library('bz2', has_headers: ['bzlib.h'],
1567                              required: get_option('bzip2'))
1568   if libbzip2.found() and not cc.links('''
1569      #include <bzlib.h>
1570      int main(void) { BZ2_bzlibVersion(); return 0; }''', dependencies: libbzip2)
1571     libbzip2 = not_found
1572     if get_option('bzip2').enabled()
1573       error('could not link libbzip2')
1574     else
1575       warning('could not link libbzip2, disabling')
1576     endif
1577   endif
1578 endif
1580 liblzfse = not_found
1581 if not get_option('lzfse').auto() or have_block
1582   liblzfse = cc.find_library('lzfse', has_headers: ['lzfse.h'],
1583                              required: get_option('lzfse'))
1584 endif
1585 if liblzfse.found() and not cc.links('''
1586    #include <lzfse.h>
1587    int main(void) { lzfse_decode_scratch_size(); return 0; }''', dependencies: liblzfse)
1588   liblzfse = not_found
1589   if get_option('lzfse').enabled()
1590     error('could not link liblzfse')
1591   else
1592     warning('could not link liblzfse, disabling')
1593   endif
1594 endif
1596 oss = not_found
1597 if get_option('oss').allowed() and have_system
1598   if not cc.has_header('sys/soundcard.h')
1599     # not found
1600   elif host_os == 'netbsd'
1601     oss = cc.find_library('ossaudio', required: get_option('oss'))
1602   else
1603     oss = declare_dependency()
1604   endif
1606   if not oss.found()
1607     if get_option('oss').enabled()
1608       error('OSS not found')
1609     endif
1610   endif
1611 endif
1612 dsound = not_found
1613 if not get_option('dsound').auto() or (host_os == 'windows' and have_system)
1614   if cc.has_header('dsound.h')
1615     dsound = declare_dependency(link_args: ['-lole32', '-ldxguid'])
1616   endif
1618   if not dsound.found()
1619     if get_option('dsound').enabled()
1620       error('DirectSound not found')
1621     endif
1622   endif
1623 endif
1625 coreaudio = not_found
1626 if not get_option('coreaudio').auto() or (host_os == 'darwin' and have_system)
1627   coreaudio = dependency('appleframeworks', modules: 'CoreAudio',
1628                          required: get_option('coreaudio'))
1629 endif
1631 opengl = not_found
1632 if not get_option('opengl').auto() or have_system or have_vhost_user_gpu
1633   epoxy = dependency('epoxy', method: 'pkg-config',
1634                       required: get_option('opengl'))
1635   if cc.has_header('epoxy/egl.h', dependencies: epoxy)
1636     opengl = epoxy
1637   elif get_option('opengl').enabled()
1638     error('epoxy/egl.h not found')
1639   endif
1640 endif
1641 gbm = not_found
1642 if (have_system or have_tools) and (virgl.found() or opengl.found())
1643   gbm = dependency('gbm', method: 'pkg-config', required: false)
1644 endif
1645 have_vhost_user_gpu = have_vhost_user_gpu and virgl.found() and opengl.found() and gbm.found()
1647 gnutls = not_found
1648 gnutls_crypto = not_found
1649 if get_option('gnutls').enabled() or (get_option('gnutls').auto() and have_system)
1650   # For general TLS support our min gnutls matches
1651   # that implied by our platform support matrix
1652   #
1653   # For the crypto backends, we look for a newer
1654   # gnutls:
1655   #
1656   #   Version 3.6.8  is needed to get XTS
1657   #   Version 3.6.13 is needed to get PBKDF
1658   #   Version 3.6.14 is needed to get HW accelerated XTS
1659   #
1660   # If newer enough gnutls isn't available, we can
1661   # still use a different crypto backend to satisfy
1662   # the platform support requirements
1663   gnutls_crypto = dependency('gnutls', version: '>=3.6.14',
1664                              method: 'pkg-config',
1665                              required: false)
1666   if gnutls_crypto.found()
1667     gnutls = gnutls_crypto
1668   else
1669     # Our min version if all we need is TLS
1670     gnutls = dependency('gnutls', version: '>=3.5.18',
1671                         method: 'pkg-config',
1672                         required: get_option('gnutls'))
1673   endif
1674 endif
1676 # We prefer use of gnutls for crypto, unless the options
1677 # explicitly asked for nettle or gcrypt.
1679 # If gnutls isn't available for crypto, then we'll prefer
1680 # gcrypt over nettle for performance reasons.
1681 gcrypt = not_found
1682 nettle = not_found
1683 hogweed = not_found
1684 crypto_sm4 = not_found
1685 xts = 'none'
1687 if get_option('nettle').enabled() and get_option('gcrypt').enabled()
1688   error('Only one of gcrypt & nettle can be enabled')
1689 endif
1691 # Explicit nettle/gcrypt request, so ignore gnutls for crypto
1692 if get_option('nettle').enabled() or get_option('gcrypt').enabled()
1693   gnutls_crypto = not_found
1694 endif
1696 if not gnutls_crypto.found()
1697   if (not get_option('gcrypt').auto() or have_system) and not get_option('nettle').enabled()
1698     gcrypt = dependency('libgcrypt', version: '>=1.8',
1699                         method: 'config-tool',
1700                         required: get_option('gcrypt'))
1701     # Debian has removed -lgpg-error from libgcrypt-config
1702     # as it "spreads unnecessary dependencies" which in
1703     # turn breaks static builds...
1704     if gcrypt.found() and get_option('prefer_static')
1705       gcrypt = declare_dependency(dependencies:
1706         [gcrypt,
1707          cc.find_library('gpg-error', required: true)],
1708         version: gcrypt.version())
1709     endif
1710     crypto_sm4 = gcrypt
1711     # SM4 ALG is available in libgcrypt >= 1.9
1712     if gcrypt.found() and not cc.links('''
1713       #include <gcrypt.h>
1714       int main(void) {
1715         gcry_cipher_hd_t handler;
1716         gcry_cipher_open(&handler, GCRY_CIPHER_SM4, GCRY_CIPHER_MODE_ECB, 0);
1717         return 0;
1718       }''', dependencies: gcrypt)
1719       crypto_sm4 = not_found
1720     endif
1721   endif
1722   if (not get_option('nettle').auto() or have_system) and not gcrypt.found()
1723     nettle = dependency('nettle', version: '>=3.4',
1724                         method: 'pkg-config',
1725                         required: get_option('nettle'))
1726     if nettle.found() and not cc.has_header('nettle/xts.h', dependencies: nettle)
1727       xts = 'private'
1728     endif
1729     crypto_sm4 = nettle
1730     # SM4 ALG is available in nettle >= 3.9
1731     if nettle.found() and not cc.links('''
1732       #include <nettle/sm4.h>
1733       int main(void) {
1734         struct sm4_ctx ctx;
1735         unsigned char key[16] = {0};
1736         sm4_set_encrypt_key(&ctx, key);
1737         return 0;
1738       }''', dependencies: nettle)
1739       crypto_sm4 = not_found
1740     endif
1741   endif
1742 endif
1744 capstone = not_found
1745 if not get_option('capstone').auto() or have_system or have_user
1746   capstone = dependency('capstone', version: '>=3.0.5',
1747                         method: 'pkg-config',
1748                         required: get_option('capstone'))
1750   # Some versions of capstone have broken pkg-config file
1751   # that reports a wrong -I path, causing the #include to
1752   # fail later. If the system has such a broken version
1753   # do not use it.
1754   if capstone.found() and not cc.compiles('#include <capstone.h>',
1755                                           dependencies: [capstone])
1756     capstone = not_found
1757     if get_option('capstone').enabled()
1758       error('capstone requested, but it does not appear to work')
1759     endif
1760   endif
1761 endif
1763 gmp = dependency('gmp', required: false, method: 'pkg-config')
1764 if nettle.found() and gmp.found()
1765   hogweed = dependency('hogweed', version: '>=3.4',
1766                        method: 'pkg-config',
1767                        required: get_option('nettle'))
1768 endif
1771 gtk = not_found
1772 gtkx11 = not_found
1773 vte = not_found
1774 have_gtk_clipboard = get_option('gtk_clipboard').enabled()
1776 if get_option('gtk') \
1777              .disable_auto_if(not have_system) \
1778              .require(pixman.found(),
1779                       error_message: 'cannot enable GTK if pixman is not available') \
1780              .allowed()
1781   gtk = dependency('gtk+-3.0', version: '>=3.22.0',
1782                    method: 'pkg-config',
1783                    required: get_option('gtk'))
1784   if gtk.found()
1785     gtkx11 = dependency('gtk+-x11-3.0', version: '>=3.22.0',
1786                         method: 'pkg-config',
1787                         required: false)
1788     gtk = declare_dependency(dependencies: [gtk, gtkx11],
1789                              version: gtk.version())
1791     if not get_option('vte').auto() or have_system
1792       vte = dependency('vte-2.91',
1793                        method: 'pkg-config',
1794                        required: get_option('vte'))
1795     endif
1796   elif have_gtk_clipboard
1797     error('GTK clipboard requested, but GTK not found')
1798   endif
1799 endif
1801 x11 = not_found
1802 if gtkx11.found()
1803   x11 = dependency('x11', method: 'pkg-config', required: gtkx11.found())
1804 endif
1805 png = not_found
1806 if get_option('png').allowed() and have_system
1807    png = dependency('libpng', version: '>=1.6.34', required: get_option('png'),
1808                     method: 'pkg-config')
1809 endif
1810 vnc = not_found
1811 jpeg = not_found
1812 sasl = not_found
1813 if get_option('vnc') \
1814              .disable_auto_if(not have_system) \
1815              .require(pixman.found(),
1816                       error_message: 'cannot enable VNC if pixman is not available') \
1817              .allowed()
1818   vnc = declare_dependency() # dummy dependency
1819   jpeg = dependency('libjpeg', required: get_option('vnc_jpeg'),
1820                     method: 'pkg-config')
1821   sasl = cc.find_library('sasl2', has_headers: ['sasl/sasl.h'],
1822                          required: get_option('vnc_sasl'))
1823   if sasl.found()
1824     sasl = declare_dependency(dependencies: sasl,
1825                               compile_args: '-DSTRUCT_IOVEC_DEFINED')
1826   endif
1827 endif
1829 pam = not_found
1830 if not get_option('auth_pam').auto() or have_system
1831   pam = cc.find_library('pam', has_headers: ['security/pam_appl.h'],
1832                         required: get_option('auth_pam'))
1833 endif
1834 if pam.found() and not cc.links('''
1835    #include <stddef.h>
1836    #include <security/pam_appl.h>
1837    int main(void) {
1838      const char *service_name = "qemu";
1839      const char *user = "frank";
1840      const struct pam_conv pam_conv = { 0 };
1841      pam_handle_t *pamh = NULL;
1842      pam_start(service_name, user, &pam_conv, &pamh);
1843      return 0;
1844    }''', dependencies: pam)
1845   pam = not_found
1846   if get_option('auth_pam').enabled()
1847     error('could not link libpam')
1848   else
1849     warning('could not link libpam, disabling')
1850   endif
1851 endif
1853 snappy = not_found
1854 if not get_option('snappy').auto() or have_system
1855   snappy = cc.find_library('snappy', has_headers: ['snappy-c.h'],
1856                            required: get_option('snappy'))
1857 endif
1858 if snappy.found() and not cc.links('''
1859    #include <snappy-c.h>
1860    int main(void) { snappy_max_compressed_length(4096); return 0; }''', dependencies: snappy)
1861   snappy = not_found
1862   if get_option('snappy').enabled()
1863     error('could not link libsnappy')
1864   else
1865     warning('could not link libsnappy, disabling')
1866   endif
1867 endif
1869 lzo = not_found
1870 if not get_option('lzo').auto() or have_system
1871   lzo = cc.find_library('lzo2', has_headers: ['lzo/lzo1x.h'],
1872                         required: get_option('lzo'))
1873 endif
1874 if lzo.found() and not cc.links('''
1875    #include <lzo/lzo1x.h>
1876    int main(void) { lzo_version(); return 0; }''', dependencies: lzo)
1877   lzo = not_found
1878   if get_option('lzo').enabled()
1879     error('could not link liblzo2')
1880   else
1881     warning('could not link liblzo2, disabling')
1882   endif
1883 endif
1885 numa = not_found
1886 if not get_option('numa').auto() or have_system or have_tools
1887   numa = cc.find_library('numa', has_headers: ['numa.h'],
1888                               required: get_option('numa'))
1889 endif
1890 if numa.found() and not cc.links('''
1891    #include <numa.h>
1892    int main(void) { return numa_available(); }
1893    ''', dependencies: numa)
1894   numa = not_found
1895   if get_option('numa').enabled()
1896     error('could not link numa')
1897   else
1898     warning('could not link numa, disabling')
1899   endif
1900 endif
1902 fdt = not_found
1903 fdt_opt = get_option('fdt')
1904 if fdt_opt == 'enabled' and get_option('wrap_mode') == 'nodownload'
1905   fdt_opt = 'system'
1906 endif
1907 if fdt_opt in ['enabled', 'system'] or (fdt_opt == 'auto' and have_system)
1908   fdt = cc.find_library('fdt', required: fdt_opt == 'system')
1909   if fdt.found() and cc.links('''
1910      #include <libfdt.h>
1911      #include <libfdt_env.h>
1912      int main(void) { fdt_find_max_phandle(NULL, NULL); return 0; }''',
1913        dependencies: fdt)
1914     fdt_opt = 'system'
1915   elif fdt_opt != 'system'
1916     fdt_opt = get_option('wrap_mode') == 'nodownload' ? 'disabled' : 'internal'
1917     fdt = not_found
1918   else
1919     error('system libfdt is too old (1.5.1 or newer required)')
1920   endif
1921 endif
1922 if fdt_opt == 'internal'
1923   assert(not fdt.found())
1924   libfdt_proj = subproject('dtc', required: true,
1925                            default_options: ['tools=false',  'yaml=disabled',
1926                                              'python=disabled', 'default_library=static'])
1927   fdt = libfdt_proj.get_variable('libfdt_dep')
1928 endif
1930 rdma = not_found
1931 if not get_option('rdma').auto() or have_system
1932   rdma_libs = [cc.find_library('rdmacm', has_headers: ['rdma/rdma_cma.h'],
1933                                required: get_option('rdma')),
1934                cc.find_library('ibverbs', required: get_option('rdma'))]
1935   rdma = declare_dependency(dependencies: rdma_libs)
1936   foreach lib: rdma_libs
1937     if not lib.found()
1938       rdma = not_found
1939     endif
1940   endforeach
1941 endif
1943 cacard = not_found
1944 if not get_option('smartcard').auto() or have_system
1945   cacard = dependency('libcacard', required: get_option('smartcard'),
1946                       version: '>=2.5.1', method: 'pkg-config')
1947 endif
1948 u2f = not_found
1949 if not get_option('u2f').auto() or have_system
1950   u2f = dependency('u2f-emu', required: get_option('u2f'),
1951                    method: 'pkg-config')
1952 endif
1953 canokey = not_found
1954 if not get_option('canokey').auto() or have_system
1955   canokey = dependency('canokey-qemu', required: get_option('canokey'),
1956                    method: 'pkg-config')
1957 endif
1958 usbredir = not_found
1959 if not get_option('usb_redir').auto() or have_system
1960   usbredir = dependency('libusbredirparser-0.5', required: get_option('usb_redir'),
1961                         version: '>=0.6', method: 'pkg-config')
1962 endif
1963 libusb = not_found
1964 if not get_option('libusb').auto() or have_system
1965   libusb = dependency('libusb-1.0', required: get_option('libusb'),
1966                       version: '>=1.0.13', method: 'pkg-config')
1967 endif
1969 libpmem = not_found
1970 if not get_option('libpmem').auto() or have_system
1971   libpmem = dependency('libpmem', required: get_option('libpmem'),
1972                        method: 'pkg-config')
1973 endif
1974 libdaxctl = not_found
1975 if not get_option('libdaxctl').auto() or have_system
1976   libdaxctl = dependency('libdaxctl', required: get_option('libdaxctl'),
1977                          version: '>=57', method: 'pkg-config')
1978 endif
1979 tasn1 = not_found
1980 if gnutls.found()
1981   tasn1 = dependency('libtasn1',
1982                      method: 'pkg-config')
1983 endif
1984 keyutils = not_found
1985 if not get_option('libkeyutils').auto() or have_block
1986   keyutils = dependency('libkeyutils', required: get_option('libkeyutils'),
1987                         method: 'pkg-config')
1988 endif
1990 has_gettid = cc.has_function('gettid')
1992 # libselinux
1993 selinux = dependency('libselinux',
1994                      required: get_option('selinux'),
1995                      method: 'pkg-config')
1997 # Malloc tests
1999 malloc = []
2000 if get_option('malloc') == 'system'
2001   has_malloc_trim = \
2002     get_option('malloc_trim').allowed() and \
2003     cc.has_function('malloc_trim', prefix: '#include <malloc.h>')
2004 else
2005   has_malloc_trim = false
2006   malloc = cc.find_library(get_option('malloc'), required: true)
2007 endif
2008 if not has_malloc_trim and get_option('malloc_trim').enabled()
2009   if get_option('malloc') == 'system'
2010     error('malloc_trim not available on this platform.')
2011   else
2012     error('malloc_trim not available with non-libc memory allocator')
2013   endif
2014 endif
2016 gnu_source_prefix = '''
2017   #ifndef _GNU_SOURCE
2018   #define _GNU_SOURCE
2019   #endif
2022 # Check whether the glibc provides STATX_BASIC_STATS
2024 has_statx = cc.has_header_symbol('sys/stat.h', 'STATX_BASIC_STATS', prefix: gnu_source_prefix)
2026 # Check whether statx() provides mount ID information
2028 has_statx_mnt_id = cc.has_header_symbol('sys/stat.h', 'STATX_MNT_ID', prefix: gnu_source_prefix)
2030 have_vhost_user_blk_server = get_option('vhost_user_blk_server') \
2031   .require(host_os == 'linux',
2032            error_message: 'vhost_user_blk_server requires linux') \
2033   .require(have_vhost_user,
2034            error_message: 'vhost_user_blk_server requires vhost-user support') \
2035   .disable_auto_if(not have_tools and not have_system) \
2036   .allowed()
2038 if get_option('fuse').disabled() and get_option('fuse_lseek').enabled()
2039   error('Cannot enable fuse-lseek while fuse is disabled')
2040 endif
2042 fuse = dependency('fuse3', required: get_option('fuse'),
2043                   version: '>=3.1', method: 'pkg-config')
2045 fuse_lseek = not_found
2046 if get_option('fuse_lseek').allowed()
2047   if fuse.version().version_compare('>=3.8')
2048     # Dummy dependency
2049     fuse_lseek = declare_dependency()
2050   elif get_option('fuse_lseek').enabled()
2051     if fuse.found()
2052       error('fuse-lseek requires libfuse >=3.8, found ' + fuse.version())
2053     else
2054       error('fuse-lseek requires libfuse, which was not found')
2055     endif
2056   endif
2057 endif
2059 have_libvduse = (host_os == 'linux')
2060 if get_option('libvduse').enabled()
2061     if host_os != 'linux'
2062         error('libvduse requires linux')
2063     endif
2064 elif get_option('libvduse').disabled()
2065     have_libvduse = false
2066 endif
2068 have_vduse_blk_export = (have_libvduse and host_os == 'linux')
2069 if get_option('vduse_blk_export').enabled()
2070     if host_os != 'linux'
2071         error('vduse_blk_export requires linux')
2072     elif not have_libvduse
2073         error('vduse_blk_export requires libvduse support')
2074     endif
2075 elif get_option('vduse_blk_export').disabled()
2076     have_vduse_blk_export = false
2077 endif
2079 # libbpf
2080 bpf_version = '1.1.0'
2081 libbpf = dependency('libbpf', version: '>=' + bpf_version, required: get_option('bpf'), method: 'pkg-config')
2082 if libbpf.found() and not cc.links('''
2083    #include <bpf/libbpf.h>
2084    #include <linux/bpf.h>
2085    int main(void)
2086    {
2087      // check flag availability
2088      int flag = BPF_F_MMAPABLE;
2089      bpf_object__destroy_skeleton(NULL);
2090      return 0;
2091    }''', dependencies: libbpf)
2092   libbpf = not_found
2093   if get_option('bpf').enabled()
2094     error('libbpf skeleton/mmaping test failed')
2095   else
2096     warning('libbpf skeleton/mmaping test failed, disabling')
2097   endif
2098 endif
2100 # libxdp
2101 libxdp = not_found
2102 if not get_option('af_xdp').auto() or have_system
2103     libxdp = dependency('libxdp', required: get_option('af_xdp'),
2104                         version: '>=1.4.0', method: 'pkg-config')
2105 endif
2107 # libdw
2108 libdw = not_found
2109 if not get_option('libdw').auto() or \
2110         (not get_option('prefer_static') and (have_system or have_user))
2111     libdw = dependency('libdw',
2112                        method: 'pkg-config',
2113                        required: get_option('libdw'))
2114 endif
2116 #################
2117 # config-host.h #
2118 #################
2120 config_host_data = configuration_data()
2122 audio_drivers_selected = []
2123 if have_system
2124   audio_drivers_available = {
2125     'alsa': alsa.found(),
2126     'coreaudio': coreaudio.found(),
2127     'dsound': dsound.found(),
2128     'jack': jack.found(),
2129     'oss': oss.found(),
2130     'pa': pulse.found(),
2131     'pipewire': pipewire.found(),
2132     'sdl': sdl.found(),
2133     'sndio': sndio.found(),
2134   }
2135   foreach k, v: audio_drivers_available
2136     config_host_data.set('CONFIG_AUDIO_' + k.to_upper(), v)
2137   endforeach
2139   # Default to native drivers first, OSS second, SDL third
2140   audio_drivers_priority = \
2141     [ 'pa', 'coreaudio', 'dsound', 'sndio', 'oss' ] + \
2142     (host_os == 'linux' ? [] : [ 'sdl' ])
2143   audio_drivers_default = []
2144   foreach k: audio_drivers_priority
2145     if audio_drivers_available[k]
2146       audio_drivers_default += k
2147     endif
2148   endforeach
2150   foreach k: get_option('audio_drv_list')
2151     if k == 'default'
2152       audio_drivers_selected += audio_drivers_default
2153     elif not audio_drivers_available[k]
2154       error('Audio driver "@0@" not available.'.format(k))
2155     else
2156       audio_drivers_selected += k
2157     endif
2158   endforeach
2159 endif
2160 config_host_data.set('CONFIG_AUDIO_DRIVERS',
2161                      '"' + '", "'.join(audio_drivers_selected) + '", ')
2163 have_host_block_device = (host_os != 'darwin' or
2164     cc.has_header('IOKit/storage/IOMedia.h'))
2166 dbus_display = get_option('dbus_display') \
2167   .require(gio.version().version_compare('>=2.64'),
2168            error_message: '-display dbus requires glib>=2.64') \
2169   .require(gdbus_codegen.found(),
2170            error_message: gdbus_codegen_error.format('-display dbus')) \
2171   .allowed()
2173 have_virtfs = get_option('virtfs') \
2174     .require(host_os == 'linux' or host_os == 'darwin',
2175              error_message: 'virtio-9p (virtfs) requires Linux or macOS') \
2176     .require(host_os == 'linux' or cc.has_function('pthread_fchdir_np'),
2177              error_message: 'virtio-9p (virtfs) on macOS requires the presence of pthread_fchdir_np') \
2178     .require(host_os == 'darwin' or libattr.found(),
2179              error_message: 'virtio-9p (virtfs) on Linux requires libattr-devel') \
2180     .disable_auto_if(not have_tools and not have_system) \
2181     .allowed()
2183 have_virtfs_proxy_helper = get_option('virtfs_proxy_helper') \
2184     .require(host_os != 'darwin', error_message: 'the virtfs proxy helper is incompatible with macOS') \
2185     .require(have_virtfs, error_message: 'the virtfs proxy helper requires that virtfs is enabled') \
2186     .disable_auto_if(not have_tools) \
2187     .require(libcap_ng.found(), error_message: 'the virtfs proxy helper requires libcap-ng') \
2188     .allowed()
2190 if get_option('block_drv_ro_whitelist') == ''
2191   config_host_data.set('CONFIG_BDRV_RO_WHITELIST', '')
2192 else
2193   config_host_data.set('CONFIG_BDRV_RO_WHITELIST',
2194         '"' + get_option('block_drv_ro_whitelist').replace(',', '", "') + '", ')
2195 endif
2196 if get_option('block_drv_rw_whitelist') == ''
2197   config_host_data.set('CONFIG_BDRV_RW_WHITELIST', '')
2198 else
2199   config_host_data.set('CONFIG_BDRV_RW_WHITELIST',
2200         '"' + get_option('block_drv_rw_whitelist').replace(',', '", "') + '", ')
2201 endif
2203 foreach k : get_option('trace_backends')
2204   config_host_data.set('CONFIG_TRACE_' + k.to_upper(), true)
2205 endforeach
2206 config_host_data.set_quoted('CONFIG_TRACE_FILE', get_option('trace_file'))
2207 config_host_data.set_quoted('CONFIG_TLS_PRIORITY', get_option('tls_priority'))
2208 if iasl.found()
2209   config_host_data.set_quoted('CONFIG_IASL', iasl.full_path())
2210 endif
2211 config_host_data.set_quoted('CONFIG_BINDIR', get_option('prefix') / get_option('bindir'))
2212 config_host_data.set_quoted('CONFIG_PREFIX', get_option('prefix'))
2213 config_host_data.set_quoted('CONFIG_QEMU_CONFDIR', get_option('prefix') / qemu_confdir)
2214 config_host_data.set_quoted('CONFIG_QEMU_DATADIR', get_option('prefix') / qemu_datadir)
2215 config_host_data.set_quoted('CONFIG_QEMU_DESKTOPDIR', get_option('prefix') / qemu_desktopdir)
2217 qemu_firmwarepath = ''
2218 foreach k : get_option('qemu_firmwarepath')
2219   qemu_firmwarepath += '"' + get_option('prefix') / k + '", '
2220 endforeach
2221 config_host_data.set('CONFIG_QEMU_FIRMWAREPATH', qemu_firmwarepath)
2223 config_host_data.set_quoted('CONFIG_QEMU_HELPERDIR', get_option('prefix') / get_option('libexecdir'))
2224 config_host_data.set_quoted('CONFIG_QEMU_ICONDIR', get_option('prefix') / qemu_icondir)
2225 config_host_data.set_quoted('CONFIG_QEMU_LOCALEDIR', get_option('prefix') / get_option('localedir'))
2226 config_host_data.set_quoted('CONFIG_QEMU_LOCALSTATEDIR', get_option('prefix') / get_option('localstatedir'))
2227 config_host_data.set_quoted('CONFIG_QEMU_MODDIR', get_option('prefix') / qemu_moddir)
2228 config_host_data.set_quoted('CONFIG_SYSCONFDIR', get_option('prefix') / get_option('sysconfdir'))
2230 if enable_modules
2231   config_host_data.set('CONFIG_STAMP', run_command(
2232       meson.current_source_dir() / 'scripts/qemu-stamp.py',
2233       meson.project_version(), get_option('pkgversion'), '--',
2234       meson.current_source_dir() / 'configure',
2235       capture: true, check: true).stdout().strip())
2236 endif
2238 have_slirp_smbd = get_option('slirp_smbd') \
2239   .require(host_os != 'windows', error_message: 'Host smbd not supported on this platform.') \
2240   .allowed()
2241 if have_slirp_smbd
2242   smbd_path = get_option('smbd')
2243   if smbd_path == ''
2244     smbd_path = (host_os == 'sunos' ? '/usr/sfw/sbin/smbd' : '/usr/sbin/smbd')
2245   endif
2246   config_host_data.set_quoted('CONFIG_SMBD_COMMAND', smbd_path)
2247 endif
2249 config_host_data.set('HOST_' + host_arch.to_upper(), 1)
2251 kvm_targets_c = '""'
2252 if get_option('kvm').allowed() and host_os == 'linux'
2253   kvm_targets_c = '"' + '" ,"'.join(kvm_targets) + '"'
2254 endif
2255 config_host_data.set('CONFIG_KVM_TARGETS', kvm_targets_c)
2257 if get_option('module_upgrades') and not enable_modules
2258   error('Cannot enable module-upgrades as modules are not enabled')
2259 endif
2260 config_host_data.set('CONFIG_MODULE_UPGRADES', get_option('module_upgrades'))
2262 config_host_data.set('CONFIG_ATTR', libattr.found())
2263 config_host_data.set('CONFIG_BDRV_WHITELIST_TOOLS', get_option('block_drv_whitelist_in_tools'))
2264 config_host_data.set('CONFIG_BRLAPI', brlapi.found())
2265 config_host_data.set('CONFIG_BSD', host_os in bsd_oses)
2266 config_host_data.set('CONFIG_CAPSTONE', capstone.found())
2267 config_host_data.set('CONFIG_COCOA', cocoa.found())
2268 config_host_data.set('CONFIG_DARWIN', host_os == 'darwin')
2269 config_host_data.set('CONFIG_FDT', fdt.found())
2270 config_host_data.set('CONFIG_FUZZ', get_option('fuzzing'))
2271 config_host_data.set('CONFIG_GCOV', get_option('b_coverage'))
2272 config_host_data.set('CONFIG_LIBUDEV', libudev.found())
2273 config_host_data.set('CONFIG_LINUX', host_os == 'linux')
2274 config_host_data.set('CONFIG_POSIX', host_os != 'windows')
2275 config_host_data.set('CONFIG_WIN32', host_os == 'windows')
2276 config_host_data.set('CONFIG_LZO', lzo.found())
2277 config_host_data.set('CONFIG_MPATH', mpathpersist.found())
2278 config_host_data.set('CONFIG_BLKIO', blkio.found())
2279 if blkio.found()
2280   config_host_data.set('CONFIG_BLKIO_VHOST_VDPA_FD',
2281                        blkio.version().version_compare('>=1.3.0'))
2282 endif
2283 config_host_data.set('CONFIG_CURL', curl.found())
2284 config_host_data.set('CONFIG_CURSES', curses.found())
2285 config_host_data.set('CONFIG_GBM', gbm.found())
2286 config_host_data.set('CONFIG_GIO', gio.found())
2287 config_host_data.set('CONFIG_GLUSTERFS', glusterfs.found())
2288 if glusterfs.found()
2289   config_host_data.set('CONFIG_GLUSTERFS_XLATOR_OPT', glusterfs.version().version_compare('>=4'))
2290   config_host_data.set('CONFIG_GLUSTERFS_DISCARD', glusterfs.version().version_compare('>=5'))
2291   config_host_data.set('CONFIG_GLUSTERFS_FALLOCATE', glusterfs.version().version_compare('>=6'))
2292   config_host_data.set('CONFIG_GLUSTERFS_ZEROFILL', glusterfs.version().version_compare('>=6'))
2293   config_host_data.set('CONFIG_GLUSTERFS_FTRUNCATE_HAS_STAT', glusterfs_ftruncate_has_stat)
2294   config_host_data.set('CONFIG_GLUSTERFS_IOCB_HAS_STAT', glusterfs_iocb_has_stat)
2295 endif
2296 config_host_data.set('CONFIG_GTK', gtk.found())
2297 config_host_data.set('CONFIG_VTE', vte.found())
2298 config_host_data.set('CONFIG_GTK_CLIPBOARD', have_gtk_clipboard)
2299 config_host_data.set('CONFIG_HEXAGON_IDEF_PARSER', get_option('hexagon_idef_parser'))
2300 config_host_data.set('CONFIG_LIBATTR', have_old_libattr)
2301 config_host_data.set('CONFIG_LIBCAP_NG', libcap_ng.found())
2302 config_host_data.set('CONFIG_EBPF', libbpf.found())
2303 config_host_data.set('CONFIG_AF_XDP', libxdp.found())
2304 config_host_data.set('CONFIG_LIBDAXCTL', libdaxctl.found())
2305 config_host_data.set('CONFIG_LIBISCSI', libiscsi.found())
2306 config_host_data.set('CONFIG_LIBNFS', libnfs.found())
2307 config_host_data.set('CONFIG_LIBSSH', libssh.found())
2308 config_host_data.set('CONFIG_LINUX_AIO', libaio.found())
2309 config_host_data.set('CONFIG_LINUX_IO_URING', linux_io_uring.found())
2310 config_host_data.set('CONFIG_LIBPMEM', libpmem.found())
2311 config_host_data.set('CONFIG_MODULES', enable_modules)
2312 config_host_data.set('CONFIG_NUMA', numa.found())
2313 if numa.found()
2314   config_host_data.set('HAVE_NUMA_HAS_PREFERRED_MANY',
2315                        cc.has_function('numa_has_preferred_many',
2316                                        dependencies: numa))
2317 endif
2318 config_host_data.set('CONFIG_OPENGL', opengl.found())
2319 config_host_data.set('CONFIG_PLUGIN', get_option('plugins'))
2320 config_host_data.set('CONFIG_RBD', rbd.found())
2321 config_host_data.set('CONFIG_RDMA', rdma.found())
2322 config_host_data.set('CONFIG_RELOCATABLE', get_option('relocatable'))
2323 config_host_data.set('CONFIG_SAFESTACK', get_option('safe_stack'))
2324 config_host_data.set('CONFIG_SDL', sdl.found())
2325 config_host_data.set('CONFIG_SDL_IMAGE', sdl_image.found())
2326 config_host_data.set('CONFIG_SECCOMP', seccomp.found())
2327 if seccomp.found()
2328   config_host_data.set('CONFIG_SECCOMP_SYSRAWRC', seccomp_has_sysrawrc)
2329 endif
2330 config_host_data.set('CONFIG_PIXMAN', pixman.found())
2331 config_host_data.set('CONFIG_SLIRP', slirp.found())
2332 config_host_data.set('CONFIG_SNAPPY', snappy.found())
2333 config_host_data.set('CONFIG_SOLARIS', host_os == 'sunos')
2334 if get_option('tcg').allowed()
2335   config_host_data.set('CONFIG_TCG', 1)
2336   config_host_data.set('CONFIG_TCG_INTERPRETER', tcg_arch == 'tci')
2337 endif
2338 config_host_data.set('CONFIG_TPM', have_tpm)
2339 config_host_data.set('CONFIG_TSAN', get_option('tsan'))
2340 config_host_data.set('CONFIG_USB_LIBUSB', libusb.found())
2341 config_host_data.set('CONFIG_VDE', vde.found())
2342 config_host_data.set('CONFIG_VHOST', have_vhost)
2343 config_host_data.set('CONFIG_VHOST_NET', have_vhost_net)
2344 config_host_data.set('CONFIG_VHOST_NET_USER', have_vhost_net_user)
2345 config_host_data.set('CONFIG_VHOST_NET_VDPA', have_vhost_net_vdpa)
2346 config_host_data.set('CONFIG_VHOST_KERNEL', have_vhost_kernel)
2347 config_host_data.set('CONFIG_VHOST_USER', have_vhost_user)
2348 config_host_data.set('CONFIG_VHOST_CRYPTO', have_vhost_user_crypto)
2349 config_host_data.set('CONFIG_VHOST_VDPA', have_vhost_vdpa)
2350 config_host_data.set('CONFIG_VMNET', vmnet.found())
2351 config_host_data.set('CONFIG_VHOST_USER_BLK_SERVER', have_vhost_user_blk_server)
2352 config_host_data.set('CONFIG_VDUSE_BLK_EXPORT', have_vduse_blk_export)
2353 config_host_data.set('CONFIG_PNG', png.found())
2354 config_host_data.set('CONFIG_VNC', vnc.found())
2355 config_host_data.set('CONFIG_VNC_JPEG', jpeg.found())
2356 config_host_data.set('CONFIG_VNC_SASL', sasl.found())
2357 if virgl.found()
2358   config_host_data.set('HAVE_VIRGL_D3D_INFO_EXT',
2359                        cc.has_member('struct virgl_renderer_resource_info_ext', 'd3d_tex2d',
2360                                      prefix: '#include <virglrenderer.h>',
2361                                      dependencies: virgl))
2362 endif
2363 config_host_data.set('CONFIG_VIRTFS', have_virtfs)
2364 config_host_data.set('CONFIG_VTE', vte.found())
2365 config_host_data.set('CONFIG_XKBCOMMON', xkbcommon.found())
2366 config_host_data.set('CONFIG_KEYUTILS', keyutils.found())
2367 config_host_data.set('CONFIG_GETTID', has_gettid)
2368 config_host_data.set('CONFIG_GNUTLS', gnutls.found())
2369 config_host_data.set('CONFIG_GNUTLS_CRYPTO', gnutls_crypto.found())
2370 config_host_data.set('CONFIG_TASN1', tasn1.found())
2371 config_host_data.set('CONFIG_GCRYPT', gcrypt.found())
2372 config_host_data.set('CONFIG_NETTLE', nettle.found())
2373 config_host_data.set('CONFIG_CRYPTO_SM4', crypto_sm4.found())
2374 config_host_data.set('CONFIG_HOGWEED', hogweed.found())
2375 config_host_data.set('CONFIG_QEMU_PRIVATE_XTS', xts == 'private')
2376 config_host_data.set('CONFIG_MALLOC_TRIM', has_malloc_trim)
2377 config_host_data.set('CONFIG_STATX', has_statx)
2378 config_host_data.set('CONFIG_STATX_MNT_ID', has_statx_mnt_id)
2379 config_host_data.set('CONFIG_ZSTD', zstd.found())
2380 config_host_data.set('CONFIG_QPL', qpl.found())
2381 config_host_data.set('CONFIG_UADK', uadk.found())
2382 config_host_data.set('CONFIG_FUSE', fuse.found())
2383 config_host_data.set('CONFIG_FUSE_LSEEK', fuse_lseek.found())
2384 config_host_data.set('CONFIG_SPICE_PROTOCOL', spice_protocol.found())
2385 if spice_protocol.found()
2386 config_host_data.set('CONFIG_SPICE_PROTOCOL_MAJOR', spice_protocol.version().split('.')[0])
2387 config_host_data.set('CONFIG_SPICE_PROTOCOL_MINOR', spice_protocol.version().split('.')[1])
2388 config_host_data.set('CONFIG_SPICE_PROTOCOL_MICRO', spice_protocol.version().split('.')[2])
2389 endif
2390 config_host_data.set('CONFIG_SPICE', spice.found())
2391 config_host_data.set('CONFIG_X11', x11.found())
2392 config_host_data.set('CONFIG_DBUS_DISPLAY', dbus_display)
2393 config_host_data.set('CONFIG_CFI', get_option('cfi'))
2394 config_host_data.set('CONFIG_SELINUX', selinux.found())
2395 config_host_data.set('CONFIG_XEN_BACKEND', xen.found())
2396 config_host_data.set('CONFIG_LIBDW', libdw.found())
2397 if xen.found()
2398   # protect from xen.version() having less than three components
2399   xen_version = xen.version().split('.') + ['0', '0']
2400   xen_ctrl_version = xen_version[0] + \
2401     ('0' + xen_version[1]).substring(-2) + \
2402     ('0' + xen_version[2]).substring(-2)
2403   config_host_data.set('CONFIG_XEN_CTRL_INTERFACE_VERSION', xen_ctrl_version)
2404 endif
2405 config_host_data.set('QEMU_VERSION', '"@0@"'.format(meson.project_version()))
2406 config_host_data.set('QEMU_VERSION_MAJOR', meson.project_version().split('.')[0])
2407 config_host_data.set('QEMU_VERSION_MINOR', meson.project_version().split('.')[1])
2408 config_host_data.set('QEMU_VERSION_MICRO', meson.project_version().split('.')[2])
2410 config_host_data.set_quoted('CONFIG_HOST_DSOSUF', host_dsosuf)
2411 config_host_data.set('HAVE_HOST_BLOCK_DEVICE', have_host_block_device)
2413 have_coroutine_pool = get_option('coroutine_pool')
2414 if get_option('debug_stack_usage') and have_coroutine_pool
2415   message('Disabling coroutine pool to measure stack usage')
2416   have_coroutine_pool = false
2417 endif
2418 config_host_data.set('CONFIG_COROUTINE_POOL', have_coroutine_pool)
2419 config_host_data.set('CONFIG_DEBUG_GRAPH_LOCK', get_option('debug_graph_lock'))
2420 config_host_data.set('CONFIG_DEBUG_MUTEX', get_option('debug_mutex'))
2421 config_host_data.set('CONFIG_DEBUG_STACK_USAGE', get_option('debug_stack_usage'))
2422 config_host_data.set('CONFIG_DEBUG_TCG', get_option('debug_tcg'))
2423 config_host_data.set('CONFIG_DEBUG_REMAP', get_option('debug_remap'))
2424 config_host_data.set('CONFIG_QOM_CAST_DEBUG', get_option('qom_cast_debug'))
2425 config_host_data.set('CONFIG_REPLICATION', get_option('replication').allowed())
2427 # has_header
2428 config_host_data.set('CONFIG_EPOLL', cc.has_header('sys/epoll.h'))
2429 config_host_data.set('CONFIG_LINUX_MAGIC_H', cc.has_header('linux/magic.h'))
2430 config_host_data.set('CONFIG_VALGRIND_H', cc.has_header('valgrind/valgrind.h'))
2431 config_host_data.set('HAVE_BTRFS_H', cc.has_header('linux/btrfs.h'))
2432 config_host_data.set('HAVE_DRM_H', cc.has_header('libdrm/drm.h'))
2433 config_host_data.set('HAVE_PTY_H', cc.has_header('pty.h'))
2434 config_host_data.set('HAVE_SYS_DISK_H', cc.has_header('sys/disk.h'))
2435 config_host_data.set('HAVE_SYS_IOCCOM_H', cc.has_header('sys/ioccom.h'))
2436 config_host_data.set('HAVE_SYS_KCOV_H', cc.has_header('sys/kcov.h'))
2437 if host_os == 'windows'
2438   config_host_data.set('HAVE_AFUNIX_H', cc.has_header('afunix.h'))
2439 endif
2441 # has_function
2442 config_host_data.set('CONFIG_CLOSE_RANGE', cc.has_function('close_range'))
2443 config_host_data.set('CONFIG_ACCEPT4', cc.has_function('accept4'))
2444 config_host_data.set('CONFIG_CLOCK_ADJTIME', cc.has_function('clock_adjtime'))
2445 config_host_data.set('CONFIG_DUP3', cc.has_function('dup3'))
2446 config_host_data.set('CONFIG_FALLOCATE', cc.has_function('fallocate'))
2447 config_host_data.set('CONFIG_POSIX_FALLOCATE', cc.has_function('posix_fallocate'))
2448 config_host_data.set('CONFIG_GETCPU', cc.has_function('getcpu', prefix: gnu_source_prefix))
2449 config_host_data.set('CONFIG_SCHED_GETCPU', cc.has_function('sched_getcpu', prefix: '#include <sched.h>'))
2450 # Note that we need to specify prefix: here to avoid incorrectly
2451 # thinking that Windows has posix_memalign()
2452 config_host_data.set('CONFIG_POSIX_MEMALIGN', cc.has_function('posix_memalign', prefix: '#include <stdlib.h>'))
2453 config_host_data.set('CONFIG_ALIGNED_MALLOC', cc.has_function('_aligned_malloc'))
2454 config_host_data.set('CONFIG_VALLOC', cc.has_function('valloc'))
2455 config_host_data.set('CONFIG_MEMALIGN', cc.has_function('memalign'))
2456 config_host_data.set('CONFIG_PPOLL', cc.has_function('ppoll'))
2457 config_host_data.set('CONFIG_PREADV', cc.has_function('preadv', prefix: '#include <sys/uio.h>'))
2458 config_host_data.set('CONFIG_PTHREAD_FCHDIR_NP', cc.has_function('pthread_fchdir_np'))
2459 config_host_data.set('CONFIG_SENDFILE', cc.has_function('sendfile'))
2460 config_host_data.set('CONFIG_SETNS', cc.has_function('setns') and cc.has_function('unshare'))
2461 config_host_data.set('CONFIG_SYNCFS', cc.has_function('syncfs'))
2462 config_host_data.set('CONFIG_SYNC_FILE_RANGE', cc.has_function('sync_file_range'))
2463 config_host_data.set('CONFIG_TIMERFD', cc.has_function('timerfd_create'))
2464 config_host_data.set('HAVE_COPY_FILE_RANGE', cc.has_function('copy_file_range'))
2465 config_host_data.set('HAVE_GETIFADDRS', cc.has_function('getifaddrs'))
2466 config_host_data.set('HAVE_GLIB_WITH_SLICE_ALLOCATOR', glib_has_gslice)
2467 config_host_data.set('HAVE_OPENPTY', cc.has_function('openpty', dependencies: util))
2468 config_host_data.set('HAVE_STRCHRNUL', cc.has_function('strchrnul'))
2469 config_host_data.set('HAVE_SYSTEM_FUNCTION', cc.has_function('system', prefix: '#include <stdlib.h>'))
2470 if rbd.found()
2471   config_host_data.set('HAVE_RBD_NAMESPACE_EXISTS',
2472                        cc.has_function('rbd_namespace_exists',
2473                                        dependencies: rbd,
2474                                        prefix: '#include <rbd/librbd.h>'))
2475 endif
2476 if rdma.found()
2477   config_host_data.set('HAVE_IBV_ADVISE_MR',
2478                        cc.has_function('ibv_advise_mr',
2479                                        dependencies: rdma,
2480                                        prefix: '#include <infiniband/verbs.h>'))
2481 endif
2483 have_asan_fiber = false
2484 if get_option('sanitizers') and \
2485    not cc.has_function('__sanitizer_start_switch_fiber',
2486                          args: '-fsanitize=address',
2487                          prefix: '#include <sanitizer/asan_interface.h>')
2488   warning('Missing ASAN due to missing fiber annotation interface')
2489   warning('Without code annotation, the report may be inferior.')
2490 else
2491   have_asan_fiber = true
2492 endif
2493 config_host_data.set('CONFIG_ASAN_IFACE_FIBER', have_asan_fiber)
2495 have_inotify_init = cc.has_header_symbol('sys/inotify.h', 'inotify_init')
2496 have_inotify_init1 = cc.has_header_symbol('sys/inotify.h', 'inotify_init1')
2497 inotify = not_found
2498 if (have_inotify_init or have_inotify_init1) and host_os == 'freebsd'
2499   # libinotify-kqueue
2500   inotify = cc.find_library('inotify')
2501   if have_inotify_init
2502     have_inotify_init = inotify.found()
2503   endif
2504   if have_inotify_init1
2505     have_inotify_init1 = inotify.found()
2506   endif
2507 endif
2508 config_host_data.set('CONFIG_INOTIFY', have_inotify_init)
2509 config_host_data.set('CONFIG_INOTIFY1', have_inotify_init1)
2511 # has_header_symbol
2512 config_host_data.set('CONFIG_BLKZONED',
2513                      cc.has_header_symbol('linux/blkzoned.h', 'BLKOPENZONE'))
2514 config_host_data.set('CONFIG_EPOLL_CREATE1',
2515                      cc.has_header_symbol('sys/epoll.h', 'epoll_create1'))
2516 config_host_data.set('CONFIG_FALLOCATE_PUNCH_HOLE',
2517                      cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_PUNCH_HOLE') and
2518                      cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_KEEP_SIZE'))
2519 config_host_data.set('CONFIG_FALLOCATE_ZERO_RANGE',
2520                      cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_ZERO_RANGE'))
2521 config_host_data.set('CONFIG_FIEMAP',
2522                      cc.has_header('linux/fiemap.h') and
2523                      cc.has_header_symbol('linux/fs.h', 'FS_IOC_FIEMAP'))
2524 config_host_data.set('CONFIG_GETRANDOM',
2525                      cc.has_function('getrandom') and
2526                      cc.has_header_symbol('sys/random.h', 'GRND_NONBLOCK'))
2527 config_host_data.set('CONFIG_PRCTL_PR_SET_TIMERSLACK',
2528                      cc.has_header_symbol('sys/prctl.h', 'PR_SET_TIMERSLACK'))
2529 config_host_data.set('CONFIG_RTNETLINK',
2530                      cc.has_header_symbol('linux/rtnetlink.h', 'IFLA_PROTO_DOWN'))
2531 config_host_data.set('CONFIG_SYSMACROS',
2532                      cc.has_header_symbol('sys/sysmacros.h', 'makedev'))
2533 config_host_data.set('HAVE_OPTRESET',
2534                      cc.has_header_symbol('getopt.h', 'optreset'))
2535 config_host_data.set('HAVE_IPPROTO_MPTCP',
2536                      cc.has_header_symbol('netinet/in.h', 'IPPROTO_MPTCP'))
2538 # has_member
2539 config_host_data.set('HAVE_SIGEV_NOTIFY_THREAD_ID',
2540                      cc.has_member('struct sigevent', 'sigev_notify_thread_id',
2541                                    prefix: '#include <signal.h>'))
2542 config_host_data.set('HAVE_STRUCT_STAT_ST_ATIM',
2543                      cc.has_member('struct stat', 'st_atim',
2544                                    prefix: '#include <sys/stat.h>'))
2545 config_host_data.set('HAVE_BLK_ZONE_REP_CAPACITY',
2546                      cc.has_member('struct blk_zone', 'capacity',
2547                                    prefix: '#include <linux/blkzoned.h>'))
2549 # has_type
2550 config_host_data.set('CONFIG_IOVEC',
2551                      cc.has_type('struct iovec',
2552                                  prefix: '#include <sys/uio.h>'))
2553 config_host_data.set('HAVE_UTMPX',
2554                      cc.has_type('struct utmpx',
2555                                  prefix: '#include <utmpx.h>'))
2557 config_host_data.set('CONFIG_EVENTFD', cc.links('''
2558   #include <sys/eventfd.h>
2559   int main(void) { return eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); }'''))
2560 config_host_data.set('CONFIG_FDATASYNC', cc.links(gnu_source_prefix + '''
2561   #include <unistd.h>
2562   int main(void) {
2563   #if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
2564   return fdatasync(0);
2565   #else
2566   #error Not supported
2567   #endif
2568   }'''))
2570 has_madvise = cc.links(gnu_source_prefix + '''
2571   #include <sys/types.h>
2572   #include <sys/mman.h>
2573   #include <stddef.h>
2574   int main(void) { return madvise(NULL, 0, MADV_DONTNEED); }''')
2575 missing_madvise_proto = false
2576 if has_madvise
2577   # Some platforms (illumos and Solaris before Solaris 11) provide madvise()
2578   # but forget to prototype it. In this case, has_madvise will be true (the
2579   # test program links despite a compile warning). To detect the
2580   # missing-prototype case, we try again with a definitely-bogus prototype.
2581   # This will only compile if the system headers don't provide the prototype;
2582   # otherwise the conflicting prototypes will cause a compiler error.
2583   missing_madvise_proto = cc.links(gnu_source_prefix + '''
2584     #include <sys/types.h>
2585     #include <sys/mman.h>
2586     #include <stddef.h>
2587     extern int madvise(int);
2588     int main(void) { return madvise(0); }''')
2589 endif
2590 config_host_data.set('CONFIG_MADVISE', has_madvise)
2591 config_host_data.set('HAVE_MADVISE_WITHOUT_PROTOTYPE', missing_madvise_proto)
2593 config_host_data.set('CONFIG_MEMFD', cc.links(gnu_source_prefix + '''
2594   #include <sys/mman.h>
2595   int main(void) { return memfd_create("foo", MFD_ALLOW_SEALING); }'''))
2596 config_host_data.set('CONFIG_OPEN_BY_HANDLE', cc.links(gnu_source_prefix + '''
2597   #include <fcntl.h>
2598   #if !defined(AT_EMPTY_PATH)
2599   # error missing definition
2600   #else
2601   int main(void) { struct file_handle fh; return open_by_handle_at(0, &fh, 0); }
2602   #endif'''))
2604 # On Darwin posix_madvise() has the same return semantics as plain madvise(),
2605 # i.e. errno is set and -1 is returned. That's not really how POSIX defines the
2606 # function. On the flip side, it has madvise() which is preferred anyways.
2607 if host_os != 'darwin'
2608   config_host_data.set('CONFIG_POSIX_MADVISE', cc.links(gnu_source_prefix + '''
2609     #include <sys/mman.h>
2610     #include <stddef.h>
2611     int main(void) { return posix_madvise(NULL, 0, POSIX_MADV_DONTNEED); }'''))
2612 endif
2614 config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_W_TID', cc.links(gnu_source_prefix + '''
2615   #include <pthread.h>
2617   static void *f(void *p) { return NULL; }
2618   int main(void)
2619   {
2620     pthread_t thread;
2621     pthread_create(&thread, 0, f, 0);
2622     pthread_setname_np(thread, "QEMU");
2623     return 0;
2624   }''', dependencies: threads))
2625 config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_WO_TID', cc.links(gnu_source_prefix + '''
2626   #include <pthread.h>
2628   static void *f(void *p) { pthread_setname_np("QEMU"); return NULL; }
2629   int main(void)
2630   {
2631     pthread_t thread;
2632     pthread_create(&thread, 0, f, 0);
2633     return 0;
2634   }''', dependencies: threads))
2635 config_host_data.set('CONFIG_PTHREAD_SET_NAME_NP', cc.links(gnu_source_prefix + '''
2636   #include <pthread.h>
2637   #include <pthread_np.h>
2639   static void *f(void *p) { return NULL; }
2640   int main(void)
2641   {
2642     pthread_t thread;
2643     pthread_create(&thread, 0, f, 0);
2644     pthread_set_name_np(thread, "QEMU");
2645     return 0;
2646   }''', dependencies: threads))
2647 config_host_data.set('CONFIG_PTHREAD_CONDATTR_SETCLOCK', cc.links(gnu_source_prefix + '''
2648   #include <pthread.h>
2649   #include <time.h>
2651   int main(void)
2652   {
2653     pthread_condattr_t attr
2654     pthread_condattr_init(&attr);
2655     pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
2656     return 0;
2657   }''', dependencies: threads))
2658 config_host_data.set('CONFIG_PTHREAD_AFFINITY_NP', cc.links(gnu_source_prefix + '''
2659   #include <pthread.h>
2661   static void *f(void *p) { return NULL; }
2662   int main(void)
2663   {
2664     int setsize = CPU_ALLOC_SIZE(64);
2665     pthread_t thread;
2666     cpu_set_t *cpuset;
2667     pthread_create(&thread, 0, f, 0);
2668     cpuset = CPU_ALLOC(64);
2669     CPU_ZERO_S(setsize, cpuset);
2670     pthread_setaffinity_np(thread, setsize, cpuset);
2671     pthread_getaffinity_np(thread, setsize, cpuset);
2672     CPU_FREE(cpuset);
2673     return 0;
2674   }''', dependencies: threads))
2675 config_host_data.set('CONFIG_SIGNALFD', cc.links(gnu_source_prefix + '''
2676   #include <sys/signalfd.h>
2677   #include <stddef.h>
2678   int main(void) { return signalfd(-1, NULL, SFD_CLOEXEC); }'''))
2679 config_host_data.set('CONFIG_SPLICE', cc.links(gnu_source_prefix + '''
2680   #include <unistd.h>
2681   #include <fcntl.h>
2682   #include <limits.h>
2684   int main(void)
2685   {
2686     int len, fd = 0;
2687     len = tee(STDIN_FILENO, STDOUT_FILENO, INT_MAX, SPLICE_F_NONBLOCK);
2688     splice(STDIN_FILENO, NULL, fd, NULL, len, SPLICE_F_MOVE);
2689     return 0;
2690   }'''))
2692 config_host_data.set('HAVE_MLOCKALL', cc.links(gnu_source_prefix + '''
2693   #include <sys/mman.h>
2694   int main(void) {
2695     return mlockall(MCL_FUTURE);
2696   }'''))
2698 have_l2tpv3 = false
2699 if get_option('l2tpv3').allowed() and have_system
2700   have_l2tpv3 = cc.has_type('struct mmsghdr',
2701     prefix: gnu_source_prefix + '''
2702       #include <sys/socket.h>
2703       #include <linux/ip.h>''')
2704 endif
2705 config_host_data.set('CONFIG_L2TPV3', have_l2tpv3)
2707 have_netmap = false
2708 if get_option('netmap').allowed() and have_system
2709   have_netmap = cc.compiles('''
2710     #include <inttypes.h>
2711     #include <net/if.h>
2712     #include <net/netmap.h>
2713     #include <net/netmap_user.h>
2714     #if (NETMAP_API < 11) || (NETMAP_API > 15)
2715     #error
2716     #endif
2717     int main(void) { return 0; }''')
2718   if not have_netmap and get_option('netmap').enabled()
2719     error('Netmap headers not available')
2720   endif
2721 endif
2722 config_host_data.set('CONFIG_NETMAP', have_netmap)
2724 # Work around a system header bug with some kernel/XFS header
2725 # versions where they both try to define 'struct fsxattr':
2726 # xfs headers will not try to redefine structs from linux headers
2727 # if this macro is set.
2728 config_host_data.set('HAVE_FSXATTR', cc.links('''
2729   #include <linux/fs.h>
2730   struct fsxattr foo;
2731   int main(void) {
2732     return 0;
2733   }'''))
2735 # Some versions of Mac OS X incorrectly define SIZE_MAX
2736 config_host_data.set('HAVE_BROKEN_SIZE_MAX', not cc.compiles('''
2737     #include <stdint.h>
2738     #include <stdio.h>
2739     int main(void) {
2740         return printf("%zu", SIZE_MAX);
2741     }''', args: ['-Werror']))
2743 # See if 64-bit atomic operations are supported.
2744 # Note that without __atomic builtins, we can only
2745 # assume atomic loads/stores max at pointer size.
2746 config_host_data.set('CONFIG_ATOMIC64', cc.links('''
2747   #include <stdint.h>
2748   int main(void)
2749   {
2750     uint64_t x = 0, y = 0;
2751     y = __atomic_load_n(&x, __ATOMIC_RELAXED);
2752     __atomic_store_n(&x, y, __ATOMIC_RELAXED);
2753     __atomic_compare_exchange_n(&x, &y, x, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
2754     __atomic_exchange_n(&x, y, __ATOMIC_RELAXED);
2755     __atomic_fetch_add(&x, y, __ATOMIC_RELAXED);
2756     return 0;
2757   }'''))
2759 has_int128_type = cc.compiles('''
2760   __int128_t a;
2761   __uint128_t b;
2762   int main(void) { b = a; }''')
2763 config_host_data.set('CONFIG_INT128_TYPE', has_int128_type)
2765 has_int128 = has_int128_type and cc.links('''
2766   __int128_t a;
2767   __uint128_t b;
2768   int main (void) {
2769     a = a + b;
2770     b = a * b;
2771     a = a * a;
2772     return 0;
2773   }''')
2774 config_host_data.set('CONFIG_INT128', has_int128)
2776 if has_int128_type
2777   # "do we have 128-bit atomics which are handled inline and specifically not
2778   # via libatomic". The reason we can't use libatomic is documented in the
2779   # comment starting "GCC is a house divided" in include/qemu/atomic128.h.
2780   # We only care about these operations on 16-byte aligned pointers, so
2781   # force 16-byte alignment of the pointer, which may be greater than
2782   # __alignof(unsigned __int128) for the host.
2783   atomic_test_128 = '''
2784     int main(int ac, char **av) {
2785       __uint128_t *p = __builtin_assume_aligned(av[ac - 1], 16);
2786       p[1] = __atomic_load_n(&p[0], __ATOMIC_RELAXED);
2787       __atomic_store_n(&p[2], p[3], __ATOMIC_RELAXED);
2788       __atomic_compare_exchange_n(&p[4], &p[5], p[6], 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
2789       return 0;
2790     }'''
2791   has_atomic128 = cc.links(atomic_test_128)
2793   config_host_data.set('CONFIG_ATOMIC128', has_atomic128)
2795   if not has_atomic128
2796     # Even with __builtin_assume_aligned, the above test may have failed
2797     # without optimization enabled.  Try again with optimizations locally
2798     # enabled for the function.  See
2799     #   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107389
2800     has_atomic128_opt = cc.links('__attribute__((optimize("O1")))' + atomic_test_128)
2801     config_host_data.set('CONFIG_ATOMIC128_OPT', has_atomic128_opt)
2803     if not has_atomic128_opt
2804       config_host_data.set('CONFIG_CMPXCHG128', cc.links('''
2805         int main(void)
2806         {
2807           __uint128_t x = 0, y = 0;
2808           __sync_val_compare_and_swap_16(&x, y, x);
2809           return 0;
2810         }
2811       '''))
2812     endif
2813   endif
2814 endif
2816 config_host_data.set('CONFIG_GETAUXVAL', cc.links(gnu_source_prefix + '''
2817   #include <sys/auxv.h>
2818   int main(void) {
2819     return getauxval(AT_HWCAP) == 0;
2820   }'''))
2822 config_host_data.set('CONFIG_USBFS', have_linux_user and cc.compiles('''
2823   #include <linux/usbdevice_fs.h>
2825   #ifndef USBDEVFS_GET_CAPABILITIES
2826   #error "USBDEVFS_GET_CAPABILITIES undefined"
2827   #endif
2829   #ifndef USBDEVFS_DISCONNECT_CLAIM
2830   #error "USBDEVFS_DISCONNECT_CLAIM undefined"
2831   #endif
2833   int main(void) { return 0; }'''))
2835 have_keyring = get_option('keyring') \
2836   .require(host_os == 'linux', error_message: 'keyring is only available on Linux') \
2837   .require(cc.compiles('''
2838     #include <errno.h>
2839     #include <asm/unistd.h>
2840     #include <linux/keyctl.h>
2841     #include <sys/syscall.h>
2842     #include <unistd.h>
2843     int main(void) {
2844         return syscall(__NR_keyctl, KEYCTL_READ, 0, NULL, NULL, 0);
2845     }'''), error_message: 'keyctl syscall not available on this system').allowed()
2846 config_host_data.set('CONFIG_SECRET_KEYRING', have_keyring)
2848 have_cpuid_h = cc.links('''
2849   #include <cpuid.h>
2850   int main(void) {
2851     unsigned a, b, c, d;
2852     unsigned max = __get_cpuid_max(0, 0);
2854     if (max >= 1) {
2855         __cpuid(1, a, b, c, d);
2856     }
2858     if (max >= 7) {
2859         __cpuid_count(7, 0, a, b, c, d);
2860     }
2862     return 0;
2863   }''')
2864 config_host_data.set('CONFIG_CPUID_H', have_cpuid_h)
2866 # Don't bother to advertise asm/hwprobe.h for old versions that do
2867 # not contain RISCV_HWPROBE_EXT_ZBA.
2868 config_host_data.set('CONFIG_ASM_HWPROBE_H',
2869                      cc.has_header_symbol('asm/hwprobe.h',
2870                                           'RISCV_HWPROBE_EXT_ZBA'))
2872 config_host_data.set('CONFIG_AVX2_OPT', get_option('avx2') \
2873   .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable AVX2') \
2874   .require(cc.links('''
2875     #include <cpuid.h>
2876     #include <immintrin.h>
2877     static int __attribute__((target("avx2"))) bar(void *a) {
2878       __m256i x = *(__m256i *)a;
2879       return _mm256_testz_si256(x, x);
2880     }
2881     int main(int argc, char *argv[]) { return bar(argv[argc - 1]); }
2882   '''), error_message: 'AVX2 not available').allowed())
2884 config_host_data.set('CONFIG_AVX512BW_OPT', get_option('avx512bw') \
2885   .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable AVX512BW') \
2886   .require(cc.links('''
2887     #include <cpuid.h>
2888     #include <immintrin.h>
2889     static int __attribute__((target("avx512bw"))) bar(void *a) {
2890       __m512i *x = a;
2891       __m512i res= _mm512_abs_epi8(*x);
2892       return res[1];
2893     }
2894     int main(int argc, char *argv[]) { return bar(argv[0]); }
2895   '''), error_message: 'AVX512BW not available').allowed())
2897 # For both AArch64 and AArch32, detect if builtins are available.
2898 config_host_data.set('CONFIG_ARM_AES_BUILTIN', cc.compiles('''
2899     #include <arm_neon.h>
2900     #ifndef __ARM_FEATURE_AES
2901     __attribute__((target("+crypto")))
2902     #endif
2903     void foo(uint8x16_t *p) { *p = vaesmcq_u8(*p); }
2904   '''))
2906 if get_option('membarrier').disabled()
2907   have_membarrier = false
2908 elif host_os == 'windows'
2909   have_membarrier = true
2910 elif host_os == 'linux'
2911   have_membarrier = cc.compiles('''
2912     #include <linux/membarrier.h>
2913     #include <sys/syscall.h>
2914     #include <unistd.h>
2915     #include <stdlib.h>
2916     int main(void) {
2917         syscall(__NR_membarrier, MEMBARRIER_CMD_QUERY, 0);
2918         syscall(__NR_membarrier, MEMBARRIER_CMD_SHARED, 0);
2919         exit(0);
2920     }''')
2921 endif
2922 config_host_data.set('CONFIG_MEMBARRIER', get_option('membarrier') \
2923   .require(have_membarrier, error_message: 'membarrier system call not available') \
2924   .allowed())
2926 have_afalg = get_option('crypto_afalg') \
2927   .require(cc.compiles(gnu_source_prefix + '''
2928     #include <errno.h>
2929     #include <sys/types.h>
2930     #include <sys/socket.h>
2931     #include <linux/if_alg.h>
2932     int main(void) {
2933       int sock;
2934       sock = socket(AF_ALG, SOCK_SEQPACKET, 0);
2935       return sock;
2936     }
2937   '''), error_message: 'AF_ALG requested but could not be detected').allowed()
2938 config_host_data.set('CONFIG_AF_ALG', have_afalg)
2940 config_host_data.set('CONFIG_AF_VSOCK', cc.has_header_symbol(
2941   'linux/vm_sockets.h', 'AF_VSOCK',
2942   prefix: '#include <sys/socket.h>',
2945 have_vss = false
2946 have_vss_sdk = false # old xp/2003 SDK
2947 if host_os == 'windows' and 'cpp' in all_languages
2948   have_vss = cxx.compiles('''
2949     #define __MIDL_user_allocate_free_DEFINED__
2950     #include <vss.h>
2951     int main(void) { return VSS_CTX_BACKUP; }''')
2952   have_vss_sdk = cxx.has_header('vscoordint.h')
2953 endif
2954 config_host_data.set('HAVE_VSS_SDK', have_vss_sdk)
2956 # Older versions of MinGW do not import _lock_file and _unlock_file properly.
2957 # This was fixed for v6.0.0 with commit b48e3ac8969d.
2958 if host_os == 'windows'
2959   config_host_data.set('HAVE__LOCK_FILE', cc.links('''
2960     #include <stdio.h>
2961     int main(void) {
2962       _lock_file(NULL);
2963       _unlock_file(NULL);
2964       return 0;
2965     }''', name: '_lock_file and _unlock_file'))
2966 endif
2968 if host_os == 'windows'
2969   mingw_has_setjmp_longjmp = cc.links('''
2970     #include <setjmp.h>
2971     int main(void) {
2972       /*
2973        * These functions are not available in setjmp header, but may be
2974        * available at link time, from libmingwex.a.
2975        */
2976       extern int __mingw_setjmp(jmp_buf);
2977       extern void __attribute__((noreturn)) __mingw_longjmp(jmp_buf, int);
2978       jmp_buf env;
2979       __mingw_setjmp(env);
2980       __mingw_longjmp(env, 0);
2981     }
2982   ''', name: 'mingw setjmp and longjmp')
2984   if cpu == 'aarch64' and not mingw_has_setjmp_longjmp
2985     error('mingw must provide setjmp/longjmp for windows-arm64')
2986   endif
2987 endif
2989 ########################
2990 # Target configuration #
2991 ########################
2993 minikconf = find_program('scripts/minikconf.py')
2995 config_all_accel = {}
2996 config_all_devices = {}
2997 config_devices_mak_list = []
2998 config_devices_h = {}
2999 config_target_h = {}
3000 config_target_mak = {}
3002 disassemblers = {
3003   'alpha' : ['CONFIG_ALPHA_DIS'],
3004   'avr' : ['CONFIG_AVR_DIS'],
3005   'cris' : ['CONFIG_CRIS_DIS'],
3006   'hexagon' : ['CONFIG_HEXAGON_DIS'],
3007   'hppa' : ['CONFIG_HPPA_DIS'],
3008   'i386' : ['CONFIG_I386_DIS'],
3009   'x86_64' : ['CONFIG_I386_DIS'],
3010   'm68k' : ['CONFIG_M68K_DIS'],
3011   'microblaze' : ['CONFIG_MICROBLAZE_DIS'],
3012   'mips' : ['CONFIG_MIPS_DIS'],
3013   'or1k' : ['CONFIG_OPENRISC_DIS'],
3014   'ppc' : ['CONFIG_PPC_DIS'],
3015   'riscv' : ['CONFIG_RISCV_DIS'],
3016   'rx' : ['CONFIG_RX_DIS'],
3017   's390' : ['CONFIG_S390_DIS'],
3018   'sh4' : ['CONFIG_SH4_DIS'],
3019   'sparc' : ['CONFIG_SPARC_DIS'],
3020   'xtensa' : ['CONFIG_XTENSA_DIS'],
3021   'loongarch' : ['CONFIG_LOONGARCH_DIS'],
3024 have_ivshmem = config_host_data.get('CONFIG_EVENTFD')
3025 host_kconfig = \
3026   (get_option('fuzzing') ? ['CONFIG_FUZZ=y'] : []) + \
3027   (have_tpm ? ['CONFIG_TPM=y'] : []) + \
3028   (pixman.found() ? ['CONFIG_PIXMAN=y'] : []) + \
3029   (spice.found() ? ['CONFIG_SPICE=y'] : []) + \
3030   (have_ivshmem ? ['CONFIG_IVSHMEM=y'] : []) + \
3031   (opengl.found() ? ['CONFIG_OPENGL=y'] : []) + \
3032   (x11.found() ? ['CONFIG_X11=y'] : []) + \
3033   (fdt.found() ? ['CONFIG_FDT=y'] : []) + \
3034   (have_vhost_user ? ['CONFIG_VHOST_USER=y'] : []) + \
3035   (have_vhost_vdpa ? ['CONFIG_VHOST_VDPA=y'] : []) + \
3036   (have_vhost_kernel ? ['CONFIG_VHOST_KERNEL=y'] : []) + \
3037   (have_virtfs ? ['CONFIG_VIRTFS=y'] : []) + \
3038   (host_os == 'linux' ? ['CONFIG_LINUX=y'] : []) + \
3039   (multiprocess_allowed ? ['CONFIG_MULTIPROCESS_ALLOWED=y'] : []) + \
3040   (vfio_user_server_allowed ? ['CONFIG_VFIO_USER_SERVER_ALLOWED=y'] : []) + \
3041   (hv_balloon ? ['CONFIG_HV_BALLOON_POSSIBLE=y'] : [])
3043 ignored = [ 'TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_ARCH' ]
3045 default_targets = 'CONFIG_DEFAULT_TARGETS' in config_host
3046 actual_target_dirs = []
3047 fdt_required = []
3048 foreach target : target_dirs
3049   config_target = { 'TARGET_NAME': target.split('-')[0] }
3050   if target.endswith('linux-user')
3051     if host_os != 'linux'
3052       if default_targets
3053         continue
3054       endif
3055       error('Target @0@ is only available on a Linux host'.format(target))
3056     endif
3057     config_target += { 'CONFIG_LINUX_USER': 'y' }
3058   elif target.endswith('bsd-user')
3059     if host_os not in bsd_oses
3060       if default_targets
3061         continue
3062       endif
3063       error('Target @0@ is only available on a BSD host'.format(target))
3064     endif
3065     config_target += { 'CONFIG_BSD_USER': 'y' }
3066   elif target.endswith('softmmu')
3067     config_target += { 'CONFIG_SYSTEM_ONLY': 'y' }
3068     config_target += { 'CONFIG_SOFTMMU': 'y' }
3069   endif
3070   if target.endswith('-user')
3071     config_target += {
3072       'CONFIG_USER_ONLY': 'y',
3073       'CONFIG_QEMU_INTERP_PREFIX':
3074         get_option('interp_prefix').replace('%M', config_target['TARGET_NAME'])
3075     }
3076   endif
3078   target_kconfig = []
3079   foreach sym: accelerators
3080     if sym == 'CONFIG_TCG' or target in accelerator_targets.get(sym, [])
3081       config_target += { sym: 'y' }
3082       config_all_accel += { sym: 'y' }
3083       if target in modular_tcg
3084         config_target += { 'CONFIG_TCG_MODULAR': 'y' }
3085       else
3086         config_target += { 'CONFIG_TCG_BUILTIN': 'y' }
3087       endif
3088       target_kconfig += [ sym + '=y' ]
3089     endif
3090   endforeach
3091   if target_kconfig.length() == 0
3092     if default_targets
3093       continue
3094     endif
3095     error('No accelerator available for target @0@'.format(target))
3096   endif
3098   config_target += keyval.load('configs/targets' / target + '.mak')
3099   config_target += { 'TARGET_' + config_target['TARGET_ARCH'].to_upper(): 'y' }
3101   if 'TARGET_NEED_FDT' in config_target and not fdt.found()
3102     if default_targets
3103       warning('Disabling ' + target + ' due to missing libfdt')
3104     else
3105       fdt_required += target
3106     endif
3107     continue
3108   endif
3110   actual_target_dirs += target
3112   # Add default keys
3113   if 'TARGET_BASE_ARCH' not in config_target
3114     config_target += {'TARGET_BASE_ARCH': config_target['TARGET_ARCH']}
3115   endif
3116   if 'TARGET_ABI_DIR' not in config_target
3117     config_target += {'TARGET_ABI_DIR': config_target['TARGET_ARCH']}
3118   endif
3119   if 'TARGET_BIG_ENDIAN' not in config_target
3120     config_target += {'TARGET_BIG_ENDIAN': 'n'}
3121   endif
3123   foreach k, v: disassemblers
3124     if host_arch.startswith(k) or config_target['TARGET_BASE_ARCH'].startswith(k)
3125       foreach sym: v
3126         config_target += { sym: 'y' }
3127       endforeach
3128     endif
3129   endforeach
3131   config_target_data = configuration_data()
3132   foreach k, v: config_target
3133     if not k.startswith('TARGET_') and not k.startswith('CONFIG_')
3134       # do nothing
3135     elif ignored.contains(k)
3136       # do nothing
3137     elif k == 'TARGET_BASE_ARCH'
3138       # Note that TARGET_BASE_ARCH ends up in config-target.h but it is
3139       # not used to select files from sourcesets.
3140       config_target_data.set('TARGET_' + v.to_upper(), 1)
3141     elif k == 'TARGET_NAME' or k == 'CONFIG_QEMU_INTERP_PREFIX'
3142       config_target_data.set_quoted(k, v)
3143     elif v == 'y'
3144       config_target_data.set(k, 1)
3145     elif v == 'n'
3146       config_target_data.set(k, 0)
3147     else
3148       config_target_data.set(k, v)
3149     endif
3150   endforeach
3151   config_target_data.set('QEMU_ARCH',
3152                          'QEMU_ARCH_' + config_target['TARGET_BASE_ARCH'].to_upper())
3153   config_target_h += {target: configure_file(output: target + '-config-target.h',
3154                                                configuration: config_target_data)}
3156   if target.endswith('-softmmu')
3157     target_kconfig += 'CONFIG_' + config_target['TARGET_ARCH'].to_upper() + '=y'
3158     target_kconfig += 'CONFIG_TARGET_BIG_ENDIAN=' + config_target['TARGET_BIG_ENDIAN']
3160     config_input = meson.get_external_property(target, 'default')
3161     config_devices_mak = target + '-config-devices.mak'
3162     config_devices_mak = configure_file(
3163       input: ['configs/devices' / target / config_input + '.mak', 'Kconfig'],
3164       output: config_devices_mak,
3165       depfile: config_devices_mak + '.d',
3166       capture: true,
3167       command: [minikconf,
3168                 get_option('default_devices') ? '--defconfig' : '--allnoconfig',
3169                 config_devices_mak, '@DEPFILE@', '@INPUT@',
3170                 host_kconfig, target_kconfig])
3172     config_devices_data = configuration_data()
3173     config_devices = keyval.load(config_devices_mak)
3174     foreach k, v: config_devices
3175       config_devices_data.set(k, 1)
3176     endforeach
3177     config_devices_mak_list += config_devices_mak
3178     config_devices_h += {target: configure_file(output: target + '-config-devices.h',
3179                                                 configuration: config_devices_data)}
3180     config_target += config_devices
3181     config_all_devices += config_devices
3182   endif
3183   config_target_mak += {target: config_target}
3184 endforeach
3185 target_dirs = actual_target_dirs
3187 target_configs_h = []
3188 foreach target: target_dirs
3189   target_configs_h += config_target_h[target]
3190   target_configs_h += config_devices_h.get(target, [])
3191 endforeach
3192 genh += custom_target('config-poison.h',
3193                       input: [target_configs_h],
3194                       output: 'config-poison.h',
3195                       capture: true,
3196                       command: [find_program('scripts/make-config-poison.sh'),
3197                                 target_configs_h])
3199 if fdt_required.length() > 0
3200   error('fdt disabled but required by targets ' + ', '.join(fdt_required))
3201 endif
3203 ###############
3204 # Subprojects #
3205 ###############
3207 libvfio_user_dep = not_found
3208 if have_system and vfio_user_server_allowed
3209   libvfio_user_proj = subproject('libvfio-user', required: true)
3210   libvfio_user_dep = libvfio_user_proj.get_variable('libvfio_user_dep')
3211 endif
3213 vhost_user = not_found
3214 if host_os == 'linux' and have_vhost_user
3215   libvhost_user = subproject('libvhost-user')
3216   vhost_user = libvhost_user.get_variable('vhost_user_dep')
3217 endif
3219 libvduse = not_found
3220 if have_libvduse
3221   libvduse_proj = subproject('libvduse')
3222   libvduse = libvduse_proj.get_variable('libvduse_dep')
3223 endif
3225 #####################
3226 # Generated sources #
3227 #####################
3229 genh += configure_file(output: 'config-host.h', configuration: config_host_data)
3231 hxtool = find_program('scripts/hxtool')
3232 shaderinclude = find_program('scripts/shaderinclude.py')
3233 qapi_gen = find_program('scripts/qapi-gen.py')
3234 qapi_gen_depends = [ meson.current_source_dir() / 'scripts/qapi/__init__.py',
3235                      meson.current_source_dir() / 'scripts/qapi/commands.py',
3236                      meson.current_source_dir() / 'scripts/qapi/common.py',
3237                      meson.current_source_dir() / 'scripts/qapi/error.py',
3238                      meson.current_source_dir() / 'scripts/qapi/events.py',
3239                      meson.current_source_dir() / 'scripts/qapi/expr.py',
3240                      meson.current_source_dir() / 'scripts/qapi/gen.py',
3241                      meson.current_source_dir() / 'scripts/qapi/introspect.py',
3242                      meson.current_source_dir() / 'scripts/qapi/main.py',
3243                      meson.current_source_dir() / 'scripts/qapi/parser.py',
3244                      meson.current_source_dir() / 'scripts/qapi/schema.py',
3245                      meson.current_source_dir() / 'scripts/qapi/source.py',
3246                      meson.current_source_dir() / 'scripts/qapi/types.py',
3247                      meson.current_source_dir() / 'scripts/qapi/visit.py',
3248                      meson.current_source_dir() / 'scripts/qapi-gen.py'
3251 tracetool = [
3252   python, files('scripts/tracetool.py'),
3253    '--backend=' + ','.join(get_option('trace_backends'))
3255 tracetool_depends = files(
3256   'scripts/tracetool/backend/log.py',
3257   'scripts/tracetool/backend/__init__.py',
3258   'scripts/tracetool/backend/dtrace.py',
3259   'scripts/tracetool/backend/ftrace.py',
3260   'scripts/tracetool/backend/simple.py',
3261   'scripts/tracetool/backend/syslog.py',
3262   'scripts/tracetool/backend/ust.py',
3263   'scripts/tracetool/format/ust_events_c.py',
3264   'scripts/tracetool/format/ust_events_h.py',
3265   'scripts/tracetool/format/__init__.py',
3266   'scripts/tracetool/format/d.py',
3267   'scripts/tracetool/format/simpletrace_stap.py',
3268   'scripts/tracetool/format/c.py',
3269   'scripts/tracetool/format/h.py',
3270   'scripts/tracetool/format/log_stap.py',
3271   'scripts/tracetool/format/stap.py',
3272   'scripts/tracetool/__init__.py',
3275 qemu_version_cmd = [find_program('scripts/qemu-version.sh'),
3276                     meson.current_source_dir(),
3277                     get_option('pkgversion'), meson.project_version()]
3278 qemu_version = custom_target('qemu-version.h',
3279                              output: 'qemu-version.h',
3280                              command: qemu_version_cmd,
3281                              capture: true,
3282                              build_by_default: true,
3283                              build_always_stale: true)
3284 genh += qemu_version
3286 hxdep = []
3287 hx_headers = [
3288   ['qemu-options.hx', 'qemu-options.def'],
3289   ['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
3291 if have_system
3292   hx_headers += [
3293     ['hmp-commands.hx', 'hmp-commands.h'],
3294     ['hmp-commands-info.hx', 'hmp-commands-info.h'],
3295   ]
3296 endif
3297 foreach d : hx_headers
3298   hxdep += custom_target(d[1],
3299                 input: files(d[0]),
3300                 output: d[1],
3301                 capture: true,
3302                 command: [hxtool, '-h', '@INPUT0@'])
3303 endforeach
3304 genh += hxdep
3306 ###############
3307 # Trace files #
3308 ###############
3310 # TODO: add each directory to the subdirs from its own meson.build, once
3311 # we have those
3312 trace_events_subdirs = [
3313   'crypto',
3314   'qapi',
3315   'qom',
3316   'monitor',
3317   'util',
3318   'gdbstub',
3320 if have_linux_user
3321   trace_events_subdirs += [ 'linux-user' ]
3322 endif
3323 if have_bsd_user
3324   trace_events_subdirs += [ 'bsd-user' ]
3325 endif
3326 if have_block
3327   trace_events_subdirs += [
3328     'authz',
3329     'block',
3330     'io',
3331     'nbd',
3332     'scsi',
3333   ]
3334 endif
3335 if have_system
3336   trace_events_subdirs += [
3337     'accel/kvm',
3338     'audio',
3339     'backends',
3340     'backends/tpm',
3341     'chardev',
3342     'ebpf',
3343     'hw/9pfs',
3344     'hw/acpi',
3345     'hw/adc',
3346     'hw/alpha',
3347     'hw/arm',
3348     'hw/audio',
3349     'hw/block',
3350     'hw/char',
3351     'hw/display',
3352     'hw/dma',
3353     'hw/fsi',
3354     'hw/hyperv',
3355     'hw/i2c',
3356     'hw/i386',
3357     'hw/i386/xen',
3358     'hw/i386/kvm',
3359     'hw/ide',
3360     'hw/input',
3361     'hw/intc',
3362     'hw/isa',
3363     'hw/mem',
3364     'hw/mips',
3365     'hw/misc',
3366     'hw/misc/macio',
3367     'hw/net',
3368     'hw/net/can',
3369     'hw/nubus',
3370     'hw/nvme',
3371     'hw/nvram',
3372     'hw/pci',
3373     'hw/pci-host',
3374     'hw/ppc',
3375     'hw/rtc',
3376     'hw/s390x',
3377     'hw/scsi',
3378     'hw/sd',
3379     'hw/sh4',
3380     'hw/sparc',
3381     'hw/sparc64',
3382     'hw/ssi',
3383     'hw/timer',
3384     'hw/tpm',
3385     'hw/ufs',
3386     'hw/usb',
3387     'hw/vfio',
3388     'hw/virtio',
3389     'hw/watchdog',
3390     'hw/xen',
3391     'hw/gpio',
3392     'migration',
3393     'net',
3394     'system',
3395     'ui',
3396     'hw/remote',
3397   ]
3398 endif
3399 if have_system or have_user
3400   trace_events_subdirs += [
3401     'accel/tcg',
3402     'hw/core',
3403     'target/arm',
3404     'target/arm/hvf',
3405     'target/hppa',
3406     'target/i386',
3407     'target/i386/kvm',
3408     'target/loongarch',
3409     'target/mips/tcg',
3410     'target/ppc',
3411     'target/riscv',
3412     'target/s390x',
3413     'target/s390x/kvm',
3414     'target/sparc',
3415   ]
3416 endif
3418 ###################
3419 # Collect sources #
3420 ###################
3422 authz_ss = ss.source_set()
3423 blockdev_ss = ss.source_set()
3424 block_ss = ss.source_set()
3425 chardev_ss = ss.source_set()
3426 common_ss = ss.source_set()
3427 crypto_ss = ss.source_set()
3428 hwcore_ss = ss.source_set()
3429 io_ss = ss.source_set()
3430 qmp_ss = ss.source_set()
3431 qom_ss = ss.source_set()
3432 system_ss = ss.source_set()
3433 specific_fuzz_ss = ss.source_set()
3434 specific_ss = ss.source_set()
3435 stub_ss = ss.source_set()
3436 trace_ss = ss.source_set()
3437 user_ss = ss.source_set()
3438 util_ss = ss.source_set()
3440 # accel modules
3441 qtest_module_ss = ss.source_set()
3442 tcg_module_ss = ss.source_set()
3444 modules = {}
3445 target_modules = {}
3446 hw_arch = {}
3447 target_arch = {}
3448 target_system_arch = {}
3449 target_user_arch = {}
3451 # NOTE: the trace/ subdirectory needs the qapi_trace_events variable
3452 # that is filled in by qapi/.
3453 subdir('qapi')
3454 subdir('qobject')
3455 subdir('stubs')
3456 subdir('trace')
3457 subdir('util')
3458 subdir('qom')
3459 subdir('authz')
3460 subdir('crypto')
3461 subdir('ui')
3462 subdir('gdbstub')
3463 if have_system
3464   subdir('hw')
3465 else
3466   subdir('hw/core')
3467 endif
3469 if enable_modules
3470   libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
3471   modulecommon = declare_dependency(objects: libmodulecommon.extract_all_objects(recursive: false), compile_args: '-DBUILD_DSO')
3472 endif
3474 qom_ss = qom_ss.apply({})
3475 libqom = static_library('qom', qom_ss.sources() + genh,
3476                         dependencies: [qom_ss.dependencies()],
3477                         build_by_default: false)
3478 qom = declare_dependency(objects: libqom.extract_all_objects(recursive: false),
3479                          dependencies: qom_ss.dependencies())
3481 event_loop_base = files('event-loop-base.c')
3482 event_loop_base = static_library('event-loop-base',
3483                                  sources: event_loop_base + genh,
3484                                  build_by_default: false)
3485 event_loop_base = declare_dependency(objects: event_loop_base.extract_all_objects(recursive: false),
3486                                      dependencies: [qom])
3488 stub_ss = stub_ss.apply({})
3490 util_ss.add_all(trace_ss)
3491 util_ss = util_ss.apply({})
3492 libqemuutil = static_library('qemuutil',
3493                              build_by_default: false,
3494                              sources: util_ss.sources() + stub_ss.sources() + genh,
3495                              dependencies: [util_ss.dependencies(), libm, threads, glib, socket, malloc])
3496 qemuutil = declare_dependency(link_with: libqemuutil,
3497                               sources: genh + version_res,
3498                               dependencies: [event_loop_base])
3500 if have_system or have_user
3501   decodetree = generator(find_program('scripts/decodetree.py'),
3502                          output: 'decode-@BASENAME@.c.inc',
3503                          arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
3504   subdir('libdecnumber')
3505   subdir('target')
3506 endif
3508 subdir('audio')
3509 subdir('io')
3510 subdir('chardev')
3511 subdir('fsdev')
3512 subdir('dump')
3514 if have_block
3515   block_ss.add(files(
3516     'block.c',
3517     'blockjob.c',
3518     'job.c',
3519     'qemu-io-cmds.c',
3520   ))
3521   if config_host_data.get('CONFIG_REPLICATION')
3522     block_ss.add(files('replication.c'))
3523   endif
3525   subdir('nbd')
3526   subdir('scsi')
3527   subdir('block')
3529   blockdev_ss.add(files(
3530     'blockdev.c',
3531     'blockdev-nbd.c',
3532     'iothread.c',
3533     'job-qmp.c',
3534   ))
3536   # os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
3537   # os-win32.c does not
3538   if host_os == 'windows'
3539     system_ss.add(files('os-win32.c'))
3540   else
3541     blockdev_ss.add(files('os-posix.c'))
3542   endif
3543 endif
3545 common_ss.add(files('cpu-common.c'))
3546 specific_ss.add(files('cpu-target.c'))
3548 subdir('system')
3550 # Work around a gcc bug/misfeature wherein constant propagation looks
3551 # through an alias:
3552 #   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99696
3553 # to guess that a const variable is always zero.  Without lto, this is
3554 # impossible, as the alias is restricted to page-vary-common.c.  Indeed,
3555 # without lto, not even the alias is required -- we simply use different
3556 # declarations in different compilation units.
3557 pagevary = files('page-vary-common.c')
3558 if get_option('b_lto')
3559   pagevary_flags = ['-fno-lto']
3560   if get_option('cfi')
3561     pagevary_flags += '-fno-sanitize=cfi-icall'
3562   endif
3563   pagevary = static_library('page-vary-common', sources: pagevary + genh,
3564                             c_args: pagevary_flags)
3565   pagevary = declare_dependency(link_with: pagevary)
3566 endif
3567 common_ss.add(pagevary)
3568 specific_ss.add(files('page-target.c', 'page-vary-target.c'))
3570 subdir('backends')
3571 subdir('disas')
3572 subdir('migration')
3573 subdir('monitor')
3574 subdir('net')
3575 subdir('replay')
3576 subdir('semihosting')
3577 subdir('stats')
3578 subdir('tcg')
3579 subdir('fpu')
3580 subdir('accel')
3581 subdir('plugins')
3582 subdir('ebpf')
3584 common_user_inc = []
3586 subdir('common-user')
3587 subdir('bsd-user')
3588 subdir('linux-user')
3590 # needed for fuzzing binaries
3591 subdir('tests/qtest/libqos')
3592 subdir('tests/qtest/fuzz')
3594 # accel modules
3595 tcg_real_module_ss = ss.source_set()
3596 tcg_real_module_ss.add_all(when: 'CONFIG_TCG_MODULAR', if_true: tcg_module_ss)
3597 specific_ss.add_all(when: 'CONFIG_TCG_BUILTIN', if_true: tcg_module_ss)
3598 target_modules += { 'accel' : { 'qtest': qtest_module_ss,
3599                                 'tcg': tcg_real_module_ss }}
3601 ##############################################
3602 # Internal static_libraries and dependencies #
3603 ##############################################
3605 modinfo_collect = find_program('scripts/modinfo-collect.py')
3606 modinfo_generate = find_program('scripts/modinfo-generate.py')
3607 modinfo_files = []
3609 block_mods = []
3610 system_mods = []
3611 emulator_modules = []
3612 foreach d, list : modules
3613   if not (d == 'block' ? have_block : have_system)
3614     continue
3615   endif
3617   foreach m, module_ss : list
3618     if enable_modules
3619       module_ss.add(modulecommon)
3620       module_ss = module_ss.apply(config_all_devices, strict: false)
3621       sl = static_library(d + '-' + m, [genh, module_ss.sources()],
3622                           dependencies: module_ss.dependencies(), pic: true)
3623       if d == 'block'
3624         block_mods += sl
3625       else
3626         system_mods += sl
3627       endif
3628       emulator_modules += shared_module(sl.name(),
3629                     name_prefix: '',
3630                     objects: sl.extract_all_objects(recursive: false),
3631                     dependencies: module_ss.dependencies(),
3632                     install: true,
3633                     install_dir: qemu_moddir)
3634       if module_ss.sources() != []
3635         # FIXME: Should use sl.extract_all_objects(recursive: true) as
3636         # input. Sources can be used multiple times but objects are
3637         # unique when it comes to lookup in compile_commands.json.
3638         # Depnds on a mesion version with
3639         # https://github.com/mesonbuild/meson/pull/8900
3640         modinfo_files += custom_target(d + '-' + m + '.modinfo',
3641                                        output: d + '-' + m + '.modinfo',
3642                                        input: module_ss.sources() + genh,
3643                                        capture: true,
3644                                        command: [modinfo_collect, module_ss.sources()])
3645       endif
3646     else
3647       if d == 'block'
3648         block_ss.add_all(module_ss)
3649       else
3650         system_ss.add_all(module_ss)
3651       endif
3652     endif
3653   endforeach
3654 endforeach
3656 foreach d, list : target_modules
3657   foreach m, module_ss : list
3658     if enable_modules
3659       module_ss.add(modulecommon)
3660       foreach target : target_dirs
3661         if target.endswith('-softmmu')
3662           config_target = config_target_mak[target]
3663           target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
3664           c_args = ['-DCOMPILING_PER_TARGET',
3665                     '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
3666                     '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
3667           target_module_ss = module_ss.apply(config_target, strict: false)
3668           if target_module_ss.sources() != []
3669             module_name = d + '-' + m + '-' + config_target['TARGET_NAME']
3670             sl = static_library(module_name,
3671                                 [genh, target_module_ss.sources()],
3672                                 dependencies: target_module_ss.dependencies(),
3673                                 include_directories: target_inc,
3674                                 c_args: c_args,
3675                                 pic: true)
3676             system_mods += sl
3677             emulator_modules += shared_module(sl.name(),
3678                     name_prefix: '',
3679                     objects: sl.extract_all_objects(recursive: false),
3680                     dependencies: target_module_ss.dependencies(),
3681                     install: true,
3682                     install_dir: qemu_moddir)
3683             # FIXME: Should use sl.extract_all_objects(recursive: true) too.
3684             modinfo_files += custom_target(module_name + '.modinfo',
3685                                            output: module_name + '.modinfo',
3686                                            input: target_module_ss.sources() + genh,
3687                                            capture: true,
3688                                            command: [modinfo_collect, '--target', target, target_module_ss.sources()])
3689           endif
3690         endif
3691       endforeach
3692     else
3693       specific_ss.add_all(module_ss)
3694     endif
3695   endforeach
3696 endforeach
3698 if enable_modules
3699   foreach target : target_dirs
3700     if target.endswith('-softmmu')
3701       config_target = config_target_mak[target]
3702       config_devices_mak = target + '-config-devices.mak'
3703       modinfo_src = custom_target('modinfo-' + target + '.c',
3704                                   output: 'modinfo-' + target + '.c',
3705                                   input: modinfo_files,
3706                                   command: [modinfo_generate, '--devices', config_devices_mak, '@INPUT@'],
3707                                   capture: true)
3709       modinfo_lib = static_library('modinfo-' + target + '.c', modinfo_src)
3710       modinfo_dep = declare_dependency(link_with: modinfo_lib)
3712       arch = config_target['TARGET_NAME'] == 'sparc64' ? 'sparc64' : config_target['TARGET_BASE_ARCH']
3713       hw_arch[arch].add(modinfo_dep)
3714     endif
3715   endforeach
3717   if emulator_modules.length() > 0
3718     alias_target('modules', emulator_modules)
3719   endif
3720 endif
3722 nm = find_program('nm')
3723 undefsym = find_program('scripts/undefsym.py')
3724 block_syms = custom_target('block.syms', output: 'block.syms',
3725                              input: [libqemuutil, block_mods],
3726                              capture: true,
3727                              command: [undefsym, nm, '@INPUT@'])
3728 qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
3729                              input: [libqemuutil, system_mods],
3730                              capture: true,
3731                              command: [undefsym, nm, '@INPUT@'])
3733 authz_ss = authz_ss.apply({})
3734 libauthz = static_library('authz', authz_ss.sources() + genh,
3735                           dependencies: [authz_ss.dependencies()],
3736                           build_by_default: false)
3738 authz = declare_dependency(objects: libauthz.extract_all_objects(recursive: false),
3739                            dependencies: [authz_ss.dependencies(), qom])
3741 crypto_ss = crypto_ss.apply({})
3742 libcrypto = static_library('crypto', crypto_ss.sources() + genh,
3743                            dependencies: [crypto_ss.dependencies()],
3744                            build_by_default: false)
3746 crypto = declare_dependency(objects: libcrypto.extract_all_objects(recursive: false),
3747                             dependencies: [crypto_ss.dependencies(), authz, qom])
3749 io_ss = io_ss.apply({})
3750 libio = static_library('io', io_ss.sources() + genh,
3751                        dependencies: [io_ss.dependencies()],
3752                        link_with: libqemuutil,
3753                        build_by_default: false)
3755 io = declare_dependency(objects: libio.extract_all_objects(recursive: false),
3756                         dependencies: [io_ss.dependencies(), crypto, qom])
3758 libmigration = static_library('migration', sources: migration_files + genh,
3759                               build_by_default: false)
3760 migration = declare_dependency(objects: libmigration.extract_all_objects(recursive: false),
3761                                dependencies: [qom, io])
3762 system_ss.add(migration)
3764 block_ss = block_ss.apply({})
3765 libblock = static_library('block', block_ss.sources() + genh,
3766                           dependencies: block_ss.dependencies(),
3767                           build_by_default: false)
3769 block = declare_dependency(objects: libblock.extract_all_objects(recursive: false),
3770                            dependencies: [block_ss.dependencies(), crypto, io])
3772 blockdev_ss = blockdev_ss.apply({})
3773 libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
3774                              dependencies: blockdev_ss.dependencies(),
3775                              build_by_default: false)
3777 blockdev = declare_dependency(objects: libblockdev.extract_all_objects(recursive: false),
3778                               dependencies: [blockdev_ss.dependencies(), block, event_loop_base])
3780 qmp_ss = qmp_ss.apply({})
3781 libqmp = static_library('qmp', qmp_ss.sources() + genh,
3782                         dependencies: qmp_ss.dependencies(),
3783                         build_by_default: false)
3785 qmp = declare_dependency(objects: libqmp.extract_all_objects(recursive: false),
3786                          dependencies: qmp_ss.dependencies())
3788 libchardev = static_library('chardev', chardev_ss.sources() + genh,
3789                             dependencies: chardev_ss.dependencies(),
3790                             build_by_default: false)
3792 chardev = declare_dependency(objects: libchardev.extract_all_objects(recursive: false),
3793                              dependencies: chardev_ss.dependencies())
3795 hwcore_ss = hwcore_ss.apply({})
3796 libhwcore = static_library('hwcore', sources: hwcore_ss.sources() + genh,
3797                            build_by_default: false)
3798 hwcore = declare_dependency(objects: libhwcore.extract_all_objects(recursive: false))
3799 common_ss.add(hwcore)
3801 ###########
3802 # Targets #
3803 ###########
3805 system_ss.add(authz, blockdev, chardev, crypto, io, qmp)
3806 common_ss.add(qom, qemuutil)
3808 common_ss.add_all(when: 'CONFIG_SYSTEM_ONLY', if_true: [system_ss])
3809 common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
3811 # Note that this library is never used directly (only through extract_objects)
3812 # and is not built by default; therefore, source files not used by the build
3813 # configuration will be in build.ninja, but are never built by default.
3814 common_all = static_library('common',
3815                             build_by_default: false,
3816                             sources: common_ss.all_sources() + genh,
3817                             include_directories: common_user_inc,
3818                             implicit_include_directories: false,
3819                             dependencies: common_ss.all_dependencies())
3821 feature_to_c = find_program('scripts/feature_to_c.py')
3823 if host_os == 'darwin'
3824   entitlement = find_program('scripts/entitlement.sh')
3825 endif
3827 traceable = []
3828 emulators = {}
3829 foreach target : target_dirs
3830   config_target = config_target_mak[target]
3831   target_name = config_target['TARGET_NAME']
3832   target_base_arch = config_target['TARGET_BASE_ARCH']
3833   arch_srcs = [config_target_h[target]]
3834   arch_deps = []
3835   c_args = ['-DCOMPILING_PER_TARGET',
3836             '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
3837             '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
3838   link_args = emulator_link_args
3840   target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
3841   if host_os == 'linux'
3842     target_inc += include_directories('linux-headers', is_system: true)
3843   endif
3844   if target.endswith('-softmmu')
3845     target_type='system'
3846     t = target_system_arch[target_base_arch].apply(config_target, strict: false)
3847     arch_srcs += t.sources()
3848     arch_deps += t.dependencies()
3850     hw_dir = target_name == 'sparc64' ? 'sparc64' : target_base_arch
3851     if hw_arch.has_key(hw_dir)
3852       hw = hw_arch[hw_dir].apply(config_target, strict: false)
3853       arch_srcs += hw.sources()
3854       arch_deps += hw.dependencies()
3855     endif
3857     arch_srcs += config_devices_h[target]
3858     link_args += ['@block.syms', '@qemu.syms']
3859   else
3860     abi = config_target['TARGET_ABI_DIR']
3861     target_type='user'
3862     target_inc += common_user_inc
3863     if target_base_arch in target_user_arch
3864       t = target_user_arch[target_base_arch].apply(config_target, strict: false)
3865       arch_srcs += t.sources()
3866       arch_deps += t.dependencies()
3867     endif
3868     if 'CONFIG_LINUX_USER' in config_target
3869       base_dir = 'linux-user'
3870     endif
3871     if 'CONFIG_BSD_USER' in config_target
3872       base_dir = 'bsd-user'
3873       target_inc += include_directories('bsd-user/' / host_os)
3874       target_inc += include_directories('bsd-user/host/' / host_arch)
3875       dir = base_dir / abi
3876       arch_srcs += files(dir / 'signal.c', dir / 'target_arch_cpu.c')
3877     endif
3878     target_inc += include_directories(
3879       base_dir,
3880       base_dir / abi,
3881     )
3882     if 'CONFIG_LINUX_USER' in config_target
3883       dir = base_dir / abi
3884       arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
3885       if config_target.has_key('TARGET_SYSTBL_ABI')
3886         arch_srcs += \
3887           syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
3888                                              extra_args : config_target['TARGET_SYSTBL_ABI'])
3889       endif
3890     endif
3891   endif
3893   if 'TARGET_XML_FILES' in config_target
3894     gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
3895                                 output: target + '-gdbstub-xml.c',
3896                                 input: files(config_target['TARGET_XML_FILES'].split()),
3897                                 command: [feature_to_c, '@INPUT@'],
3898                                 capture: true)
3899     arch_srcs += gdbstub_xml
3900   endif
3902   t = target_arch[target_base_arch].apply(config_target, strict: false)
3903   arch_srcs += t.sources()
3904   arch_deps += t.dependencies()
3906   target_common = common_ss.apply(config_target, strict: false)
3907   objects = common_all.extract_objects(target_common.sources())
3908   arch_deps += target_common.dependencies()
3910   target_specific = specific_ss.apply(config_target, strict: false)
3911   arch_srcs += target_specific.sources()
3912   arch_deps += target_specific.dependencies()
3914   # allow using headers from the dependencies but do not include the sources,
3915   # because this emulator only needs those in "objects".  For external
3916   # dependencies, the full dependency is included below in the executable.
3917   lib_deps = []
3918   foreach dep : arch_deps
3919     lib_deps += dep.partial_dependency(compile_args: true, includes: true)
3920   endforeach
3922   lib = static_library('qemu-' + target,
3923                  sources: arch_srcs + genh,
3924                  dependencies: lib_deps,
3925                  objects: objects,
3926                  include_directories: target_inc,
3927                  c_args: c_args,
3928                  build_by_default: false)
3930   if target.endswith('-softmmu')
3931     execs = [{
3932       'name': 'qemu-system-' + target_name,
3933       'win_subsystem': 'console',
3934       'sources': files('system/main.c'),
3935       'dependencies': []
3936     }]
3937     if host_os == 'windows' and (sdl.found() or gtk.found())
3938       execs += [{
3939         'name': 'qemu-system-' + target_name + 'w',
3940         'win_subsystem': 'windows',
3941         'sources': files('system/main.c'),
3942         'dependencies': []
3943       }]
3944     endif
3945     if get_option('fuzzing')
3946       specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
3947       execs += [{
3948         'name': 'qemu-fuzz-' + target_name,
3949         'win_subsystem': 'console',
3950         'sources': specific_fuzz.sources(),
3951         'dependencies': specific_fuzz.dependencies(),
3952       }]
3953     endif
3954   else
3955     execs = [{
3956       'name': 'qemu-' + target_name,
3957       'win_subsystem': 'console',
3958       'sources': [],
3959       'dependencies': []
3960     }]
3961   endif
3962   foreach exe: execs
3963     exe_name = exe['name']
3964     if host_os == 'darwin'
3965       exe_name += '-unsigned'
3966     endif
3968     emulator = executable(exe_name, exe['sources'],
3969                install: true,
3970                c_args: c_args,
3971                dependencies: arch_deps + exe['dependencies'],
3972                objects: lib.extract_all_objects(recursive: true),
3973                link_depends: [block_syms, qemu_syms],
3974                link_args: link_args,
3975                win_subsystem: exe['win_subsystem'])
3977     if host_os == 'darwin'
3978       icon = 'pc-bios/qemu.rsrc'
3979       build_input = [emulator, files(icon)]
3980       install_input = [
3981         get_option('bindir') / exe_name,
3982         meson.current_source_dir() / icon
3983       ]
3984       if 'CONFIG_HVF' in config_target
3985         entitlements = 'accel/hvf/entitlements.plist'
3986         build_input += files(entitlements)
3987         install_input += meson.current_source_dir() / entitlements
3988       endif
3990       emulators += {exe['name'] : custom_target(exe['name'],
3991                    input: build_input,
3992                    output: exe['name'],
3993                    command: [entitlement, '@OUTPUT@', '@INPUT@'])
3994       }
3996       meson.add_install_script(entitlement, '--install',
3997                                get_option('bindir') / exe['name'],
3998                                install_input)
3999     else
4000       emulators += {exe['name']: emulator}
4001     endif
4003     traceable += [{
4004       'exe': exe['name'],
4005       'probe-prefix': 'qemu.' + target_type + '.' + target_name,
4006     }]
4008   endforeach
4009 endforeach
4011 # Other build targets
4013 if get_option('plugins')
4014   install_headers('include/qemu/qemu-plugin.h')
4015   if host_os == 'windows'
4016     # On windows, we want to deliver the qemu_plugin_api.lib file in the qemu installer,
4017     # so that plugin authors can compile against it.
4018     install_data(win32_qemu_plugin_api_lib, install_dir: 'lib')
4019   endif
4020 endif
4022 subdir('qga')
4024 # Don't build qemu-keymap if xkbcommon is not explicitly enabled
4025 # when we don't build tools or system
4026 if xkbcommon.found()
4027   # used for the update-keymaps target, so include rules even if !have_tools
4028   qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
4029                            dependencies: [qemuutil, xkbcommon], install: have_tools)
4030 endif
4032 if have_tools
4033   qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
4034              link_args: '@block.syms', link_depends: block_syms,
4035              dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
4036   qemu_io = executable('qemu-io', files('qemu-io.c'),
4037              link_args: '@block.syms', link_depends: block_syms,
4038              dependencies: [block, qemuutil], install: true)
4039   qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
4040                link_args: '@block.syms', link_depends: block_syms,
4041                dependencies: [blockdev, qemuutil, selinux],
4042                install: true)
4044   subdir('storage-daemon')
4046   foreach exe: [ 'qemu-img', 'qemu-io', 'qemu-nbd', 'qemu-storage-daemon']
4047     traceable += [{
4048       'exe': exe,
4049       'probe-prefix': 'qemu.' + exe.substring(5).replace('-', '_')
4050     }]
4051   endforeach
4053   subdir('contrib/elf2dmp')
4055   executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
4056              dependencies: qemuutil,
4057              install: true)
4059   if have_vhost_user
4060     subdir('contrib/vhost-user-blk')
4061     subdir('contrib/vhost-user-gpu')
4062     subdir('contrib/vhost-user-input')
4063     subdir('contrib/vhost-user-scsi')
4064   endif
4066   if host_os == 'linux'
4067     executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
4068                dependencies: [qemuutil, libcap_ng],
4069                install: true,
4070                install_dir: get_option('libexecdir'))
4072     executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
4073                dependencies: [authz, crypto, io, qom, qemuutil,
4074                               libcap_ng, mpathpersist],
4075                install: true)
4076   endif
4078   if have_ivshmem
4079     subdir('contrib/ivshmem-client')
4080     subdir('contrib/ivshmem-server')
4081   endif
4082 endif
4084 if stap.found()
4085   foreach t: traceable
4086     foreach stp: [
4087       {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / t['exe'], 'install': false},
4088       {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / t['exe'], 'install': true},
4089       {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
4090       {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
4091     ]
4092       cmd = [
4093         tracetool, '--group=all', '--format=' + stp['fmt'],
4094         '--binary=' + stp['bin'],
4095         '--probe-prefix=' + t['probe-prefix'],
4096         '@INPUT@', '@OUTPUT@'
4097       ]
4099       custom_target(t['exe'] + stp['ext'],
4100                     input: trace_events_all,
4101                     output: t['exe'] + stp['ext'],
4102                     install: stp['install'],
4103                     install_dir: get_option('datadir') / 'systemtap/tapset',
4104                     command: cmd,
4105                     depend_files: tracetool_depends)
4106     endforeach
4107   endforeach
4108 endif
4110 subdir('scripts')
4111 subdir('tools')
4112 subdir('pc-bios')
4113 subdir('docs')
4114 subdir('tests')
4115 if gtk.found()
4116   subdir('po')
4117 endif
4119 if host_machine.system() == 'windows'
4120   nsis_cmd = [
4121     find_program('scripts/nsis.py'),
4122     '@OUTPUT@',
4123     get_option('prefix'),
4124     meson.current_source_dir(),
4125     glib_pc.get_variable('bindir'),
4126     host_machine.cpu(),
4127     '--',
4128     '-DDISPLAYVERSION=' + meson.project_version(),
4129   ]
4130   if build_docs
4131     nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
4132   endif
4133   if gtk.found()
4134     nsis_cmd += '-DCONFIG_GTK=y'
4135   endif
4137   nsis = custom_target('nsis',
4138                        output: 'qemu-setup-' + meson.project_version() + '.exe',
4139                        input: files('qemu.nsi'),
4140                        build_always_stale: true,
4141                        command: nsis_cmd + ['@INPUT@'])
4142   alias_target('installer', nsis)
4143 endif
4145 #########################
4146 # Configuration summary #
4147 #########################
4149 # Build environment
4150 summary_info = {}
4151 summary_info += {'Build directory':   meson.current_build_dir()}
4152 summary_info += {'Source path':       meson.current_source_dir()}
4153 summary_info += {'Download dependencies': get_option('wrap_mode') != 'nodownload'}
4154 summary(summary_info, bool_yn: true, section: 'Build environment')
4156 # Directories
4157 summary_info += {'Install prefix':    get_option('prefix')}
4158 summary_info += {'BIOS directory':    qemu_datadir}
4159 pathsep = host_os == 'windows' ? ';' : ':'
4160 summary_info += {'firmware path':     pathsep.join(get_option('qemu_firmwarepath'))}
4161 summary_info += {'binary directory':  get_option('prefix') / get_option('bindir')}
4162 summary_info += {'library directory': get_option('prefix') / get_option('libdir')}
4163 summary_info += {'module directory':  qemu_moddir}
4164 summary_info += {'libexec directory': get_option('prefix') / get_option('libexecdir')}
4165 summary_info += {'include directory': get_option('prefix') / get_option('includedir')}
4166 summary_info += {'config directory':  get_option('prefix') / get_option('sysconfdir')}
4167 if host_os != 'windows'
4168   summary_info += {'local state directory': get_option('prefix') / get_option('localstatedir')}
4169   summary_info += {'Manual directory':      get_option('prefix') / get_option('mandir')}
4170 else
4171   summary_info += {'local state directory': 'queried at runtime'}
4172 endif
4173 summary_info += {'Doc directory':     get_option('prefix') / get_option('docdir')}
4174 summary(summary_info, bool_yn: true, section: 'Directories')
4176 # Host binaries
4177 summary_info = {}
4178 summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
4179 summary_info += {'sphinx-build':      sphinx_build}
4181 # FIXME: the [binaries] section of machine files, which can be probed
4182 # with find_program(), would be great for passing gdb and genisoimage
4183 # paths from configure to Meson.  However, there seems to be no way to
4184 # hide a program (for example if gdb is too old).
4185 if config_host.has_key('GDB')
4186   summary_info += {'gdb':             config_host['GDB']}
4187 endif
4188 summary_info += {'iasl':              iasl}
4189 summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
4190 if host_os == 'windows' and have_ga
4191   summary_info += {'wixl':            wixl}
4192 endif
4193 if slirp.found() and have_system
4194   summary_info += {'smbd':            have_slirp_smbd ? smbd_path : false}
4195 endif
4196 summary(summary_info, bool_yn: true, section: 'Host binaries')
4198 # Configurable features
4199 summary_info = {}
4200 summary_info += {'Documentation':     build_docs}
4201 summary_info += {'system-mode emulation': have_system}
4202 summary_info += {'user-mode emulation': have_user}
4203 summary_info += {'block layer':       have_block}
4204 summary_info += {'Install blobs':     get_option('install_blobs')}
4205 summary_info += {'module support':    enable_modules}
4206 if enable_modules
4207   summary_info += {'alternative module path': get_option('module_upgrades')}
4208 endif
4209 summary_info += {'fuzzing support':   get_option('fuzzing')}
4210 if have_system
4211   summary_info += {'Audio drivers':     ' '.join(audio_drivers_selected)}
4212 endif
4213 summary_info += {'Trace backends':    ','.join(get_option('trace_backends'))}
4214 if 'simple' in get_option('trace_backends')
4215   summary_info += {'Trace output file': get_option('trace_file') + '-<pid>'}
4216 endif
4217 summary_info += {'D-Bus display':     dbus_display}
4218 summary_info += {'QOM debugging':     get_option('qom_cast_debug')}
4219 summary_info += {'Relocatable install': get_option('relocatable')}
4220 summary_info += {'vhost-kernel support': have_vhost_kernel}
4221 summary_info += {'vhost-net support': have_vhost_net}
4222 summary_info += {'vhost-user support': have_vhost_user}
4223 summary_info += {'vhost-user-crypto support': have_vhost_user_crypto}
4224 summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
4225 summary_info += {'vhost-vdpa support': have_vhost_vdpa}
4226 summary_info += {'build guest agent': have_ga}
4227 summary(summary_info, bool_yn: true, section: 'Configurable features')
4229 # Compilation information
4230 summary_info = {}
4231 summary_info += {'host CPU':          cpu}
4232 summary_info += {'host endianness':   build_machine.endian()}
4233 summary_info += {'C compiler':        ' '.join(meson.get_compiler('c').cmd_array())}
4234 summary_info += {'Host C compiler':   ' '.join(meson.get_compiler('c', native: true).cmd_array())}
4235 if 'cpp' in all_languages
4236   summary_info += {'C++ compiler':    ' '.join(meson.get_compiler('cpp').cmd_array())}
4237 else
4238   summary_info += {'C++ compiler':      false}
4239 endif
4240 if 'objc' in all_languages
4241   summary_info += {'Objective-C compiler': ' '.join(meson.get_compiler('objc').cmd_array())}
4242 else
4243   summary_info += {'Objective-C compiler': false}
4244 endif
4245 option_cflags = (get_option('debug') ? ['-g'] : [])
4246 if get_option('optimization') != 'plain'
4247   option_cflags += ['-O' + get_option('optimization')]
4248 endif
4249 summary_info += {'CFLAGS':            ' '.join(get_option('c_args') + option_cflags)}
4250 if 'cpp' in all_languages
4251   summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args') + option_cflags)}
4252 endif
4253 if 'objc' in all_languages
4254   summary_info += {'OBJCFLAGS':       ' '.join(get_option('objc_args') + option_cflags)}
4255 endif
4256 link_args = get_option('c_link_args')
4257 if link_args.length() > 0
4258   summary_info += {'LDFLAGS':         ' '.join(link_args)}
4259 endif
4260 summary_info += {'QEMU_CFLAGS':       ' '.join(qemu_common_flags + qemu_cflags)}
4261 if 'cpp' in all_languages
4262   summary_info += {'QEMU_CXXFLAGS':     ' '.join(qemu_common_flags + qemu_cxxflags)}
4263 endif
4264 if 'objc' in all_languages
4265   summary_info += {'QEMU_OBJCFLAGS':    ' '.join(qemu_common_flags)}
4266 endif
4267 summary_info += {'QEMU_LDFLAGS':      ' '.join(qemu_ldflags)}
4268 summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
4269 summary_info += {'PIE':               get_option('b_pie')}
4270 summary_info += {'static build':      get_option('prefer_static')}
4271 summary_info += {'malloc trim support': has_malloc_trim}
4272 summary_info += {'membarrier':        have_membarrier}
4273 summary_info += {'debug graph lock':  get_option('debug_graph_lock')}
4274 summary_info += {'debug stack usage': get_option('debug_stack_usage')}
4275 summary_info += {'mutex debugging':   get_option('debug_mutex')}
4276 summary_info += {'memory allocator':  get_option('malloc')}
4277 summary_info += {'avx2 optimization': config_host_data.get('CONFIG_AVX2_OPT')}
4278 summary_info += {'avx512bw optimization': config_host_data.get('CONFIG_AVX512BW_OPT')}
4279 summary_info += {'gcov':              get_option('b_coverage')}
4280 summary_info += {'thread sanitizer':  get_option('tsan')}
4281 summary_info += {'CFI support':       get_option('cfi')}
4282 if get_option('cfi')
4283   summary_info += {'CFI debug support': get_option('cfi_debug')}
4284 endif
4285 summary_info += {'strip binaries':    get_option('strip')}
4286 summary_info += {'sparse':            sparse}
4287 summary_info += {'mingw32 support':   host_os == 'windows'}
4288 summary(summary_info, bool_yn: true, section: 'Compilation')
4290 # snarf the cross-compilation information for tests
4291 summary_info = {}
4292 have_cross = false
4293 foreach target: target_dirs
4294   tcg_mak = meson.current_build_dir() / 'tests/tcg' / target / 'config-target.mak'
4295   if fs.exists(tcg_mak)
4296     config_cross_tcg = keyval.load(tcg_mak)
4297     if 'CC' in config_cross_tcg
4298       summary_info += {config_cross_tcg['TARGET_NAME']: config_cross_tcg['CC']}
4299       have_cross = true
4300     endif
4301   endif
4302 endforeach
4303 if have_cross
4304   summary(summary_info, bool_yn: true, section: 'Cross compilers')
4305 endif
4307 # Targets and accelerators
4308 summary_info = {}
4309 if have_system
4310   summary_info += {'KVM support':       config_all_accel.has_key('CONFIG_KVM')}
4311   summary_info += {'HVF support':       config_all_accel.has_key('CONFIG_HVF')}
4312   summary_info += {'WHPX support':      config_all_accel.has_key('CONFIG_WHPX')}
4313   summary_info += {'NVMM support':      config_all_accel.has_key('CONFIG_NVMM')}
4314   summary_info += {'Xen support':       xen.found()}
4315   if xen.found()
4316     summary_info += {'xen ctrl version':  xen.version()}
4317   endif
4318   summary_info += {'Xen emulation':     config_all_devices.has_key('CONFIG_XEN_EMU')}
4319 endif
4320 summary_info += {'TCG support':       config_all_accel.has_key('CONFIG_TCG')}
4321 if config_all_accel.has_key('CONFIG_TCG')
4322   if get_option('tcg_interpreter')
4323     summary_info += {'TCG backend':   'TCI (TCG with bytecode interpreter, slow)'}
4324   else
4325     summary_info += {'TCG backend':   'native (@0@)'.format(cpu)}
4326   endif
4327   summary_info += {'TCG plugins':       get_option('plugins')}
4328   summary_info += {'TCG debug enabled': get_option('debug_tcg')}
4329   if have_linux_user or have_bsd_user
4330     summary_info += {'syscall buffer debugging support': get_option('debug_remap')}
4331   endif
4332 endif
4333 summary_info += {'target list':       ' '.join(target_dirs)}
4334 if have_system
4335   summary_info += {'default devices':   get_option('default_devices')}
4336   summary_info += {'out of process emulation': multiprocess_allowed}
4337   summary_info += {'vfio-user server': vfio_user_server_allowed}
4338 endif
4339 summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
4341 # Block layer
4342 summary_info = {}
4343 summary_info += {'coroutine backend': coroutine_backend}
4344 summary_info += {'coroutine pool':    have_coroutine_pool}
4345 if have_block
4346   summary_info += {'Block whitelist (rw)': get_option('block_drv_rw_whitelist')}
4347   summary_info += {'Block whitelist (ro)': get_option('block_drv_ro_whitelist')}
4348   summary_info += {'Use block whitelist in tools': get_option('block_drv_whitelist_in_tools')}
4349   summary_info += {'VirtFS (9P) support':    have_virtfs}
4350   summary_info += {'VirtFS (9P) Proxy Helper support (deprecated)': have_virtfs_proxy_helper}
4351   summary_info += {'replication support': config_host_data.get('CONFIG_REPLICATION')}
4352   summary_info += {'bochs support':     get_option('bochs').allowed()}
4353   summary_info += {'cloop support':     get_option('cloop').allowed()}
4354   summary_info += {'dmg support':       get_option('dmg').allowed()}
4355   summary_info += {'qcow v1 support':   get_option('qcow1').allowed()}
4356   summary_info += {'vdi support':       get_option('vdi').allowed()}
4357   summary_info += {'vhdx support':      get_option('vhdx').allowed()}
4358   summary_info += {'vmdk support':      get_option('vmdk').allowed()}
4359   summary_info += {'vpc support':       get_option('vpc').allowed()}
4360   summary_info += {'vvfat support':     get_option('vvfat').allowed()}
4361   summary_info += {'qed support':       get_option('qed').allowed()}
4362   summary_info += {'parallels support': get_option('parallels').allowed()}
4363   summary_info += {'FUSE exports':      fuse}
4364   summary_info += {'VDUSE block exports': have_vduse_blk_export}
4365 endif
4366 summary(summary_info, bool_yn: true, section: 'Block layer support')
4368 # Crypto
4369 summary_info = {}
4370 summary_info += {'TLS priority':      get_option('tls_priority')}
4371 summary_info += {'GNUTLS support':    gnutls}
4372 if gnutls.found()
4373   summary_info += {'  GNUTLS crypto':   gnutls_crypto.found()}
4374 endif
4375 summary_info += {'libgcrypt':         gcrypt}
4376 summary_info += {'nettle':            nettle}
4377 if nettle.found()
4378    summary_info += {'  XTS':             xts != 'private'}
4379 endif
4380 summary_info += {'SM4 ALG support':   crypto_sm4}
4381 summary_info += {'AF_ALG support':    have_afalg}
4382 summary_info += {'rng-none':          get_option('rng_none')}
4383 summary_info += {'Linux keyring':     have_keyring}
4384 summary_info += {'Linux keyutils':    keyutils}
4385 summary(summary_info, bool_yn: true, section: 'Crypto')
4387 # UI
4388 summary_info = {}
4389 if host_os == 'darwin'
4390   summary_info += {'Cocoa support':           cocoa}
4391 endif
4392 summary_info += {'SDL support':       sdl}
4393 summary_info += {'SDL image support': sdl_image}
4394 summary_info += {'GTK support':       gtk}
4395 summary_info += {'pixman':            pixman}
4396 summary_info += {'VTE support':       vte}
4397 summary_info += {'PNG support':       png}
4398 summary_info += {'VNC support':       vnc}
4399 if vnc.found()
4400   summary_info += {'VNC SASL support':  sasl}
4401   summary_info += {'VNC JPEG support':  jpeg}
4402 endif
4403 summary_info += {'spice protocol support': spice_protocol}
4404 if spice_protocol.found()
4405   summary_info += {'  spice server support': spice}
4406 endif
4407 summary_info += {'curses support':    curses}
4408 summary_info += {'brlapi support':    brlapi}
4409 summary(summary_info, bool_yn: true, section: 'User interface')
4411 # Graphics backends
4412 summary_info = {}
4413 summary_info += {'VirGL support':     virgl}
4414 summary_info += {'Rutabaga support':  rutabaga}
4415 summary(summary_info, bool_yn: true, section: 'Graphics backends')
4417 # Audio backends
4418 summary_info = {}
4419 if host_os not in ['darwin', 'haiku', 'windows']
4420   summary_info += {'OSS support':     oss}
4421   summary_info += {'sndio support':   sndio}
4422 elif host_os == 'darwin'
4423   summary_info += {'CoreAudio support': coreaudio}
4424 elif host_os == 'windows'
4425   summary_info += {'DirectSound support': dsound}
4426 endif
4427 if host_os == 'linux'
4428   summary_info += {'ALSA support':    alsa}
4429   summary_info += {'PulseAudio support': pulse}
4430 endif
4431 summary_info += {'PipeWire support':  pipewire}
4432 summary_info += {'JACK support':      jack}
4433 summary(summary_info, bool_yn: true, section: 'Audio backends')
4435 # Network backends
4436 summary_info = {}
4437 if host_os == 'darwin'
4438   summary_info += {'vmnet.framework support': vmnet}
4439 endif
4440 summary_info += {'AF_XDP support':    libxdp}
4441 summary_info += {'slirp support':     slirp}
4442 summary_info += {'vde support':       vde}
4443 summary_info += {'netmap support':    have_netmap}
4444 summary_info += {'l2tpv3 support':    have_l2tpv3}
4445 summary(summary_info, bool_yn: true, section: 'Network backends')
4447 # Libraries
4448 summary_info = {}
4449 summary_info += {'libtasn1':          tasn1}
4450 summary_info += {'PAM':               pam}
4451 summary_info += {'iconv support':     iconv}
4452 summary_info += {'blkio support':     blkio}
4453 summary_info += {'curl support':      curl}
4454 summary_info += {'Multipath support': mpathpersist}
4455 summary_info += {'Linux AIO support': libaio}
4456 summary_info += {'Linux io_uring support': linux_io_uring}
4457 summary_info += {'ATTR/XATTR support': libattr}
4458 summary_info += {'RDMA support':      rdma}
4459 summary_info += {'fdt support':       fdt_opt == 'internal' ? 'internal' : fdt}
4460 summary_info += {'libcap-ng support': libcap_ng}
4461 summary_info += {'bpf support':       libbpf}
4462 summary_info += {'rbd support':       rbd}
4463 summary_info += {'smartcard support': cacard}
4464 summary_info += {'U2F support':       u2f}
4465 summary_info += {'libusb':            libusb}
4466 summary_info += {'usb net redir':     usbredir}
4467 summary_info += {'OpenGL support (epoxy)': opengl}
4468 summary_info += {'GBM':               gbm}
4469 summary_info += {'libiscsi support':  libiscsi}
4470 summary_info += {'libnfs support':    libnfs}
4471 if host_os == 'windows'
4472   if have_ga
4473     summary_info += {'QGA VSS support':   have_qga_vss}
4474   endif
4475 endif
4476 summary_info += {'seccomp support':   seccomp}
4477 summary_info += {'GlusterFS support': glusterfs}
4478 summary_info += {'hv-balloon support': hv_balloon}
4479 summary_info += {'TPM support':       have_tpm}
4480 summary_info += {'libssh support':    libssh}
4481 summary_info += {'lzo support':       lzo}
4482 summary_info += {'snappy support':    snappy}
4483 summary_info += {'bzip2 support':     libbzip2}
4484 summary_info += {'lzfse support':     liblzfse}
4485 summary_info += {'zstd support':      zstd}
4486 summary_info += {'Query Processing Library support': qpl}
4487 summary_info += {'UADK Library support': uadk}
4488 summary_info += {'NUMA host support': numa}
4489 summary_info += {'capstone':          capstone}
4490 summary_info += {'libpmem support':   libpmem}
4491 summary_info += {'libdaxctl support': libdaxctl}
4492 summary_info += {'libudev':           libudev}
4493 # Dummy dependency, keep .found()
4494 summary_info += {'FUSE lseek':        fuse_lseek.found()}
4495 summary_info += {'selinux':           selinux}
4496 summary_info += {'libdw':             libdw}
4497 if host_os == 'freebsd'
4498   summary_info += {'libinotify-kqueue': inotify}
4499 endif
4500 summary(summary_info, bool_yn: true, section: 'Dependencies')
4502 if host_arch == 'unknown'
4503   message()
4504   warning('UNSUPPORTED HOST CPU')
4505   message()
4506   message('Support for CPU host architecture ' + cpu + ' is not currently')
4507   message('maintained. The QEMU project does not guarantee that QEMU will')
4508   message('compile or work on this host CPU. You can help by volunteering')
4509   message('to maintain it and providing a build host for our continuous')
4510   message('integration setup.')
4511   if get_option('tcg').allowed() and target_dirs.length() > 0
4512     message()
4513     message('configure has succeeded and you can continue to build, but')
4514     message('QEMU will use a slow interpreter to emulate the target CPU.')
4515   endif
4516 endif
4518 if not supported_oses.contains(host_os)
4519   message()
4520   warning('UNSUPPORTED HOST OS')
4521   message()
4522   message('Support for host OS ' + host_os + 'is not currently maintained.')
4523   message('configure has succeeded and you can continue to build, but')
4524   message('the QEMU project does not guarantee that QEMU will compile or')
4525   message('work on this operating system. You can help by volunteering')
4526   message('to maintain it and providing a build host for our continuous')
4527   message('integration setup. This will ensure that future versions of QEMU')
4528   message('will keep working on ' + host_os + '.')
4529 endif
4531 if host_arch == 'unknown' or not supported_oses.contains(host_os)
4532   message()
4533   message('If you want to help supporting QEMU on this platform, please')
4534   message('contact the developers at qemu-devel@nongnu.org.')
4535 endif
4537 actually_reloc = get_option('relocatable')
4538 # check if get_relocated_path() is actually able to relocate paths
4539 if get_option('relocatable') and \
4540   not (get_option('prefix') / get_option('bindir')).startswith(get_option('prefix') / '')
4541   message()
4542   warning('bindir not included within prefix, the installation will not be relocatable.')
4543   actually_reloc = false
4544 endif
4545 if not actually_reloc and (host_os == 'windows' or get_option('relocatable'))
4546   if host_os == 'windows'
4547     message()
4548     warning('Windows installs should usually be relocatable.')
4549   endif
4550   message()
4551   message('QEMU will have to be installed under ' + get_option('prefix') + '.')
4552   message('Use --disable-relocatable to remove this warning.')
4553 endif