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