xref: /openbmc/qemu/meson.build (revision 915f77b2)
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())
1500config_host_data.set('CONFIG_SPICE', spice.found())
1501config_host_data.set('CONFIG_X11', x11.found())
1502config_host_data.set('CONFIG_CFI', get_option('cfi'))
1503config_host_data.set('CONFIG_SELINUX', selinux.found())
1504config_host_data.set('QEMU_VERSION', '"@0@"'.format(meson.project_version()))
1505config_host_data.set('QEMU_VERSION_MAJOR', meson.project_version().split('.')[0])
1506config_host_data.set('QEMU_VERSION_MINOR', meson.project_version().split('.')[1])
1507config_host_data.set('QEMU_VERSION_MICRO', meson.project_version().split('.')[2])
1508
1509config_host_data.set_quoted('CONFIG_HOST_DSOSUF', host_dsosuf)
1510config_host_data.set('HAVE_HOST_BLOCK_DEVICE', have_host_block_device)
1511config_host_data.set('HOST_WORDS_BIGENDIAN', host_machine.endian() == 'big')
1512
1513# has_header
1514config_host_data.set('CONFIG_EPOLL', cc.has_header('sys/epoll.h'))
1515config_host_data.set('CONFIG_LINUX_MAGIC_H', cc.has_header('linux/magic.h'))
1516config_host_data.set('CONFIG_VALGRIND_H', cc.has_header('valgrind/valgrind.h'))
1517config_host_data.set('HAVE_BTRFS_H', cc.has_header('linux/btrfs.h'))
1518config_host_data.set('HAVE_DRM_H', cc.has_header('libdrm/drm.h'))
1519config_host_data.set('HAVE_PTY_H', cc.has_header('pty.h'))
1520config_host_data.set('HAVE_SYS_DISK_H', cc.has_header('sys/disk.h'))
1521config_host_data.set('HAVE_SYS_IOCCOM_H', cc.has_header('sys/ioccom.h'))
1522config_host_data.set('HAVE_SYS_KCOV_H', cc.has_header('sys/kcov.h'))
1523
1524# has_function
1525config_host_data.set('CONFIG_ACCEPT4', cc.has_function('accept4'))
1526config_host_data.set('CONFIG_CLOCK_ADJTIME', cc.has_function('clock_adjtime'))
1527config_host_data.set('CONFIG_DUP3', cc.has_function('dup3'))
1528config_host_data.set('CONFIG_FALLOCATE', cc.has_function('fallocate'))
1529config_host_data.set('CONFIG_POSIX_FALLOCATE', cc.has_function('posix_fallocate'))
1530config_host_data.set('CONFIG_POSIX_MEMALIGN', cc.has_function('posix_memalign'))
1531config_host_data.set('CONFIG_PPOLL', cc.has_function('ppoll'))
1532config_host_data.set('CONFIG_PREADV', cc.has_function('preadv', prefix: '#include <sys/uio.h>'))
1533config_host_data.set('CONFIG_SEM_TIMEDWAIT', cc.has_function('sem_timedwait', dependencies: threads))
1534config_host_data.set('CONFIG_SENDFILE', cc.has_function('sendfile'))
1535config_host_data.set('CONFIG_SETNS', cc.has_function('setns') and cc.has_function('unshare'))
1536config_host_data.set('CONFIG_SYNCFS', cc.has_function('syncfs'))
1537config_host_data.set('CONFIG_SYNC_FILE_RANGE', cc.has_function('sync_file_range'))
1538config_host_data.set('CONFIG_TIMERFD', cc.has_function('timerfd_create'))
1539config_host_data.set('HAVE_COPY_FILE_RANGE', cc.has_function('copy_file_range'))
1540config_host_data.set('HAVE_OPENPTY', cc.has_function('openpty', dependencies: util))
1541config_host_data.set('HAVE_STRCHRNUL', cc.has_function('strchrnul'))
1542config_host_data.set('HAVE_SYSTEM_FUNCTION', cc.has_function('system', prefix: '#include <stdlib.h>'))
1543if rdma.found()
1544  config_host_data.set('HAVE_IBV_ADVISE_MR',
1545                       cc.has_function('ibv_advise_mr',
1546                                       args: config_host['RDMA_LIBS'].split(),
1547                                       prefix: '#include <infiniband/verbs.h>'))
1548endif
1549
1550# has_header_symbol
1551config_host_data.set('CONFIG_BYTESWAP_H',
1552                     cc.has_header_symbol('byteswap.h', 'bswap_32'))
1553config_host_data.set('CONFIG_EPOLL_CREATE1',
1554                     cc.has_header_symbol('sys/epoll.h', 'epoll_create1'))
1555config_host_data.set('CONFIG_HAS_ENVIRON',
1556                     cc.has_header_symbol('unistd.h', 'environ', prefix: gnu_source_prefix))
1557config_host_data.set('CONFIG_FALLOCATE_PUNCH_HOLE',
1558                     cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_PUNCH_HOLE') and
1559                     cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_KEEP_SIZE'))
1560config_host_data.set('CONFIG_FALLOCATE_ZERO_RANGE',
1561                     cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_ZERO_RANGE'))
1562config_host_data.set('CONFIG_FIEMAP',
1563                     cc.has_header('linux/fiemap.h') and
1564                     cc.has_header_symbol('linux/fs.h', 'FS_IOC_FIEMAP'))
1565config_host_data.set('CONFIG_GETRANDOM',
1566                     cc.has_function('getrandom') and
1567                     cc.has_header_symbol('sys/random.h', 'GRND_NONBLOCK'))
1568config_host_data.set('CONFIG_INOTIFY',
1569                     cc.has_header_symbol('sys/inotify.h', 'inotify_init'))
1570config_host_data.set('CONFIG_INOTIFY1',
1571                     cc.has_header_symbol('sys/inotify.h', 'inotify_init1'))
1572config_host_data.set('CONFIG_MACHINE_BSWAP_H',
1573                     cc.has_header_symbol('machine/bswap.h', 'bswap32',
1574                                          prefix: '''#include <sys/endian.h>
1575                                                     #include <sys/types.h>'''))
1576config_host_data.set('CONFIG_PRCTL_PR_SET_TIMERSLACK',
1577                     cc.has_header_symbol('sys/prctl.h', 'PR_SET_TIMERSLACK'))
1578config_host_data.set('CONFIG_RTNETLINK',
1579                     cc.has_header_symbol('linux/rtnetlink.h', 'IFLA_PROTO_DOWN'))
1580config_host_data.set('CONFIG_SYSMACROS',
1581                     cc.has_header_symbol('sys/sysmacros.h', 'makedev'))
1582config_host_data.set('HAVE_OPTRESET',
1583                     cc.has_header_symbol('getopt.h', 'optreset'))
1584config_host_data.set('HAVE_IPPROTO_MPTCP',
1585                     cc.has_header_symbol('netinet/in.h', 'IPPROTO_MPTCP'))
1586
1587# has_member
1588config_host_data.set('HAVE_SIGEV_NOTIFY_THREAD_ID',
1589                     cc.has_member('struct sigevent', 'sigev_notify_thread_id',
1590                                   prefix: '#include <signal.h>'))
1591config_host_data.set('HAVE_STRUCT_STAT_ST_ATIM',
1592                     cc.has_member('struct stat', 'st_atim',
1593                                   prefix: '#include <sys/stat.h>'))
1594
1595# has_type
1596config_host_data.set('CONFIG_IOVEC',
1597                     cc.has_type('struct iovec',
1598                                 prefix: '#include <sys/uio.h>'))
1599config_host_data.set('HAVE_UTMPX',
1600                     cc.has_type('struct utmpx',
1601                                 prefix: '#include <utmpx.h>'))
1602
1603config_host_data.set('CONFIG_EVENTFD', cc.links('''
1604  #include <sys/eventfd.h>
1605  int main(void) { return eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); }'''))
1606config_host_data.set('CONFIG_FDATASYNC', cc.links(gnu_source_prefix + '''
1607  #include <unistd.h>
1608  int main(void) {
1609  #if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
1610  return fdatasync(0);
1611  #else
1612  #error Not supported
1613  #endif
1614  }'''))
1615config_host_data.set('CONFIG_MADVISE', cc.links(gnu_source_prefix + '''
1616  #include <sys/types.h>
1617  #include <sys/mman.h>
1618  #include <stddef.h>
1619  int main(void) { return madvise(NULL, 0, MADV_DONTNEED); }'''))
1620config_host_data.set('CONFIG_MEMFD', cc.links(gnu_source_prefix + '''
1621  #include <sys/mman.h>
1622  int main(void) { return memfd_create("foo", MFD_ALLOW_SEALING); }'''))
1623config_host_data.set('CONFIG_OPEN_BY_HANDLE', cc.links(gnu_source_prefix + '''
1624  #include <fcntl.h>
1625  #if !defined(AT_EMPTY_PATH)
1626  # error missing definition
1627  #else
1628  int main(void) { struct file_handle fh; return open_by_handle_at(0, &fh, 0); }
1629  #endif'''))
1630config_host_data.set('CONFIG_PIPE2', cc.links(gnu_source_prefix + '''
1631  #include <unistd.h>
1632  #include <fcntl.h>
1633
1634  int main(void)
1635  {
1636      int pipefd[2];
1637      return pipe2(pipefd, O_CLOEXEC);
1638  }'''))
1639config_host_data.set('CONFIG_POSIX_MADVISE', cc.links(gnu_source_prefix + '''
1640  #include <sys/mman.h>
1641  #include <stddef.h>
1642  int main(void) { return posix_madvise(NULL, 0, POSIX_MADV_DONTNEED); }'''))
1643
1644config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_W_TID', cc.links(gnu_source_prefix + '''
1645  #include <pthread.h>
1646
1647  static void *f(void *p) { return NULL; }
1648  int main(void)
1649  {
1650    pthread_t thread;
1651    pthread_create(&thread, 0, f, 0);
1652    pthread_setname_np(thread, "QEMU");
1653    return 0;
1654  }''', dependencies: threads))
1655config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_WO_TID', cc.links(gnu_source_prefix + '''
1656  #include <pthread.h>
1657
1658  static void *f(void *p) { pthread_setname_np("QEMU"); return NULL; }
1659  int main(void)
1660  {
1661    pthread_t thread;
1662    pthread_create(&thread, 0, f, 0);
1663    return 0;
1664  }''', dependencies: threads))
1665
1666config_host_data.set('CONFIG_SIGNALFD', cc.links(gnu_source_prefix + '''
1667  #include <sys/signalfd.h>
1668  #include <stddef.h>
1669  int main(void) { return signalfd(-1, NULL, SFD_CLOEXEC); }'''))
1670config_host_data.set('CONFIG_SPLICE', cc.links(gnu_source_prefix + '''
1671  #include <unistd.h>
1672  #include <fcntl.h>
1673  #include <limits.h>
1674
1675  int main(void)
1676  {
1677    int len, fd = 0;
1678    len = tee(STDIN_FILENO, STDOUT_FILENO, INT_MAX, SPLICE_F_NONBLOCK);
1679    splice(STDIN_FILENO, NULL, fd, NULL, len, SPLICE_F_MOVE);
1680    return 0;
1681  }'''))
1682
1683config_host_data.set('HAVE_MLOCKALL', cc.links(gnu_source_prefix + '''
1684  #include <sys/mman.h>
1685  int main(int argc, char *argv[]) {
1686    return mlockall(MCL_FUTURE);
1687  }'''))
1688
1689have_l2tpv3 = false
1690if not get_option('l2tpv3').disabled() and have_system
1691  have_l2tpv3 = cc.has_type('struct mmsghdr',
1692    prefix: gnu_source_prefix + '''
1693      #include <sys/socket.h>
1694      #include <linux/ip.h>''')
1695endif
1696config_host_data.set('CONFIG_L2TPV3', have_l2tpv3)
1697
1698have_netmap = false
1699if not get_option('netmap').disabled() and have_system
1700  have_netmap = cc.compiles('''
1701    #include <inttypes.h>
1702    #include <net/if.h>
1703    #include <net/netmap.h>
1704    #include <net/netmap_user.h>
1705    #if (NETMAP_API < 11) || (NETMAP_API > 15)
1706    #error
1707    #endif
1708    int main(void) { return 0; }''')
1709  if not have_netmap and get_option('netmap').enabled()
1710    error('Netmap headers not available')
1711  endif
1712endif
1713config_host_data.set('CONFIG_NETMAP', have_netmap)
1714
1715# Work around a system header bug with some kernel/XFS header
1716# versions where they both try to define 'struct fsxattr':
1717# xfs headers will not try to redefine structs from linux headers
1718# if this macro is set.
1719config_host_data.set('HAVE_FSXATTR', cc.links('''
1720  #include <linux/fs.h>
1721  struct fsxattr foo;
1722  int main(void) {
1723    return 0;
1724  }'''))
1725
1726# Some versions of Mac OS X incorrectly define SIZE_MAX
1727config_host_data.set('HAVE_BROKEN_SIZE_MAX', not cc.compiles('''
1728    #include <stdint.h>
1729    #include <stdio.h>
1730    int main(int argc, char *argv[]) {
1731        return printf("%zu", SIZE_MAX);
1732    }''', args: ['-Werror']))
1733
1734# See if 64-bit atomic operations are supported.
1735# Note that without __atomic builtins, we can only
1736# assume atomic loads/stores max at pointer size.
1737config_host_data.set('CONFIG_ATOMIC64', cc.links('''
1738  #include <stdint.h>
1739  int main(void)
1740  {
1741    uint64_t x = 0, y = 0;
1742    y = __atomic_load_n(&x, __ATOMIC_RELAXED);
1743    __atomic_store_n(&x, y, __ATOMIC_RELAXED);
1744    __atomic_compare_exchange_n(&x, &y, x, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
1745    __atomic_exchange_n(&x, y, __ATOMIC_RELAXED);
1746    __atomic_fetch_add(&x, y, __ATOMIC_RELAXED);
1747    return 0;
1748  }'''))
1749
1750config_host_data.set('CONFIG_GETAUXVAL', cc.links(gnu_source_prefix + '''
1751  #include <sys/auxv.h>
1752  int main(void) {
1753    return getauxval(AT_HWCAP) == 0;
1754  }'''))
1755
1756config_host_data.set('CONFIG_AF_VSOCK', cc.compiles(gnu_source_prefix + '''
1757  #include <errno.h>
1758  #include <sys/types.h>
1759  #include <sys/socket.h>
1760  #if !defined(AF_VSOCK)
1761  # error missing AF_VSOCK flag
1762  #endif
1763  #include <linux/vm_sockets.h>
1764  int main(void) {
1765    int sock, ret;
1766    struct sockaddr_vm svm;
1767    socklen_t len = sizeof(svm);
1768    sock = socket(AF_VSOCK, SOCK_STREAM, 0);
1769    ret = getpeername(sock, (struct sockaddr *)&svm, &len);
1770    if ((ret == -1) && (errno == ENOTCONN)) {
1771        return 0;
1772    }
1773    return -1;
1774  }'''))
1775
1776ignored = ['CONFIG_QEMU_INTERP_PREFIX', # actually per-target
1777    'HAVE_GDB_BIN']
1778arrays = ['CONFIG_BDRV_RW_WHITELIST', 'CONFIG_BDRV_RO_WHITELIST']
1779strings = ['CONFIG_IASL']
1780foreach k, v: config_host
1781  if ignored.contains(k)
1782    # do nothing
1783  elif arrays.contains(k)
1784    if v != ''
1785      v = '"' + '", "'.join(v.split()) + '", '
1786    endif
1787    config_host_data.set(k, v)
1788  elif strings.contains(k)
1789    config_host_data.set_quoted(k, v)
1790  elif k.startswith('CONFIG_')
1791    config_host_data.set(k, v == 'y' ? 1 : v)
1792  endif
1793endforeach
1794
1795########################
1796# Target configuration #
1797########################
1798
1799minikconf = find_program('scripts/minikconf.py')
1800config_all = {}
1801config_all_devices = {}
1802config_all_disas = {}
1803config_devices_mak_list = []
1804config_devices_h = {}
1805config_target_h = {}
1806config_target_mak = {}
1807
1808disassemblers = {
1809  'alpha' : ['CONFIG_ALPHA_DIS'],
1810  'arm' : ['CONFIG_ARM_DIS'],
1811  'avr' : ['CONFIG_AVR_DIS'],
1812  'cris' : ['CONFIG_CRIS_DIS'],
1813  'hexagon' : ['CONFIG_HEXAGON_DIS'],
1814  'hppa' : ['CONFIG_HPPA_DIS'],
1815  'i386' : ['CONFIG_I386_DIS'],
1816  'x86_64' : ['CONFIG_I386_DIS'],
1817  'm68k' : ['CONFIG_M68K_DIS'],
1818  'microblaze' : ['CONFIG_MICROBLAZE_DIS'],
1819  'mips' : ['CONFIG_MIPS_DIS'],
1820  'nios2' : ['CONFIG_NIOS2_DIS'],
1821  'or1k' : ['CONFIG_OPENRISC_DIS'],
1822  'ppc' : ['CONFIG_PPC_DIS'],
1823  'riscv' : ['CONFIG_RISCV_DIS'],
1824  'rx' : ['CONFIG_RX_DIS'],
1825  's390' : ['CONFIG_S390_DIS'],
1826  'sh4' : ['CONFIG_SH4_DIS'],
1827  'sparc' : ['CONFIG_SPARC_DIS'],
1828  'xtensa' : ['CONFIG_XTENSA_DIS'],
1829}
1830if link_language == 'cpp'
1831  disassemblers += {
1832    'aarch64' : [ 'CONFIG_ARM_A64_DIS'],
1833    'arm' : [ 'CONFIG_ARM_DIS', 'CONFIG_ARM_A64_DIS'],
1834    'mips' : [ 'CONFIG_MIPS_DIS', 'CONFIG_NANOMIPS_DIS'],
1835  }
1836endif
1837
1838have_ivshmem = config_host_data.get('CONFIG_EVENTFD')
1839host_kconfig = \
1840  (get_option('fuzzing') ? ['CONFIG_FUZZ=y'] : []) + \
1841  ('CONFIG_TPM' in config_host ? ['CONFIG_TPM=y'] : []) + \
1842  (spice.found() ? ['CONFIG_SPICE=y'] : []) + \
1843  (have_ivshmem ? ['CONFIG_IVSHMEM=y'] : []) + \
1844  ('CONFIG_OPENGL' in config_host ? ['CONFIG_OPENGL=y'] : []) + \
1845  (x11.found() ? ['CONFIG_X11=y'] : []) + \
1846  ('CONFIG_VHOST_USER' in config_host ? ['CONFIG_VHOST_USER=y'] : []) + \
1847  ('CONFIG_VHOST_VDPA' in config_host ? ['CONFIG_VHOST_VDPA=y'] : []) + \
1848  ('CONFIG_VHOST_KERNEL' in config_host ? ['CONFIG_VHOST_KERNEL=y'] : []) + \
1849  (have_virtfs ? ['CONFIG_VIRTFS=y'] : []) + \
1850  ('CONFIG_LINUX' in config_host ? ['CONFIG_LINUX=y'] : []) + \
1851  ('CONFIG_PVRDMA' in config_host ? ['CONFIG_PVRDMA=y'] : []) + \
1852  (multiprocess_allowed ? ['CONFIG_MULTIPROCESS_ALLOWED=y'] : [])
1853
1854ignored = [ 'TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_ARCH' ]
1855
1856default_targets = 'CONFIG_DEFAULT_TARGETS' in config_host
1857actual_target_dirs = []
1858fdt_required = []
1859foreach target : target_dirs
1860  config_target = { 'TARGET_NAME': target.split('-')[0] }
1861  if target.endswith('linux-user')
1862    if targetos != 'linux'
1863      if default_targets
1864        continue
1865      endif
1866      error('Target @0@ is only available on a Linux host'.format(target))
1867    endif
1868    config_target += { 'CONFIG_LINUX_USER': 'y' }
1869  elif target.endswith('bsd-user')
1870    if 'CONFIG_BSD' not in config_host
1871      if default_targets
1872        continue
1873      endif
1874      error('Target @0@ is only available on a BSD host'.format(target))
1875    endif
1876    config_target += { 'CONFIG_BSD_USER': 'y' }
1877  elif target.endswith('softmmu')
1878    config_target += { 'CONFIG_SOFTMMU': 'y' }
1879  endif
1880  if target.endswith('-user')
1881    config_target += {
1882      'CONFIG_USER_ONLY': 'y',
1883      'CONFIG_QEMU_INTERP_PREFIX':
1884        config_host['CONFIG_QEMU_INTERP_PREFIX'].format(config_target['TARGET_NAME'])
1885    }
1886  endif
1887
1888  accel_kconfig = []
1889  foreach sym: accelerators
1890    if sym == 'CONFIG_TCG' or target in accelerator_targets.get(sym, [])
1891      config_target += { sym: 'y' }
1892      config_all += { sym: 'y' }
1893      if sym == 'CONFIG_TCG' and tcg_arch == 'tci'
1894        config_target += { 'CONFIG_TCG_INTERPRETER': 'y' }
1895      elif sym == 'CONFIG_XEN' and have_xen_pci_passthrough
1896        config_target += { 'CONFIG_XEN_PCI_PASSTHROUGH': 'y' }
1897      endif
1898      if target in modular_tcg
1899        config_target += { 'CONFIG_TCG_MODULAR': 'y' }
1900      else
1901        config_target += { 'CONFIG_TCG_BUILTIN': 'y' }
1902      endif
1903      accel_kconfig += [ sym + '=y' ]
1904    endif
1905  endforeach
1906  if accel_kconfig.length() == 0
1907    if default_targets
1908      continue
1909    endif
1910    error('No accelerator available for target @0@'.format(target))
1911  endif
1912
1913  actual_target_dirs += target
1914  config_target += keyval.load('configs/targets' / target + '.mak')
1915  config_target += { 'TARGET_' + config_target['TARGET_ARCH'].to_upper(): 'y' }
1916
1917  if 'TARGET_NEED_FDT' in config_target
1918    fdt_required += target
1919  endif
1920
1921  # Add default keys
1922  if 'TARGET_BASE_ARCH' not in config_target
1923    config_target += {'TARGET_BASE_ARCH': config_target['TARGET_ARCH']}
1924  endif
1925  if 'TARGET_ABI_DIR' not in config_target
1926    config_target += {'TARGET_ABI_DIR': config_target['TARGET_ARCH']}
1927  endif
1928
1929  foreach k, v: disassemblers
1930    if host_arch.startswith(k) or config_target['TARGET_BASE_ARCH'].startswith(k)
1931      foreach sym: v
1932        config_target += { sym: 'y' }
1933        config_all_disas += { sym: 'y' }
1934      endforeach
1935    endif
1936  endforeach
1937
1938  config_target_data = configuration_data()
1939  foreach k, v: config_target
1940    if not k.startswith('TARGET_') and not k.startswith('CONFIG_')
1941      # do nothing
1942    elif ignored.contains(k)
1943      # do nothing
1944    elif k == 'TARGET_BASE_ARCH'
1945      # Note that TARGET_BASE_ARCH ends up in config-target.h but it is
1946      # not used to select files from sourcesets.
1947      config_target_data.set('TARGET_' + v.to_upper(), 1)
1948    elif k == 'TARGET_NAME' or k == 'CONFIG_QEMU_INTERP_PREFIX'
1949      config_target_data.set_quoted(k, v)
1950    elif v == 'y'
1951      config_target_data.set(k, 1)
1952    else
1953      config_target_data.set(k, v)
1954    endif
1955  endforeach
1956  config_target_data.set('QEMU_ARCH',
1957                         'QEMU_ARCH_' + config_target['TARGET_BASE_ARCH'].to_upper())
1958  config_target_h += {target: configure_file(output: target + '-config-target.h',
1959                                               configuration: config_target_data)}
1960
1961  if target.endswith('-softmmu')
1962    config_input = meson.get_external_property(target, 'default')
1963    config_devices_mak = target + '-config-devices.mak'
1964    config_devices_mak = configure_file(
1965      input: ['configs/devices' / target / config_input + '.mak', 'Kconfig'],
1966      output: config_devices_mak,
1967      depfile: config_devices_mak + '.d',
1968      capture: true,
1969      command: [minikconf,
1970                get_option('default_devices') ? '--defconfig' : '--allnoconfig',
1971                config_devices_mak, '@DEPFILE@', '@INPUT@',
1972                host_kconfig, accel_kconfig,
1973                'CONFIG_' + config_target['TARGET_ARCH'].to_upper() + '=y'])
1974
1975    config_devices_data = configuration_data()
1976    config_devices = keyval.load(config_devices_mak)
1977    foreach k, v: config_devices
1978      config_devices_data.set(k, 1)
1979    endforeach
1980    config_devices_mak_list += config_devices_mak
1981    config_devices_h += {target: configure_file(output: target + '-config-devices.h',
1982                                                configuration: config_devices_data)}
1983    config_target += config_devices
1984    config_all_devices += config_devices
1985  endif
1986  config_target_mak += {target: config_target}
1987endforeach
1988target_dirs = actual_target_dirs
1989
1990# This configuration is used to build files that are shared by
1991# multiple binaries, and then extracted out of the "common"
1992# static_library target.
1993#
1994# We do not use all_sources()/all_dependencies(), because it would
1995# build literally all source files, including devices only used by
1996# targets that are not built for this compilation.  The CONFIG_ALL
1997# pseudo symbol replaces it.
1998
1999config_all += config_all_devices
2000config_all += config_host
2001config_all += config_all_disas
2002config_all += {
2003  'CONFIG_XEN': config_host.has_key('CONFIG_XEN_BACKEND'),
2004  'CONFIG_SOFTMMU': have_system,
2005  'CONFIG_USER_ONLY': have_user,
2006  'CONFIG_ALL': true,
2007}
2008
2009##############
2010# Submodules #
2011##############
2012
2013capstone = not_found
2014capstone_opt = get_option('capstone')
2015if capstone_opt in ['enabled', 'auto', 'system']
2016  have_internal = fs.exists(meson.current_source_dir() / 'capstone/Makefile')
2017  capstone = dependency('capstone', version: '>=4.0',
2018                        kwargs: static_kwargs, method: 'pkg-config',
2019                        required: capstone_opt == 'system' or
2020                                  capstone_opt == 'enabled' and not have_internal)
2021
2022  # Some versions of capstone have broken pkg-config file
2023  # that reports a wrong -I path, causing the #include to
2024  # fail later. If the system has such a broken version
2025  # do not use it.
2026  if capstone.found() and not cc.compiles('#include <capstone.h>',
2027                                          dependencies: [capstone])
2028    capstone = not_found
2029    if capstone_opt == 'system'
2030      error('system capstone requested, it does not appear to work')
2031    endif
2032  endif
2033
2034  if capstone.found()
2035    capstone_opt = 'system'
2036  elif have_internal
2037    capstone_opt = 'internal'
2038  else
2039    capstone_opt = 'disabled'
2040  endif
2041endif
2042if capstone_opt == 'internal'
2043  capstone_data = configuration_data()
2044  capstone_data.set('CAPSTONE_USE_SYS_DYN_MEM', '1')
2045
2046  capstone_files = files(
2047    'capstone/cs.c',
2048    'capstone/MCInst.c',
2049    'capstone/MCInstrDesc.c',
2050    'capstone/MCRegisterInfo.c',
2051    'capstone/SStream.c',
2052    'capstone/utils.c'
2053  )
2054
2055  if 'CONFIG_ARM_DIS' in config_all_disas
2056    capstone_data.set('CAPSTONE_HAS_ARM', '1')
2057    capstone_files += files(
2058      'capstone/arch/ARM/ARMDisassembler.c',
2059      'capstone/arch/ARM/ARMInstPrinter.c',
2060      'capstone/arch/ARM/ARMMapping.c',
2061      'capstone/arch/ARM/ARMModule.c'
2062    )
2063  endif
2064
2065  # FIXME: This config entry currently depends on a c++ compiler.
2066  # Which is needed for building libvixl, but not for capstone.
2067  if 'CONFIG_ARM_A64_DIS' in config_all_disas
2068    capstone_data.set('CAPSTONE_HAS_ARM64', '1')
2069    capstone_files += files(
2070      'capstone/arch/AArch64/AArch64BaseInfo.c',
2071      'capstone/arch/AArch64/AArch64Disassembler.c',
2072      'capstone/arch/AArch64/AArch64InstPrinter.c',
2073      'capstone/arch/AArch64/AArch64Mapping.c',
2074      'capstone/arch/AArch64/AArch64Module.c'
2075    )
2076  endif
2077
2078  if 'CONFIG_PPC_DIS' in config_all_disas
2079    capstone_data.set('CAPSTONE_HAS_POWERPC', '1')
2080    capstone_files += files(
2081      'capstone/arch/PowerPC/PPCDisassembler.c',
2082      'capstone/arch/PowerPC/PPCInstPrinter.c',
2083      'capstone/arch/PowerPC/PPCMapping.c',
2084      'capstone/arch/PowerPC/PPCModule.c'
2085    )
2086  endif
2087
2088  if 'CONFIG_S390_DIS' in config_all_disas
2089    capstone_data.set('CAPSTONE_HAS_SYSZ', '1')
2090    capstone_files += files(
2091      'capstone/arch/SystemZ/SystemZDisassembler.c',
2092      'capstone/arch/SystemZ/SystemZInstPrinter.c',
2093      'capstone/arch/SystemZ/SystemZMapping.c',
2094      'capstone/arch/SystemZ/SystemZModule.c',
2095      'capstone/arch/SystemZ/SystemZMCTargetDesc.c'
2096    )
2097  endif
2098
2099  if 'CONFIG_I386_DIS' in config_all_disas
2100    capstone_data.set('CAPSTONE_HAS_X86', 1)
2101    capstone_files += files(
2102      'capstone/arch/X86/X86Disassembler.c',
2103      'capstone/arch/X86/X86DisassemblerDecoder.c',
2104      'capstone/arch/X86/X86ATTInstPrinter.c',
2105      'capstone/arch/X86/X86IntelInstPrinter.c',
2106      'capstone/arch/X86/X86InstPrinterCommon.c',
2107      'capstone/arch/X86/X86Mapping.c',
2108      'capstone/arch/X86/X86Module.c'
2109    )
2110  endif
2111
2112  configure_file(output: 'capstone-defs.h', configuration: capstone_data)
2113
2114  capstone_cargs = [
2115    # FIXME: There does not seem to be a way to completely replace the c_args
2116    # that come from add_project_arguments() -- we can only add to them.
2117    # So: disable all warnings with a big hammer.
2118    '-Wno-error', '-w',
2119
2120    # Include all configuration defines via a header file, which will wind up
2121    # as a dependency on the object file, and thus changes here will result
2122    # in a rebuild.
2123    '-include', 'capstone-defs.h'
2124  ]
2125
2126  libcapstone = static_library('capstone',
2127                               build_by_default: false,
2128                               sources: capstone_files,
2129                               c_args: capstone_cargs,
2130                               include_directories: 'capstone/include')
2131  capstone = declare_dependency(link_with: libcapstone,
2132                                include_directories: 'capstone/include/capstone')
2133endif
2134
2135slirp = not_found
2136slirp_opt = 'disabled'
2137if have_system
2138  slirp_opt = get_option('slirp')
2139  if slirp_opt in ['enabled', 'auto', 'system']
2140    have_internal = fs.exists(meson.current_source_dir() / 'slirp/meson.build')
2141    slirp = dependency('slirp', kwargs: static_kwargs,
2142                       method: 'pkg-config',
2143                       required: slirp_opt == 'system' or
2144                                 slirp_opt == 'enabled' and not have_internal)
2145    if slirp.found()
2146      slirp_opt = 'system'
2147    elif have_internal
2148      slirp_opt = 'internal'
2149    else
2150      slirp_opt = 'disabled'
2151    endif
2152  endif
2153  if slirp_opt == 'internal'
2154    slirp_deps = []
2155    if targetos == 'windows'
2156      slirp_deps = cc.find_library('iphlpapi')
2157    elif targetos == 'darwin'
2158      slirp_deps = cc.find_library('resolv')
2159    endif
2160    slirp_conf = configuration_data()
2161    slirp_conf.set('SLIRP_MAJOR_VERSION', meson.project_version().split('.')[0])
2162    slirp_conf.set('SLIRP_MINOR_VERSION', meson.project_version().split('.')[1])
2163    slirp_conf.set('SLIRP_MICRO_VERSION', meson.project_version().split('.')[2])
2164    slirp_conf.set_quoted('SLIRP_VERSION_STRING', meson.project_version())
2165    slirp_cargs = ['-DG_LOG_DOMAIN="Slirp"']
2166    slirp_files = [
2167      'slirp/src/arp_table.c',
2168      'slirp/src/bootp.c',
2169      'slirp/src/cksum.c',
2170      'slirp/src/dhcpv6.c',
2171      'slirp/src/dnssearch.c',
2172      'slirp/src/if.c',
2173      'slirp/src/ip6_icmp.c',
2174      'slirp/src/ip6_input.c',
2175      'slirp/src/ip6_output.c',
2176      'slirp/src/ip_icmp.c',
2177      'slirp/src/ip_input.c',
2178      'slirp/src/ip_output.c',
2179      'slirp/src/mbuf.c',
2180      'slirp/src/misc.c',
2181      'slirp/src/ncsi.c',
2182      'slirp/src/ndp_table.c',
2183      'slirp/src/sbuf.c',
2184      'slirp/src/slirp.c',
2185      'slirp/src/socket.c',
2186      'slirp/src/state.c',
2187      'slirp/src/stream.c',
2188      'slirp/src/tcp_input.c',
2189      'slirp/src/tcp_output.c',
2190      'slirp/src/tcp_subr.c',
2191      'slirp/src/tcp_timer.c',
2192      'slirp/src/tftp.c',
2193      'slirp/src/udp.c',
2194      'slirp/src/udp6.c',
2195      'slirp/src/util.c',
2196      'slirp/src/version.c',
2197      'slirp/src/vmstate.c',
2198    ]
2199
2200    configure_file(
2201      input : 'slirp/src/libslirp-version.h.in',
2202      output : 'libslirp-version.h',
2203      configuration: slirp_conf)
2204
2205    slirp_inc = include_directories('slirp', 'slirp/src')
2206    libslirp = static_library('slirp',
2207                              build_by_default: false,
2208                              sources: slirp_files,
2209                              c_args: slirp_cargs,
2210                              include_directories: slirp_inc)
2211    slirp = declare_dependency(link_with: libslirp,
2212                               dependencies: slirp_deps,
2213                               include_directories: slirp_inc)
2214  endif
2215endif
2216
2217# For CFI, we need to compile slirp as a static library together with qemu.
2218# This is because we register slirp functions as callbacks for QEMU Timers.
2219# When using a system-wide shared libslirp, the type information for the
2220# callback is missing and the timer call produces a false positive with CFI.
2221#
2222# Now that slirp_opt has been defined, check if the selected slirp is compatible
2223# with control-flow integrity.
2224if get_option('cfi') and slirp_opt == 'system'
2225  error('Control-Flow Integrity is not compatible with system-wide slirp.' \
2226         + ' Please configure with --enable-slirp=git')
2227endif
2228
2229fdt = not_found
2230fdt_opt = get_option('fdt')
2231if have_system
2232  if fdt_opt in ['enabled', 'auto', 'system']
2233    have_internal = fs.exists(meson.current_source_dir() / 'dtc/libfdt/Makefile.libfdt')
2234    fdt = cc.find_library('fdt', kwargs: static_kwargs,
2235                          required: fdt_opt == 'system' or
2236                                    fdt_opt == 'enabled' and not have_internal)
2237    if fdt.found() and cc.links('''
2238       #include <libfdt.h>
2239       #include <libfdt_env.h>
2240       int main(void) { fdt_check_full(NULL, 0); return 0; }''',
2241         dependencies: fdt)
2242      fdt_opt = 'system'
2243    elif fdt_opt == 'system'
2244       error('system libfdt requested, but it is too old (1.5.1 or newer required)')
2245    elif have_internal
2246      fdt_opt = 'internal'
2247    else
2248      fdt_opt = 'disabled'
2249      fdt = not_found
2250    endif
2251  endif
2252  if fdt_opt == 'internal'
2253    fdt_files = files(
2254      'dtc/libfdt/fdt.c',
2255      'dtc/libfdt/fdt_ro.c',
2256      'dtc/libfdt/fdt_wip.c',
2257      'dtc/libfdt/fdt_sw.c',
2258      'dtc/libfdt/fdt_rw.c',
2259      'dtc/libfdt/fdt_strerror.c',
2260      'dtc/libfdt/fdt_empty_tree.c',
2261      'dtc/libfdt/fdt_addresses.c',
2262      'dtc/libfdt/fdt_overlay.c',
2263      'dtc/libfdt/fdt_check.c',
2264    )
2265
2266    fdt_inc = include_directories('dtc/libfdt')
2267    libfdt = static_library('fdt',
2268                            build_by_default: false,
2269                            sources: fdt_files,
2270                            include_directories: fdt_inc)
2271    fdt = declare_dependency(link_with: libfdt,
2272                             include_directories: fdt_inc)
2273  endif
2274endif
2275if not fdt.found() and fdt_required.length() > 0
2276  error('fdt not available but required by targets ' + ', '.join(fdt_required))
2277endif
2278
2279config_host_data.set('CONFIG_CAPSTONE', capstone.found())
2280config_host_data.set('CONFIG_FDT', fdt.found())
2281config_host_data.set('CONFIG_SLIRP', slirp.found())
2282
2283#####################
2284# Generated sources #
2285#####################
2286
2287genh += configure_file(output: 'config-host.h', configuration: config_host_data)
2288
2289hxtool = find_program('scripts/hxtool')
2290shaderinclude = find_program('scripts/shaderinclude.pl')
2291qapi_gen = find_program('scripts/qapi-gen.py')
2292qapi_gen_depends = [ meson.current_source_dir() / 'scripts/qapi/__init__.py',
2293                     meson.current_source_dir() / 'scripts/qapi/commands.py',
2294                     meson.current_source_dir() / 'scripts/qapi/common.py',
2295                     meson.current_source_dir() / 'scripts/qapi/error.py',
2296                     meson.current_source_dir() / 'scripts/qapi/events.py',
2297                     meson.current_source_dir() / 'scripts/qapi/expr.py',
2298                     meson.current_source_dir() / 'scripts/qapi/gen.py',
2299                     meson.current_source_dir() / 'scripts/qapi/introspect.py',
2300                     meson.current_source_dir() / 'scripts/qapi/parser.py',
2301                     meson.current_source_dir() / 'scripts/qapi/schema.py',
2302                     meson.current_source_dir() / 'scripts/qapi/source.py',
2303                     meson.current_source_dir() / 'scripts/qapi/types.py',
2304                     meson.current_source_dir() / 'scripts/qapi/visit.py',
2305                     meson.current_source_dir() / 'scripts/qapi/common.py',
2306                     meson.current_source_dir() / 'scripts/qapi-gen.py'
2307]
2308
2309tracetool = [
2310  python, files('scripts/tracetool.py'),
2311   '--backend=' + ','.join(get_option('trace_backends'))
2312]
2313tracetool_depends = files(
2314  'scripts/tracetool/backend/log.py',
2315  'scripts/tracetool/backend/__init__.py',
2316  'scripts/tracetool/backend/dtrace.py',
2317  'scripts/tracetool/backend/ftrace.py',
2318  'scripts/tracetool/backend/simple.py',
2319  'scripts/tracetool/backend/syslog.py',
2320  'scripts/tracetool/backend/ust.py',
2321  'scripts/tracetool/format/tcg_h.py',
2322  'scripts/tracetool/format/ust_events_c.py',
2323  'scripts/tracetool/format/ust_events_h.py',
2324  'scripts/tracetool/format/__init__.py',
2325  'scripts/tracetool/format/d.py',
2326  'scripts/tracetool/format/tcg_helper_c.py',
2327  'scripts/tracetool/format/simpletrace_stap.py',
2328  'scripts/tracetool/format/c.py',
2329  'scripts/tracetool/format/h.py',
2330  'scripts/tracetool/format/tcg_helper_h.py',
2331  'scripts/tracetool/format/log_stap.py',
2332  'scripts/tracetool/format/stap.py',
2333  'scripts/tracetool/format/tcg_helper_wrapper_h.py',
2334  'scripts/tracetool/__init__.py',
2335  'scripts/tracetool/transform.py',
2336  'scripts/tracetool/vcpu.py'
2337)
2338
2339qemu_version_cmd = [find_program('scripts/qemu-version.sh'),
2340                    meson.current_source_dir(),
2341                    config_host['PKGVERSION'], meson.project_version()]
2342qemu_version = custom_target('qemu-version.h',
2343                             output: 'qemu-version.h',
2344                             command: qemu_version_cmd,
2345                             capture: true,
2346                             build_by_default: true,
2347                             build_always_stale: true)
2348genh += qemu_version
2349
2350hxdep = []
2351hx_headers = [
2352  ['qemu-options.hx', 'qemu-options.def'],
2353  ['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
2354]
2355if have_system
2356  hx_headers += [
2357    ['hmp-commands.hx', 'hmp-commands.h'],
2358    ['hmp-commands-info.hx', 'hmp-commands-info.h'],
2359  ]
2360endif
2361foreach d : hx_headers
2362  hxdep += custom_target(d[1],
2363                input: files(d[0]),
2364                output: d[1],
2365                capture: true,
2366                build_by_default: true, # to be removed when added to a target
2367                command: [hxtool, '-h', '@INPUT0@'])
2368endforeach
2369genh += hxdep
2370
2371###################
2372# Collect sources #
2373###################
2374
2375authz_ss = ss.source_set()
2376blockdev_ss = ss.source_set()
2377block_ss = ss.source_set()
2378bsd_user_ss = ss.source_set()
2379chardev_ss = ss.source_set()
2380common_ss = ss.source_set()
2381crypto_ss = ss.source_set()
2382hwcore_ss = ss.source_set()
2383io_ss = ss.source_set()
2384linux_user_ss = ss.source_set()
2385qmp_ss = ss.source_set()
2386qom_ss = ss.source_set()
2387softmmu_ss = ss.source_set()
2388specific_fuzz_ss = ss.source_set()
2389specific_ss = ss.source_set()
2390stub_ss = ss.source_set()
2391trace_ss = ss.source_set()
2392user_ss = ss.source_set()
2393util_ss = ss.source_set()
2394
2395# accel modules
2396qtest_module_ss = ss.source_set()
2397tcg_module_ss = ss.source_set()
2398
2399modules = {}
2400target_modules = {}
2401hw_arch = {}
2402target_arch = {}
2403target_softmmu_arch = {}
2404target_user_arch = {}
2405
2406###############
2407# Trace files #
2408###############
2409
2410# TODO: add each directory to the subdirs from its own meson.build, once
2411# we have those
2412trace_events_subdirs = [
2413  'crypto',
2414  'qapi',
2415  'qom',
2416  'monitor',
2417  'util',
2418]
2419if have_user
2420  trace_events_subdirs += [ 'linux-user' ]
2421endif
2422if have_block
2423  trace_events_subdirs += [
2424    'authz',
2425    'block',
2426    'io',
2427    'nbd',
2428    'scsi',
2429  ]
2430endif
2431if have_system
2432  trace_events_subdirs += [
2433    'accel/kvm',
2434    'audio',
2435    'backends',
2436    'backends/tpm',
2437    'chardev',
2438    'ebpf',
2439    'hw/9pfs',
2440    'hw/acpi',
2441    'hw/adc',
2442    'hw/alpha',
2443    'hw/arm',
2444    'hw/audio',
2445    'hw/block',
2446    'hw/block/dataplane',
2447    'hw/char',
2448    'hw/display',
2449    'hw/dma',
2450    'hw/hppa',
2451    'hw/hyperv',
2452    'hw/i2c',
2453    'hw/i386',
2454    'hw/i386/xen',
2455    'hw/ide',
2456    'hw/input',
2457    'hw/intc',
2458    'hw/isa',
2459    'hw/mem',
2460    'hw/mips',
2461    'hw/misc',
2462    'hw/misc/macio',
2463    'hw/net',
2464    'hw/net/can',
2465    'hw/nubus',
2466    'hw/nvme',
2467    'hw/nvram',
2468    'hw/pci',
2469    'hw/pci-host',
2470    'hw/ppc',
2471    'hw/rdma',
2472    'hw/rdma/vmw',
2473    'hw/rtc',
2474    'hw/s390x',
2475    'hw/scsi',
2476    'hw/sd',
2477    'hw/sh4',
2478    'hw/sparc',
2479    'hw/sparc64',
2480    'hw/ssi',
2481    'hw/timer',
2482    'hw/tpm',
2483    'hw/usb',
2484    'hw/vfio',
2485    'hw/virtio',
2486    'hw/watchdog',
2487    'hw/xen',
2488    'hw/gpio',
2489    'migration',
2490    'net',
2491    'softmmu',
2492    'ui',
2493    'hw/remote',
2494  ]
2495endif
2496if have_system or have_user
2497  trace_events_subdirs += [
2498    'accel/tcg',
2499    'hw/core',
2500    'target/arm',
2501    'target/arm/hvf',
2502    'target/hppa',
2503    'target/i386',
2504    'target/i386/kvm',
2505    'target/mips/tcg',
2506    'target/ppc',
2507    'target/riscv',
2508    'target/s390x',
2509    'target/s390x/kvm',
2510    'target/sparc',
2511  ]
2512endif
2513
2514vhost_user = not_found
2515if 'CONFIG_VHOST_USER' in config_host
2516  libvhost_user = subproject('libvhost-user')
2517  vhost_user = libvhost_user.get_variable('vhost_user_dep')
2518endif
2519
2520subdir('qapi')
2521subdir('qobject')
2522subdir('stubs')
2523subdir('trace')
2524subdir('util')
2525subdir('qom')
2526subdir('authz')
2527subdir('crypto')
2528subdir('ui')
2529
2530
2531if enable_modules
2532  libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
2533  modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
2534endif
2535
2536stub_ss = stub_ss.apply(config_all, strict: false)
2537
2538util_ss.add_all(trace_ss)
2539util_ss = util_ss.apply(config_all, strict: false)
2540libqemuutil = static_library('qemuutil',
2541                             sources: util_ss.sources() + stub_ss.sources() + genh,
2542                             dependencies: [util_ss.dependencies(), libm, threads, glib, socket, malloc, pixman])
2543qemuutil = declare_dependency(link_with: libqemuutil,
2544                              sources: genh + version_res)
2545
2546if have_system or have_user
2547  decodetree = generator(find_program('scripts/decodetree.py'),
2548                         output: 'decode-@BASENAME@.c.inc',
2549                         arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
2550  subdir('libdecnumber')
2551  subdir('target')
2552endif
2553
2554subdir('audio')
2555subdir('io')
2556subdir('chardev')
2557subdir('fsdev')
2558subdir('dump')
2559
2560if have_block
2561  block_ss.add(files(
2562    'block.c',
2563    'blockjob.c',
2564    'job.c',
2565    'qemu-io-cmds.c',
2566  ))
2567  block_ss.add(when: 'CONFIG_REPLICATION', if_true: files('replication.c'))
2568
2569  subdir('nbd')
2570  subdir('scsi')
2571  subdir('block')
2572
2573  blockdev_ss.add(files(
2574    'blockdev.c',
2575    'blockdev-nbd.c',
2576    'iothread.c',
2577    'job-qmp.c',
2578  ), gnutls)
2579
2580  # os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
2581  # os-win32.c does not
2582  blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c'))
2583  softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')])
2584endif
2585
2586common_ss.add(files('cpus-common.c'))
2587
2588subdir('softmmu')
2589
2590common_ss.add(capstone)
2591specific_ss.add(files('cpu.c', 'disas.c', 'gdbstub.c'), capstone)
2592
2593# Work around a gcc bug/misfeature wherein constant propagation looks
2594# through an alias:
2595#   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99696
2596# to guess that a const variable is always zero.  Without lto, this is
2597# impossible, as the alias is restricted to page-vary-common.c.  Indeed,
2598# without lto, not even the alias is required -- we simply use different
2599# declarations in different compilation units.
2600pagevary = files('page-vary-common.c')
2601if get_option('b_lto')
2602  pagevary_flags = ['-fno-lto']
2603  if get_option('cfi')
2604    pagevary_flags += '-fno-sanitize=cfi-icall'
2605  endif
2606  pagevary = static_library('page-vary-common', sources: pagevary,
2607                            c_args: pagevary_flags)
2608  pagevary = declare_dependency(link_with: pagevary)
2609endif
2610common_ss.add(pagevary)
2611specific_ss.add(files('page-vary.c'))
2612
2613subdir('backends')
2614subdir('disas')
2615subdir('migration')
2616subdir('monitor')
2617subdir('net')
2618subdir('replay')
2619subdir('semihosting')
2620subdir('hw')
2621subdir('tcg')
2622subdir('fpu')
2623subdir('accel')
2624subdir('plugins')
2625subdir('bsd-user')
2626subdir('linux-user')
2627subdir('ebpf')
2628
2629specific_ss.add_all(when: 'CONFIG_BSD_USER', if_true: bsd_user_ss)
2630
2631linux_user_ss.add(files('thunk.c'))
2632specific_ss.add_all(when: 'CONFIG_LINUX_USER', if_true: linux_user_ss)
2633
2634# needed for fuzzing binaries
2635subdir('tests/qtest/libqos')
2636subdir('tests/qtest/fuzz')
2637
2638# accel modules
2639tcg_real_module_ss = ss.source_set()
2640tcg_real_module_ss.add_all(when: 'CONFIG_TCG_MODULAR', if_true: tcg_module_ss)
2641specific_ss.add_all(when: 'CONFIG_TCG_BUILTIN', if_true: tcg_module_ss)
2642target_modules += { 'accel' : { 'qtest': qtest_module_ss,
2643                                'tcg': tcg_real_module_ss }}
2644
2645########################
2646# Library dependencies #
2647########################
2648
2649modinfo_collect = find_program('scripts/modinfo-collect.py')
2650modinfo_generate = find_program('scripts/modinfo-generate.py')
2651modinfo_files = []
2652
2653block_mods = []
2654softmmu_mods = []
2655foreach d, list : modules
2656  foreach m, module_ss : list
2657    if enable_modules and targetos != 'windows'
2658      module_ss = module_ss.apply(config_all, strict: false)
2659      sl = static_library(d + '-' + m, [genh, module_ss.sources()],
2660                          dependencies: [modulecommon, module_ss.dependencies()], pic: true)
2661      if d == 'block'
2662        block_mods += sl
2663      else
2664        softmmu_mods += sl
2665      endif
2666      if module_ss.sources() != []
2667        # FIXME: Should use sl.extract_all_objects(recursive: true) as
2668        # input. Sources can be used multiple times but objects are
2669        # unique when it comes to lookup in compile_commands.json.
2670        # Depnds on a mesion version with
2671        # https://github.com/mesonbuild/meson/pull/8900
2672        modinfo_files += custom_target(d + '-' + m + '.modinfo',
2673                                       output: d + '-' + m + '.modinfo',
2674                                       input: module_ss.sources() + genh,
2675                                       capture: true,
2676                                       command: [modinfo_collect, module_ss.sources()])
2677      endif
2678    else
2679      if d == 'block'
2680        block_ss.add_all(module_ss)
2681      else
2682        softmmu_ss.add_all(module_ss)
2683      endif
2684    endif
2685  endforeach
2686endforeach
2687
2688foreach d, list : target_modules
2689  foreach m, module_ss : list
2690    if enable_modules and targetos != 'windows'
2691      foreach target : target_dirs
2692        if target.endswith('-softmmu')
2693          config_target = config_target_mak[target]
2694          config_target += config_host
2695          target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
2696          c_args = ['-DNEED_CPU_H',
2697                    '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
2698                    '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
2699          target_module_ss = module_ss.apply(config_target, strict: false)
2700          if target_module_ss.sources() != []
2701            module_name = d + '-' + m + '-' + config_target['TARGET_NAME']
2702            sl = static_library(module_name,
2703                                [genh, target_module_ss.sources()],
2704                                dependencies: [modulecommon, target_module_ss.dependencies()],
2705                                include_directories: target_inc,
2706                                c_args: c_args,
2707                                pic: true)
2708            softmmu_mods += sl
2709            # FIXME: Should use sl.extract_all_objects(recursive: true) too.
2710            modinfo_files += custom_target(module_name + '.modinfo',
2711                                           output: module_name + '.modinfo',
2712                                           input: target_module_ss.sources() + genh,
2713                                           capture: true,
2714                                           command: [modinfo_collect, '--target', target, target_module_ss.sources()])
2715          endif
2716        endif
2717      endforeach
2718    else
2719      specific_ss.add_all(module_ss)
2720    endif
2721  endforeach
2722endforeach
2723
2724if enable_modules
2725  modinfo_src = custom_target('modinfo.c',
2726                              output: 'modinfo.c',
2727                              input: modinfo_files,
2728                              command: [modinfo_generate, '@INPUT@'],
2729                              capture: true)
2730  modinfo_lib = static_library('modinfo', modinfo_src)
2731  modinfo_dep = declare_dependency(link_whole: modinfo_lib)
2732  softmmu_ss.add(modinfo_dep)
2733endif
2734
2735nm = find_program('nm')
2736undefsym = find_program('scripts/undefsym.py')
2737block_syms = custom_target('block.syms', output: 'block.syms',
2738                             input: [libqemuutil, block_mods],
2739                             capture: true,
2740                             command: [undefsym, nm, '@INPUT@'])
2741qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
2742                             input: [libqemuutil, softmmu_mods],
2743                             capture: true,
2744                             command: [undefsym, nm, '@INPUT@'])
2745
2746qom_ss = qom_ss.apply(config_host, strict: false)
2747libqom = static_library('qom', qom_ss.sources() + genh,
2748                        dependencies: [qom_ss.dependencies()],
2749                        name_suffix: 'fa')
2750
2751qom = declare_dependency(link_whole: libqom)
2752
2753authz_ss = authz_ss.apply(config_host, strict: false)
2754libauthz = static_library('authz', authz_ss.sources() + genh,
2755                          dependencies: [authz_ss.dependencies()],
2756                          name_suffix: 'fa',
2757                          build_by_default: false)
2758
2759authz = declare_dependency(link_whole: libauthz,
2760                           dependencies: qom)
2761
2762crypto_ss = crypto_ss.apply(config_host, strict: false)
2763libcrypto = static_library('crypto', crypto_ss.sources() + genh,
2764                           dependencies: [crypto_ss.dependencies()],
2765                           name_suffix: 'fa',
2766                           build_by_default: false)
2767
2768crypto = declare_dependency(link_whole: libcrypto,
2769                            dependencies: [authz, qom])
2770
2771io_ss = io_ss.apply(config_host, strict: false)
2772libio = static_library('io', io_ss.sources() + genh,
2773                       dependencies: [io_ss.dependencies()],
2774                       link_with: libqemuutil,
2775                       name_suffix: 'fa',
2776                       build_by_default: false)
2777
2778io = declare_dependency(link_whole: libio, dependencies: [crypto, qom])
2779
2780libmigration = static_library('migration', sources: migration_files + genh,
2781                              name_suffix: 'fa',
2782                              build_by_default: false)
2783migration = declare_dependency(link_with: libmigration,
2784                               dependencies: [zlib, qom, io])
2785softmmu_ss.add(migration)
2786
2787block_ss = block_ss.apply(config_host, strict: false)
2788libblock = static_library('block', block_ss.sources() + genh,
2789                          dependencies: block_ss.dependencies(),
2790                          link_depends: block_syms,
2791                          name_suffix: 'fa',
2792                          build_by_default: false)
2793
2794block = declare_dependency(link_whole: [libblock],
2795                           link_args: '@block.syms',
2796                           dependencies: [crypto, io])
2797
2798blockdev_ss = blockdev_ss.apply(config_host, strict: false)
2799libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
2800                             dependencies: blockdev_ss.dependencies(),
2801                             name_suffix: 'fa',
2802                             build_by_default: false)
2803
2804blockdev = declare_dependency(link_whole: [libblockdev],
2805                              dependencies: [block])
2806
2807qmp_ss = qmp_ss.apply(config_host, strict: false)
2808libqmp = static_library('qmp', qmp_ss.sources() + genh,
2809                        dependencies: qmp_ss.dependencies(),
2810                        name_suffix: 'fa',
2811                        build_by_default: false)
2812
2813qmp = declare_dependency(link_whole: [libqmp])
2814
2815libchardev = static_library('chardev', chardev_ss.sources() + genh,
2816                            name_suffix: 'fa',
2817                            dependencies: [gnutls],
2818                            build_by_default: false)
2819
2820chardev = declare_dependency(link_whole: libchardev)
2821
2822hwcore_ss = hwcore_ss.apply(config_host, strict: false)
2823libhwcore = static_library('hwcore', sources: hwcore_ss.sources() + genh,
2824                           name_suffix: 'fa',
2825                           build_by_default: false)
2826hwcore = declare_dependency(link_whole: libhwcore)
2827common_ss.add(hwcore)
2828
2829###########
2830# Targets #
2831###########
2832
2833foreach m : block_mods + softmmu_mods
2834  shared_module(m.name(),
2835                name_prefix: '',
2836                link_whole: m,
2837                install: true,
2838                install_dir: qemu_moddir)
2839endforeach
2840
2841softmmu_ss.add(authz, blockdev, chardev, crypto, io, qmp)
2842common_ss.add(qom, qemuutil)
2843
2844common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss])
2845common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
2846
2847common_all = common_ss.apply(config_all, strict: false)
2848common_all = static_library('common',
2849                            build_by_default: false,
2850                            sources: common_all.sources() + genh,
2851                            implicit_include_directories: false,
2852                            dependencies: common_all.dependencies(),
2853                            name_suffix: 'fa')
2854
2855feature_to_c = find_program('scripts/feature_to_c.sh')
2856
2857emulators = {}
2858foreach target : target_dirs
2859  config_target = config_target_mak[target]
2860  target_name = config_target['TARGET_NAME']
2861  target_base_arch = config_target['TARGET_BASE_ARCH']
2862  arch_srcs = [config_target_h[target]]
2863  arch_deps = []
2864  c_args = ['-DNEED_CPU_H',
2865            '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
2866            '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
2867  link_args = emulator_link_args
2868
2869  config_target += config_host
2870  target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
2871  if targetos == 'linux'
2872    target_inc += include_directories('linux-headers', is_system: true)
2873  endif
2874  if target.endswith('-softmmu')
2875    qemu_target_name = 'qemu-system-' + target_name
2876    target_type='system'
2877    t = target_softmmu_arch[target_base_arch].apply(config_target, strict: false)
2878    arch_srcs += t.sources()
2879    arch_deps += t.dependencies()
2880
2881    hw_dir = target_name == 'sparc64' ? 'sparc64' : target_base_arch
2882    hw = hw_arch[hw_dir].apply(config_target, strict: false)
2883    arch_srcs += hw.sources()
2884    arch_deps += hw.dependencies()
2885
2886    arch_srcs += config_devices_h[target]
2887    link_args += ['@block.syms', '@qemu.syms']
2888  else
2889    abi = config_target['TARGET_ABI_DIR']
2890    target_type='user'
2891    qemu_target_name = 'qemu-' + target_name
2892    if target_base_arch in target_user_arch
2893      t = target_user_arch[target_base_arch].apply(config_target, strict: false)
2894      arch_srcs += t.sources()
2895      arch_deps += t.dependencies()
2896    endif
2897    if 'CONFIG_LINUX_USER' in config_target
2898      base_dir = 'linux-user'
2899      target_inc += include_directories('linux-user/host/' / host_arch)
2900    endif
2901    if 'CONFIG_BSD_USER' in config_target
2902      base_dir = 'bsd-user'
2903      target_inc += include_directories('bsd-user/' / targetos)
2904      dir = base_dir / abi
2905      arch_srcs += files(dir / 'target_arch_cpu.c')
2906    endif
2907    target_inc += include_directories(
2908      base_dir,
2909      base_dir / abi,
2910    )
2911    if 'CONFIG_LINUX_USER' in config_target
2912      dir = base_dir / abi
2913      arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
2914      if config_target.has_key('TARGET_SYSTBL_ABI')
2915        arch_srcs += \
2916          syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
2917                                             extra_args : config_target['TARGET_SYSTBL_ABI'])
2918      endif
2919    endif
2920  endif
2921
2922  if 'TARGET_XML_FILES' in config_target
2923    gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
2924                                output: target + '-gdbstub-xml.c',
2925                                input: files(config_target['TARGET_XML_FILES'].split()),
2926                                command: [feature_to_c, '@INPUT@'],
2927                                capture: true)
2928    arch_srcs += gdbstub_xml
2929  endif
2930
2931  t = target_arch[target_base_arch].apply(config_target, strict: false)
2932  arch_srcs += t.sources()
2933  arch_deps += t.dependencies()
2934
2935  target_common = common_ss.apply(config_target, strict: false)
2936  objects = common_all.extract_objects(target_common.sources())
2937  deps = target_common.dependencies()
2938
2939  target_specific = specific_ss.apply(config_target, strict: false)
2940  arch_srcs += target_specific.sources()
2941  arch_deps += target_specific.dependencies()
2942
2943  lib = static_library('qemu-' + target,
2944                 sources: arch_srcs + genh,
2945                 dependencies: arch_deps,
2946                 objects: objects,
2947                 include_directories: target_inc,
2948                 c_args: c_args,
2949                 build_by_default: false,
2950                 name_suffix: 'fa')
2951
2952  if target.endswith('-softmmu')
2953    execs = [{
2954      'name': 'qemu-system-' + target_name,
2955      'win_subsystem': 'console',
2956      'sources': files('softmmu/main.c'),
2957      'dependencies': []
2958    }]
2959    if targetos == 'windows' and (sdl.found() or gtk.found())
2960      execs += [{
2961        'name': 'qemu-system-' + target_name + 'w',
2962        'win_subsystem': 'windows',
2963        'sources': files('softmmu/main.c'),
2964        'dependencies': []
2965      }]
2966    endif
2967    if get_option('fuzzing')
2968      specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
2969      execs += [{
2970        'name': 'qemu-fuzz-' + target_name,
2971        'win_subsystem': 'console',
2972        'sources': specific_fuzz.sources(),
2973        'dependencies': specific_fuzz.dependencies(),
2974      }]
2975    endif
2976  else
2977    execs = [{
2978      'name': 'qemu-' + target_name,
2979      'win_subsystem': 'console',
2980      'sources': [],
2981      'dependencies': []
2982    }]
2983  endif
2984  foreach exe: execs
2985    exe_name = exe['name']
2986    if targetos == 'darwin'
2987      exe_name += '-unsigned'
2988    endif
2989
2990    emulator = executable(exe_name, exe['sources'],
2991               install: true,
2992               c_args: c_args,
2993               dependencies: arch_deps + deps + exe['dependencies'],
2994               objects: lib.extract_all_objects(recursive: true),
2995               link_language: link_language,
2996               link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
2997               link_args: link_args,
2998               win_subsystem: exe['win_subsystem'])
2999
3000    if targetos == 'darwin'
3001      icon = 'pc-bios/qemu.rsrc'
3002      build_input = [emulator, files(icon)]
3003      install_input = [
3004        get_option('bindir') / exe_name,
3005        meson.current_source_dir() / icon
3006      ]
3007      if 'CONFIG_HVF' in config_target
3008        entitlements = 'accel/hvf/entitlements.plist'
3009        build_input += files(entitlements)
3010        install_input += meson.current_source_dir() / entitlements
3011      endif
3012
3013      emulators += {exe['name'] : custom_target(exe['name'],
3014                   input: build_input,
3015                   output: exe['name'],
3016                   command: [
3017                     files('scripts/entitlement.sh'),
3018                     '@OUTPUT@',
3019                     '@INPUT@'
3020                   ])
3021      }
3022
3023      meson.add_install_script('scripts/entitlement.sh', '--install',
3024                               get_option('bindir') / exe['name'],
3025                               install_input)
3026    else
3027      emulators += {exe['name']: emulator}
3028    endif
3029
3030    if stap.found()
3031      foreach stp: [
3032        {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
3033        {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
3034        {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
3035        {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
3036      ]
3037        custom_target(exe['name'] + stp['ext'],
3038                      input: trace_events_all,
3039                      output: exe['name'] + stp['ext'],
3040                      install: stp['install'],
3041                      install_dir: get_option('datadir') / 'systemtap/tapset',
3042                      command: [
3043                        tracetool, '--group=all', '--format=' + stp['fmt'],
3044                        '--binary=' + stp['bin'],
3045                        '--target-name=' + target_name,
3046                        '--target-type=' + target_type,
3047                        '--probe-prefix=qemu.' + target_type + '.' + target_name,
3048                        '@INPUT@', '@OUTPUT@'
3049                      ],
3050                      depend_files: tracetool_depends)
3051      endforeach
3052    endif
3053  endforeach
3054endforeach
3055
3056# Other build targets
3057
3058if 'CONFIG_PLUGIN' in config_host
3059  install_headers('include/qemu/qemu-plugin.h')
3060endif
3061
3062if 'CONFIG_GUEST_AGENT' in config_host
3063  subdir('qga')
3064elif get_option('guest_agent_msi').enabled()
3065  error('Guest agent MSI requested, but the guest agent is not being built')
3066endif
3067
3068# Don't build qemu-keymap if xkbcommon is not explicitly enabled
3069# when we don't build tools or system
3070if xkbcommon.found()
3071  # used for the update-keymaps target, so include rules even if !have_tools
3072  qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
3073                           dependencies: [qemuutil, xkbcommon], install: have_tools)
3074endif
3075
3076if have_tools
3077  qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
3078             dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
3079  qemu_io = executable('qemu-io', files('qemu-io.c'),
3080             dependencies: [block, qemuutil], install: true)
3081  qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
3082               dependencies: [blockdev, qemuutil, gnutls, selinux],
3083               install: true)
3084
3085  subdir('storage-daemon')
3086  subdir('contrib/rdmacm-mux')
3087  subdir('contrib/elf2dmp')
3088
3089  executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
3090             dependencies: qemuutil,
3091             install: true)
3092
3093  if 'CONFIG_VHOST_USER' in config_host
3094    subdir('contrib/vhost-user-blk')
3095    subdir('contrib/vhost-user-gpu')
3096    subdir('contrib/vhost-user-input')
3097    subdir('contrib/vhost-user-scsi')
3098  endif
3099
3100  if targetos == 'linux'
3101    executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
3102               dependencies: [qemuutil, libcap_ng],
3103               install: true,
3104               install_dir: get_option('libexecdir'))
3105
3106    executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
3107               dependencies: [authz, crypto, io, qom, qemuutil,
3108                              libcap_ng, mpathpersist],
3109               install: true)
3110  endif
3111
3112  if have_ivshmem
3113    subdir('contrib/ivshmem-client')
3114    subdir('contrib/ivshmem-server')
3115  endif
3116endif
3117
3118subdir('scripts')
3119subdir('tools')
3120subdir('pc-bios')
3121subdir('docs')
3122subdir('tests')
3123if gtk.found()
3124  subdir('po')
3125endif
3126
3127if host_machine.system() == 'windows'
3128  nsis_cmd = [
3129    find_program('scripts/nsis.py'),
3130    '@OUTPUT@',
3131    get_option('prefix'),
3132    meson.current_source_dir(),
3133    host_machine.cpu(),
3134    '--',
3135    '-DDISPLAYVERSION=' + meson.project_version(),
3136  ]
3137  if build_docs
3138    nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
3139  endif
3140  if gtk.found()
3141    nsis_cmd += '-DCONFIG_GTK=y'
3142  endif
3143
3144  nsis = custom_target('nsis',
3145                       output: 'qemu-setup-' + meson.project_version() + '.exe',
3146                       input: files('qemu.nsi'),
3147                       build_always_stale: true,
3148                       command: nsis_cmd + ['@INPUT@'])
3149  alias_target('installer', nsis)
3150endif
3151
3152#########################
3153# Configuration summary #
3154#########################
3155
3156# Directories
3157summary_info = {}
3158summary_info += {'Install prefix':    get_option('prefix')}
3159summary_info += {'BIOS directory':    qemu_datadir}
3160summary_info += {'firmware path':     get_option('qemu_firmwarepath')}
3161summary_info += {'binary directory':  get_option('bindir')}
3162summary_info += {'library directory': get_option('libdir')}
3163summary_info += {'module directory':  qemu_moddir}
3164summary_info += {'libexec directory': get_option('libexecdir')}
3165summary_info += {'include directory': get_option('includedir')}
3166summary_info += {'config directory':  get_option('sysconfdir')}
3167if targetos != 'windows'
3168  summary_info += {'local state directory': get_option('localstatedir')}
3169  summary_info += {'Manual directory':      get_option('mandir')}
3170else
3171  summary_info += {'local state directory': 'queried at runtime'}
3172endif
3173summary_info += {'Doc directory':     get_option('docdir')}
3174summary_info += {'Build directory':   meson.current_build_dir()}
3175summary_info += {'Source path':       meson.current_source_dir()}
3176summary_info += {'GIT submodules':    config_host['GIT_SUBMODULES']}
3177summary(summary_info, bool_yn: true, section: 'Directories')
3178
3179# Host binaries
3180summary_info = {}
3181summary_info += {'git':               config_host['GIT']}
3182summary_info += {'make':              config_host['MAKE']}
3183summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
3184summary_info += {'sphinx-build':      sphinx_build}
3185if config_host.has_key('HAVE_GDB_BIN')
3186  summary_info += {'gdb':             config_host['HAVE_GDB_BIN']}
3187endif
3188summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
3189if targetos == 'windows' and config_host.has_key('CONFIG_GUEST_AGENT')
3190  summary_info += {'wixl':            wixl}
3191endif
3192if slirp_opt != 'disabled' and 'CONFIG_SLIRP_SMBD' in config_host
3193  summary_info += {'smbd':            config_host['CONFIG_SMBD_COMMAND']}
3194endif
3195summary(summary_info, bool_yn: true, section: 'Host binaries')
3196
3197# Configurable features
3198summary_info = {}
3199summary_info += {'Documentation':     build_docs}
3200summary_info += {'system-mode emulation': have_system}
3201summary_info += {'user-mode emulation': have_user}
3202summary_info += {'block layer':       have_block}
3203summary_info += {'Install blobs':     get_option('install_blobs')}
3204summary_info += {'module support':    config_host.has_key('CONFIG_MODULES')}
3205if config_host.has_key('CONFIG_MODULES')
3206  summary_info += {'alternative module path': config_host.has_key('CONFIG_MODULE_UPGRADES')}
3207endif
3208summary_info += {'fuzzing support':   get_option('fuzzing')}
3209if have_system
3210  summary_info += {'Audio drivers':     ' '.join(audio_drivers_selected)}
3211endif
3212summary_info += {'Trace backends':    ','.join(get_option('trace_backends'))}
3213if 'simple' in get_option('trace_backends')
3214  summary_info += {'Trace output file': get_option('trace_file') + '-<pid>'}
3215endif
3216summary_info += {'QOM debugging':     config_host.has_key('CONFIG_QOM_CAST_DEBUG')}
3217summary_info += {'vhost-kernel support': config_host.has_key('CONFIG_VHOST_KERNEL')}
3218summary_info += {'vhost-net support': config_host.has_key('CONFIG_VHOST_NET')}
3219summary_info += {'vhost-crypto support': config_host.has_key('CONFIG_VHOST_CRYPTO')}
3220summary_info += {'vhost-scsi support': config_host.has_key('CONFIG_VHOST_SCSI')}
3221summary_info += {'vhost-vsock support': config_host.has_key('CONFIG_VHOST_VSOCK')}
3222summary_info += {'vhost-user support': config_host.has_key('CONFIG_VHOST_USER')}
3223summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
3224summary_info += {'vhost-user-fs support': config_host.has_key('CONFIG_VHOST_USER_FS')}
3225summary_info += {'vhost-vdpa support': config_host.has_key('CONFIG_VHOST_VDPA')}
3226summary_info += {'build guest agent': config_host.has_key('CONFIG_GUEST_AGENT')}
3227summary(summary_info, bool_yn: true, section: 'Configurable features')
3228
3229# Compilation information
3230summary_info = {}
3231summary_info += {'host CPU':          cpu}
3232summary_info += {'host endianness':   build_machine.endian()}
3233summary_info += {'C compiler':        ' '.join(meson.get_compiler('c').cmd_array())}
3234summary_info += {'Host C compiler':   ' '.join(meson.get_compiler('c', native: true).cmd_array())}
3235if link_language == 'cpp'
3236  summary_info += {'C++ compiler':    ' '.join(meson.get_compiler('cpp').cmd_array())}
3237else
3238  summary_info += {'C++ compiler':      false}
3239endif
3240if targetos == 'darwin'
3241  summary_info += {'Objective-C compiler': ' '.join(meson.get_compiler('objc').cmd_array())}
3242endif
3243if targetos == 'windows'
3244  if 'WIN_SDK' in config_host
3245    summary_info += {'Windows SDK':   config_host['WIN_SDK']}
3246  endif
3247endif
3248summary_info += {'CFLAGS':            ' '.join(get_option('c_args')
3249                                               + ['-O' + get_option('optimization')]
3250                                               + (get_option('debug') ? ['-g'] : []))}
3251if link_language == 'cpp'
3252  summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args')
3253                                               + ['-O' + get_option('optimization')]
3254                                               + (get_option('debug') ? ['-g'] : []))}
3255endif
3256link_args = get_option(link_language + '_link_args')
3257if link_args.length() > 0
3258  summary_info += {'LDFLAGS':         ' '.join(link_args)}
3259endif
3260summary_info += {'QEMU_CFLAGS':       config_host['QEMU_CFLAGS']}
3261summary_info += {'QEMU_LDFLAGS':      config_host['QEMU_LDFLAGS']}
3262summary_info += {'profiler':          config_host.has_key('CONFIG_PROFILER')}
3263summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
3264summary_info += {'PIE':               get_option('b_pie')}
3265summary_info += {'static build':      config_host.has_key('CONFIG_STATIC')}
3266summary_info += {'malloc trim support': has_malloc_trim}
3267summary_info += {'membarrier':        config_host.has_key('CONFIG_MEMBARRIER')}
3268summary_info += {'debug stack usage': config_host.has_key('CONFIG_DEBUG_STACK_USAGE')}
3269summary_info += {'mutex debugging':   config_host.has_key('CONFIG_DEBUG_MUTEX')}
3270summary_info += {'memory allocator':  get_option('malloc')}
3271summary_info += {'avx2 optimization': config_host.has_key('CONFIG_AVX2_OPT')}
3272summary_info += {'avx512f optimization': config_host.has_key('CONFIG_AVX512F_OPT')}
3273summary_info += {'gprof enabled':     config_host.has_key('CONFIG_GPROF')}
3274summary_info += {'gcov':              get_option('b_coverage')}
3275summary_info += {'thread sanitizer':  config_host.has_key('CONFIG_TSAN')}
3276summary_info += {'CFI support':       get_option('cfi')}
3277if get_option('cfi')
3278  summary_info += {'CFI debug support': get_option('cfi_debug')}
3279endif
3280summary_info += {'strip binaries':    get_option('strip')}
3281summary_info += {'sparse':            sparse}
3282summary_info += {'mingw32 support':   targetos == 'windows'}
3283
3284# snarf the cross-compilation information for tests
3285foreach target: target_dirs
3286  tcg_mak = meson.current_build_dir() / 'tests/tcg' / 'config-' + target + '.mak'
3287  if fs.exists(tcg_mak)
3288    config_cross_tcg = keyval.load(tcg_mak)
3289    target = config_cross_tcg['TARGET_NAME']
3290    compiler = ''
3291    if 'DOCKER_CROSS_CC_GUEST' in config_cross_tcg
3292      summary_info += {target + ' tests': config_cross_tcg['DOCKER_CROSS_CC_GUEST'] +
3293                                          ' via ' + config_cross_tcg['DOCKER_IMAGE']}
3294    elif 'CROSS_CC_GUEST' in config_cross_tcg
3295      summary_info += {target + ' tests'
3296                                : config_cross_tcg['CROSS_CC_GUEST'] }
3297    endif
3298   endif
3299endforeach
3300
3301summary(summary_info, bool_yn: true, section: 'Compilation')
3302
3303# Targets and accelerators
3304summary_info = {}
3305if have_system
3306  summary_info += {'KVM support':       config_all.has_key('CONFIG_KVM')}
3307  summary_info += {'HAX support':       config_all.has_key('CONFIG_HAX')}
3308  summary_info += {'HVF support':       config_all.has_key('CONFIG_HVF')}
3309  summary_info += {'WHPX support':      config_all.has_key('CONFIG_WHPX')}
3310  summary_info += {'NVMM support':      config_all.has_key('CONFIG_NVMM')}
3311  summary_info += {'Xen support':       config_host.has_key('CONFIG_XEN_BACKEND')}
3312  if config_host.has_key('CONFIG_XEN_BACKEND')
3313    summary_info += {'xen ctrl version':  config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']}
3314  endif
3315endif
3316summary_info += {'TCG support':       config_all.has_key('CONFIG_TCG')}
3317if config_all.has_key('CONFIG_TCG')
3318  if get_option('tcg_interpreter')
3319    summary_info += {'TCG backend':   'TCI (TCG with bytecode interpreter, slow)'}
3320  else
3321    summary_info += {'TCG backend':   'native (@0@)'.format(cpu)}
3322  endif
3323  summary_info += {'TCG plugins': config_host.has_key('CONFIG_PLUGIN')}
3324  summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')}
3325endif
3326summary_info += {'target list':       ' '.join(target_dirs)}
3327if have_system
3328  summary_info += {'default devices':   get_option('default_devices')}
3329  summary_info += {'out of process emulation': multiprocess_allowed}
3330endif
3331summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
3332
3333# Block layer
3334summary_info = {}
3335summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']}
3336summary_info += {'coroutine pool':    config_host['CONFIG_COROUTINE_POOL'] == '1'}
3337if have_block
3338  summary_info += {'Block whitelist (rw)': config_host['CONFIG_BDRV_RW_WHITELIST']}
3339  summary_info += {'Block whitelist (ro)': config_host['CONFIG_BDRV_RO_WHITELIST']}
3340  summary_info += {'Use block whitelist in tools': config_host.has_key('CONFIG_BDRV_WHITELIST_TOOLS')}
3341  summary_info += {'VirtFS support':    have_virtfs}
3342  summary_info += {'build virtiofs daemon': have_virtiofsd}
3343  summary_info += {'Live block migration': config_host.has_key('CONFIG_LIVE_BLOCK_MIGRATION')}
3344  summary_info += {'replication support': config_host.has_key('CONFIG_REPLICATION')}
3345  summary_info += {'bochs support':     config_host.has_key('CONFIG_BOCHS')}
3346  summary_info += {'cloop support':     config_host.has_key('CONFIG_CLOOP')}
3347  summary_info += {'dmg support':       config_host.has_key('CONFIG_DMG')}
3348  summary_info += {'qcow v1 support':   config_host.has_key('CONFIG_QCOW1')}
3349  summary_info += {'vdi support':       config_host.has_key('CONFIG_VDI')}
3350  summary_info += {'vvfat support':     config_host.has_key('CONFIG_VVFAT')}
3351  summary_info += {'qed support':       config_host.has_key('CONFIG_QED')}
3352  summary_info += {'parallels support': config_host.has_key('CONFIG_PARALLELS')}
3353  summary_info += {'FUSE exports':      fuse}
3354endif
3355summary(summary_info, bool_yn: true, section: 'Block layer support')
3356
3357# Crypto
3358summary_info = {}
3359summary_info += {'TLS priority':      config_host['CONFIG_TLS_PRIORITY']}
3360summary_info += {'GNUTLS support':    gnutls}
3361if gnutls.found()
3362  summary_info += {'  GNUTLS crypto':   gnutls_crypto.found()}
3363endif
3364summary_info += {'libgcrypt':         gcrypt}
3365summary_info += {'nettle':            nettle}
3366if nettle.found()
3367   summary_info += {'  XTS':             xts != 'private'}
3368endif
3369summary_info += {'crypto afalg':      config_host.has_key('CONFIG_AF_ALG')}
3370summary_info += {'rng-none':          config_host.has_key('CONFIG_RNG_NONE')}
3371summary_info += {'Linux keyring':     config_host.has_key('CONFIG_SECRET_KEYRING')}
3372summary(summary_info, bool_yn: true, section: 'Crypto')
3373
3374# Libraries
3375summary_info = {}
3376if targetos == 'darwin'
3377  summary_info += {'Cocoa support':   cocoa}
3378endif
3379summary_info += {'SDL support':       sdl}
3380summary_info += {'SDL image support': sdl_image}
3381summary_info += {'GTK support':       gtk}
3382summary_info += {'pixman':            pixman}
3383summary_info += {'VTE support':       vte}
3384summary_info += {'slirp support':     slirp_opt == 'internal' ? slirp_opt : slirp}
3385summary_info += {'libtasn1':          tasn1}
3386summary_info += {'PAM':               pam}
3387summary_info += {'iconv support':     iconv}
3388summary_info += {'curses support':    curses}
3389summary_info += {'virgl support':     virgl}
3390summary_info += {'curl support':      curl}
3391summary_info += {'Multipath support': mpathpersist}
3392summary_info += {'VNC support':       vnc}
3393if vnc.found()
3394  summary_info += {'VNC SASL support':  sasl}
3395  summary_info += {'VNC JPEG support':  jpeg}
3396  summary_info += {'VNC PNG support':   png}
3397endif
3398if targetos not in ['darwin', 'haiku', 'windows']
3399  summary_info += {'OSS support':     oss}
3400elif targetos == 'darwin'
3401  summary_info += {'CoreAudio support': coreaudio}
3402elif targetos == 'windows'
3403  summary_info += {'DirectSound support': dsound}
3404endif
3405if targetos == 'linux'
3406  summary_info += {'ALSA support':    alsa}
3407  summary_info += {'PulseAudio support': pulse}
3408endif
3409summary_info += {'JACK support':      jack}
3410summary_info += {'brlapi support':    brlapi}
3411summary_info += {'vde support':       vde}
3412summary_info += {'netmap support':    have_netmap}
3413summary_info += {'l2tpv3 support':    have_l2tpv3}
3414summary_info += {'Linux AIO support': libaio}
3415summary_info += {'Linux io_uring support': linux_io_uring}
3416summary_info += {'ATTR/XATTR support': libattr}
3417summary_info += {'RDMA support':      config_host.has_key('CONFIG_RDMA')}
3418summary_info += {'PVRDMA support':    config_host.has_key('CONFIG_PVRDMA')}
3419summary_info += {'fdt support':       fdt_opt == 'disabled' ? false : fdt_opt}
3420summary_info += {'libcap-ng support': libcap_ng}
3421summary_info += {'bpf support':       libbpf}
3422summary_info += {'spice protocol support': spice_protocol}
3423if spice_protocol.found()
3424  summary_info += {'  spice server support': spice}
3425endif
3426summary_info += {'rbd support':       rbd}
3427summary_info += {'xfsctl support':    config_host.has_key('CONFIG_XFS')}
3428summary_info += {'smartcard support': cacard}
3429summary_info += {'U2F support':       u2f}
3430summary_info += {'libusb':            libusb}
3431summary_info += {'usb net redir':     usbredir}
3432summary_info += {'OpenGL support':    config_host.has_key('CONFIG_OPENGL')}
3433summary_info += {'GBM':               gbm}
3434summary_info += {'libiscsi support':  libiscsi}
3435summary_info += {'libnfs support':    libnfs}
3436if targetos == 'windows'
3437  if config_host.has_key('CONFIG_GUEST_AGENT')
3438    summary_info += {'QGA VSS support':   config_host.has_key('CONFIG_QGA_VSS')}
3439    summary_info += {'QGA w32 disk info': config_host.has_key('CONFIG_QGA_NTDDSCSI')}
3440  endif
3441endif
3442summary_info += {'seccomp support':   seccomp}
3443summary_info += {'GlusterFS support': glusterfs}
3444summary_info += {'TPM support':       config_host.has_key('CONFIG_TPM')}
3445summary_info += {'libssh support':    libssh}
3446summary_info += {'lzo support':       lzo}
3447summary_info += {'snappy support':    snappy}
3448summary_info += {'bzip2 support':     libbzip2}
3449summary_info += {'lzfse support':     liblzfse}
3450summary_info += {'zstd support':      zstd}
3451summary_info += {'NUMA host support': config_host.has_key('CONFIG_NUMA')}
3452summary_info += {'libxml2':           libxml2}
3453summary_info += {'capstone':          capstone_opt == 'internal' ? capstone_opt : capstone}
3454summary_info += {'libpmem support':   libpmem}
3455summary_info += {'libdaxctl support': libdaxctl}
3456summary_info += {'libudev':           libudev}
3457# Dummy dependency, keep .found()
3458summary_info += {'FUSE lseek':        fuse_lseek.found()}
3459summary_info += {'selinux':           selinux}
3460summary(summary_info, bool_yn: true, section: 'Dependencies')
3461
3462if not supported_cpus.contains(cpu)
3463  message()
3464  warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!')
3465  message()
3466  message('CPU host architecture ' + cpu + ' support is not currently maintained.')
3467  message('The QEMU project intends to remove support for this host CPU in')
3468  message('a future release if nobody volunteers to maintain it and to')
3469  message('provide a build host for our continuous integration setup.')
3470  message('configure has succeeded and you can continue to build, but')
3471  message('if you care about QEMU on this platform you should contact')
3472  message('us upstream at qemu-devel@nongnu.org.')
3473endif
3474
3475if not supported_oses.contains(targetos)
3476  message()
3477  warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!')
3478  message()
3479  message('Host OS ' + targetos + 'support is not currently maintained.')
3480  message('The QEMU project intends to remove support for this host OS in')
3481  message('a future release if nobody volunteers to maintain it and to')
3482  message('provide a build host for our continuous integration setup.')
3483  message('configure has succeeded and you can continue to build, but')
3484  message('if you care about QEMU on this platform you should contact')
3485  message('us upstream at qemu-devel@nongnu.org.')
3486endif
3487