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