qemu/meson.build
<<
>>
Prefs
   1project('qemu', ['c'], meson_version: '>=0.55.0',
   2        default_options: ['warning_level=1', 'c_std=gnu99', 'cpp_std=gnu++11', 'b_colorout=auto'] +
   3                         (meson.version().version_compare('>=0.56.0') ? [ 'b_staticpic=false' ] : []),
   4        version: run_command('head', meson.source_root() / 'VERSION').stdout().strip())
   5
   6not_found = dependency('', required: false)
   7if meson.version().version_compare('>=0.56.0')
   8  keyval = import('keyval')
   9else
  10  keyval = import('unstable-keyval')
  11endif
  12ss = import('sourceset')
  13fs = import('fs')
  14
  15sh = find_program('sh')
  16cc = meson.get_compiler('c')
  17config_host = keyval.load(meson.current_build_dir() / 'config-host.mak')
  18enable_modules = 'CONFIG_MODULES' in config_host
  19enable_static = 'CONFIG_STATIC' in config_host
  20
  21# Allow both shared and static libraries unless --enable-static
  22static_kwargs = enable_static ? {'static': true} : {}
  23
  24# Temporary directory used for files created while
  25# configure runs. Since it is in the build directory
  26# we can safely blow away any previous version of it
  27# (and we need not jump through hoops to try to delete
  28# it when configure exits.)
  29tmpdir = meson.current_build_dir() / 'meson-private/temp'
  30
  31if get_option('qemu_suffix').startswith('/')
  32  error('qemu_suffix cannot start with a /')
  33endif
  34
  35qemu_confdir = get_option('sysconfdir') / get_option('qemu_suffix')
  36qemu_datadir = get_option('datadir') / get_option('qemu_suffix')
  37qemu_docdir = get_option('docdir') / get_option('qemu_suffix')
  38qemu_moddir = get_option('libdir') / get_option('qemu_suffix')
  39
  40qemu_desktopdir = get_option('datadir') / 'applications'
  41qemu_icondir = get_option('datadir') / 'icons'
  42
  43config_host_data = configuration_data()
  44genh = []
  45
  46target_dirs = config_host['TARGET_DIRS'].split()
  47have_user = false
  48have_system = false
  49foreach target : target_dirs
  50  have_user = have_user or target.endswith('-user')
  51  have_system = have_system or target.endswith('-softmmu')
  52endforeach
  53have_tools = 'CONFIG_TOOLS' in config_host
  54have_block = have_system or have_tools
  55
  56python = import('python').find_installation()
  57
  58supported_oses = ['windows', 'freebsd', 'netbsd', 'openbsd', 'darwin', 'sunos', 'linux']
  59supported_cpus = ['ppc', 'ppc64', 's390x', 'riscv32', 'riscv64', 'x86', 'x86_64',
  60  'arm', 'aarch64', 'mips', 'mips64', 'sparc', 'sparc64']
  61
  62cpu = host_machine.cpu_family()
  63targetos = host_machine.system()
  64
  65if cpu in ['x86', 'x86_64']
  66  kvm_targets = ['i386-softmmu', 'x86_64-softmmu']
  67elif cpu == 'aarch64'
  68  kvm_targets = ['aarch64-softmmu']
  69elif cpu == 's390x'
  70  kvm_targets = ['s390x-softmmu']
  71elif cpu in ['ppc', 'ppc64']
  72  kvm_targets = ['ppc-softmmu', 'ppc64-softmmu']
  73elif cpu in ['mips', 'mips64']
  74  kvm_targets = ['mips-softmmu', 'mipsel-softmmu', 'mips64-softmmu', 'mips64el-softmmu']
  75else
  76  kvm_targets = []
  77endif
  78
  79accelerator_targets = { 'CONFIG_KVM': kvm_targets }
  80if cpu in ['x86', 'x86_64', 'arm', 'aarch64']
  81  # i368 emulator provides xenpv machine type for multiple architectures
  82  accelerator_targets += {
  83    'CONFIG_XEN': ['i386-softmmu', 'x86_64-softmmu'],
  84  }
  85endif
  86if cpu in ['x86', 'x86_64']
  87  accelerator_targets += {
  88    'CONFIG_HAX': ['i386-softmmu', 'x86_64-softmmu'],
  89    'CONFIG_HVF': ['x86_64-softmmu'],
  90    'CONFIG_WHPX': ['i386-softmmu', 'x86_64-softmmu'],
  91  }
  92endif
  93
  94edk2_targets = [ 'arm-softmmu', 'aarch64-softmmu', 'i386-softmmu', 'x86_64-softmmu' ]
  95install_edk2_blobs = false
  96if get_option('install_blobs')
  97  foreach target : target_dirs
  98    install_edk2_blobs = install_edk2_blobs or target in edk2_targets
  99  endforeach
 100endif
 101
 102bzip2 = find_program('bzip2', required: install_edk2_blobs)
 103
 104##################
 105# Compiler flags #
 106##################
 107
 108# Specify linker-script with add_project_link_arguments so that it is not placed
 109# within a linker --start-group/--end-group pair
 110if 'CONFIG_FUZZ' in config_host
 111   add_project_link_arguments(['-Wl,-T,',
 112                               (meson.current_source_dir() / 'tests/qtest/fuzz/fork_fuzz.ld')],
 113                              native: false, language: ['c', 'cpp', 'objc'])
 114endif
 115
 116add_global_arguments(config_host['QEMU_CFLAGS'].split(),
 117                     native: false, language: ['c', 'objc'])
 118add_global_arguments(config_host['QEMU_CXXFLAGS'].split(),
 119                     native: false, language: 'cpp')
 120add_global_link_arguments(config_host['QEMU_LDFLAGS'].split(),
 121                          native: false, language: ['c', 'cpp', 'objc'])
 122
 123if targetos == 'linux'
 124  add_project_arguments('-isystem', meson.current_source_dir() / 'linux-headers',
 125                        '-isystem', 'linux-headers',
 126                        language: ['c', 'cpp'])
 127endif
 128
 129add_project_arguments('-iquote', '.',
 130                      '-iquote', meson.current_source_dir(),
 131                      '-iquote', meson.current_source_dir() / 'include',
 132                      '-iquote', meson.current_source_dir() / 'disas/libvixl',
 133                      language: ['c', 'cpp', 'objc'])
 134
 135link_language = meson.get_external_property('link_language', 'cpp')
 136if link_language == 'cpp'
 137  add_languages('cpp', required: true, native: false)
 138endif
 139if host_machine.system() == 'darwin'
 140  add_languages('objc', required: false, native: false)
 141endif
 142
 143sparse = find_program('cgcc', required: get_option('sparse'))
 144if sparse.found()
 145  run_target('sparse',
 146             command: [find_program('scripts/check_sparse.py'),
 147                       'compile_commands.json', sparse.full_path(), '-Wbitwise',
 148                       '-Wno-transparent-union', '-Wno-old-initializer',
 149                       '-Wno-non-pointer-null'])
 150endif
 151
 152###########################################
 153# Target-specific checks and dependencies #
 154###########################################
 155
 156if targetos != 'linux' and get_option('mpath').enabled()
 157  error('Multipath is supported only on Linux')
 158endif
 159
 160if targetos != 'linux' and get_option('multiprocess').enabled()
 161  error('Multiprocess QEMU is supported only on Linux')
 162endif
 163multiprocess_allowed = targetos == 'linux' and not get_option('multiprocess').disabled()
 164
 165m = cc.find_library('m', required: false)
 166util = cc.find_library('util', required: false)
 167winmm = []
 168socket = []
 169version_res = []
 170coref = []
 171iokit = []
 172emulator_link_args = []
 173hvf = not_found
 174if targetos == 'windows'
 175  socket = cc.find_library('ws2_32')
 176  winmm = cc.find_library('winmm')
 177
 178  win = import('windows')
 179  version_res = win.compile_resources('version.rc',
 180                                      depend_files: files('pc-bios/qemu-nsis.ico'),
 181                                      include_directories: include_directories('.'))
 182elif targetos == 'darwin'
 183  coref = dependency('appleframeworks', modules: 'CoreFoundation')
 184  iokit = dependency('appleframeworks', modules: 'IOKit')
 185elif targetos == 'sunos'
 186  socket = [cc.find_library('socket'),
 187            cc.find_library('nsl'),
 188            cc.find_library('resolv')]
 189elif targetos == 'haiku'
 190  socket = [cc.find_library('posix_error_mapper'),
 191            cc.find_library('network'),
 192            cc.find_library('bsd')]
 193elif targetos == 'openbsd'
 194  if not get_option('tcg').disabled() and target_dirs.length() > 0
 195    # Disable OpenBSD W^X if available
 196    emulator_link_args = cc.get_supported_link_arguments('-Wl,-z,wxneeded')
 197  endif
 198endif
 199
 200accelerators = []
 201if not get_option('kvm').disabled() and targetos == 'linux'
 202  accelerators += 'CONFIG_KVM'
 203endif
 204if not get_option('xen').disabled() and 'CONFIG_XEN_BACKEND' in config_host
 205  accelerators += 'CONFIG_XEN'
 206  have_xen_pci_passthrough = not get_option('xen_pci_passthrough').disabled() and targetos == 'linux'
 207else
 208  have_xen_pci_passthrough = false
 209endif
 210if not get_option('whpx').disabled() and targetos == 'windows'
 211  if get_option('whpx').enabled() and host_machine.cpu() != 'x86_64'
 212    error('WHPX requires 64-bit host')
 213  elif cc.has_header('WinHvPlatform.h', required: get_option('whpx')) and \
 214       cc.has_header('WinHvEmulation.h', required: get_option('whpx'))
 215    accelerators += 'CONFIG_WHPX'
 216  endif
 217endif
 218if not get_option('hvf').disabled()
 219  hvf = dependency('appleframeworks', modules: 'Hypervisor',
 220                   required: get_option('hvf'))
 221  if hvf.found()
 222    accelerators += 'CONFIG_HVF'
 223  endif
 224endif
 225if not get_option('hax').disabled()
 226  if get_option('hax').enabled() or targetos in ['windows', 'darwin', 'netbsd']
 227    accelerators += 'CONFIG_HAX'
 228  endif
 229endif
 230
 231tcg_arch = config_host['ARCH']
 232if not get_option('tcg').disabled()
 233  if cpu not in supported_cpus
 234    if get_option('tcg_interpreter')
 235      warning('Unsupported CPU @0@, will use TCG with TCI (experimental and slow)'.format(cpu))
 236    else
 237      error('Unsupported CPU @0@, try --enable-tcg-interpreter'.format(cpu))
 238    endif
 239  elif get_option('tcg_interpreter')
 240    warning('Use of the TCG interpretor is not recommended on this host')
 241    warning('architecture. There is a native TCG execution backend available')
 242    warning('which provides substantially better performance and reliability.')
 243    warning('It is strongly recommended to remove the --enable-tcg-interpreter')
 244    warning('configuration option on this architecture to use the native')
 245    warning('backend.')
 246  endif
 247  if get_option('tcg_interpreter')
 248    tcg_arch = 'tci'
 249  elif config_host['ARCH'] == 'sparc64'
 250    tcg_arch = 'sparc'
 251  elif config_host['ARCH'] == 's390x'
 252    tcg_arch = 's390'
 253  elif config_host['ARCH'] in ['x86_64', 'x32']
 254    tcg_arch = 'i386'
 255  elif config_host['ARCH'] == 'ppc64'
 256    tcg_arch = 'ppc'
 257  elif config_host['ARCH'] in ['riscv32', 'riscv64']
 258    tcg_arch = 'riscv'
 259  endif
 260  add_project_arguments('-iquote', meson.current_source_dir() / 'tcg' / tcg_arch,
 261                        '-iquote', meson.current_source_dir() / 'accel/tcg',
 262                        language: ['c', 'cpp', 'objc'])
 263
 264  accelerators += 'CONFIG_TCG'
 265  config_host += { 'CONFIG_TCG': 'y' }
 266endif
 267
 268if 'CONFIG_KVM' not in accelerators and get_option('kvm').enabled()
 269  error('KVM not available on this platform')
 270endif
 271if 'CONFIG_HVF' not in accelerators and get_option('hvf').enabled()
 272  error('HVF not available on this platform')
 273endif
 274if 'CONFIG_WHPX' not in accelerators and get_option('whpx').enabled()
 275  error('WHPX not available on this platform')
 276endif
 277if not have_xen_pci_passthrough and get_option('xen_pci_passthrough').enabled()
 278  if 'CONFIG_XEN' in accelerators
 279    error('Xen PCI passthrough not available on this platform')
 280  else
 281    error('Xen PCI passthrough requested but Xen not enabled')
 282  endif
 283endif
 284
 285################
 286# Dependencies #
 287################
 288
 289# The path to glib.h is added to all compilation commands.  This was
 290# grandfathered in from the QEMU Makefiles.
 291add_project_arguments(config_host['GLIB_CFLAGS'].split(),
 292                      native: false, language: ['c', 'cpp', 'objc'])
 293glib = declare_dependency(compile_args: config_host['GLIB_CFLAGS'].split(),
 294                          link_args: config_host['GLIB_LIBS'].split())
 295# override glib dep with the configure results (for subprojects)
 296meson.override_dependency('glib-2.0', glib)
 297
 298gio = not_found
 299if 'CONFIG_GIO' in config_host
 300  gio = declare_dependency(compile_args: config_host['GIO_CFLAGS'].split(),
 301                           link_args: config_host['GIO_LIBS'].split())
 302endif
 303lttng = not_found
 304if 'CONFIG_TRACE_UST' in config_host
 305  lttng = declare_dependency(link_args: config_host['LTTNG_UST_LIBS'].split())
 306endif
 307urcubp = not_found
 308if 'CONFIG_TRACE_UST' in config_host
 309  urcubp = declare_dependency(link_args: config_host['URCU_BP_LIBS'].split())
 310endif
 311gcrypt = not_found
 312if 'CONFIG_GCRYPT' in config_host
 313  gcrypt = declare_dependency(compile_args: config_host['GCRYPT_CFLAGS'].split(),
 314                              link_args: config_host['GCRYPT_LIBS'].split())
 315endif
 316nettle = not_found
 317if 'CONFIG_NETTLE' in config_host
 318  nettle = declare_dependency(compile_args: config_host['NETTLE_CFLAGS'].split(),
 319                              link_args: config_host['NETTLE_LIBS'].split())
 320endif
 321gnutls = not_found
 322if 'CONFIG_GNUTLS' in config_host
 323  gnutls = declare_dependency(compile_args: config_host['GNUTLS_CFLAGS'].split(),
 324                              link_args: config_host['GNUTLS_LIBS'].split())
 325endif
 326pixman = not_found
 327if have_system or have_tools
 328  pixman = dependency('pixman-1', required: have_system, version:'>=0.21.8',
 329                      method: 'pkg-config', kwargs: static_kwargs)
 330endif
 331pam = not_found
 332if 'CONFIG_AUTH_PAM' in config_host
 333  pam = cc.find_library('pam')
 334endif
 335libaio = cc.find_library('aio', required: false)
 336zlib = dependency('zlib', required: true, kwargs: static_kwargs)
 337linux_io_uring = not_found
 338if 'CONFIG_LINUX_IO_URING' in config_host
 339  linux_io_uring = declare_dependency(compile_args: config_host['LINUX_IO_URING_CFLAGS'].split(),
 340                                      link_args: config_host['LINUX_IO_URING_LIBS'].split())
 341endif
 342libxml2 = not_found
 343if 'CONFIG_LIBXML2' in config_host
 344  libxml2 = declare_dependency(compile_args: config_host['LIBXML2_CFLAGS'].split(),
 345                               link_args: config_host['LIBXML2_LIBS'].split())
 346endif
 347libnfs = not_found
 348if not get_option('libnfs').auto() or have_block
 349  libnfs = dependency('libnfs', version: '>=1.9.3',
 350                      required: get_option('libnfs'),
 351                      method: 'pkg-config', kwargs: static_kwargs)
 352endif
 353
 354libattr_test = '''
 355  #include <stddef.h>
 356  #include <sys/types.h>
 357  #ifdef CONFIG_LIBATTR
 358  #include <attr/xattr.h>
 359  #else
 360  #include <sys/xattr.h>
 361  #endif
 362  int main(void) { getxattr(NULL, NULL, NULL, 0); setxattr(NULL, NULL, NULL, 0, 0); return 0; }'''
 363
 364libattr = not_found
 365have_old_libattr = false
 366if not get_option('attr').disabled()
 367  if cc.links(libattr_test)
 368    libattr = declare_dependency()
 369  else
 370    libattr = cc.find_library('attr', has_headers: ['attr/xattr.h'],
 371                              required: get_option('attr'),
 372                              kwargs: static_kwargs)
 373    if libattr.found() and not \
 374      cc.links(libattr_test, dependencies: libattr, args: '-DCONFIG_LIBATTR')
 375      libattr = not_found
 376      if get_option('attr').enabled()
 377        error('could not link libattr')
 378      else
 379        warning('could not link libattr, disabling')
 380      endif
 381    else
 382      have_old_libattr = libattr.found()
 383    endif
 384  endif
 385endif
 386
 387cocoa = dependency('appleframeworks', modules: 'Cocoa', required: get_option('cocoa'))
 388if cocoa.found() and get_option('sdl').enabled()
 389  error('Cocoa and SDL cannot be enabled at the same time')
 390endif
 391if cocoa.found() and get_option('gtk').enabled()
 392  error('Cocoa and GTK+ cannot be enabled at the same time')
 393endif
 394
 395seccomp = not_found
 396if not get_option('seccomp').auto() or have_system or have_tools
 397  seccomp = dependency('libseccomp', version: '>=2.3.0',
 398                       required: get_option('seccomp'),
 399                       method: 'pkg-config', kwargs: static_kwargs)
 400endif
 401
 402libcap_ng = not_found
 403if not get_option('cap_ng').auto() or have_system or have_tools
 404  libcap_ng = cc.find_library('cap-ng', has_headers: ['cap-ng.h'],
 405                              required: get_option('cap_ng'),
 406                              kwargs: static_kwargs)
 407endif
 408if libcap_ng.found() and not cc.links('''
 409   #include <cap-ng.h>
 410   int main(void)
 411   {
 412     capng_capability_to_name(CAPNG_EFFECTIVE);
 413     return 0;
 414   }''', dependencies: libcap_ng)
 415  libcap_ng = not_found
 416  if get_option('cap_ng').enabled()
 417    error('could not link libcap-ng')
 418  else
 419    warning('could not link libcap-ng, disabling')
 420  endif
 421endif
 422
 423if get_option('xkbcommon').auto() and not have_system and not have_tools
 424  xkbcommon = not_found
 425else
 426  xkbcommon = dependency('xkbcommon', required: get_option('xkbcommon'),
 427                         method: 'pkg-config', kwargs: static_kwargs)
 428endif
 429vde = not_found
 430if config_host.has_key('CONFIG_VDE')
 431  vde = declare_dependency(link_args: config_host['VDE_LIBS'].split())
 432endif
 433pulse = not_found
 434if 'CONFIG_LIBPULSE' in config_host
 435  pulse = declare_dependency(compile_args: config_host['PULSE_CFLAGS'].split(),
 436                             link_args: config_host['PULSE_LIBS'].split())
 437endif
 438alsa = not_found
 439if 'CONFIG_ALSA' in config_host
 440  alsa = declare_dependency(compile_args: config_host['ALSA_CFLAGS'].split(),
 441                            link_args: config_host['ALSA_LIBS'].split())
 442endif
 443jack = not_found
 444if 'CONFIG_LIBJACK' in config_host
 445  jack = declare_dependency(link_args: config_host['JACK_LIBS'].split())
 446endif
 447spice = not_found
 448spice_headers = not_found
 449if 'CONFIG_SPICE' in config_host
 450  spice = declare_dependency(compile_args: config_host['SPICE_CFLAGS'].split(),
 451                             link_args: config_host['SPICE_LIBS'].split())
 452  spice_headers = declare_dependency(compile_args: config_host['SPICE_CFLAGS'].split())
 453endif
 454rt = cc.find_library('rt', required: false)
 455libdl = not_found
 456if 'CONFIG_PLUGIN' in config_host
 457  libdl = cc.find_library('dl', required: true)
 458endif
 459libiscsi = not_found
 460if not get_option('libiscsi').auto() or have_block
 461  libiscsi = dependency('libiscsi', version: '>=1.9.0',
 462                         required: get_option('libiscsi'),
 463                         method: 'pkg-config', kwargs: static_kwargs)
 464endif
 465zstd = not_found
 466if not get_option('zstd').auto() or have_block
 467  zstd = dependency('libzstd', version: '>=1.4.0',
 468                    required: get_option('zstd'),
 469                    method: 'pkg-config', kwargs: static_kwargs)
 470endif
 471gbm = not_found
 472if 'CONFIG_GBM' in config_host
 473  gbm = declare_dependency(compile_args: config_host['GBM_CFLAGS'].split(),
 474                           link_args: config_host['GBM_LIBS'].split())
 475endif
 476virgl = not_found
 477if 'CONFIG_VIRGL' in config_host
 478  virgl = declare_dependency(compile_args: config_host['VIRGL_CFLAGS'].split(),
 479                             link_args: config_host['VIRGL_LIBS'].split())
 480endif
 481curl = not_found
 482if not get_option('curl').auto() or have_block
 483  curl = dependency('libcurl', version: '>=7.29.0',
 484                    method: 'pkg-config',
 485                    required: get_option('curl'),
 486                    kwargs: static_kwargs)
 487endif
 488libudev = not_found
 489if targetos == 'linux' and (have_system or have_tools)
 490  libudev = dependency('libudev',
 491                       method: 'pkg-config',
 492                       required: get_option('libudev'),
 493                       kwargs: static_kwargs)
 494endif
 495
 496mpathlibs = [libudev]
 497mpathpersist = not_found
 498mpathpersist_new_api = false
 499if targetos == 'linux' and have_tools and not get_option('mpath').disabled()
 500  mpath_test_source_new = '''
 501    #include <libudev.h>
 502    #include <mpath_persist.h>
 503    unsigned mpath_mx_alloc_len = 1024;
 504    int logsink;
 505    static struct config *multipath_conf;
 506    extern struct udev *udev;
 507    extern struct config *get_multipath_config(void);
 508    extern void put_multipath_config(struct config *conf);
 509    struct udev *udev;
 510    struct config *get_multipath_config(void) { return multipath_conf; }
 511    void put_multipath_config(struct config *conf) { }
 512    int main(void) {
 513        udev = udev_new();
 514        multipath_conf = mpath_lib_init();
 515        return 0;
 516    }'''
 517  mpath_test_source_old = '''
 518      #include <libudev.h>
 519      #include <mpath_persist.h>
 520      unsigned mpath_mx_alloc_len = 1024;
 521      int logsink;
 522      int main(void) {
 523          struct udev *udev = udev_new();
 524          mpath_lib_init(udev);
 525          return 0;
 526      }'''
 527  libmpathpersist = cc.find_library('mpathpersist',
 528                                    required: get_option('mpath'),
 529                                    kwargs: static_kwargs)
 530  if libmpathpersist.found()
 531    mpathlibs += libmpathpersist
 532    if enable_static
 533      mpathlibs += cc.find_library('devmapper',
 534                                     required: get_option('mpath'),
 535                                     kwargs: static_kwargs)
 536    endif
 537    mpathlibs += cc.find_library('multipath',
 538                                 required: get_option('mpath'),
 539                                 kwargs: static_kwargs)
 540    foreach lib: mpathlibs
 541      if not lib.found()
 542        mpathlibs = []
 543        break
 544      endif
 545    endforeach
 546    if mpathlibs.length() == 0
 547      msg = 'Dependencies missing for libmpathpersist'
 548    elif cc.links(mpath_test_source_new, dependencies: mpathlibs)
 549      mpathpersist = declare_dependency(dependencies: mpathlibs)
 550      mpathpersist_new_api = true
 551    elif cc.links(mpath_test_source_old, dependencies: mpathlibs)
 552      mpathpersist = declare_dependency(dependencies: mpathlibs)
 553    else
 554      msg = 'Cannot detect libmpathpersist API'
 555    endif
 556    if not mpathpersist.found()
 557      if get_option('mpath').enabled()
 558        error(msg)
 559      else
 560        warning(msg + ', disabling')
 561      endif
 562    endif
 563  endif
 564endif
 565
 566iconv = not_found
 567curses = not_found
 568if have_system and not get_option('curses').disabled()
 569  curses_test = '''
 570    #include <locale.h>
 571    #include <curses.h>
 572    #include <wchar.h>
 573    int main(void) {
 574      wchar_t wch = L'w';
 575      setlocale(LC_ALL, "");
 576      resize_term(0, 0);
 577      addwstr(L"wide chars\n");
 578      addnwstr(&wch, 1);
 579      add_wch(WACS_DEGREE);
 580      return 0;
 581    }'''
 582
 583  curses_dep_list = targetos == 'windows' ? ['ncurses', 'ncursesw'] : ['ncursesw']
 584  foreach curses_dep : curses_dep_list
 585    if not curses.found()
 586      curses = dependency(curses_dep,
 587                          required: false,
 588                          method: 'pkg-config',
 589                          kwargs: static_kwargs)
 590    endif
 591  endforeach
 592  msg = get_option('curses').enabled() ? 'curses library not found' : ''
 593  curses_compile_args = ['-DNCURSES_WIDECHAR']
 594  if curses.found()
 595    if cc.links(curses_test, args: curses_compile_args, dependencies: [curses])
 596      curses = declare_dependency(compile_args: curses_compile_args, dependencies: [curses])
 597    else
 598      msg = 'curses package not usable'
 599      curses = not_found
 600    endif
 601  endif
 602  if not curses.found()
 603    has_curses_h = cc.has_header('curses.h', args: curses_compile_args)
 604    if targetos != 'windows' and not has_curses_h
 605      message('Trying with /usr/include/ncursesw')
 606      curses_compile_args += ['-I/usr/include/ncursesw']
 607      has_curses_h = cc.has_header('curses.h', args: curses_compile_args)
 608    endif
 609    if has_curses_h
 610      curses_libname_list = (targetos == 'windows' ? ['pdcurses'] : ['ncursesw', 'cursesw'])
 611      foreach curses_libname : curses_libname_list
 612        libcurses = cc.find_library(curses_libname,
 613                                    required: false,
 614                                    kwargs: static_kwargs)
 615        if libcurses.found()
 616          if cc.links(curses_test, args: curses_compile_args, dependencies: libcurses)
 617            curses = declare_dependency(compile_args: curses_compile_args,
 618                                        dependencies: [libcurses])
 619            break
 620          else
 621            msg = 'curses library not usable'
 622          endif
 623        endif
 624      endforeach
 625    endif
 626  endif
 627  if not get_option('iconv').disabled()
 628    foreach link_args : [ ['-liconv'], [] ]
 629      # Programs will be linked with glib and this will bring in libiconv on FreeBSD.
 630      # We need to use libiconv if available because mixing libiconv's headers with
 631      # the system libc does not work.
 632      # However, without adding glib to the dependencies -L/usr/local/lib will not be
 633      # included in the command line and libiconv will not be found.
 634      if cc.links('''
 635        #include <iconv.h>
 636        int main(void) {
 637          iconv_t conv = iconv_open("WCHAR_T", "UCS-2");
 638          return conv != (iconv_t) -1;
 639        }''', args: config_host['GLIB_CFLAGS'].split() + config_host['GLIB_LIBS'].split() + link_args)
 640        iconv = declare_dependency(link_args: link_args, dependencies: glib)
 641        break
 642      endif
 643    endforeach
 644  endif
 645  if curses.found() and not iconv.found()
 646    if get_option('iconv').enabled()
 647      error('iconv not available')
 648    endif
 649    msg = 'iconv required for curses UI but not available'
 650    curses = not_found
 651  endif
 652  if not curses.found() and msg != ''
 653    if get_option('curses').enabled()
 654      error(msg)
 655    else
 656      warning(msg + ', disabling')
 657    endif
 658  endif
 659endif
 660
 661brlapi = not_found
 662if not get_option('brlapi').auto() or have_system
 663  brlapi = cc.find_library('brlapi', has_headers: ['brlapi.h'],
 664                         required: get_option('brlapi'),
 665                         kwargs: static_kwargs)
 666  if brlapi.found() and not cc.links('''
 667     #include <brlapi.h>
 668     #include <stddef.h>
 669     int main(void) { return brlapi__openConnection (NULL, NULL, NULL); }''', dependencies: brlapi)
 670    brlapi = not_found
 671    if get_option('brlapi').enabled()
 672      error('could not link brlapi')
 673    else
 674      warning('could not link brlapi, disabling')
 675    endif
 676  endif
 677endif
 678
 679sdl = not_found
 680if not get_option('sdl').auto() or (have_system and not cocoa.found())
 681  sdl = dependency('sdl2', required: get_option('sdl'), kwargs: static_kwargs)
 682  sdl_image = not_found
 683endif
 684if sdl.found()
 685  # work around 2.0.8 bug
 686  sdl = declare_dependency(compile_args: '-Wno-undef',
 687                           dependencies: sdl)
 688  sdl_image = dependency('SDL2_image', required: get_option('sdl_image'),
 689                         method: 'pkg-config', kwargs: static_kwargs)
 690else
 691  if get_option('sdl_image').enabled()
 692    error('sdl-image required, but SDL was @0@'.format(
 693          get_option('sdl').disabled() ? 'disabled' : 'not found'))
 694  endif
 695  sdl_image = not_found
 696endif
 697
 698rbd = not_found
 699if not get_option('rbd').auto() or have_block
 700  librados = cc.find_library('rados', required: get_option('rbd'),
 701                             kwargs: static_kwargs)
 702  librbd = cc.find_library('rbd', has_headers: ['rbd/librbd.h'],
 703                           required: get_option('rbd'),
 704                           kwargs: static_kwargs)
 705  if librados.found() and librbd.found()
 706    if cc.links('''
 707      #include <stdio.h>
 708      #include <rbd/librbd.h>
 709      int main(void) {
 710        rados_t cluster;
 711        rados_create(&cluster, NULL);
 712        return 0;
 713      }''', dependencies: [librbd, librados])
 714      rbd = declare_dependency(dependencies: [librbd, librados])
 715    elif get_option('rbd').enabled()
 716      error('could not link librados')
 717    else
 718      warning('could not link librados, disabling')
 719    endif
 720  endif
 721endif
 722
 723glusterfs = not_found
 724glusterfs_ftruncate_has_stat = false
 725glusterfs_iocb_has_stat = false
 726if not get_option('glusterfs').auto() or have_block
 727  glusterfs = dependency('glusterfs-api', version: '>=3',
 728                         required: get_option('glusterfs'),
 729                         method: 'pkg-config', kwargs: static_kwargs)
 730  if glusterfs.found()
 731    glusterfs_ftruncate_has_stat = cc.links('''
 732      #include <glusterfs/api/glfs.h>
 733
 734      int
 735      main(void)
 736      {
 737          /* new glfs_ftruncate() passes two additional args */
 738          return glfs_ftruncate(NULL, 0, NULL, NULL);
 739      }
 740    ''', dependencies: glusterfs)
 741    glusterfs_iocb_has_stat = cc.links('''
 742      #include <glusterfs/api/glfs.h>
 743
 744      /* new glfs_io_cbk() passes two additional glfs_stat structs */
 745      static void
 746      glusterfs_iocb(glfs_fd_t *fd, ssize_t ret, struct glfs_stat *prestat, struct glfs_stat *poststat, void *data)
 747      {}
 748
 749      int
 750      main(void)
 751      {
 752          glfs_io_cbk iocb = &glusterfs_iocb;
 753          iocb(NULL, 0 , NULL, NULL, NULL);
 754          return 0;
 755      }
 756    ''', dependencies: glusterfs)
 757  endif
 758endif
 759libssh = not_found
 760if 'CONFIG_LIBSSH' in config_host
 761  libssh = declare_dependency(compile_args: config_host['LIBSSH_CFLAGS'].split(),
 762                              link_args: config_host['LIBSSH_LIBS'].split())
 763endif
 764libbzip2 = not_found
 765if not get_option('bzip2').auto() or have_block
 766  libbzip2 = cc.find_library('bz2', has_headers: ['bzlib.h'],
 767                             required: get_option('bzip2'),
 768                             kwargs: static_kwargs)
 769  if libbzip2.found() and not cc.links('''
 770     #include <bzlib.h>
 771     int main(void) { BZ2_bzlibVersion(); return 0; }''', dependencies: libbzip2)
 772    libbzip2 = not_found
 773    if get_option('bzip2').enabled()
 774      error('could not link libbzip2')
 775    else
 776      warning('could not link libbzip2, disabling')
 777    endif
 778  endif
 779endif
 780
 781liblzfse = not_found
 782if not get_option('lzfse').auto() or have_block
 783  liblzfse = cc.find_library('lzfse', has_headers: ['lzfse.h'],
 784                             required: get_option('lzfse'),
 785                             kwargs: static_kwargs)
 786endif
 787if liblzfse.found() and not cc.links('''
 788   #include <lzfse.h>
 789   int main(void) { lzfse_decode_scratch_size(); return 0; }''', dependencies: liblzfse)
 790  liblzfse = not_found
 791  if get_option('lzfse').enabled()
 792    error('could not link liblzfse')
 793  else
 794    warning('could not link liblzfse, disabling')
 795  endif
 796endif
 797
 798oss = not_found
 799if 'CONFIG_AUDIO_OSS' in config_host
 800  oss = declare_dependency(link_args: config_host['OSS_LIBS'].split())
 801endif
 802dsound = not_found
 803if 'CONFIG_AUDIO_DSOUND' in config_host
 804  dsound = declare_dependency(link_args: config_host['DSOUND_LIBS'].split())
 805endif
 806coreaudio = not_found
 807if 'CONFIG_AUDIO_COREAUDIO' in config_host
 808  coreaudio = declare_dependency(link_args: config_host['COREAUDIO_LIBS'].split())
 809endif
 810opengl = not_found
 811if 'CONFIG_OPENGL' in config_host
 812  opengl = declare_dependency(compile_args: config_host['OPENGL_CFLAGS'].split(),
 813                              link_args: config_host['OPENGL_LIBS'].split())
 814endif
 815
 816gtk = not_found
 817gtkx11 = not_found
 818if not get_option('gtk').auto() or (have_system and not cocoa.found())
 819  gtk = dependency('gtk+-3.0', version: '>=3.22.0',
 820                   method: 'pkg-config',
 821                   required: get_option('gtk'),
 822                   kwargs: static_kwargs)
 823  if gtk.found()
 824    gtkx11 = dependency('gtk+-x11-3.0', version: '>=3.22.0',
 825                        method: 'pkg-config',
 826                        required: false,
 827                        kwargs: static_kwargs)
 828    gtk = declare_dependency(dependencies: [gtk, gtkx11])
 829  endif
 830endif
 831
 832vte = not_found
 833if 'CONFIG_VTE' in config_host
 834  vte = declare_dependency(compile_args: config_host['VTE_CFLAGS'].split(),
 835                           link_args: config_host['VTE_LIBS'].split())
 836endif
 837x11 = not_found
 838if gtkx11.found() or 'lm32-softmmu' in target_dirs
 839  x11 = dependency('x11', method: 'pkg-config', required: gtkx11.found(),
 840                   kwargs: static_kwargs)
 841endif
 842vnc = not_found
 843png = not_found
 844jpeg = not_found
 845sasl = not_found
 846if get_option('vnc').enabled()
 847  vnc = declare_dependency() # dummy dependency
 848  png = dependency('libpng', required: get_option('vnc_png'),
 849                   method: 'pkg-config', kwargs: static_kwargs)
 850  jpeg = dependency('libjpeg', required: get_option('vnc_jpeg'),
 851                    method: 'pkg-config', kwargs: static_kwargs)
 852  sasl = cc.find_library('sasl2', has_headers: ['sasl/sasl.h'],
 853                         required: get_option('vnc_sasl'),
 854                         kwargs: static_kwargs)
 855  if sasl.found()
 856    sasl = declare_dependency(dependencies: sasl,
 857                              compile_args: '-DSTRUCT_IOVEC_DEFINED')
 858  endif
 859endif
 860
 861snappy = not_found
 862if not get_option('snappy').auto() or have_system
 863  snappy = cc.find_library('snappy', has_headers: ['snappy-c.h'],
 864                           required: get_option('snappy'),
 865                           kwargs: static_kwargs)
 866endif
 867if snappy.found() and not cc.links('''
 868   #include <snappy-c.h>
 869   int main(void) { snappy_max_compressed_length(4096); return 0; }''', dependencies: snappy)
 870  snappy = not_found
 871  if get_option('snappy').enabled()
 872    error('could not link libsnappy')
 873  else
 874    warning('could not link libsnappy, disabling')
 875  endif
 876endif
 877
 878lzo = not_found
 879if not get_option('lzo').auto() or have_system
 880  lzo = cc.find_library('lzo2', has_headers: ['lzo/lzo1x.h'],
 881                        required: get_option('lzo'),
 882                        kwargs: static_kwargs)
 883endif
 884if lzo.found() and not cc.links('''
 885   #include <lzo/lzo1x.h>
 886   int main(void) { lzo_version(); return 0; }''', dependencies: lzo)
 887  lzo = not_found
 888  if get_option('lzo').enabled()
 889    error('could not link liblzo2')
 890  else
 891    warning('could not link liblzo2, disabling')
 892  endif
 893endif
 894
 895rdma = not_found
 896if 'CONFIG_RDMA' in config_host
 897  rdma = declare_dependency(link_args: config_host['RDMA_LIBS'].split())
 898endif
 899numa = not_found
 900if 'CONFIG_NUMA' in config_host
 901  numa = declare_dependency(link_args: config_host['NUMA_LIBS'].split())
 902endif
 903xen = not_found
 904if 'CONFIG_XEN_BACKEND' in config_host
 905  xen = declare_dependency(compile_args: config_host['XEN_CFLAGS'].split(),
 906                           link_args: config_host['XEN_LIBS'].split())
 907endif
 908cacard = not_found
 909if 'CONFIG_SMARTCARD' in config_host
 910  cacard = declare_dependency(compile_args: config_host['SMARTCARD_CFLAGS'].split(),
 911                              link_args: config_host['SMARTCARD_LIBS'].split())
 912endif
 913u2f = not_found
 914if have_system
 915  u2f = dependency('u2f-emu', required: get_option('u2f'),
 916                   method: 'pkg-config',
 917                   kwargs: static_kwargs)
 918endif
 919usbredir = not_found
 920if 'CONFIG_USB_REDIR' in config_host
 921  usbredir = declare_dependency(compile_args: config_host['USB_REDIR_CFLAGS'].split(),
 922                                link_args: config_host['USB_REDIR_LIBS'].split())
 923endif
 924libusb = not_found
 925if 'CONFIG_USB_LIBUSB' in config_host
 926  libusb = declare_dependency(compile_args: config_host['LIBUSB_CFLAGS'].split(),
 927                              link_args: config_host['LIBUSB_LIBS'].split())
 928endif
 929libpmem = not_found
 930if 'CONFIG_LIBPMEM' in config_host
 931  libpmem = declare_dependency(compile_args: config_host['LIBPMEM_CFLAGS'].split(),
 932                               link_args: config_host['LIBPMEM_LIBS'].split())
 933endif
 934libdaxctl = not_found
 935if 'CONFIG_LIBDAXCTL' in config_host
 936  libdaxctl = declare_dependency(link_args: config_host['LIBDAXCTL_LIBS'].split())
 937endif
 938tasn1 = not_found
 939if 'CONFIG_TASN1' in config_host
 940  tasn1 = declare_dependency(compile_args: config_host['TASN1_CFLAGS'].split(),
 941                             link_args: config_host['TASN1_LIBS'].split())
 942endif
 943keyutils = dependency('libkeyutils', required: false,
 944                      method: 'pkg-config', kwargs: static_kwargs)
 945
 946has_gettid = cc.has_function('gettid')
 947
 948# Malloc tests
 949
 950malloc = []
 951if get_option('malloc') == 'system'
 952  has_malloc_trim = \
 953    not get_option('malloc_trim').disabled() and \
 954    cc.links('''#include <malloc.h>
 955                int main(void) { malloc_trim(0); return 0; }''')
 956else
 957  has_malloc_trim = false
 958  malloc = cc.find_library(get_option('malloc'), required: true)
 959endif
 960if not has_malloc_trim and get_option('malloc_trim').enabled()
 961  if get_option('malloc') == 'system'
 962    error('malloc_trim not available on this platform.')
 963  else
 964    error('malloc_trim not available with non-libc memory allocator')
 965  endif
 966endif
 967
 968# Check whether the glibc provides statx()
 969
 970statx_test = '''
 971  #ifndef _GNU_SOURCE
 972  #define _GNU_SOURCE
 973  #endif
 974  #include <sys/stat.h>
 975  int main(void) {
 976    struct statx statxbuf;
 977    statx(0, "", 0, STATX_BASIC_STATS, &statxbuf);
 978    return 0;
 979  }'''
 980
 981has_statx = cc.links(statx_test)
 982
 983have_vhost_user_blk_server = (targetos == 'linux' and
 984    'CONFIG_VHOST_USER' in config_host)
 985
 986if get_option('vhost_user_blk_server').enabled()
 987    if targetos != 'linux'
 988        error('vhost_user_blk_server requires linux')
 989    elif 'CONFIG_VHOST_USER' not in config_host
 990        error('vhost_user_blk_server requires vhost-user support')
 991    endif
 992elif get_option('vhost_user_blk_server').disabled() or not have_system
 993    have_vhost_user_blk_server = false
 994endif
 995
 996
 997if get_option('fuse').disabled() and get_option('fuse_lseek').enabled()
 998  error('Cannot enable fuse-lseek while fuse is disabled')
 999endif
