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