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