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