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