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