OSDN Git Service

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