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