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