1000
1001fuse = dependency('fuse3', required: get_option('fuse'),
1002                  version: '>=3.1', method: 'pkg-config',
1003                  kwargs: static_kwargs)
1004
1005fuse_lseek = not_found
1006if not get_option('fuse_lseek').disabled()
1007  if fuse.version().version_compare('>=3.8')
1008    # Dummy dependency
1009    fuse_lseek = declare_dependency()
1010  elif get_option('fuse_lseek').enabled()
1011    if fuse.found()
1012      error('fuse-lseek requires libfuse >=3.8, found ' + fuse.version())
1013    else
1014      error('fuse-lseek requires libfuse, which was not found')
1015    endif
1016  endif
1017endif
1018
1019if get_option('cfi')
1020  cfi_flags=[]
1021  # Check for dependency on LTO
1022  if not get_option('b_lto')
1023    error('Selected Control-Flow Integrity but LTO is disabled')
1024  endif
1025  if config_host.has_key('CONFIG_MODULES')
1026    error('Selected Control-Flow Integrity is not compatible with modules')
1027  endif
1028  # Check for cfi flags. CFI requires LTO so we can't use
1029  # get_supported_arguments, but need a more complex "compiles" which allows
1030  # custom arguments
1031  if cc.compiles('int main () { return 0; }', name: '-fsanitize=cfi-icall',
1032                 args: ['-flto', '-fsanitize=cfi-icall'] )
1033    cfi_flags += '-fsanitize=cfi-icall'
1034  else
1035    error('-fsanitize=cfi-icall is not supported by the compiler')
1036  endif
1037  if cc.compiles('int main () { return 0; }',
1038                 name: '-fsanitize-cfi-icall-generalize-pointers',
1039                 args: ['-flto', '-fsanitize=cfi-icall',
1040                        '-fsanitize-cfi-icall-generalize-pointers'] )
1041    cfi_flags += '-fsanitize-cfi-icall-generalize-pointers'
1042  else
1043    error('-fsanitize-cfi-icall-generalize-pointers is not supported by the compiler')
1044  endif
1045  if get_option('cfi_debug')
1046    if cc.compiles('int main () { return 0; }',
1047                   name: '-fno-sanitize-trap=cfi-icall',
1048                   args: ['-flto', '-fsanitize=cfi-icall',
1049                          '-fno-sanitize-trap=cfi-icall'] )
1050      cfi_flags += '-fno-sanitize-trap=cfi-icall'
1051    else
1052      error('-fno-sanitize-trap=cfi-icall is not supported by the compiler')
1053    endif
1054  endif
1055  add_global_arguments(cfi_flags, native: false, language: ['c', 'cpp', 'objc'])
1056  add_global_link_arguments(cfi_flags, native: false, language: ['c', 'cpp', 'objc'])
1057endif
1058
1059#################
1060# config-host.h #
1061#################
1062
1063have_virtfs = (targetos == 'linux' and
1064    have_system and
1065    libattr.found() and
1066    libcap_ng.found())
1067
1068have_virtfs_proxy_helper = have_virtfs and have_tools
1069
1070if get_option('virtfs').enabled()
1071  if not have_virtfs
1072    if targetos != 'linux'
1073      error('virtio-9p (virtfs) requires Linux')
1074    elif not libcap_ng.found() or not libattr.found()
1075      error('virtio-9p (virtfs) requires libcap-ng-devel and libattr-devel')
1076    elif not have_system
1077      error('virtio-9p (virtfs) needs system emulation support')
1078    endif
1079  endif
1080elif get_option('virtfs').disabled()
1081  have_virtfs = false
1082endif
1083
1084config_host_data.set_quoted('CONFIG_BINDIR', get_option('prefix') / get_option('bindir'))
1085config_host_data.set_quoted('CONFIG_PREFIX', get_option('prefix'))
1086config_host_data.set_quoted('CONFIG_QEMU_CONFDIR', get_option('prefix') / qemu_confdir)
1087config_host_data.set_quoted('CONFIG_QEMU_DATADIR', get_option('prefix') / qemu_datadir)
1088config_host_data.set_quoted('CONFIG_QEMU_DESKTOPDIR', get_option('prefix') / qemu_desktopdir)
1089config_host_data.set_quoted('CONFIG_QEMU_FIRMWAREPATH', get_option('qemu_firmwarepath'))
1090config_host_data.set_quoted('CONFIG_QEMU_HELPERDIR', get_option('prefix') / get_option('libexecdir'))
1091config_host_data.set_quoted('CONFIG_QEMU_ICONDIR', get_option('prefix') / qemu_icondir)
1092config_host_data.set_quoted('CONFIG_QEMU_LOCALEDIR', get_option('prefix') / get_option('localedir'))
1093config_host_data.set_quoted('CONFIG_QEMU_LOCALSTATEDIR', get_option('prefix') / get_option('localstatedir'))
1094config_host_data.set_quoted('CONFIG_QEMU_MODDIR', get_option('prefix') / qemu_moddir)
1095config_host_data.set_quoted('CONFIG_SYSCONFDIR', get_option('prefix') / get_option('sysconfdir'))
1096
1097config_host_data.set('CONFIG_ATTR', libattr.found())
1098config_host_data.set('CONFIG_BRLAPI', brlapi.found())
1099config_host_data.set('CONFIG_COCOA', cocoa.found())
1100config_host_data.set('CONFIG_LIBUDEV', libudev.found())
1101config_host_data.set('CONFIG_LZO', lzo.found())
1102config_host_data.set('CONFIG_MPATH', mpathpersist.found())
1103config_host_data.set('CONFIG_MPATH_NEW_API', mpathpersist_new_api)
1104config_host_data.set('CONFIG_CURL', curl.found())
1105config_host_data.set('CONFIG_CURSES', curses.found())
1106config_host_data.set('CONFIG_GLUSTERFS', glusterfs.found())
1107if glusterfs.found()
1108  config_host_data.set('CONFIG_GLUSTERFS_XLATOR_OPT', glusterfs.version().version_compare('>=4'))
1109  config_host_data.set('CONFIG_GLUSTERFS_DISCARD', glusterfs.version().version_compare('>=5'))
1110  config_host_data.set('CONFIG_GLUSTERFS_FALLOCATE', glusterfs.version().version_compare('>=6'))
1111  config_host_data.set('CONFIG_GLUSTERFS_ZEROFILL', glusterfs.version().version_compare('>=6'))
1112  config_host_data.set('CONFIG_GLUSTERFS_FTRUNCATE_HAS_STAT', glusterfs_ftruncate_has_stat)
1113  config_host_data.set('CONFIG_GLUSTERFS_IOCB_HAS_STAT', glusterfs_iocb_has_stat)
1114endif
1115config_host_data.set('CONFIG_GTK', gtk.found())
1116config_host_data.set('CONFIG_LIBATTR', have_old_libattr)
1117config_host_data.set('CONFIG_LIBCAP_NG', libcap_ng.found())
1118config_host_data.set('CONFIG_LIBISCSI', libiscsi.found())
1119config_host_data.set('CONFIG_LIBNFS', libnfs.found())
1120config_host_data.set('CONFIG_RBD', rbd.found())
1121config_host_data.set('CONFIG_SDL', sdl.found())
1122config_host_data.set('CONFIG_SDL_IMAGE', sdl_image.found())
1123config_host_data.set('CONFIG_SECCOMP', seccomp.found())
1124config_host_data.set('CONFIG_SNAPPY', snappy.found())
1125config_host_data.set('CONFIG_VHOST_USER_BLK_SERVER', have_vhost_user_blk_server)
1126config_host_data.set('CONFIG_VNC', vnc.found())
1127config_host_data.set('CONFIG_VNC_JPEG', jpeg.found())
1128config_host_data.set('CONFIG_VNC_PNG', png.found())
1129config_host_data.set('CONFIG_VNC_SASL', sasl.found())
1130config_host_data.set('CONFIG_VIRTFS', have_virtfs)
1131config_host_data.set('CONFIG_XKBCOMMON', xkbcommon.found())
1132config_host_data.set('CONFIG_KEYUTILS', keyutils.found())
1133config_host_data.set('CONFIG_GETTID', has_gettid)
1134config_host_data.set('CONFIG_MALLOC_TRIM', has_malloc_trim)
1135config_host_data.set('CONFIG_STATX', has_statx)
1136config_host_data.set('CONFIG_ZSTD', zstd.found())
1137config_host_data.set('CONFIG_FUSE', fuse.found())
1138config_host_data.set('CONFIG_FUSE_LSEEK', fuse_lseek.found())
1139config_host_data.set('CONFIG_X11', x11.found())
1140config_host_data.set('CONFIG_CFI', get_option('cfi'))
1141config_host_data.set('QEMU_VERSION', '"@0@"'.format(meson.project_version()))
1142config_host_data.set('QEMU_VERSION_MAJOR', meson.project_version().split('.')[0])
1143config_host_data.set('QEMU_VERSION_MINOR', meson.project_version().split('.')[1])
1144config_host_data.set('QEMU_VERSION_MICRO', meson.project_version().split('.')[2])
1145
1146config_host_data.set('HAVE_BTRFS_H', cc.has_header('linux/btrfs.h'))
1147config_host_data.set('HAVE_DRM_H', cc.has_header('libdrm/drm.h'))
1148config_host_data.set('HAVE_PTY_H', cc.has_header('pty.h'))
1149config_host_data.set('HAVE_SYS_IOCCOM_H', cc.has_header('sys/ioccom.h'))
1150config_host_data.set('HAVE_SYS_KCOV_H', cc.has_header('sys/kcov.h'))
1151config_host_data.set('HAVE_SYSTEM_FUNCTION', cc.has_function('system', prefix: '#include <stdlib.h>'))
1152
1153config_host_data.set('CONFIG_PREADV', cc.has_function('preadv', prefix: '#include <sys/uio.h>'))
1154
1155ignored = ['CONFIG_QEMU_INTERP_PREFIX'] # actually per-target
1156arrays = ['CONFIG_AUDIO_DRIVERS', 'CONFIG_BDRV_RW_WHITELIST', 'CONFIG_BDRV_RO_WHITELIST']
1157strings = ['HOST_DSOSUF', 'CONFIG_IASL']
1158foreach k, v: config_host
1159  if ignored.contains(k)
1160    # do nothing
1161  elif arrays.contains(k)
1162    if v != ''
1163      v = '"' + '", "'.join(v.split()) + '", '
1164    endif
1165    config_host_data.set(k, v)
1166  elif k == 'ARCH'
1167    config_host_data.set('HOST_' + v.to_upper(), 1)
1168  elif strings.contains(k)
1169    if not k.startswith('CONFIG_')
1170      k = 'CONFIG_' + k.to_upper()
1171    endif
1172    config_host_data.set_quoted(k, v)
1173  elif k.startswith('CONFIG_') or k.startswith('HAVE_') or k.startswith('HOST_')
1174    config_host_data.set(k, v == 'y' ? 1 : v)
1175  endif
1176endforeach
1177
1178########################
1179# Target configuration #
1180########################
1181
1182minikconf = find_program('scripts/minikconf.py')
1183config_all = {}
1184config_all_devices = {}
1185config_all_disas = {}
1186config_devices_mak_list = []
1187config_devices_h = {}
1188config_target_h = {}
1189config_target_mak = {}
1190
1191disassemblers = {
1192  'alpha' : ['CONFIG_ALPHA_DIS'],
1193  'arm' : ['CONFIG_ARM_DIS'],
1194  'avr' : ['CONFIG_AVR_DIS'],
1195  'cris' : ['CONFIG_CRIS_DIS'],
1196  'hexagon' : ['CONFIG_HEXAGON_DIS'],
1197  'hppa' : ['CONFIG_HPPA_DIS'],
1198  'i386' : ['CONFIG_I386_DIS'],
1199  'x86_64' : ['CONFIG_I386_DIS'],
1200  'x32' : ['CONFIG_I386_DIS'],
1201  'lm32' : ['CONFIG_LM32_DIS'],
1202  'm68k' : ['CONFIG_M68K_DIS'],
1203  'microblaze' : ['CONFIG_MICROBLAZE_DIS'],
1204  'mips' : ['CONFIG_MIPS_DIS'],
1205  'moxie' : ['CONFIG_MOXIE_DIS'],
1206  'nios2' : ['CONFIG_NIOS2_DIS'],
1207  'or1k' : ['CONFIG_OPENRISC_DIS'],
1208  'ppc' : ['CONFIG_PPC_DIS'],
1209  'riscv' : ['CONFIG_RISCV_DIS'],
1210  'rx' : ['CONFIG_RX_DIS'],
1211  's390' : ['CONFIG_S390_DIS'],
1212  'sh4' : ['CONFIG_SH4_DIS'],
1213  'sparc' : ['CONFIG_SPARC_DIS'],
1214  'xtensa' : ['CONFIG_XTENSA_DIS'],
1215}
1216if link_language == 'cpp'
1217  disassemblers += {
1218    'aarch64' : [ 'CONFIG_ARM_A64_DIS'],
1219    'arm' : [ 'CONFIG_ARM_DIS', 'CONFIG_ARM_A64_DIS'],
1220    'mips' : [ 'CONFIG_MIPS_DIS', 'CONFIG_NANOMIPS_DIS'],
1221  }
1222endif
1223
1224host_kconfig = \
1225  ('CONFIG_TPM' in config_host ? ['CONFIG_TPM=y'] : []) + \
1226  ('CONFIG_SPICE' in config_host ? ['CONFIG_SPICE=y'] : []) + \
1227  ('CONFIG_IVSHMEM' in config_host ? ['CONFIG_IVSHMEM=y'] : []) + \
1228  ('CONFIG_OPENGL' in config_host ? ['CONFIG_OPENGL=y'] : []) + \
1229  (x11.found() ? ['CONFIG_X11=y'] : []) + \
1230  ('CONFIG_VHOST_USER' in config_host ? ['CONFIG_VHOST_USER=y'] : []) + \
1231  ('CONFIG_VHOST_VDPA' in config_host ? ['CONFIG_VHOST_VDPA=y'] : []) + \
1232  ('CONFIG_VHOST_KERNEL' in config_host ? ['CONFIG_VHOST_KERNEL=y'] : []) + \
1233  (have_virtfs ? ['CONFIG_VIRTFS=y'] : []) + \
1234  ('CONFIG_LINUX' in config_host ? ['CONFIG_LINUX=y'] : []) + \
1235  ('CONFIG_PVRDMA' in config_host ? ['CONFIG_PVRDMA=y'] : []) + \
1236  (multiprocess_allowed ? ['CONFIG_MULTIPROCESS_ALLOWED=y'] : [])
1237
1238ignored = [ 'TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_ARCH' ]
1239
1240default_targets = 'CONFIG_DEFAULT_TARGETS' in config_host
1241actual_target_dirs = []
1242fdt_required = []
1243foreach target : target_dirs
1244  config_target = { 'TARGET_NAME': target.split('-')[0] }
1245  if target.endswith('linux-user')
1246    if targetos != 'linux'
1247      if default_targets
1248        continue
1249      endif
1250      error('Target @0@ is only available on a Linux host'.format(target))
1251    endif
1252    config_target += { 'CONFIG_LINUX_USER': 'y' }
1253  elif target.endswith('bsd-user')
1254    if 'CONFIG_BSD' not in config_host
1255      if default_targets
1256        continue
1257      endif
1258      error('Target @0@ is only available on a BSD host'.format(target))
1259    endif
1260    config_target += { 'CONFIG_BSD_USER': 'y' }
1261  elif target.endswith('softmmu')
1262    config_target += { 'CONFIG_SOFTMMU': 'y' }
1263  endif
1264  if target.endswith('-user')
1265    config_target += {
1266      'CONFIG_USER_ONLY': 'y',
1267      'CONFIG_QEMU_INTERP_PREFIX':
1268        config_host['CONFIG_QEMU_INTERP_PREFIX'].format(config_target['TARGET_NAME'])
1269    }
1270  endif
1271
1272  accel_kconfig = []
1273  foreach sym: accelerators
1274    if sym == 'CONFIG_TCG' or target in accelerator_targets.get(sym, [])
1275      config_target += { sym: 'y' }
1276      config_all += { sym: 'y' }
1277      if sym == 'CONFIG_TCG' and tcg_arch == 'tci'
1278        config_target += { 'CONFIG_TCG_INTERPRETER': 'y' }
1279      elif sym == 'CONFIG_XEN' and have_xen_pci_passthrough
1280        config_target += { 'CONFIG_XEN_PCI_PASSTHROUGH': 'y' }
1281      endif
1282      accel_kconfig += [ sym + '=y' ]
1283    endif
1284  endforeach
1285  if accel_kconfig.length() == 0
1286    if default_targets
1287      continue
1288    endif
1289    error('No accelerator available for target @0@'.format(target))
1290  endif
1291
1292  actual_target_dirs += target
1293  config_target += keyval.load('default-configs/targets' / target + '.mak')
1294  config_target += { 'TARGET_' + config_target['TARGET_ARCH'].to_upper(): 'y' }
1295
1296  if 'TARGET_NEED_FDT' in config_target
1297    fdt_required += target
1298  endif
1299
1300  # Add default keys
1301  if 'TARGET_BASE_ARCH' not in config_target
1302    config_target += {'TARGET_BASE_ARCH': config_target['TARGET_ARCH']}
1303  endif
1304  if 'TARGET_ABI_DIR' not in config_target
1305    config_target += {'TARGET_ABI_DIR': config_target['TARGET_ARCH']}
1306  endif
1307
1308  foreach k, v: disassemblers
1309    if config_host['ARCH'].startswith(k) or config_target['TARGET_BASE_ARCH'].startswith(k)
1310      foreach sym: v
1311        config_target += { sym: 'y' }
1312        config_all_disas += { sym: 'y' }
1313      endforeach
1314    endif
1315  endforeach
1316
1317  config_target_data = configuration_data()
1318  foreach k, v: config_target
1319    if not k.startswith('TARGET_') and not k.startswith('CONFIG_')
1320      # do nothing
1321    elif ignored.contains(k)
1322      # do nothing
1323    elif k == 'TARGET_BASE_ARCH'
1324      # Note that TARGET_BASE_ARCH ends up in config-target.h but it is
1325      # not used to select files from sourcesets.
1326      config_target_data.set('TARGET_' + v.to_upper(), 1)
1327    elif k == 'TARGET_NAME' or k == 'CONFIG_QEMU_INTERP_PREFIX'
1328      config_target_data.set_quoted(k, v)
1329    elif v == 'y'
1330      config_target_data.set(k, 1)
1331    else
1332      config_target_data.set(k, v)
1333    endif
1334  endforeach
1335  config_target_h += {target: configure_file(output: target + '-config-target.h',
1336                                               configuration: config_target_data)}
1337
1338  if target.endswith('-softmmu')
1339    config_devices_mak = target + '-config-devices.mak'
1340    config_devices_mak = configure_file(
1341      input: ['default-configs/devices' / target + '.mak', 'Kconfig'],
1342      output: config_devices_mak,
1343      depfile: config_devices_mak + '.d',
1344      capture: true,
1345      command: [minikconf,
1346                get_option('default_devices') ? '--defconfig' : '--allnoconfig',
1347                config_devices_mak, '@DEPFILE@', '@INPUT@',
1348                host_kconfig, accel_kconfig])
1349
1350    config_devices_data = configuration_data()
1351    config_devices = keyval.load(config_devices_mak)
1352    foreach k, v: config_devices
1353      config_devices_data.set(k, 1)
1354    endforeach
1355    config_devices_mak_list += config_devices_mak
1356    config_devices_h += {target: configure_file(output: target + '-config-devices.h',
1357                                                configuration: config_devices_data)}
1358    config_target += config_devices
1359    config_all_devices += config_devices
1360  endif
1361  config_target_mak += {target: config_target}
1362endforeach
1363target_dirs = actual_target_dirs
1364
1365# This configuration is used to build files that are shared by
1366# multiple binaries, and then extracted out of the "common"
1367# static_library target.
1368#
1369# We do not use all_sources()/all_dependencies(), because it would
1370# build literally all source files, including devices only used by
1371# targets that are not built for this compilation.  The CONFIG_ALL
1372# pseudo symbol replaces it.
1373
1374config_all += config_all_devices
1375config_all += config_host
1376config_all += config_all_disas
1377config_all += {
1378  'CONFIG_XEN': config_host.has_key('CONFIG_XEN_BACKEND'),
1379  'CONFIG_SOFTMMU': have_system,
1380  'CONFIG_USER_ONLY': have_user,
1381  'CONFIG_ALL': true,
1382}
1383
1384##############
1385# Submodules #
1386##############
1387
1388capstone = not_found
1389capstone_opt = get_option('capstone')
1390if capstone_opt in ['enabled', 'auto', 'system']
1391  have_internal = fs.exists(meson.current_source_dir() / 'capstone/Makefile')
1392  capstone = dependency('capstone', version: '>=4.0',
1393                        kwargs: static_kwargs, method: 'pkg-config',
1394                        required: capstone_opt == 'system' or
1395                                  capstone_opt == 'enabled' and not have_internal)
1396  if capstone.found()
1397    capstone_opt = 'system'
1398  elif have_internal
1399    capstone_opt = 'internal'
1400  else
1401    capstone_opt = 'disabled'
1402  endif
1403endif
1404if capstone_opt == 'internal'
1405  capstone_data = configuration_data()
1406  capstone_data.set('CAPSTONE_USE_SYS_DYN_MEM', '1')
1407
1408  capstone_files = files(
1409    'capstone/cs.c',
1410    'capstone/MCInst.c',
1411    'capstone/MCInstrDesc.c',
1412    'capstone/MCRegisterInfo.c',
1413    'capstone/SStream.c',
1414    'capstone/utils.c'
1415  )
1416
1417  if 'CONFIG_ARM_DIS' in config_all_disas
1418    capstone_data.set('CAPSTONE_HAS_ARM', '1')
1419    capstone_files += files(
1420      'capstone/arch/ARM/ARMDisassembler.c',
1421      'capstone/arch/ARM/ARMInstPrinter.c',
1422      'capstone/arch/ARM/ARMMapping.c',
1423      'capstone/arch/ARM/ARMModule.c'
1424    )
1425  endif
1426
1427  # FIXME: This config entry currently depends on a c++ compiler.
1428  # Which is needed for building libvixl, but not for capstone.
1429  if 'CONFIG_ARM_A64_DIS' in config_all_disas
1430    capstone_data.set('CAPSTONE_HAS_ARM64', '1')
1431    capstone_files += files(
1432      'capstone/arch/AArch64/AArch64BaseInfo.c',
1433      'capstone/arch/AArch64/AArch64Disassembler.c',
1434      'capstone/arch/AArch64/AArch64InstPrinter.c',
1435      'capstone/arch/AArch64/AArch64Mapping.c',
1436      'capstone/arch/AArch64/AArch64Module.c'
1437    )
1438  endif
1439
1440  if 'CONFIG_PPC_DIS' in config_all_disas
1441    capstone_data.set('CAPSTONE_HAS_POWERPC', '1')
1442    capstone_files += files(
1443      'capstone/arch/PowerPC/PPCDisassembler.c',
1444      'capstone/arch/PowerPC/PPCInstPrinter.c',
1445      'capstone/arch/PowerPC/PPCMapping.c',
1446      'capstone/arch/PowerPC/PPCModule.c'
1447    )
1448  endif
1449
1450  if 'CONFIG_S390_DIS' in config_all_disas
1451    capstone_data.set('CAPSTONE_HAS_SYSZ', '1')
1452    capstone_files += files(
1453      'capstone/arch/SystemZ/SystemZDisassembler.c',
1454      'capstone/arch/SystemZ/SystemZInstPrinter.c',
1455      'capstone/arch/SystemZ/SystemZMapping.c',
1456      'capstone/arch/SystemZ/SystemZModule.c',
1457      'capstone/arch/SystemZ/SystemZMCTargetDesc.c'
1458    )
1459  endif
1460
1461  if 'CONFIG_I386_DIS' in config_all_disas
1462    capstone_data.set('CAPSTONE_HAS_X86', 1)
1463    capstone_files += files(
1464      'capstone/arch/X86/X86Disassembler.c',
1465      'capstone/arch/X86/X86DisassemblerDecoder.c',
1466      'capstone/arch/X86/X86ATTInstPrinter.c',
1467      'capstone/arch/X86/X86IntelInstPrinter.c',
1468      'capstone/arch/X86/X86InstPrinterCommon.c',
1469      'capstone/arch/X86/X86Mapping.c',
1470      'capstone/arch/X86/X86Module.c'
1471    )
1472  endif
1473
1474  configure_file(output: 'capstone-defs.h', configuration: capstone_data)
1475
1476  capstone_cargs = [
1477    # FIXME: There does not seem to be a way to completely replace the c_args
1478    # that come from add_project_arguments() -- we can only add to them.
1479    # So: disable all warnings with a big hammer.
1480    '-Wno-error', '-w',
1481
1482    # Include all configuration defines via a header file, which will wind up
1483    # as a dependency on the object file, and thus changes here will result
1484    # in a rebuild.
1485    '-include', 'capstone-defs.h'
1486  ]
1487
1488  libcapstone = static_library('capstone',
1489                               build_by_default: false,
1490                               sources: capstone_files,
1491                               c_args: capstone_cargs,
1492                               include_directories: 'capstone/include')
1493  capstone = declare_dependency(link_with: libcapstone,
1494                                include_directories: 'capstone/include/capstone')
1495endif
1496
1497slirp = not_found
1498slirp_opt = 'disabled'
1499if have_system
1500  slirp_opt = get_option('slirp')
1501  if slirp_opt in ['enabled', 'auto', 'system']
1502    have_internal = fs.exists(meson.current_source_dir() / 'slirp/meson.build')
1503    slirp = dependency('slirp', kwargs: static_kwargs,
1504                       method: 'pkg-config',
1505                       required: slirp_opt == 'system' or
1506                                 slirp_opt == 'enabled' and not have_internal)
1507    if slirp.found()
1508      slirp_opt = 'system'
1509    elif have_internal
1510      slirp_opt = 'internal'
1511    else
1512      slirp_opt = 'disabled'
1513    endif
1514  endif
1515  if slirp_opt == 'internal'
1516    slirp_deps = []
1517    if targetos == 'windows'
1518      slirp_deps = cc.find_library('iphlpapi')
1519    endif
1520    slirp_conf = configuration_data()
1521    slirp_conf.set('SLIRP_MAJOR_VERSION', meson.project_version().split('.')[0])
1522    slirp_conf.set('SLIRP_MINOR_VERSION', meson.project_version().split('.')[1])
1523    slirp_conf.set('SLIRP_MICRO_VERSION', meson.project_version().split('.')[2])
1524    slirp_conf.set_quoted('SLIRP_VERSION_STRING', meson.project_version())
1525    slirp_cargs = ['-DG_LOG_DOMAIN="Slirp"']
1526    slirp_files = [
1527      'slirp/src/arp_table.c',
1528      'slirp/src/bootp.c',
1529      'slirp/src/cksum.c',
1530      'slirp/src/dhcpv6.c',
1531      'slirp/src/dnssearch.c',
1532      'slirp/src/if.c',
1533      'slirp/src/ip6_icmp.c',
1534      'slirp/src/ip6_input.c',
1535      'slirp/src/ip6_output.c',
1536      'slirp/src/ip_icmp.c',
1537      'slirp/src/ip_input.c',
1538      'slirp/src/ip_output.c',
1539      'slirp/src/mbuf.c',
1540      'slirp/src/misc.c',
1541      'slirp/src/ncsi.c',
1542      'slirp/src/ndp_table.c',
1543      'slirp/src/sbuf.c',
1544      'slirp/src/slirp.c',
1545      'slirp/src/socket.c',
1546      'slirp/src/state.c',
1547      'slirp/src/stream.c',
1548      'slirp/src/tcp_input.c',
1549      'slirp/src/tcp_output.c',
1550      'slirp/src/tcp_subr.c',
1551      'slirp/src/tcp_timer.c',
1552      'slirp/src/tftp.c',
1553      'slirp/src/udp.c',
1554      'slirp/src/udp6.c',
1555      'slirp/src/util.c',
1556      'slirp/src/version.c',
1557      'slirp/src/vmstate.c',
1558    ]
1559
1560    configure_file(
1561      input : 'slirp/src/libslirp-version.h.in',
1562      output : 'libslirp-version.h',
1563      configuration: slirp_conf)
1564
1565    slirp_inc = include_directories('slirp', 'slirp/src')
1566    libslirp = static_library('slirp',
1567                              build_by_default: false,
1568                              sources: slirp_files,
1569                              c_args: slirp_cargs,
1570                              include_directories: slirp_inc)
1571    slirp = declare_dependency(link_with: libslirp,
1572                               dependencies: slirp_deps,
1573                               include_directories: slirp_inc)
1574  endif
1575endif
1576
1577# For CFI, we need to compile slirp as a static library together with qemu.
1578# This is because we register slirp functions as callbacks for QEMU Timers.
1579# When using a system-wide shared libslirp, the type information for the
1580# callback is missing and the timer call produces a false positive with CFI.
1581#
1582# Now that slirp_opt has been defined, check if the selected slirp is compatible
1583# with control-flow integrity.
1584if get_option('cfi') and slirp_opt == 'system'
1585  error('Control-Flow Integrity is not compatible with system-wide slirp.' \
1586         + ' Please configure with --enable-slirp=git')
1587endif
1588
1589fdt = not_found
1590fdt_opt = get_option('fdt')
1591if have_system
1592  if fdt_opt in ['enabled', 'auto', 'system']
1593    have_internal = fs.exists(meson.current_source_dir() / 'dtc/libfdt/Makefile.libfdt')
1594    fdt = cc.find_library('fdt', kwargs: static_kwargs,
1595                          required: fdt_opt == 'system' or
1596                                    fdt_opt == 'enabled' and not have_internal)
1597    if fdt.found() and cc.links('''
1598       #include <libfdt.h>
1599       #include <libfdt_env.h>
1600       int main(void) { fdt_check_full(NULL, 0); return 0; }''',
1601         dependencies: fdt)
1602      fdt_opt = 'system'
1603    elif have_internal
1604      fdt_opt = 'internal'
1605    else
1606      fdt_opt = 'disabled'
1607    endif
1608  endif
1609  if fdt_opt == 'internal'
1610    fdt_files = files(
1611      'dtc/libfdt/fdt.c',
1612      'dtc/libfdt/fdt_ro.c',
1613      'dtc/libfdt/fdt_wip.c',
1614      'dtc/libfdt/fdt_sw.c',
1615      'dtc/libfdt/fdt_rw.c',
1616      'dtc/libfdt/fdt_strerror.c',
1617      'dtc/libfdt/fdt_empty_tree.c',
1618      'dtc/libfdt/fdt_addresses.c',
1619      'dtc/libfdt/fdt_overlay.c',
1620      'dtc/libfdt/fdt_check.c',
1621    )
1622
1623    fdt_inc = include_directories('dtc/libfdt')
1624    libfdt = static_library('fdt',
1625                            build_by_default: false,
1626                            sources: fdt_files,
1627                            include_directories: fdt_inc)
1628    fdt = declare_dependency(link_with: libfdt,
1629                             include_directories: fdt_inc)
1630  endif
1631endif
1632if not fdt.found() and fdt_required.length() > 0
1633  error('fdt not available but required by targets ' + ', '.join(fdt_required))
1634endif
1635
1636config_host_data.set('CONFIG_CAPSTONE', capstone.found())
1637config_host_data.set('CONFIG_FDT', fdt.found())
1638config_host_data.set('CONFIG_SLIRP', slirp.found())
1639
1640#####################
1641# Generated sources #
1642#####################
1643
1644genh += configure_file(output: 'config-host.h', configuration: config_host_data)
1645
1646hxtool = find_program('scripts/hxtool')
1647shaderinclude = find_program('scripts/shaderinclude.pl')
1648qapi_gen = find_program('scripts/qapi-gen.py')
1649qapi_gen_depends = [ meson.source_root() / 'scripts/qapi/__init__.py',
1650                     meson.source_root() / 'scripts/qapi/commands.py',
1651                     meson.source_root() / 'scripts/qapi/common.py',
1652                     meson.source_root() / 'scripts/qapi/error.py',
1653                     meson.source_root() / 'scripts/qapi/events.py',
1654                     meson.source_root() / 'scripts/qapi/expr.py',
1655                     meson.source_root() / 'scripts/qapi/gen.py',
1656                     meson.source_root() / 'scripts/qapi/introspect.py',
1657                     meson.source_root() / 'scripts/qapi/parser.py',
1658                     meson.source_root() / 'scripts/qapi/schema.py',
1659                     meson.source_root() / 'scripts/qapi/source.py',
1660                     meson.source_root() / 'scripts/qapi/types.py',
1661                     meson.source_root() / 'scripts/qapi/visit.py',
1662                     meson.source_root() / 'scripts/qapi/common.py',
1663                     meson.source_root() / 'scripts/qapi-gen.py'
1664]
1665
1666tracetool = [
1667  python, files('scripts/tracetool.py'),
1668   '--backend=' + config_host['TRACE_BACKENDS']
1669]
1670tracetool_depends = files(
1671  'scripts/tracetool/backend/log.py',
1672  'scripts/tracetool/backend/__init__.py',
1673  'scripts/tracetool/backend/dtrace.py',
1674  'scripts/tracetool/backend/ftrace.py',
1675  'scripts/tracetool/backend/simple.py',
1676  'scripts/tracetool/backend/syslog.py',
1677  'scripts/tracetool/backend/ust.py',
1678  'scripts/tracetool/format/tcg_h.py',
1679  'scripts/tracetool/format/ust_events_c.py',
1680  'scripts/tracetool/format/ust_events_h.py',
1681  'scripts/tracetool/format/__init__.py',
1682  'scripts/tracetool/format/d.py',
1683  'scripts/tracetool/format/tcg_helper_c.py',
1684  'scripts/tracetool/format/simpletrace_stap.py',
1685  'scripts/tracetool/format/c.py',
1686  'scripts/tracetool/format/h.py',
1687  'scripts/tracetool/format/tcg_helper_h.py',
1688  'scripts/tracetool/format/log_stap.py',
1689  'scripts/tracetool/format/stap.py',
1690  'scripts/tracetool/format/tcg_helper_wrapper_h.py',
1691  'scripts/tracetool/__init__.py',
1692  'scripts/tracetool/transform.py',
1693  'scripts/tracetool/vcpu.py'
1694)
1695
1696qemu_version_cmd = [find_program('scripts/qemu-version.sh'),
1697                    meson.current_source_dir(),
1698                    config_host['PKGVERSION'], meson.project_version()]
1699qemu_version = custom_target('qemu-version.h',
1700                             output: 'qemu-version.h',
1701                             command: qemu_version_cmd,
1702                             capture: true,
1703                             build_by_default: true,
1704                             build_always_stale: true)
1705genh += qemu_version
1706
1707hxdep = []
1708hx_headers = [
1709  ['qemu-options.hx', 'qemu-options.def'],
1710  ['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
1711]
1712if have_system
1713  hx_headers += [
1714    ['hmp-commands.hx', 'hmp-commands.h'],
1715    ['hmp-commands-info.hx', 'hmp-commands-info.h'],
1716  ]
1717endif
1718foreach d : hx_headers
1719  hxdep += custom_target(d[1],
1720                input: files(d[0]),
1721                output: d[1],
1722                capture: true,
1723                build_by_default: true, # to be removed when added to a target
1724                command: [hxtool, '-h', '@INPUT0@'])
1725endforeach
1726genh += hxdep
1727
1728###################
1729# Collect sources #
1730###################
1731
1732authz_ss = ss.source_set()
1733blockdev_ss = ss.source_set()
1734block_ss = ss.source_set()
1735bsd_user_ss = ss.source_set()
1736chardev_ss = ss.source_set()
1737common_ss = ss.source_set()
1738crypto_ss = ss.source_set()
1739io_ss = ss.source_set()
1740linux_user_ss = ss.source_set()
1741qmp_ss = ss.source_set()
1742qom_ss = ss.source_set()
1743softmmu_ss = ss.source_set()
1744specific_fuzz_ss = ss.source_set()
1745specific_ss = ss.source_set()
1746stub_ss = ss.source_set()
1747trace_ss = ss.source_set()
1748user_ss = ss.source_set()
1749util_ss = ss.source_set()
1750
1751modules = {}
1752hw_arch = {}
1753target_arch = {}
1754target_softmmu_arch = {}
1755
1756###############
1757# Trace files #
1758###############
1759
1760# TODO: add each directory to the subdirs from its own meson.build, once
1761# we have those
1762trace_events_subdirs = [
1763  'crypto',
1764  'qapi',
1765  'qom',
1766  'monitor',
1767  'util',
1768]
1769if have_user
1770  trace_events_subdirs += [ 'linux-user' ]
1771endif
1772if have_block
1773  trace_events_subdirs += [
1774    'authz',
1775    'block',
1776    'io',
1777    'nbd',
1778    'scsi',
1779  ]
1780endif
1781if have_system
1782  trace_events_subdirs += [
1783    'accel/kvm',
1784    'audio',
1785    'backends',
1786    'backends/tpm',
1787    'chardev',
1788    'hw/9pfs',
1789    'hw/acpi',
1790    'hw/adc',
1791    'hw/alpha',
1792    'hw/arm',
1793    'hw/audio',
1794    'hw/block',
1795    'hw/block/dataplane',
1796    'hw/char',
1797    'hw/display',
1798    'hw/dma',
1799    'hw/hppa',
1800    'hw/hyperv',
1801    'hw/i2c',
1802    'hw/i386',
1803    'hw/i386/xen',
1804    'hw/ide',
1805    'hw/input',
1806    'hw/intc',
1807    'hw/isa',
1808    'hw/mem',
1809    'hw/mips',
1810    'hw/misc',
1811    'hw/misc/macio',
1812    'hw/net',
1813    'hw/net/can',
1814    'hw/nvram',
1815    'hw/pci',
1816    'hw/pci-host',
1817    'hw/ppc',
1818    'hw/rdma',
1819    'hw/rdma/vmw',
1820    'hw/rtc',
1821    'hw/s390x',
1822    'hw/scsi',
1823    'hw/sd',
1824    'hw/sparc',
1825    'hw/sparc64',
1826    'hw/ssi',
1827    'hw/timer',
1828    'hw/tpm',
1829    'hw/usb',
1830    'hw/vfio',
1831    'hw/virtio',
1832    'hw/watchdog',
1833    'hw/xen',
1834    'hw/gpio',
1835    'migration',
1836    'net',
1837    'softmmu',
1838    'ui',
1839    'hw/remote',
1840  ]
1841endif
1842if have_system or have_user
1843  trace_events_subdirs += [
1844    'accel/tcg',
1845    'hw/core',
1846    'target/arm',
1847    'target/hppa',
1848    'target/i386',
1849    'target/i386/kvm',
1850    'target/mips',
1851    'target/ppc',
1852    'target/riscv',
1853    'target/s390x',
1854    'target/sparc',
1855  ]
1856endif
1857
1858vhost_user = not_found
1859if 'CONFIG_VHOST_USER' in config_host
1860  libvhost_user = subproject('libvhost-user')
1861  vhost_user = libvhost_user.get_variable('vhost_user_dep')
1862endif
1863
1864subdir('qapi')
1865subdir('qobject')
1866subdir('stubs')
1867subdir('trace')
1868subdir('util')
1869subdir('qom')
1870subdir('authz')
1871subdir('crypto')
1872subdir('ui')
1873
1874
1875if enable_modules
1876  libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
1877  modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
1878endif
1879
1880stub_ss = stub_ss.apply(config_all, strict: false)
1881
1882util_ss.add_all(trace_ss)
1883util_ss = util_ss.apply(config_all, strict: false)
1884libqemuutil = static_library('qemuutil',
1885                             sources: util_ss.sources() + stub_ss.sources() + genh,
1886                             dependencies: [util_ss.dependencies(), m, glib, socket, malloc])
1887qemuutil = declare_dependency(link_with: libqemuutil,
1888                              sources: genh + version_res)
1889
1890if have_system or have_user
1891  decodetree = generator(find_program('scripts/decodetree.py'),
1892                         output: 'decode-@BASENAME@.c.inc',
1893                         arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
1894  subdir('libdecnumber')
1895  subdir('target')
1896endif
1897
1898subdir('audio')
1899subdir('io')
1900subdir('chardev')
1901subdir('fsdev')
1902subdir('dump')
1903
1904if have_block
1905  block_ss.add(files(
1906    'block.c',
1907    'blockjob.c',
1908    'job.c',
1909    'qemu-io-cmds.c',
1910  ))
1911  block_ss.add(when: 'CONFIG_REPLICATION', if_true: files('replication.c'))
1912
1913  subdir('nbd')
1914  subdir('scsi')
1915  subdir('block')
1916
1917  blockdev_ss.add(files(
1918    'blockdev.c',
1919    'blockdev-nbd.c',
1920    'iothread.c',
1921    'job-qmp.c',
1922  ), gnutls)
1923
1924  # os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
1925  # os-win32.c does not
1926  blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c'))
1927  softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')])
1928endif
1929
1930common_ss.add(files('cpus-common.c'))
1931
1932subdir('softmmu')
1933
1934common_ss.add(capstone)
1935specific_ss.add(files('cpu.c', 'disas.c', 'gdbstub.c'), capstone)
1936specific_ss.add(when: 'CONFIG_TCG', if_true: files(
1937  'fpu/softfloat.c',
1938  'tcg/optimize.c',
1939  'tcg/tcg-common.c',
1940  'tcg/tcg-op-gvec.c',
1941  'tcg/tcg-op-vec.c',
1942  'tcg/tcg-op.c',
1943  'tcg/tcg.c',
1944))
1945specific_ss.add(when: 'CONFIG_TCG_INTERPRETER', if_true: files('tcg/tci.c'))
1946
1947# Work around a gcc bug/misfeature wherein constant propagation looks
1948# through an alias:
1949#   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99696
1950# to guess that a const variable is always zero.  Without lto, this is
1951# impossible, as the alias is restricted to page-vary-common.c.  Indeed,
1952# without lto, not even the alias is required -- we simply use different
1953# declarations in different compilation units.
1954pagevary = files('page-vary-common.c')
1955if get_option('b_lto')
1956  pagevary_flags = ['-fno-lto']
1957  if get_option('cfi')
1958    pagevary_flags += '-fno-sanitize=cfi-icall'
1959  endif
1960  pagevary = static_library('page-vary-common', sources: pagevary,
1961                            c_args: pagevary_flags)
1962  pagevary = declare_dependency(link_with: pagevary)
1963endif
1964common_ss.add(pagevary)
1965specific_ss.add(files('page-vary.c'))
1966
1967subdir('backends')
1968subdir('disas')
1969subdir('migration')
1970subdir('monitor')
1971subdir('net')
1972subdir('replay')
1973subdir('semihosting')
1974subdir('hw')
1975subdir('accel')
1976subdir('plugins')
1977subdir('bsd-user')
1978subdir('linux-user')
1979
1980bsd_user_ss.add(files('gdbstub.c'))
1981specific_ss.add_all(when: 'CONFIG_BSD_USER', if_true: bsd_user_ss)
1982
1983linux_user_ss.add(files('gdbstub.c', 'thunk.c'))
1984specific_ss.add_all(when: 'CONFIG_LINUX_USER', if_true: linux_user_ss)
1985
1986# needed for fuzzing binaries
1987subdir('tests/qtest/libqos')
1988subdir('tests/qtest/fuzz')
1989
1990########################
1991# Library dependencies #
1992########################
1993
1994block_mods = []
1995softmmu_mods = []
1996foreach d, list : modules
1997  foreach m, module_ss : list
1998    if enable_modules and targetos != 'windows'
1999      module_ss = module_ss.apply(config_all, strict: false)
2000      sl = static_library(d + '-' + m, [genh, module_ss.sources()],
2001                          dependencies: [modulecommon, module_ss.dependencies()], pic: true)
2002      if d == 'block'
2003        block_mods += sl
2004      else
2005        softmmu_mods += sl
2006      endif
2007    else
2008      if d == 'block'
2009        block_ss.add_all(module_ss)
2010      else
2011        softmmu_ss.add_all(module_ss)
2012      endif
2013    endif
2014  endforeach
2015endforeach
2016
2017nm = find_program('nm')
2018undefsym = find_program('scripts/undefsym.py')
2019block_syms = custom_target('block.syms', output: 'block.syms',
2020                             input: [libqemuutil, block_mods],
2021                             capture: true,
2022                             command: [undefsym, nm, '@INPUT@'])
2023qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
2024                             input: [libqemuutil, softmmu_mods],
2025                             capture: true,
2026                             command: [undefsym, nm, '@INPUT@'])
2027
2028qom_ss = qom_ss.apply(config_host, strict: false)
2029libqom = static_library('qom', qom_ss.sources() + genh,
2030                        dependencies: [qom_ss.dependencies()],
2031                        name_suffix: 'fa')
2032
2033qom = declare_dependency(link_whole: libqom)
2034
2035authz_ss = authz_ss.apply(config_host, strict: false)
2036libauthz = static_library('authz', authz_ss.sources() + genh,
2037                          dependencies: [authz_ss.dependencies()],
2038                          name_suffix: 'fa',
2039                          build_by_default: false)
2040
2041authz = declare_dependency(link_whole: libauthz,
2042                           dependencies: qom)
2043
2044crypto_ss = crypto_ss.apply(config_host, strict: false)
2045libcrypto = static_library('crypto', crypto_ss.sources() + genh,
2046                           dependencies: [crypto_ss.dependencies()],
2047                           name_suffix: 'fa',
2048                           build_by_default: false)
2049
2050crypto = declare_dependency(link_whole: libcrypto,
2051                            dependencies: [authz, qom])
2052
2053io_ss = io_ss.apply(config_host, strict: false)
2054libio = static_library('io', io_ss.sources() + genh,
2055                       dependencies: [io_ss.dependencies()],
2056                       link_with: libqemuutil,
2057                       name_suffix: 'fa',
2058                       build_by_default: false)
2059
2060io = declare_dependency(link_whole: libio, dependencies: [crypto, qom])
2061
2062libmigration = static_library('migration', sources: migration_files + genh,
2063                              name_suffix: 'fa',
2064                              build_by_default: false)
2065migration = declare_dependency(link_with: libmigration,
2066                               dependencies: [zlib, qom, io])
2067softmmu_ss.add(migration)
2068
2069block_ss = block_ss.apply(config_host, strict: false)
2070libblock = static_library('block', block_ss.sources() + genh,
2071                          dependencies: block_ss.dependencies(),
2072                          link_depends: block_syms,
2073                          name_suffix: 'fa',
2074                          build_by_default: false)
2075
2076block = declare_dependency(link_whole: [libblock],
2077                           link_args: '@block.syms',
2078                           dependencies: [crypto, io])
2079
2080blockdev_ss = blockdev_ss.apply(config_host, strict: false)
2081libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
2082                             dependencies: blockdev_ss.dependencies(),
2083                             name_suffix: 'fa',
2084                             build_by_default: false)
2085
2086blockdev = declare_dependency(link_whole: [libblockdev],
2087                              dependencies: [block])
2088
2089qmp_ss = qmp_ss.apply(config_host, strict: false)
2090libqmp = static_library('qmp', qmp_ss.sources() + genh,
2091                        dependencies: qmp_ss.dependencies(),
2092                        name_suffix: 'fa',
2093                        build_by_default: false)
2094
2095qmp = declare_dependency(link_whole: [libqmp])
2096
2097libchardev = static_library('chardev', chardev_ss.sources() + genh,
2098                            name_suffix: 'fa',
2099                            dependencies: [gnutls],
2100                            build_by_default: false)
2101
2102chardev = declare_dependency(link_whole: libchardev)
2103
2104libhwcore = static_library('hwcore', sources: hwcore_files + genh,
2105                           name_suffix: 'fa',
2106                           build_by_default: false)
2107hwcore = declare_dependency(link_whole: libhwcore)
2108common_ss.add(hwcore)
2109
2110###########
2111# Targets #
2112###########
2113
2114foreach m : block_mods + softmmu_mods
2115  shared_module(m.name(),
2116                name_prefix: '',
2117                link_whole: m,
2118                install: true,
2119                install_dir: qemu_moddir)
2120endforeach
2121
2122softmmu_ss.add(authz, blockdev, chardev, crypto, io, qmp)
2123common_ss.add(qom, qemuutil)
2124
2125common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss])
2126common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
2127
2128common_all = common_ss.apply(config_all, strict: false)
2129common_all = static_library('common',
2130                            build_by_default: false,
2131                            sources: common_all.sources() + genh,
2132                            dependencies: common_all.dependencies(),
2133                            name_suffix: 'fa')
2134
2135feature_to_c = find_program('scripts/feature_to_c.sh')
2136
2137emulators = {}
2138foreach target : target_dirs
2139  config_target = config_target_mak[target]
2140  target_name = config_target['TARGET_NAME']
2141  arch = config_target['TARGET_BASE_ARCH']
2142  arch_srcs = [config_target_h[target]]
2143  arch_deps = []
2144  c_args = ['-DNEED_CPU_H',
2145            '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
2146            '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
2147  link_args = emulator_link_args
2148
2149  config_target += config_host
2150  target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
2151  if targetos == 'linux'
2152    target_inc += include_directories('linux-headers', is_system: true)
2153  endif
2154  if target.endswith('-softmmu')
2155    qemu_target_name = 'qemu-system-' + target_name
2156    target_type='system'
2157    t = target_softmmu_arch[arch].apply(config_target, strict: false)
2158    arch_srcs += t.sources()
2159    arch_deps += t.dependencies()
2160
2161    hw_dir = target_name == 'sparc64' ? 'sparc64' : arch
2162    hw = hw_arch[hw_dir].apply(config_target, strict: false)
2163    arch_srcs += hw.sources()
2164    arch_deps += hw.dependencies()
2165
2166    arch_srcs += config_devices_h[target]
2167    link_args += ['@block.syms', '@qemu.syms']
2168  else
2169    abi = config_target['TARGET_ABI_DIR']
2170    target_type='user'
2171    qemu_target_name = 'qemu-' + target_name
2172    if 'CONFIG_LINUX_USER' in config_target
2173      base_dir = 'linux-user'
2174      target_inc += include_directories('linux-user/host/' / config_host['ARCH'])
2175    else
2176      base_dir = 'bsd-user'
2177      target_inc += include_directories('bsd-user/freebsd')
2178    endif
2179    target_inc += include_directories(
2180      base_dir,
2181      base_dir / abi,
2182    )
2183    if 'CONFIG_LINUX_USER' in config_target
2184      dir = base_dir / abi
2185      arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
2186      if config_target.has_key('TARGET_SYSTBL_ABI')
2187        arch_srcs += \
2188          syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
2189                                             extra_args : config_target['TARGET_SYSTBL_ABI'])
2190      endif
2191    endif
2192  endif
2193
2194  if 'TARGET_XML_FILES' in config_target
2195    gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
2196                                output: target + '-gdbstub-xml.c',
2197                                input: files(config_target['TARGET_XML_FILES'].split()),
2198                                command: [feature_to_c, '@INPUT@'],
2199                                capture: true)
2200    arch_srcs += gdbstub_xml
2201  endif
2202
2203  t = target_arch[arch].apply(config_target, strict: false)
2204  arch_srcs += t.sources()
2205  arch_deps += t.dependencies()
2206
2207  target_common = common_ss.apply(config_target, strict: false)
2208  objects = common_all.extract_objects(target_common.sources())
2209  deps = target_common.dependencies()
2210
2211  target_specific = specific_ss.apply(config_target, strict: false)
2212  arch_srcs += target_specific.sources()
2213  arch_deps += target_specific.dependencies()
2214
2215  lib = static_library('qemu-' + target,
2216                 sources: arch_srcs + genh,
2217                 dependencies: arch_deps,
2218                 objects: objects,
2219                 include_directories: target_inc,
2220                 c_args: c_args,
2221                 build_by_default: false,
2222                 name_suffix: 'fa')
2223
2224  if target.endswith('-softmmu')
2225    execs = [{
2226      'name': 'qemu-system-' + target_name,
2227      'gui': false,
2228      'sources': files('softmmu/main.c'),
2229      'dependencies': []
2230    }]
2231    if targetos == 'windows' and (sdl.found() or gtk.found())
2232      execs += [{
2233        'name': 'qemu-system-' + target_name + 'w',
2234        'gui': true,
2235        'sources': files('softmmu/main.c'),
2236        'dependencies': []
2237      }]
2238    endif
2239    if config_host.has_key('CONFIG_FUZZ')
2240      specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
2241      execs += [{
2242        'name': 'qemu-fuzz-' + target_name,
2243        'gui': false,
2244        'sources': specific_fuzz.sources(),
2245        'dependencies': specific_fuzz.dependencies(),
2246      }]
2247    endif
2248  else
2249    execs = [{
2250      'name': 'qemu-' + target_name,
2251      'gui': false,
2252      'sources': [],
2253      'dependencies': []
2254    }]
2255  endif
2256  foreach exe: execs
2257    exe_name = exe['name']
2258    exe_sign = 'CONFIG_HVF' in config_target
2259    if exe_sign
2260      exe_name += '-unsigned'
2261    endif
2262
2263    emulator = executable(exe_name, exe['sources'],
2264               install: true,
2265               c_args: c_args,
2266               dependencies: arch_deps + deps + exe['dependencies'],
2267               objects: lib.extract_all_objects(recursive: true),
2268               link_language: link_language,
2269               link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
2270               link_args: link_args,
2271               gui_app: exe['gui'])
2272
2273    if exe_sign
2274      emulators += {exe['name'] : custom_target(exe['name'],
2275                   depends: emulator,
2276                   output: exe['name'],
2277                   command: [
2278                     meson.current_source_dir() / 'scripts/entitlement.sh',
2279                     meson.current_build_dir() / exe_name,
2280                     meson.current_build_dir() / exe['name'],
2281                     meson.current_source_dir() / 'accel/hvf/entitlements.plist'
2282                   ])
2283      }
2284
2285      meson.add_install_script('scripts/entitlement.sh', '--install',
2286                               get_option('bindir') / exe_name,
2287                               get_option('bindir') / exe['name'],
2288                               meson.current_source_dir() / 'accel/hvf/entitlements.plist')
2289    else
2290      emulators += {exe['name']: emulator}
2291    endif
2292
2293    if 'CONFIG_TRACE_SYSTEMTAP' in config_host
2294      foreach stp: [
2295        {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
2296        {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
2297        {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
2298        {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
2299      ]
2300        custom_target(exe['name'] + stp['ext'],
2301                      input: trace_events_all,
2302                      output: exe['name'] + stp['ext'],
2303                      install: stp['install'],
2304                      install_dir: get_option('datadir') / 'systemtap/tapset',
2305                      command: [
2306                        tracetool, '--group=all', '--format=' + stp['fmt'],
2307                        '--binary=' + stp['bin'],
2308                        '--target-name=' + target_name,
2309                        '--target-type=' + target_type,
2310                        '--probe-prefix=qemu.' + target_type + '.' + target_name,
2311                        '@INPUT@', '@OUTPUT@'
2312                      ],
2313                      depend_files: tracetool_depends)
2314      endforeach
2315    endif
2316  endforeach
2317endforeach
2318
2319# Other build targets
2320
2321if 'CONFIG_PLUGIN' in config_host
2322  install_headers('include/qemu/qemu-plugin.h')
2323endif
2324
2325if 'CONFIG_GUEST_AGENT' in config_host
2326  subdir('qga')
2327elif get_option('guest_agent_msi').enabled()
2328  error('Guest agent MSI requested, but the guest agent is not being built')
2329endif
2330
2331# Don't build qemu-keymap if xkbcommon is not explicitly enabled
2332# when we don't build tools or system
2333if xkbcommon.found()
2334  # used for the update-keymaps target, so include rules even if !have_tools
2335  qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
2336                           dependencies: [qemuutil, xkbcommon], install: have_tools)
2337endif
2338
2339if have_tools
2340  qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
2341             dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
2342  qemu_io = executable('qemu-io', files('qemu-io.c'),
2343             dependencies: [block, qemuutil], install: true)
2344  qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
2345               dependencies: [blockdev, qemuutil, gnutls], install: true)
2346
2347  subdir('storage-daemon')
2348  subdir('contrib/rdmacm-mux')
2349  subdir('contrib/elf2dmp')
2350
2351  executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
2352             dependencies: qemuutil,
2353             install: true)
2354
2355  if 'CONFIG_VHOST_USER' in config_host
2356    subdir('contrib/vhost-user-blk')
2357    subdir('contrib/vhost-user-gpu')
2358    subdir('contrib/vhost-user-input')
2359    subdir('contrib/vhost-user-scsi')
2360  endif
2361
2362  if targetos == 'linux'
2363    executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
2364               dependencies: [qemuutil, libcap_ng],
2365               install: true,
2366               install_dir: get_option('libexecdir'))
2367
2368    executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
2369               dependencies: [authz, crypto, io, qom, qemuutil,
2370                              libcap_ng, mpathpersist],
2371               install: true)
2372  endif
2373
2374  if 'CONFIG_IVSHMEM' in config_host
2375    subdir('contrib/ivshmem-client')
2376    subdir('contrib/ivshmem-server')
2377  endif
2378endif
2379
2380subdir('scripts')
2381subdir('tools')
2382subdir('pc-bios')
2383subdir('docs')
2384subdir('tests')
2385if gtk.found()
2386  subdir('po')
2387endif
2388
2389if host_machine.system() == 'windows'
2390  nsis_cmd = [
2391    find_program('scripts/nsis.py'),
2392    '@OUTPUT@',
2393    get_option('prefix'),
2394    meson.current_source_dir(),
2395    host_machine.cpu(),
2396    '--',
2397    '-DDISPLAYVERSION=' + meson.project_version(),
2398  ]
2399  if build_docs
2400    nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
2401  endif
2402  if gtk.found()
2403    nsis_cmd += '-DCONFIG_GTK=y'
2404  endif
2405
2406  nsis = custom_target('nsis',
2407                       output: 'qemu-setup-' + meson.project_version() + '.exe',
2408                       input: files('qemu.nsi'),
2409                       build_always_stale: true,
2410                       command: nsis_cmd + ['@INPUT@'])
2411  alias_target('installer', nsis)
2412endif
2413
2414#########################
2415# Configuration summary #
2416#########################
2417
2418# Directories
2419summary_info = {}
2420summary_info += {'Install prefix':    get_option('prefix')}
2421summary_info += {'BIOS directory':    qemu_datadir}
2422summary_info += {'firmware path':     get_option('qemu_firmwarepath')}
2423summary_info += {'binary directory':  get_option('bindir')}
2424summary_info += {'library directory': get_option('libdir')}
2425summary_info += {'module directory':  qemu_moddir}
2426summary_info += {'libexec directory': get_option('libexecdir')}
2427summary_info += {'include directory': get_option('includedir')}
2428summary_info += {'config directory':  get_option('sysconfdir')}
2429if targetos != 'windows'
2430  summary_info += {'local state directory': get_option('localstatedir')}
2431  summary_info += {'Manual directory':      get_option('mandir')}
2432else
2433  summary_info += {'local state directory': 'queried at runtime'}
2434endif
2435summary_info += {'Doc directory':     get_option('docdir')}
2436summary_info += {'Build directory':   meson.current_build_dir()}
2437summary_info += {'Source path':       meson.current_source_dir()}
2438summary_info += {'GIT submodules':    config_host['GIT_SUBMODULES']}
2439summary(summary_info, bool_yn: true, section: 'Directories')
2440
2441# Host binaries
2442summary_info = {}
2443summary_info += {'git':               config_host['GIT']}
2444summary_info += {'make':              config_host['MAKE']}
2445summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
2446summary_info += {'sphinx-build':      sphinx_build.found()}
2447if config_host.has_key('HAVE_GDB_BIN')
2448  summary_info += {'gdb':             config_host['HAVE_GDB_BIN']}
2449endif
2450summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
2451if targetos == 'windows' and config_host.has_key('CONFIG_GUEST_AGENT')
2452  summary_info += {'wixl':            wixl.found() ? wixl.full_path() : false}
2453endif
2454if slirp_opt != 'disabled'
2455  summary_info += {'smbd':            config_host['CONFIG_SMBD_COMMAND']}
2456endif
2457summary(summary_info, bool_yn: true, section: 'Host binaries')
2458
2459# Configurable features
2460summary_info = {}
2461summary_info += {'Documentation':     build_docs}
2462summary_info += {'system-mode emulation': have_system}
2463summary_info += {'user-mode emulation': have_user}
2464summary_info += {'block layer':       have_block}
2465summary_info += {'Install blobs':     get_option('install_blobs')}
2466summary_info += {'module support':    config_host.has_key('CONFIG_MODULES')}
2467if config_host.has_key('CONFIG_MODULES')
2468  summary_info += {'alternative module path': config_host.has_key('CONFIG_MODULE_UPGRADES')}
2469endif
2470summary_info += {'plugin support':    config_host.has_key('CONFIG_PLUGIN')}
2471summary_info += {'fuzzing support':   config_host.has_key('CONFIG_FUZZ')}
2472if have_system
2473  summary_info += {'Audio drivers':     config_host['CONFIG_AUDIO_DRIVERS']}
2474endif
2475summary_info += {'Trace backends':    config_host['TRACE_BACKENDS']}
2476if config_host['TRACE_BACKENDS'].split().contains('simple')
2477  summary_info += {'Trace output file': config_host['CONFIG_TRACE_FILE'] + '-<pid>'}
2478endif
2479summary_info += {'QOM debugging':     config_host.has_key('CONFIG_QOM_CAST_DEBUG')}
2480summary_info += {'vhost-kernel support': config_host.has_key('CONFIG_VHOST_KERNEL')}
2481summary_info += {'vhost-net support': config_host.has_key('CONFIG_VHOST_NET')}
2482summary_info += {'vhost-crypto support': config_host.has_key('CONFIG_VHOST_CRYPTO')}
2483summary_info += {'vhost-scsi support': config_host.has_key('CONFIG_VHOST_SCSI')}
2484summary_info += {'vhost-vsock support': config_host.has_key('CONFIG_VHOST_VSOCK')}
2485summary_info += {'vhost-user support': config_host.has_key('CONFIG_VHOST_USER')}
2486summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
2487summary_info += {'vhost-user-fs support': config_host.has_key('CONFIG_VHOST_USER_FS')}
2488summary_info += {'vhost-vdpa support': config_host.has_key('CONFIG_VHOST_VDPA')}
2489summary_info += {'build guest agent': config_host.has_key('CONFIG_GUEST_AGENT')}
2490summary(summary_info, bool_yn: true, section: 'Configurable features')
2491
2492# Compilation information
2493summary_info = {}
2494summary_info += {'host CPU':          cpu}
2495summary_info += {'host endianness':   build_machine.endian()}
2496summary_info += {'C compiler':        meson.get_compiler('c').cmd_array()[0]}
2497summary_info += {'Host C compiler':   meson.get_compiler('c', native: true).cmd_array()[0]}
2498if link_language == 'cpp'
2499  summary_info += {'C++ compiler':      meson.get_compiler('cpp').cmd_array()[0]}
2500else
2501  summary_info += {'C++ compiler':      false}
2502endif
2503if targetos == 'darwin'
2504  summary_info += {'Objective-C compiler': meson.get_compiler('objc').cmd_array()[0]}
2505endif
2506if targetos == 'windows'
2507  if 'WIN_SDK' in config_host
2508    summary_info += {'Windows SDK':   config_host['WIN_SDK']}
2509  endif
2510endif
2511summary_info += {'ARFLAGS':           config_host['ARFLAGS']}
2512summary_info += {'CFLAGS':            ' '.join(get_option('c_args')
2513                                               + ['-O' + get_option('optimization')]
2514                                               + (get_option('debug') ? ['-g'] : []))}
2515if link_language == 'cpp'
2516  summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args')
2517                                               + ['-O' + get_option('optimization')]
2518                                               + (get_option('debug') ? ['-g'] : []))}
2519endif
2520link_args = get_option(link_language + '_link_args')
2521if link_args.length() > 0
2522  summary_info += {'LDFLAGS':         ' '.join(link_args)}
2523endif
2524summary_info += {'QEMU_CFLAGS':       config_host['QEMU_CFLAGS']}
2525summary_info += {'QEMU_LDFLAGS':      config_host['QEMU_LDFLAGS']}
2526summary_info += {'profiler':          config_host.has_key('CONFIG_PROFILER')}
2527summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
2528summary_info += {'PIE':               get_option('b_pie')}
2529summary_info += {'static build':      config_host.has_key('CONFIG_STATIC')}
2530summary_info += {'malloc trim support': has_malloc_trim}
2531summary_info += {'membarrier':        config_host.has_key('CONFIG_MEMBARRIER')}
2532summary_info += {'preadv support':    config_host_data.get('CONFIG_PREADV')}
2533summary_info += {'fdatasync':         config_host.has_key('CONFIG_FDATASYNC')}
2534summary_info += {'madvise':           config_host.has_key('CONFIG_MADVISE')}
2535summary_info += {'posix_madvise':     config_host.has_key('CONFIG_POSIX_MADVISE')}
2536summary_info += {'posix_memalign':    config_host.has_key('CONFIG_POSIX_MEMALIGN')}
2537summary_info += {'debug stack usage': config_host.has_key('CONFIG_DEBUG_STACK_USAGE')}
2538summary_info += {'mutex debugging':   config_host.has_key('CONFIG_DEBUG_MUTEX')}
2539summary_info += {'memory allocator':  get_option('malloc')}
2540summary_info += {'avx2 optimization': config_host.has_key('CONFIG_AVX2_OPT')}
2541summary_info += {'avx512f optimization': config_host.has_key('CONFIG_AVX512F_OPT')}
2542summary_info += {'gprof enabled':     config_host.has_key('CONFIG_GPROF')}
2543summary_info += {'gcov':              get_option('b_coverage')}
2544summary_info += {'thread sanitizer':  config_host.has_key('CONFIG_TSAN')}
2545summary_info += {'CFI support':       get_option('cfi')}
2546if get_option('cfi')
2547  summary_info += {'CFI debug support': get_option('cfi_debug')}
2548endif
2549summary_info += {'strip binaries':    get_option('strip')}
2550summary_info += {'sparse':            sparse.found() ? sparse.full_path() : false}
2551summary_info += {'mingw32 support':   targetos == 'windows'}
2552
2553# snarf the cross-compilation information for tests
2554foreach target: target_dirs
2555  tcg_mak = meson.current_build_dir() / 'tests/tcg' / 'config-' + target + '.mak'
2556  if fs.exists(tcg_mak)
2557    config_cross_tcg = keyval.load(tcg_mak)
2558    target = config_cross_tcg['TARGET_NAME']
2559    compiler = ''
2560    if 'DOCKER_CROSS_CC_GUEST' in config_cross_tcg
2561      summary_info += {target + ' tests': config_cross_tcg['DOCKER_CROSS_CC_GUEST'] +
2562                                          ' via ' + config_cross_tcg['DOCKER_IMAGE']}
2563    elif 'CROSS_CC_GUEST' in config_cross_tcg
2564      summary_info += {target + ' tests'
2565                                : config_cross_tcg['CROSS_CC_GUEST'] }
2566    endif
2567   endif
2568endforeach
2569
2570summary(summary_info, bool_yn: true, section: 'Compilation')
2571
2572# Targets and accelerators
2573summary_info = {}
2574if have_system
2575  summary_info += {'KVM support':       config_all.has_key('CONFIG_KVM')}
2576  summary_info += {'HAX support':       config_all.has_key('CONFIG_HAX')}
2577  summary_info += {'HVF support':       config_all.has_key('CONFIG_HVF')}
2578  summary_info += {'WHPX support':      config_all.has_key('CONFIG_WHPX')}
2579  summary_info += {'Xen support':       config_host.has_key('CONFIG_XEN_BACKEND')}
2580  if config_host.has_key('CONFIG_XEN_BACKEND')
2581    summary_info += {'xen ctrl version':  config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']}
2582  endif
2583endif
2584summary_info += {'TCG support':       config_all.has_key('CONFIG_TCG')}
2585if config_all.has_key('CONFIG_TCG')
2586  if get_option('tcg_interpreter')
2587    summary_info += {'TCG backend':   'TCI (TCG with bytecode interpreter, experimental and slow)'}
2588  else
2589    summary_info += {'TCG backend':   'native (@0@)'.format(cpu)}
2590  endif
2591  summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')}
2592endif
2593summary_info += {'target list':       ' '.join(target_dirs)}
2594if have_system
2595  summary_info += {'default devices':   get_option('default_devices')}
2596  summary_info += {'out of process emulation': multiprocess_allowed}
2597endif
2598summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
2599
2600# Block layer
2601summary_info = {}
2602summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']}
2603summary_info += {'coroutine pool':    config_host['CONFIG_COROUTINE_POOL'] == '1'}
2604if have_block
2605  summary_info += {'Block whitelist (rw)': config_host['CONFIG_BDRV_RW_WHITELIST']}
2606  summary_info += {'Block whitelist (ro)': config_host['CONFIG_BDRV_RO_WHITELIST']}
2607  summary_info += {'VirtFS support':    have_virtfs}
2608  summary_info += {'build virtiofs daemon': have_virtiofsd}
2609  summary_info += {'Live block migration': config_host.has_key('CONFIG_LIVE_BLOCK_MIGRATION')}
2610  summary_info += {'replication support': config_host.has_key('CONFIG_REPLICATION')}
2611  summary_info += {'bochs support':     config_host.has_key('CONFIG_BOCHS')}
2612  summary_info += {'cloop support':     config_host.has_key('CONFIG_CLOOP')}
2613  summary_info += {'dmg support':       config_host.has_key('CONFIG_DMG')}
2614  summary_info += {'qcow v1 support':   config_host.has_key('CONFIG_QCOW1')}
2615  summary_info += {'vdi support':       config_host.has_key('CONFIG_VDI')}
2616  summary_info += {'vvfat support':     config_host.has_key('CONFIG_VVFAT')}
2617  summary_info += {'qed support':       config_host.has_key('CONFIG_QED')}
2618  summary_info += {'parallels support': config_host.has_key('CONFIG_PARALLELS')}
2619  summary_info += {'sheepdog support':  config_host.has_key('CONFIG_SHEEPDOG')}
2620  summary_info += {'FUSE exports':      fuse.found()}
2621endif
2622summary(summary_info, bool_yn: true, section: 'Block layer support')
2623
2624# Crypto
2625summary_info = {}
2626summary_info += {'TLS priority':      config_host['CONFIG_TLS_PRIORITY']}
2627summary_info += {'GNUTLS support':    config_host.has_key('CONFIG_GNUTLS')}
2628# TODO: add back version
2629summary_info += {'libgcrypt':         config_host.has_key('CONFIG_GCRYPT')}
2630if config_host.has_key('CONFIG_GCRYPT')
2631   summary_info += {'  hmac':            config_host.has_key('CONFIG_GCRYPT_HMAC')}
2632   summary_info += {'  XTS':             not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')}
2633endif
2634# TODO: add back version
2635summary_info += {'nettle':            config_host.has_key('CONFIG_NETTLE')}
2636if config_host.has_key('CONFIG_NETTLE')
2637   summary_info += {'  XTS':             not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')}
2638endif
2639summary_info += {'crypto afalg':      config_host.has_key('CONFIG_AF_ALG')}
2640summary_info += {'rng-none':          config_host.has_key('CONFIG_RNG_NONE')}
2641summary_info += {'Linux keyring':     config_host.has_key('CONFIG_SECRET_KEYRING')}
2642summary(summary_info, bool_yn: true, section: 'Crypto')
2643
2644# Libraries
2645summary_info = {}
2646if targetos == 'darwin'
2647  summary_info += {'Cocoa support':   cocoa.found()}
2648endif
2649# TODO: add back version
2650summary_info += {'SDL support':       sdl.found()}
2651summary_info += {'SDL image support': sdl_image.found()}
2652# TODO: add back version
2653summary_info += {'GTK support':       gtk.found()}
2654summary_info += {'pixman':            pixman.found()}
2655# TODO: add back version
2656summary_info += {'VTE support':       config_host.has_key('CONFIG_VTE')}
2657# TODO: add back version
2658summary_info += {'slirp support':     slirp_opt == 'disabled' ? false : slirp_opt}
2659summary_info += {'libtasn1':          config_host.has_key('CONFIG_TASN1')}
2660summary_info += {'PAM':               config_host.has_key('CONFIG_AUTH_PAM')}
2661summary_info += {'iconv support':     iconv.found()}
2662summary_info += {'curses support':    curses.found()}
2663# TODO: add back version
2664summary_info += {'virgl support':     config_host.has_key('CONFIG_VIRGL')}
2665summary_info += {'curl support':      curl.found()}
2666summary_info += {'Multipath support': mpathpersist.found()}
2667summary_info += {'VNC support':       vnc.found()}
2668if vnc.found()
2669  summary_info += {'VNC SASL support':  sasl.found()}
2670  summary_info += {'VNC JPEG support':  jpeg.found()}
2671  summary_info += {'VNC PNG support':   png.found()}
2672endif
2673summary_info += {'brlapi support':    brlapi.found()}
2674summary_info += {'vde support':       config_host.has_key('CONFIG_VDE')}
2675summary_info += {'netmap support':    config_host.has_key('CONFIG_NETMAP')}
2676summary_info += {'Linux AIO support': config_host.has_key('CONFIG_LINUX_AIO')}
2677summary_info += {'Linux io_uring support': config_host.has_key('CONFIG_LINUX_IO_URING')}
2678summary_info += {'ATTR/XATTR support': libattr.found()}
2679summary_info += {'RDMA support':      config_host.has_key('CONFIG_RDMA')}
2680summary_info += {'PVRDMA support':    config_host.has_key('CONFIG_PVRDMA')}
2681summary_info += {'fdt support':       fdt_opt == 'disabled' ? false : fdt_opt}
2682summary_info += {'libcap-ng support': libcap_ng.found()}
2683# TODO: add back protocol and server version
2684summary_info += {'spice support':     config_host.has_key('CONFIG_SPICE')}
2685summary_info += {'rbd support':       rbd.found()}
2686summary_info += {'xfsctl support':    config_host.has_key('CONFIG_XFS')}
2687summary_info += {'smartcard support': config_host.has_key('CONFIG_SMARTCARD')}
2688summary_info += {'U2F support':       u2f.found()}
2689summary_info += {'libusb':            config_host.has_key('CONFIG_USB_LIBUSB')}
2690summary_info += {'usb net redir':     config_host.has_key('CONFIG_USB_REDIR')}
2691summary_info += {'OpenGL support':    config_host.has_key('CONFIG_OPENGL')}
2692summary_info += {'GBM':               config_host.has_key('CONFIG_GBM')}
2693summary_info += {'libiscsi support':  libiscsi.found()}
2694summary_info += {'libnfs support':    libnfs.found()}
2695if targetos == 'windows'
2696  if config_host.has_key('CONFIG_GUEST_AGENT')
2697    summary_info += {'QGA VSS support':   config_host.has_key('CONFIG_QGA_VSS')}
2698    summary_info += {'QGA w32 disk info': config_host.has_key('CONFIG_QGA_NTDDSCSI')}
2699  endif
2700endif
2701summary_info += {'seccomp support':   seccomp.found()}
2702summary_info += {'GlusterFS support': glusterfs.found()}
2703summary_info += {'TPM support':       config_host.has_key('CONFIG_TPM')}
2704summary_info += {'libssh support':    config_host.has_key('CONFIG_LIBSSH')}
2705summary_info += {'lzo support':       lzo.found()}
2706summary_info += {'snappy support':    snappy.found()}
2707summary_info += {'bzip2 support':     libbzip2.found()}
2708summary_info += {'lzfse support':     liblzfse.found()}
2709summary_info += {'zstd support':      zstd.found()}
2710summary_info += {'NUMA host support': config_host.has_key('CONFIG_NUMA')}
2711summary_info += {'libxml2':           config_host.has_key('CONFIG_LIBXML2')}
2712summary_info += {'capstone':          capstone_opt == 'disabled' ? false : capstone_opt}
2713summary_info += {'libpmem support':   config_host.has_key('CONFIG_LIBPMEM')}
2714summary_info += {'libdaxctl support': config_host.has_key('CONFIG_LIBDAXCTL')}
2715summary_info += {'libudev':           libudev.found()}
2716summary_info += {'FUSE lseek':        fuse_lseek.found()}
2717summary(summary_info, bool_yn: true, section: 'Dependencies')
2718
2719if not supported_cpus.contains(cpu)
2720  message()
2721  warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!')
2722  message()
2723  message('CPU host architecture ' + cpu + ' support is not currently maintained.')
2724  message('The QEMU project intends to remove support for this host CPU in')
2725  message('a future release if nobody volunteers to maintain it and to')
2726  message('provide a build host for our continuous integration setup.')
2727  message('configure has succeeded and you can continue to build, but')
2728  message('if you care about QEMU on this platform you should contact')
2729  message('us upstream at qemu-devel@nongnu.org.')
2730endif
2731
2732if not supported_oses.contains(targetos)
2733  message()
2734  warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!')
2735  message()
2736  message('Host OS ' + targetos + 'support is not currently maintained.')
2737  message('The QEMU project intends to remove support for this host OS in')
2738  message('a future release if nobody volunteers to maintain it and to')
2739  message('provide a build host for our continuous integration setup.')
2740  message('configure has succeeded and you can continue to build, but')
2741  message('if you care about QEMU on this platform you should contact')
2742  message('us upstream at qemu-devel@nongnu.org.')
2743endif
2744