xref: /openbmc/qemu/meson.build (revision 3cb1a410)
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
2435if have_system
2436  fdt_opt = get_option('fdt')
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
2479else
2480  fdt_opt = 'disabled'
2481endif
2482if not fdt.found() and fdt_required.length() > 0
2483  error('fdt not available but required by targets ' + ', '.join(fdt_required))
2484endif
2485
2486config_host_data.set('CONFIG_CAPSTONE', capstone.found())
2487config_host_data.set('CONFIG_FDT', fdt.found())
2488config_host_data.set('CONFIG_SLIRP', slirp.found())
2489
2490#####################
2491# Generated sources #
2492#####################
2493
2494genh += configure_file(output: 'config-host.h', configuration: config_host_data)
2495
2496hxtool = find_program('scripts/hxtool')
2497shaderinclude = find_program('scripts/shaderinclude.pl')
2498qapi_gen = find_program('scripts/qapi-gen.py')
2499qapi_gen_depends = [ meson.current_source_dir() / 'scripts/qapi/__init__.py',
2500                     meson.current_source_dir() / 'scripts/qapi/commands.py',
2501                     meson.current_source_dir() / 'scripts/qapi/common.py',
2502                     meson.current_source_dir() / 'scripts/qapi/error.py',
2503                     meson.current_source_dir() / 'scripts/qapi/events.py',
2504                     meson.current_source_dir() / 'scripts/qapi/expr.py',
2505                     meson.current_source_dir() / 'scripts/qapi/gen.py',
2506                     meson.current_source_dir() / 'scripts/qapi/introspect.py',
2507                     meson.current_source_dir() / 'scripts/qapi/parser.py',
2508                     meson.current_source_dir() / 'scripts/qapi/schema.py',
2509                     meson.current_source_dir() / 'scripts/qapi/source.py',
2510                     meson.current_source_dir() / 'scripts/qapi/types.py',
2511                     meson.current_source_dir() / 'scripts/qapi/visit.py',
2512                     meson.current_source_dir() / 'scripts/qapi/common.py',
2513                     meson.current_source_dir() / 'scripts/qapi-gen.py'
2514]
2515
2516tracetool = [
2517  python, files('scripts/tracetool.py'),
2518   '--backend=' + ','.join(get_option('trace_backends'))
2519]
2520tracetool_depends = files(
2521  'scripts/tracetool/backend/log.py',
2522  'scripts/tracetool/backend/__init__.py',
2523  'scripts/tracetool/backend/dtrace.py',
2524  'scripts/tracetool/backend/ftrace.py',
2525  'scripts/tracetool/backend/simple.py',
2526  'scripts/tracetool/backend/syslog.py',
2527  'scripts/tracetool/backend/ust.py',
2528  'scripts/tracetool/format/ust_events_c.py',
2529  'scripts/tracetool/format/ust_events_h.py',
2530  'scripts/tracetool/format/__init__.py',
2531  'scripts/tracetool/format/d.py',
2532  'scripts/tracetool/format/simpletrace_stap.py',
2533  'scripts/tracetool/format/c.py',
2534  'scripts/tracetool/format/h.py',
2535  'scripts/tracetool/format/log_stap.py',
2536  'scripts/tracetool/format/stap.py',
2537  'scripts/tracetool/__init__.py',
2538  'scripts/tracetool/transform.py',
2539  'scripts/tracetool/vcpu.py'
2540)
2541
2542qemu_version_cmd = [find_program('scripts/qemu-version.sh'),
2543                    meson.current_source_dir(),
2544                    config_host['PKGVERSION'], meson.project_version()]
2545qemu_version = custom_target('qemu-version.h',
2546                             output: 'qemu-version.h',
2547                             command: qemu_version_cmd,
2548                             capture: true,
2549                             build_by_default: true,
2550                             build_always_stale: true)
2551genh += qemu_version
2552
2553hxdep = []
2554hx_headers = [
2555  ['qemu-options.hx', 'qemu-options.def'],
2556  ['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
2557]
2558if have_system
2559  hx_headers += [
2560    ['hmp-commands.hx', 'hmp-commands.h'],
2561    ['hmp-commands-info.hx', 'hmp-commands-info.h'],
2562  ]
2563endif
2564foreach d : hx_headers
2565  hxdep += custom_target(d[1],
2566                input: files(d[0]),
2567                output: d[1],
2568                capture: true,
2569                build_by_default: true, # to be removed when added to a target
2570                command: [hxtool, '-h', '@INPUT0@'])
2571endforeach
2572genh += hxdep
2573
2574###################
2575# Collect sources #
2576###################
2577
2578authz_ss = ss.source_set()
2579blockdev_ss = ss.source_set()
2580block_ss = ss.source_set()
2581chardev_ss = ss.source_set()
2582common_ss = ss.source_set()
2583crypto_ss = ss.source_set()
2584hwcore_ss = ss.source_set()
2585io_ss = ss.source_set()
2586qmp_ss = ss.source_set()
2587qom_ss = ss.source_set()
2588softmmu_ss = ss.source_set()
2589specific_fuzz_ss = ss.source_set()
2590specific_ss = ss.source_set()
2591stub_ss = ss.source_set()
2592trace_ss = ss.source_set()
2593user_ss = ss.source_set()
2594util_ss = ss.source_set()
2595
2596# accel modules
2597qtest_module_ss = ss.source_set()
2598tcg_module_ss = ss.source_set()
2599
2600modules = {}
2601target_modules = {}
2602hw_arch = {}
2603target_arch = {}
2604target_softmmu_arch = {}
2605target_user_arch = {}
2606
2607###############
2608# Trace files #
2609###############
2610
2611# TODO: add each directory to the subdirs from its own meson.build, once
2612# we have those
2613trace_events_subdirs = [
2614  'crypto',
2615  'qapi',
2616  'qom',
2617  'monitor',
2618  'util',
2619]
2620if have_linux_user
2621  trace_events_subdirs += [ 'linux-user' ]
2622endif
2623if have_bsd_user
2624  trace_events_subdirs += [ 'bsd-user' ]
2625endif
2626if have_block
2627  trace_events_subdirs += [
2628    'authz',
2629    'block',
2630    'io',
2631    'nbd',
2632    'scsi',
2633  ]
2634endif
2635if have_system
2636  trace_events_subdirs += [
2637    'accel/kvm',
2638    'audio',
2639    'backends',
2640    'backends/tpm',
2641    'chardev',
2642    'ebpf',
2643    'hw/9pfs',
2644    'hw/acpi',
2645    'hw/adc',
2646    'hw/alpha',
2647    'hw/arm',
2648    'hw/audio',
2649    'hw/block',
2650    'hw/block/dataplane',
2651    'hw/char',
2652    'hw/display',
2653    'hw/dma',
2654    'hw/hppa',
2655    'hw/hyperv',
2656    'hw/i2c',
2657    'hw/i386',
2658    'hw/i386/xen',
2659    'hw/ide',
2660    'hw/input',
2661    'hw/intc',
2662    'hw/isa',
2663    'hw/mem',
2664    'hw/mips',
2665    'hw/misc',
2666    'hw/misc/macio',
2667    'hw/net',
2668    'hw/net/can',
2669    'hw/nubus',
2670    'hw/nvme',
2671    'hw/nvram',
2672    'hw/pci',
2673    'hw/pci-host',
2674    'hw/ppc',
2675    'hw/rdma',
2676    'hw/rdma/vmw',
2677    'hw/rtc',
2678    'hw/s390x',
2679    'hw/scsi',
2680    'hw/sd',
2681    'hw/sh4',
2682    'hw/sparc',
2683    'hw/sparc64',
2684    'hw/ssi',
2685    'hw/timer',
2686    'hw/tpm',
2687    'hw/usb',
2688    'hw/vfio',
2689    'hw/virtio',
2690    'hw/watchdog',
2691    'hw/xen',
2692    'hw/gpio',
2693    'migration',
2694    'net',
2695    'softmmu',
2696    'ui',
2697    'hw/remote',
2698  ]
2699endif
2700if have_system or have_user
2701  trace_events_subdirs += [
2702    'accel/tcg',
2703    'hw/core',
2704    'target/arm',
2705    'target/arm/hvf',
2706    'target/hppa',
2707    'target/i386',
2708    'target/i386/kvm',
2709    'target/mips/tcg',
2710    'target/nios2',
2711    'target/ppc',
2712    'target/riscv',
2713    'target/s390x',
2714    'target/s390x/kvm',
2715    'target/sparc',
2716  ]
2717endif
2718
2719vhost_user = not_found
2720if 'CONFIG_VHOST_USER' in config_host
2721  libvhost_user = subproject('libvhost-user')
2722  vhost_user = libvhost_user.get_variable('vhost_user_dep')
2723endif
2724
2725# NOTE: the trace/ subdirectory needs the qapi_trace_events variable
2726# that is filled in by qapi/.
2727subdir('qapi')
2728subdir('qobject')
2729subdir('stubs')
2730subdir('trace')
2731subdir('util')
2732subdir('qom')
2733subdir('authz')
2734subdir('crypto')
2735subdir('ui')
2736
2737
2738if enable_modules
2739  libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
2740  modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
2741endif
2742
2743stub_ss = stub_ss.apply(config_all, strict: false)
2744
2745util_ss.add_all(trace_ss)
2746util_ss = util_ss.apply(config_all, strict: false)
2747libqemuutil = static_library('qemuutil',
2748                             sources: util_ss.sources() + stub_ss.sources() + genh,
2749                             dependencies: [util_ss.dependencies(), libm, threads, glib, socket, malloc, pixman])
2750qemuutil = declare_dependency(link_with: libqemuutil,
2751                              sources: genh + version_res)
2752
2753if have_system or have_user
2754  decodetree = generator(find_program('scripts/decodetree.py'),
2755                         output: 'decode-@BASENAME@.c.inc',
2756                         arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
2757  subdir('libdecnumber')
2758  subdir('target')
2759endif
2760
2761subdir('audio')
2762subdir('io')
2763subdir('chardev')
2764subdir('fsdev')
2765subdir('dump')
2766
2767if have_block
2768  block_ss.add(files(
2769    'block.c',
2770    'blockjob.c',
2771    'job.c',
2772    'qemu-io-cmds.c',
2773  ))
2774  if config_host_data.get('CONFIG_REPLICATION')
2775    block_ss.add(files('replication.c'))
2776  endif
2777
2778  subdir('nbd')
2779  subdir('scsi')
2780  subdir('block')
2781
2782  blockdev_ss.add(files(
2783    'blockdev.c',
2784    'blockdev-nbd.c',
2785    'iothread.c',
2786    'job-qmp.c',
2787  ), gnutls)
2788
2789  # os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
2790  # os-win32.c does not
2791  blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c'))
2792  softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')])
2793endif
2794
2795common_ss.add(files('cpus-common.c'))
2796
2797subdir('softmmu')
2798
2799common_ss.add(capstone)
2800specific_ss.add(files('cpu.c', 'disas.c', 'gdbstub.c'), capstone)
2801
2802# Work around a gcc bug/misfeature wherein constant propagation looks
2803# through an alias:
2804#   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99696
2805# to guess that a const variable is always zero.  Without lto, this is
2806# impossible, as the alias is restricted to page-vary-common.c.  Indeed,
2807# without lto, not even the alias is required -- we simply use different
2808# declarations in different compilation units.
2809pagevary = files('page-vary-common.c')
2810if get_option('b_lto')
2811  pagevary_flags = ['-fno-lto']
2812  if get_option('cfi')
2813    pagevary_flags += '-fno-sanitize=cfi-icall'
2814  endif
2815  pagevary = static_library('page-vary-common', sources: pagevary,
2816                            c_args: pagevary_flags)
2817  pagevary = declare_dependency(link_with: pagevary)
2818endif
2819common_ss.add(pagevary)
2820specific_ss.add(files('page-vary.c'))
2821
2822subdir('backends')
2823subdir('disas')
2824subdir('migration')
2825subdir('monitor')
2826subdir('net')
2827subdir('replay')
2828subdir('semihosting')
2829subdir('hw')
2830subdir('tcg')
2831subdir('fpu')
2832subdir('accel')
2833subdir('plugins')
2834subdir('ebpf')
2835
2836common_user_inc = []
2837
2838subdir('common-user')
2839subdir('bsd-user')
2840subdir('linux-user')
2841
2842# needed for fuzzing binaries
2843subdir('tests/qtest/libqos')
2844subdir('tests/qtest/fuzz')
2845
2846# accel modules
2847tcg_real_module_ss = ss.source_set()
2848tcg_real_module_ss.add_all(when: 'CONFIG_TCG_MODULAR', if_true: tcg_module_ss)
2849specific_ss.add_all(when: 'CONFIG_TCG_BUILTIN', if_true: tcg_module_ss)
2850target_modules += { 'accel' : { 'qtest': qtest_module_ss,
2851                                'tcg': tcg_real_module_ss }}
2852
2853########################
2854# Library dependencies #
2855########################
2856
2857modinfo_collect = find_program('scripts/modinfo-collect.py')
2858modinfo_generate = find_program('scripts/modinfo-generate.py')
2859modinfo_files = []
2860
2861block_mods = []
2862softmmu_mods = []
2863foreach d, list : modules
2864  foreach m, module_ss : list
2865    if enable_modules and targetos != 'windows'
2866      module_ss = module_ss.apply(config_all, strict: false)
2867      sl = static_library(d + '-' + m, [genh, module_ss.sources()],
2868                          dependencies: [modulecommon, module_ss.dependencies()], pic: true)
2869      if d == 'block'
2870        block_mods += sl
2871      else
2872        softmmu_mods += sl
2873      endif
2874      if module_ss.sources() != []
2875        # FIXME: Should use sl.extract_all_objects(recursive: true) as
2876        # input. Sources can be used multiple times but objects are
2877        # unique when it comes to lookup in compile_commands.json.
2878        # Depnds on a mesion version with
2879        # https://github.com/mesonbuild/meson/pull/8900
2880        modinfo_files += custom_target(d + '-' + m + '.modinfo',
2881                                       output: d + '-' + m + '.modinfo',
2882                                       input: module_ss.sources() + genh,
2883                                       capture: true,
2884                                       command: [modinfo_collect, module_ss.sources()])
2885      endif
2886    else
2887      if d == 'block'
2888        block_ss.add_all(module_ss)
2889      else
2890        softmmu_ss.add_all(module_ss)
2891      endif
2892    endif
2893  endforeach
2894endforeach
2895
2896foreach d, list : target_modules
2897  foreach m, module_ss : list
2898    if enable_modules and targetos != 'windows'
2899      foreach target : target_dirs
2900        if target.endswith('-softmmu')
2901          config_target = config_target_mak[target]
2902          config_target += config_host
2903          target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
2904          c_args = ['-DNEED_CPU_H',
2905                    '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
2906                    '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
2907          target_module_ss = module_ss.apply(config_target, strict: false)
2908          if target_module_ss.sources() != []
2909            module_name = d + '-' + m + '-' + config_target['TARGET_NAME']
2910            sl = static_library(module_name,
2911                                [genh, target_module_ss.sources()],
2912                                dependencies: [modulecommon, target_module_ss.dependencies()],
2913                                include_directories: target_inc,
2914                                c_args: c_args,
2915                                pic: true)
2916            softmmu_mods += sl
2917            # FIXME: Should use sl.extract_all_objects(recursive: true) too.
2918            modinfo_files += custom_target(module_name + '.modinfo',
2919                                           output: module_name + '.modinfo',
2920                                           input: target_module_ss.sources() + genh,
2921                                           capture: true,
2922                                           command: [modinfo_collect, '--target', target, target_module_ss.sources()])
2923          endif
2924        endif
2925      endforeach
2926    else
2927      specific_ss.add_all(module_ss)
2928    endif
2929  endforeach
2930endforeach
2931
2932if enable_modules
2933  modinfo_src = custom_target('modinfo.c',
2934                              output: 'modinfo.c',
2935                              input: modinfo_files,
2936                              command: [modinfo_generate, '@INPUT@'],
2937                              capture: true)
2938  modinfo_lib = static_library('modinfo', modinfo_src)
2939  modinfo_dep = declare_dependency(link_whole: modinfo_lib)
2940  softmmu_ss.add(modinfo_dep)
2941endif
2942
2943nm = find_program('nm')
2944undefsym = find_program('scripts/undefsym.py')
2945block_syms = custom_target('block.syms', output: 'block.syms',
2946                             input: [libqemuutil, block_mods],
2947                             capture: true,
2948                             command: [undefsym, nm, '@INPUT@'])
2949qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
2950                             input: [libqemuutil, softmmu_mods],
2951                             capture: true,
2952                             command: [undefsym, nm, '@INPUT@'])
2953
2954qom_ss = qom_ss.apply(config_host, strict: false)
2955libqom = static_library('qom', qom_ss.sources() + genh,
2956                        dependencies: [qom_ss.dependencies()],
2957                        name_suffix: 'fa')
2958
2959qom = declare_dependency(link_whole: libqom)
2960
2961authz_ss = authz_ss.apply(config_host, strict: false)
2962libauthz = static_library('authz', authz_ss.sources() + genh,
2963                          dependencies: [authz_ss.dependencies()],
2964                          name_suffix: 'fa',
2965                          build_by_default: false)
2966
2967authz = declare_dependency(link_whole: libauthz,
2968                           dependencies: qom)
2969
2970crypto_ss = crypto_ss.apply(config_host, strict: false)
2971libcrypto = static_library('crypto', crypto_ss.sources() + genh,
2972                           dependencies: [crypto_ss.dependencies()],
2973                           name_suffix: 'fa',
2974                           build_by_default: false)
2975
2976crypto = declare_dependency(link_whole: libcrypto,
2977                            dependencies: [authz, qom])
2978
2979io_ss = io_ss.apply(config_host, strict: false)
2980libio = static_library('io', io_ss.sources() + genh,
2981                       dependencies: [io_ss.dependencies()],
2982                       link_with: libqemuutil,
2983                       name_suffix: 'fa',
2984                       build_by_default: false)
2985
2986io = declare_dependency(link_whole: libio, dependencies: [crypto, qom])
2987
2988libmigration = static_library('migration', sources: migration_files + genh,
2989                              name_suffix: 'fa',
2990                              build_by_default: false)
2991migration = declare_dependency(link_with: libmigration,
2992                               dependencies: [zlib, qom, io])
2993softmmu_ss.add(migration)
2994
2995block_ss = block_ss.apply(config_host, strict: false)
2996libblock = static_library('block', block_ss.sources() + genh,
2997                          dependencies: block_ss.dependencies(),
2998                          link_depends: block_syms,
2999                          name_suffix: 'fa',
3000                          build_by_default: false)
3001
3002block = declare_dependency(link_whole: [libblock],
3003                           link_args: '@block.syms',
3004                           dependencies: [crypto, io])
3005
3006blockdev_ss = blockdev_ss.apply(config_host, strict: false)
3007libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
3008                             dependencies: blockdev_ss.dependencies(),
3009                             name_suffix: 'fa',
3010                             build_by_default: false)
3011
3012blockdev = declare_dependency(link_whole: [libblockdev],
3013                              dependencies: [block])
3014
3015qmp_ss = qmp_ss.apply(config_host, strict: false)
3016libqmp = static_library('qmp', qmp_ss.sources() + genh,
3017                        dependencies: qmp_ss.dependencies(),
3018                        name_suffix: 'fa',
3019                        build_by_default: false)
3020
3021qmp = declare_dependency(link_whole: [libqmp])
3022
3023libchardev = static_library('chardev', chardev_ss.sources() + genh,
3024                            name_suffix: 'fa',
3025                            dependencies: [gnutls],
3026                            build_by_default: false)
3027
3028chardev = declare_dependency(link_whole: libchardev)
3029
3030hwcore_ss = hwcore_ss.apply(config_host, strict: false)
3031libhwcore = static_library('hwcore', sources: hwcore_ss.sources() + genh,
3032                           name_suffix: 'fa',
3033                           build_by_default: false)
3034hwcore = declare_dependency(link_whole: libhwcore)
3035common_ss.add(hwcore)
3036
3037###########
3038# Targets #
3039###########
3040
3041emulator_modules = []
3042foreach m : block_mods + softmmu_mods
3043  emulator_modules += shared_module(m.name(),
3044                build_by_default: true,
3045                name_prefix: '',
3046                link_whole: m,
3047                install: true,
3048                install_dir: qemu_moddir)
3049endforeach
3050
3051softmmu_ss.add(authz, blockdev, chardev, crypto, io, qmp)
3052common_ss.add(qom, qemuutil)
3053
3054common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss])
3055common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
3056
3057common_all = common_ss.apply(config_all, strict: false)
3058common_all = static_library('common',
3059                            build_by_default: false,
3060                            sources: common_all.sources() + genh,
3061                            include_directories: common_user_inc,
3062                            implicit_include_directories: false,
3063                            dependencies: common_all.dependencies(),
3064                            name_suffix: 'fa')
3065
3066feature_to_c = find_program('scripts/feature_to_c.sh')
3067
3068emulators = {}
3069foreach target : target_dirs
3070  config_target = config_target_mak[target]
3071  target_name = config_target['TARGET_NAME']
3072  target_base_arch = config_target['TARGET_BASE_ARCH']
3073  arch_srcs = [config_target_h[target]]
3074  arch_deps = []
3075  c_args = ['-DNEED_CPU_H',
3076            '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
3077            '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
3078  link_args = emulator_link_args
3079
3080  config_target += config_host
3081  target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
3082  if targetos == 'linux'
3083    target_inc += include_directories('linux-headers', is_system: true)
3084  endif
3085  if target.endswith('-softmmu')
3086    qemu_target_name = 'qemu-system-' + target_name
3087    target_type='system'
3088    t = target_softmmu_arch[target_base_arch].apply(config_target, strict: false)
3089    arch_srcs += t.sources()
3090    arch_deps += t.dependencies()
3091
3092    hw_dir = target_name == 'sparc64' ? 'sparc64' : target_base_arch
3093    hw = hw_arch[hw_dir].apply(config_target, strict: false)
3094    arch_srcs += hw.sources()
3095    arch_deps += hw.dependencies()
3096
3097    arch_srcs += config_devices_h[target]
3098    link_args += ['@block.syms', '@qemu.syms']
3099  else
3100    abi = config_target['TARGET_ABI_DIR']
3101    target_type='user'
3102    target_inc += common_user_inc
3103    qemu_target_name = 'qemu-' + target_name
3104    if target_base_arch in target_user_arch
3105      t = target_user_arch[target_base_arch].apply(config_target, strict: false)
3106      arch_srcs += t.sources()
3107      arch_deps += t.dependencies()
3108    endif
3109    if 'CONFIG_LINUX_USER' in config_target
3110      base_dir = 'linux-user'
3111    endif
3112    if 'CONFIG_BSD_USER' in config_target
3113      base_dir = 'bsd-user'
3114      target_inc += include_directories('bsd-user/' / targetos)
3115      target_inc += include_directories('bsd-user/host/' / host_arch)
3116      dir = base_dir / abi
3117      arch_srcs += files(dir / 'signal.c', dir / 'target_arch_cpu.c')
3118    endif
3119    target_inc += include_directories(
3120      base_dir,
3121      base_dir / abi,
3122    )
3123    if 'CONFIG_LINUX_USER' in config_target
3124      dir = base_dir / abi
3125      arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
3126      if config_target.has_key('TARGET_SYSTBL_ABI')
3127        arch_srcs += \
3128          syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
3129                                             extra_args : config_target['TARGET_SYSTBL_ABI'])
3130      endif
3131    endif
3132  endif
3133
3134  if 'TARGET_XML_FILES' in config_target
3135    gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
3136                                output: target + '-gdbstub-xml.c',
3137                                input: files(config_target['TARGET_XML_FILES'].split()),
3138                                command: [feature_to_c, '@INPUT@'],
3139                                capture: true)
3140    arch_srcs += gdbstub_xml
3141  endif
3142
3143  t = target_arch[target_base_arch].apply(config_target, strict: false)
3144  arch_srcs += t.sources()
3145  arch_deps += t.dependencies()
3146
3147  target_common = common_ss.apply(config_target, strict: false)
3148  objects = common_all.extract_objects(target_common.sources())
3149  deps = target_common.dependencies()
3150
3151  target_specific = specific_ss.apply(config_target, strict: false)
3152  arch_srcs += target_specific.sources()
3153  arch_deps += target_specific.dependencies()
3154
3155  lib = static_library('qemu-' + target,
3156                 sources: arch_srcs + genh,
3157                 dependencies: arch_deps,
3158                 objects: objects,
3159                 include_directories: target_inc,
3160                 c_args: c_args,
3161                 build_by_default: false,
3162                 name_suffix: 'fa')
3163
3164  if target.endswith('-softmmu')
3165    execs = [{
3166      'name': 'qemu-system-' + target_name,
3167      'win_subsystem': 'console',
3168      'sources': files('softmmu/main.c'),
3169      'dependencies': []
3170    }]
3171    if targetos == 'windows' and (sdl.found() or gtk.found())
3172      execs += [{
3173        'name': 'qemu-system-' + target_name + 'w',
3174        'win_subsystem': 'windows',
3175        'sources': files('softmmu/main.c'),
3176        'dependencies': []
3177      }]
3178    endif
3179    if get_option('fuzzing')
3180      specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
3181      execs += [{
3182        'name': 'qemu-fuzz-' + target_name,
3183        'win_subsystem': 'console',
3184        'sources': specific_fuzz.sources(),
3185        'dependencies': specific_fuzz.dependencies(),
3186      }]
3187    endif
3188  else
3189    execs = [{
3190      'name': 'qemu-' + target_name,
3191      'win_subsystem': 'console',
3192      'sources': [],
3193      'dependencies': []
3194    }]
3195  endif
3196  foreach exe: execs
3197    exe_name = exe['name']
3198    if targetos == 'darwin'
3199      exe_name += '-unsigned'
3200    endif
3201
3202    emulator = executable(exe_name, exe['sources'],
3203               install: true,
3204               c_args: c_args,
3205               dependencies: arch_deps + deps + exe['dependencies'],
3206               objects: lib.extract_all_objects(recursive: true),
3207               link_language: link_language,
3208               link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
3209               link_args: link_args,
3210               win_subsystem: exe['win_subsystem'])
3211
3212    if targetos == 'darwin'
3213      icon = 'pc-bios/qemu.rsrc'
3214      build_input = [emulator, files(icon)]
3215      install_input = [
3216        get_option('bindir') / exe_name,
3217        meson.current_source_dir() / icon
3218      ]
3219      if 'CONFIG_HVF' in config_target
3220        entitlements = 'accel/hvf/entitlements.plist'
3221        build_input += files(entitlements)
3222        install_input += meson.current_source_dir() / entitlements
3223      endif
3224
3225      entitlement = find_program('scripts/entitlement.sh')
3226      emulators += {exe['name'] : custom_target(exe['name'],
3227                   input: build_input,
3228                   output: exe['name'],
3229                   command: [entitlement, '@OUTPUT@', '@INPUT@'])
3230      }
3231
3232      meson.add_install_script(entitlement, '--install',
3233                               get_option('bindir') / exe['name'],
3234                               install_input)
3235    else
3236      emulators += {exe['name']: emulator}
3237    endif
3238
3239    if stap.found()
3240      foreach stp: [
3241        {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
3242        {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
3243        {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
3244        {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
3245      ]
3246        custom_target(exe['name'] + stp['ext'],
3247                      input: trace_events_all,
3248                      output: exe['name'] + stp['ext'],
3249                      install: stp['install'],
3250                      install_dir: get_option('datadir') / 'systemtap/tapset',
3251                      command: [
3252                        tracetool, '--group=all', '--format=' + stp['fmt'],
3253                        '--binary=' + stp['bin'],
3254                        '--target-name=' + target_name,
3255                        '--target-type=' + target_type,
3256                        '--probe-prefix=qemu.' + target_type + '.' + target_name,
3257                        '@INPUT@', '@OUTPUT@'
3258                      ],
3259                      depend_files: tracetool_depends)
3260      endforeach
3261    endif
3262  endforeach
3263endforeach
3264
3265# Other build targets
3266
3267if 'CONFIG_PLUGIN' in config_host
3268  install_headers('include/qemu/qemu-plugin.h')
3269endif
3270
3271subdir('qga')
3272
3273# Don't build qemu-keymap if xkbcommon is not explicitly enabled
3274# when we don't build tools or system
3275if xkbcommon.found()
3276  # used for the update-keymaps target, so include rules even if !have_tools
3277  qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
3278                           dependencies: [qemuutil, xkbcommon], install: have_tools)
3279endif
3280
3281if have_tools
3282  qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
3283             dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
3284  qemu_io = executable('qemu-io', files('qemu-io.c'),
3285             dependencies: [block, qemuutil], install: true)
3286  qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
3287               dependencies: [blockdev, qemuutil, gnutls, selinux],
3288               install: true)
3289
3290  subdir('storage-daemon')
3291  subdir('contrib/rdmacm-mux')
3292  subdir('contrib/elf2dmp')
3293
3294  executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
3295             dependencies: qemuutil,
3296             install: true)
3297
3298  if 'CONFIG_VHOST_USER' in config_host
3299    subdir('contrib/vhost-user-blk')
3300    subdir('contrib/vhost-user-gpu')
3301    subdir('contrib/vhost-user-input')
3302    subdir('contrib/vhost-user-scsi')
3303  endif
3304
3305  if targetos == 'linux'
3306    executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
3307               dependencies: [qemuutil, libcap_ng],
3308               install: true,
3309               install_dir: get_option('libexecdir'))
3310
3311    executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
3312               dependencies: [authz, crypto, io, qom, qemuutil,
3313                              libcap_ng, mpathpersist],
3314               install: true)
3315  endif
3316
3317  if have_ivshmem
3318    subdir('contrib/ivshmem-client')
3319    subdir('contrib/ivshmem-server')
3320  endif
3321endif
3322
3323subdir('scripts')
3324subdir('tools')
3325subdir('pc-bios')
3326subdir('docs')
3327subdir('tests')
3328if gtk.found()
3329  subdir('po')
3330endif
3331
3332if host_machine.system() == 'windows'
3333  nsis_cmd = [
3334    find_program('scripts/nsis.py'),
3335    '@OUTPUT@',
3336    get_option('prefix'),
3337    meson.current_source_dir(),
3338    host_machine.cpu(),
3339    '--',
3340    '-DDISPLAYVERSION=' + meson.project_version(),
3341  ]
3342  if build_docs
3343    nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
3344  endif
3345  if gtk.found()
3346    nsis_cmd += '-DCONFIG_GTK=y'
3347  endif
3348
3349  nsis = custom_target('nsis',
3350                       output: 'qemu-setup-' + meson.project_version() + '.exe',
3351                       input: files('qemu.nsi'),
3352                       build_always_stale: true,
3353                       command: nsis_cmd + ['@INPUT@'])
3354  alias_target('installer', nsis)
3355endif
3356
3357#########################
3358# Configuration summary #
3359#########################
3360
3361# Directories
3362summary_info = {}
3363summary_info += {'Install prefix':    get_option('prefix')}
3364summary_info += {'BIOS directory':    qemu_datadir}
3365summary_info += {'firmware path':     get_option('qemu_firmwarepath')}
3366summary_info += {'binary directory':  get_option('bindir')}
3367summary_info += {'library directory': get_option('libdir')}
3368summary_info += {'module directory':  qemu_moddir}
3369summary_info += {'libexec directory': get_option('libexecdir')}
3370summary_info += {'include directory': get_option('includedir')}
3371summary_info += {'config directory':  get_option('sysconfdir')}
3372if targetos != 'windows'
3373  summary_info += {'local state directory': get_option('localstatedir')}
3374  summary_info += {'Manual directory':      get_option('mandir')}
3375else
3376  summary_info += {'local state directory': 'queried at runtime'}
3377endif
3378summary_info += {'Doc directory':     get_option('docdir')}
3379summary_info += {'Build directory':   meson.current_build_dir()}
3380summary_info += {'Source path':       meson.current_source_dir()}
3381summary_info += {'GIT submodules':    config_host['GIT_SUBMODULES']}
3382summary(summary_info, bool_yn: true, section: 'Directories')
3383
3384# Host binaries
3385summary_info = {}
3386summary_info += {'git':               config_host['GIT']}
3387summary_info += {'make':              config_host['MAKE']}
3388summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
3389summary_info += {'sphinx-build':      sphinx_build}
3390if config_host.has_key('HAVE_GDB_BIN')
3391  summary_info += {'gdb':             config_host['HAVE_GDB_BIN']}
3392endif
3393if get_option('iasl') != ''
3394  summary_info += {'iasl':            get_option('iasl')}
3395else
3396  summary_info += {'iasl':            false}
3397endif
3398summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
3399if targetos == 'windows' and have_ga
3400  summary_info += {'wixl':            wixl}
3401endif
3402if slirp_opt != 'disabled' and have_system
3403  summary_info += {'smbd':            have_slirp_smbd ? smbd_path : false}
3404endif
3405summary(summary_info, bool_yn: true, section: 'Host binaries')
3406
3407# Configurable features
3408summary_info = {}
3409summary_info += {'Documentation':     build_docs}
3410summary_info += {'system-mode emulation': have_system}
3411summary_info += {'user-mode emulation': have_user}
3412summary_info += {'block layer':       have_block}
3413summary_info += {'Install blobs':     get_option('install_blobs')}
3414summary_info += {'module support':    config_host.has_key('CONFIG_MODULES')}
3415if config_host.has_key('CONFIG_MODULES')
3416  summary_info += {'alternative module path': config_host.has_key('CONFIG_MODULE_UPGRADES')}
3417endif
3418summary_info += {'fuzzing support':   get_option('fuzzing')}
3419if have_system
3420  summary_info += {'Audio drivers':     ' '.join(audio_drivers_selected)}
3421endif
3422summary_info += {'Trace backends':    ','.join(get_option('trace_backends'))}
3423if 'simple' in get_option('trace_backends')
3424  summary_info += {'Trace output file': get_option('trace_file') + '-<pid>'}
3425endif
3426summary_info += {'D-Bus display':     dbus_display}
3427summary_info += {'QOM debugging':     get_option('qom_cast_debug')}
3428summary_info += {'vhost-kernel support': config_host.has_key('CONFIG_VHOST_KERNEL')}
3429summary_info += {'vhost-net support': config_host.has_key('CONFIG_VHOST_NET')}
3430summary_info += {'vhost-crypto support': config_host.has_key('CONFIG_VHOST_CRYPTO')}
3431summary_info += {'vhost-scsi support': config_host.has_key('CONFIG_VHOST_SCSI')}
3432summary_info += {'vhost-vsock support': config_host.has_key('CONFIG_VHOST_VSOCK')}
3433summary_info += {'vhost-user support': config_host.has_key('CONFIG_VHOST_USER')}
3434summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
3435summary_info += {'vhost-user-fs support': config_host.has_key('CONFIG_VHOST_USER_FS')}
3436summary_info += {'vhost-vdpa support': config_host.has_key('CONFIG_VHOST_VDPA')}
3437summary_info += {'build guest agent': have_ga}
3438summary(summary_info, bool_yn: true, section: 'Configurable features')
3439
3440# Compilation information
3441summary_info = {}
3442summary_info += {'host CPU':          cpu}
3443summary_info += {'host endianness':   build_machine.endian()}
3444summary_info += {'C compiler':        ' '.join(meson.get_compiler('c').cmd_array())}
3445summary_info += {'Host C compiler':   ' '.join(meson.get_compiler('c', native: true).cmd_array())}
3446if link_language == 'cpp'
3447  summary_info += {'C++ compiler':    ' '.join(meson.get_compiler('cpp').cmd_array())}
3448else
3449  summary_info += {'C++ compiler':      false}
3450endif
3451if targetos == 'darwin'
3452  summary_info += {'Objective-C compiler': ' '.join(meson.get_compiler('objc').cmd_array())}
3453endif
3454summary_info += {'CFLAGS':            ' '.join(get_option('c_args')
3455                                               + ['-O' + get_option('optimization')]
3456                                               + (get_option('debug') ? ['-g'] : []))}
3457if link_language == 'cpp'
3458  summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args')
3459                                               + ['-O' + get_option('optimization')]
3460                                               + (get_option('debug') ? ['-g'] : []))}
3461endif
3462link_args = get_option(link_language + '_link_args')
3463if link_args.length() > 0
3464  summary_info += {'LDFLAGS':         ' '.join(link_args)}
3465endif
3466summary_info += {'QEMU_CFLAGS':       config_host['QEMU_CFLAGS']}
3467summary_info += {'QEMU_LDFLAGS':      config_host['QEMU_LDFLAGS']}
3468summary_info += {'profiler':          get_option('profiler')}
3469summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
3470summary_info += {'PIE':               get_option('b_pie')}
3471summary_info += {'static build':      config_host.has_key('CONFIG_STATIC')}
3472summary_info += {'malloc trim support': has_malloc_trim}
3473summary_info += {'membarrier':        have_membarrier}
3474summary_info += {'debug stack usage': get_option('debug_stack_usage')}
3475summary_info += {'mutex debugging':   get_option('debug_mutex')}
3476summary_info += {'memory allocator':  get_option('malloc')}
3477summary_info += {'avx2 optimization': config_host_data.get('CONFIG_AVX2_OPT')}
3478summary_info += {'avx512f optimization': config_host_data.get('CONFIG_AVX512F_OPT')}
3479summary_info += {'gprof enabled':     get_option('gprof')}
3480summary_info += {'gcov':              get_option('b_coverage')}
3481summary_info += {'thread sanitizer':  config_host.has_key('CONFIG_TSAN')}
3482summary_info += {'CFI support':       get_option('cfi')}
3483if get_option('cfi')
3484  summary_info += {'CFI debug support': get_option('cfi_debug')}
3485endif
3486summary_info += {'strip binaries':    get_option('strip')}
3487summary_info += {'sparse':            sparse}
3488summary_info += {'mingw32 support':   targetos == 'windows'}
3489
3490# snarf the cross-compilation information for tests
3491foreach target: target_dirs
3492  tcg_mak = meson.current_build_dir() / 'tests/tcg' / 'config-' + target + '.mak'
3493  if fs.exists(tcg_mak)
3494    config_cross_tcg = keyval.load(tcg_mak)
3495    target = config_cross_tcg['TARGET_NAME']
3496    compiler = ''
3497    if 'DOCKER_CROSS_CC_GUEST' in config_cross_tcg
3498      summary_info += {target + ' tests': config_cross_tcg['DOCKER_CROSS_CC_GUEST'] +
3499                                          ' via ' + config_cross_tcg['DOCKER_IMAGE']}
3500    elif 'CROSS_CC_GUEST' in config_cross_tcg
3501      summary_info += {target + ' tests'
3502                                : config_cross_tcg['CROSS_CC_GUEST'] }
3503    endif
3504   endif
3505endforeach
3506
3507summary(summary_info, bool_yn: true, section: 'Compilation')
3508
3509# Targets and accelerators
3510summary_info = {}
3511if have_system
3512  summary_info += {'KVM support':       config_all.has_key('CONFIG_KVM')}
3513  summary_info += {'HAX support':       config_all.has_key('CONFIG_HAX')}
3514  summary_info += {'HVF support':       config_all.has_key('CONFIG_HVF')}
3515  summary_info += {'WHPX support':      config_all.has_key('CONFIG_WHPX')}
3516  summary_info += {'NVMM support':      config_all.has_key('CONFIG_NVMM')}
3517  summary_info += {'Xen support':       config_host.has_key('CONFIG_XEN_BACKEND')}
3518  if config_host.has_key('CONFIG_XEN_BACKEND')
3519    summary_info += {'xen ctrl version':  config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']}
3520  endif
3521endif
3522summary_info += {'TCG support':       config_all.has_key('CONFIG_TCG')}
3523if config_all.has_key('CONFIG_TCG')
3524  if get_option('tcg_interpreter')
3525    summary_info += {'TCG backend':   'TCI (TCG with bytecode interpreter, slow)'}
3526  else
3527    summary_info += {'TCG backend':   'native (@0@)'.format(cpu)}
3528  endif
3529  summary_info += {'TCG plugins': config_host.has_key('CONFIG_PLUGIN')}
3530  summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')}
3531endif
3532summary_info += {'target list':       ' '.join(target_dirs)}
3533if have_system
3534  summary_info += {'default devices':   get_option('default_devices')}
3535  summary_info += {'out of process emulation': multiprocess_allowed}
3536endif
3537summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
3538
3539# Block layer
3540summary_info = {}
3541summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']}
3542summary_info += {'coroutine pool':    have_coroutine_pool}
3543if have_block
3544  summary_info += {'Block whitelist (rw)': config_host['CONFIG_BDRV_RW_WHITELIST']}
3545  summary_info += {'Block whitelist (ro)': config_host['CONFIG_BDRV_RO_WHITELIST']}
3546  summary_info += {'Use block whitelist in tools': get_option('block_drv_whitelist_in_tools')}
3547  summary_info += {'VirtFS support':    have_virtfs}
3548  summary_info += {'build virtiofs daemon': have_virtiofsd}
3549  summary_info += {'Live block migration': config_host_data.get('CONFIG_LIVE_BLOCK_MIGRATION')}
3550  summary_info += {'replication support': config_host_data.get('CONFIG_REPLICATION')}
3551  summary_info += {'bochs support':     get_option('bochs').allowed()}
3552  summary_info += {'cloop support':     get_option('cloop').allowed()}
3553  summary_info += {'dmg support':       get_option('dmg').allowed()}
3554  summary_info += {'qcow v1 support':   get_option('qcow1').allowed()}
3555  summary_info += {'vdi support':       get_option('vdi').allowed()}
3556  summary_info += {'vvfat support':     get_option('vvfat').allowed()}
3557  summary_info += {'qed support':       get_option('qed').allowed()}
3558  summary_info += {'parallels support': get_option('parallels').allowed()}
3559  summary_info += {'FUSE exports':      fuse}
3560endif
3561summary(summary_info, bool_yn: true, section: 'Block layer support')
3562
3563# Crypto
3564summary_info = {}
3565summary_info += {'TLS priority':      config_host['CONFIG_TLS_PRIORITY']}
3566summary_info += {'GNUTLS support':    gnutls}
3567if gnutls.found()
3568  summary_info += {'  GNUTLS crypto':   gnutls_crypto.found()}
3569endif
3570summary_info += {'libgcrypt':         gcrypt}
3571summary_info += {'nettle':            nettle}
3572if nettle.found()
3573   summary_info += {'  XTS':             xts != 'private'}
3574endif
3575summary_info += {'AF_ALG support':    have_afalg}
3576summary_info += {'rng-none':          get_option('rng_none')}
3577summary_info += {'Linux keyring':     config_host.has_key('CONFIG_SECRET_KEYRING')}
3578summary(summary_info, bool_yn: true, section: 'Crypto')
3579
3580# Libraries
3581summary_info = {}
3582if targetos == 'darwin'
3583  summary_info += {'Cocoa support':   cocoa}
3584endif
3585summary_info += {'SDL support':       sdl}
3586summary_info += {'SDL image support': sdl_image}
3587summary_info += {'GTK support':       gtk}
3588summary_info += {'pixman':            pixman}
3589summary_info += {'VTE support':       vte}
3590summary_info += {'slirp support':     slirp_opt == 'internal' ? slirp_opt : slirp}
3591summary_info += {'libtasn1':          tasn1}
3592summary_info += {'PAM':               pam}
3593summary_info += {'iconv support':     iconv}
3594summary_info += {'curses support':    curses}
3595summary_info += {'virgl support':     virgl}
3596summary_info += {'curl support':      curl}
3597summary_info += {'Multipath support': mpathpersist}
3598summary_info += {'VNC support':       vnc}
3599if vnc.found()
3600  summary_info += {'VNC SASL support':  sasl}
3601  summary_info += {'VNC JPEG support':  jpeg}
3602  summary_info += {'VNC PNG support':   png}
3603endif
3604if targetos not in ['darwin', 'haiku', 'windows']
3605  summary_info += {'OSS support':     oss}
3606elif targetos == 'darwin'
3607  summary_info += {'CoreAudio support': coreaudio}
3608elif targetos == 'windows'
3609  summary_info += {'DirectSound support': dsound}
3610endif
3611if targetos == 'linux'
3612  summary_info += {'ALSA support':    alsa}
3613  summary_info += {'PulseAudio support': pulse}
3614endif
3615summary_info += {'JACK support':      jack}
3616summary_info += {'brlapi support':    brlapi}
3617summary_info += {'vde support':       vde}
3618summary_info += {'netmap support':    have_netmap}
3619summary_info += {'l2tpv3 support':    have_l2tpv3}
3620summary_info += {'Linux AIO support': libaio}
3621summary_info += {'Linux io_uring support': linux_io_uring}
3622summary_info += {'ATTR/XATTR support': libattr}
3623summary_info += {'RDMA support':      config_host.has_key('CONFIG_RDMA')}
3624summary_info += {'PVRDMA support':    config_host.has_key('CONFIG_PVRDMA')}
3625summary_info += {'fdt support':       fdt_opt == 'disabled' ? false : fdt_opt}
3626summary_info += {'libcap-ng support': libcap_ng}
3627summary_info += {'bpf support':       libbpf}
3628summary_info += {'spice protocol support': spice_protocol}
3629if spice_protocol.found()
3630  summary_info += {'  spice server support': spice}
3631endif
3632summary_info += {'rbd support':       rbd}
3633summary_info += {'smartcard support': cacard}
3634summary_info += {'U2F support':       u2f}
3635summary_info += {'libusb':            libusb}
3636summary_info += {'usb net redir':     usbredir}
3637summary_info += {'OpenGL support':    config_host.has_key('CONFIG_OPENGL')}
3638summary_info += {'GBM':               gbm}
3639summary_info += {'libiscsi support':  libiscsi}
3640summary_info += {'libnfs support':    libnfs}
3641if targetos == 'windows'
3642  if have_ga
3643    summary_info += {'QGA VSS support':   have_qga_vss}
3644    summary_info += {'QGA w32 disk info': have_ntddscsi}
3645  endif
3646endif
3647summary_info += {'seccomp support':   seccomp}
3648summary_info += {'GlusterFS support': glusterfs}
3649summary_info += {'TPM support':       have_tpm}
3650summary_info += {'libssh support':    libssh}
3651summary_info += {'lzo support':       lzo}
3652summary_info += {'snappy support':    snappy}
3653summary_info += {'bzip2 support':     libbzip2}
3654summary_info += {'lzfse support':     liblzfse}
3655summary_info += {'zstd support':      zstd}
3656summary_info += {'NUMA host support': numa}
3657summary_info += {'capstone':          capstone_opt == 'internal' ? capstone_opt : capstone}
3658summary_info += {'libpmem support':   libpmem}
3659summary_info += {'libdaxctl support': libdaxctl}
3660summary_info += {'libudev':           libudev}
3661# Dummy dependency, keep .found()
3662summary_info += {'FUSE lseek':        fuse_lseek.found()}
3663summary_info += {'selinux':           selinux}
3664summary(summary_info, bool_yn: true, section: 'Dependencies')
3665
3666if not supported_cpus.contains(cpu)
3667  message()
3668  warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!')
3669  message()
3670  message('CPU host architecture ' + cpu + ' support is not currently maintained.')
3671  message('The QEMU project intends to remove support for this host CPU in')
3672  message('a future release if nobody volunteers to maintain it and to')
3673  message('provide a build host for our continuous integration setup.')
3674  message('configure has succeeded and you can continue to build, but')
3675  message('if you care about QEMU on this platform you should contact')
3676  message('us upstream at qemu-devel@nongnu.org.')
3677endif
3678
3679if not supported_oses.contains(targetos)
3680  message()
3681  warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!')
3682  message()
3683  message('Host OS ' + targetos + 'support is not currently maintained.')
3684  message('The QEMU project intends to remove support for this host OS in')
3685  message('a future release if nobody volunteers to maintain it and to')
3686  message('provide a build host for our continuous integration setup.')
3687  message('configure has succeeded and you can continue to build, but')
3688  message('if you care about QEMU on this platform you should contact')
3689  message('us upstream at qemu-devel@nongnu.org.')
3690endif
3691