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