OSDN Git Service

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