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