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