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