Skip to content
Snippets Groups Projects
meson.build 92.3 KiB
Newer Older
project('qemu', ['c'], meson_version: '>=0.55.0',
        default_options: ['warning_level=1', 'c_std=gnu99', 'cpp_std=gnu++11', 'b_colorout=auto'] +
                         (meson.version().version_compare('>=0.56.0') ? [ 'b_staticpic=false' ] : []),
        version: run_command('head', meson.source_root() / 'VERSION').stdout().strip())

not_found = dependency('', required: false)
if meson.version().version_compare('>=0.56.0')
  keyval = import('keyval')
else
  keyval = import('unstable-keyval')
endif
ss = import('sourceset')
sh = find_program('sh')
cc = meson.get_compiler('c')
config_host = keyval.load(meson.current_build_dir() / 'config-host.mak')
enable_modules = 'CONFIG_MODULES' in config_host
enable_static = 'CONFIG_STATIC' in config_host

# Temporary directory used for files created while
# configure runs. Since it is in the build directory
# we can safely blow away any previous version of it
# (and we need not jump through hoops to try to delete
# it when configure exits.)
tmpdir = meson.current_build_dir() / 'meson-private/temp'

if get_option('qemu_suffix').startswith('/')
  error('qemu_suffix cannot start with a /')
endif

qemu_confdir = get_option('sysconfdir') / get_option('qemu_suffix')
qemu_datadir = get_option('datadir') / get_option('qemu_suffix')
qemu_docdir = get_option('docdir') / get_option('qemu_suffix')
qemu_moddir = get_option('libdir') / get_option('qemu_suffix')

qemu_desktopdir = get_option('datadir') / 'applications'
qemu_icondir = get_option('datadir') / 'icons'

config_host_data = configuration_data()
genh = []
target_dirs = config_host['TARGET_DIRS'].split()
have_user = false
have_system = false
foreach target : target_dirs
  have_user = have_user or target.endswith('-user')
  have_system = have_system or target.endswith('-softmmu')
endforeach
have_tools = 'CONFIG_TOOLS' in config_host
have_block = have_system or have_tools

python = import('python').find_installation()

supported_oses = ['windows', 'freebsd', 'netbsd', 'openbsd', 'darwin', 'sunos', 'linux']
supported_cpus = ['ppc', 'ppc64', 's390x', 'riscv32', 'riscv64', 'x86', 'x86_64',
  'arm', 'aarch64', 'mips', 'mips64', 'sparc', 'sparc64']

cpu = host_machine.cpu_family()
targetos = host_machine.system()

if cpu in ['x86', 'x86_64']
  kvm_targets = ['i386-softmmu', 'x86_64-softmmu']
elif cpu == 'aarch64'
  kvm_targets = ['aarch64-softmmu']
elif cpu == 's390x'
  kvm_targets = ['s390x-softmmu']
elif cpu in ['ppc', 'ppc64']
  kvm_targets = ['ppc-softmmu', 'ppc64-softmmu']
elif cpu in ['mips', 'mips64']
  kvm_targets = ['mips-softmmu', 'mipsel-softmmu', 'mips64-softmmu', 'mips64el-softmmu']
else
  kvm_targets = []
endif

accelerator_targets = { 'CONFIG_KVM': kvm_targets }
if cpu in ['x86', 'x86_64', 'arm', 'aarch64']
  # i368 emulator provides xenpv machine type for multiple architectures
  accelerator_targets += {
    'CONFIG_XEN': ['i386-softmmu', 'x86_64-softmmu'],
  }
endif
if cpu in ['x86', 'x86_64']
  accelerator_targets += {
    'CONFIG_HAX': ['i386-softmmu', 'x86_64-softmmu'],
    'CONFIG_HVF': ['x86_64-softmmu'],
    'CONFIG_WHPX': ['i386-softmmu', 'x86_64-softmmu'],
  }
endif

##################
# Compiler flags #
##################

# Specify linker-script with add_project_link_arguments so that it is not placed
# within a linker --start-group/--end-group pair
if 'CONFIG_FUZZ' in config_host
   add_project_link_arguments(['-Wl,-T,',
                               (meson.current_source_dir() / 'tests/qtest/fuzz/fork_fuzz.ld')],
                              native: false, language: ['c', 'cpp', 'objc'])
endif

add_project_arguments(config_host['QEMU_CFLAGS'].split(),
                      native: false, language: ['c', 'objc'])
add_project_arguments(config_host['QEMU_CXXFLAGS'].split(),
                      native: false, language: 'cpp')
add_project_link_arguments(config_host['QEMU_LDFLAGS'].split(),
                           native: false, language: ['c', 'cpp', 'objc'])

if targetos == 'linux'
  add_project_arguments('-isystem', meson.current_source_dir() / 'linux-headers',
                        '-isystem', 'linux-headers',
                        language: ['c', 'cpp'])
endif

if 'CONFIG_TCG_INTERPRETER' in config_host
  tcg_arch = 'tci'
elif config_host['ARCH'] == 'sparc64'
  tcg_arch = 'sparc'
elif config_host['ARCH'] == 's390x'
  tcg_arch = 's390'
elif config_host['ARCH'] in ['x86_64', 'x32']
  tcg_arch = 'i386'
elif config_host['ARCH'] == 'ppc64'
  tcg_arch = 'ppc'
elif config_host['ARCH'] in ['riscv32', 'riscv64']
  tcg_arch = 'riscv'
else
  tcg_arch = config_host['ARCH']
endif
add_project_arguments('-iquote', meson.current_source_dir() / 'tcg' / tcg_arch,
                      '-iquote', '.',
                      '-iquote', meson.current_source_dir(),
                      '-iquote', meson.current_source_dir() / 'accel/tcg',
                      '-iquote', meson.current_source_dir() / 'include',
                      '-iquote', meson.current_source_dir() / 'disas/libvixl',
                      language: ['c', 'cpp', 'objc'])
link_language = meson.get_external_property('link_language', 'cpp')
if link_language == 'cpp'
  add_languages('cpp', required: true, native: false)
endif
if host_machine.system() == 'darwin'
  add_languages('objc', required: false, native: false)
endif

sparse = find_program('cgcc', required: get_option('sparse'))
if sparse.found()
  run_target('sparse',
             command: [find_program('scripts/check_sparse.py'),
                       'compile_commands.json', sparse.full_path(), '-Wbitwise',
                       '-Wno-transparent-union', '-Wno-old-initializer',
                       '-Wno-non-pointer-null'])
###########################################
# Target-specific checks and dependencies #
###########################################

if targetos != 'linux' and get_option('mpath').enabled()
  error('Multipath is supported only on Linux')
endif

m = cc.find_library('m', required: false)
util = cc.find_library('util', required: false)
version_res = []
coref = []
iokit = []
emulator_link_args = []
if targetos == 'windows'
  socket = cc.find_library('ws2_32')
  winmm = cc.find_library('winmm')

  win = import('windows')
  version_res = win.compile_resources('version.rc',
                                      depend_files: files('pc-bios/qemu-nsis.ico'),
                                      include_directories: include_directories('.'))
elif targetos == 'darwin'
  coref = dependency('appleframeworks', modules: 'CoreFoundation')
  iokit = dependency('appleframeworks', modules: 'IOKit')
elif targetos == 'sunos'
  socket = [cc.find_library('socket'),
            cc.find_library('nsl'),
            cc.find_library('resolv')]
elif targetos == 'haiku'
  socket = [cc.find_library('posix_error_mapper'),
            cc.find_library('network'),
            cc.find_library('bsd')]
elif targetos == 'openbsd'
  if not get_option('tcg').disabled() and target_dirs.length() > 0
    # Disable OpenBSD W^X if available
    emulator_link_args = cc.get_supported_link_arguments('-Wl,-z,wxneeded')
  endif
accelerators = []
if not get_option('kvm').disabled() and targetos == 'linux'
  accelerators += 'CONFIG_KVM'
endif
if not get_option('xen').disabled() and 'CONFIG_XEN_BACKEND' in config_host
  accelerators += 'CONFIG_XEN'
  have_xen_pci_passthrough = not get_option('xen_pci_passthrough').disabled() and targetos == 'linux'
else
  have_xen_pci_passthrough = false
endif
if not get_option('whpx').disabled() and targetos == 'windows'
  if get_option('whpx').enabled() and host_machine.cpu() != 'x86_64'
    error('WHPX requires 64-bit host')
  elif cc.has_header('WinHvPlatform.h', required: get_option('whpx')) and \
       cc.has_header('WinHvEmulation.h', required: get_option('whpx'))
    accelerators += 'CONFIG_WHPX'
  endif
endif
if not get_option('hvf').disabled()
  hvf = dependency('appleframeworks', modules: 'Hypervisor',
                   required: get_option('hvf'))
  if hvf.found()
    accelerators += 'CONFIG_HVF'
  endif
endif
if not get_option('hax').disabled()
  if get_option('hax').enabled() or targetos in ['windows', 'darwin', 'netbsd']
    accelerators += 'CONFIG_HAX'
  endif
endif
if not get_option('tcg').disabled()
  if cpu not in supported_cpus
    if 'CONFIG_TCG_INTERPRETER' in config_host
      warning('Unsupported CPU @0@, will use TCG with TCI (experimental)'.format(cpu))
    else
      error('Unsupported CPU @0@, try --enable-tcg-interpreter'.format(cpu))
    endif
  endif
  accelerators += 'CONFIG_TCG'
  config_host += { 'CONFIG_TCG': 'y' }
endif

if 'CONFIG_KVM' not in accelerators and get_option('kvm').enabled()
  error('KVM not available on this platform')
endif
if 'CONFIG_HVF' not in accelerators and get_option('hvf').enabled()
  error('HVF not available on this platform')
endif
if 'CONFIG_WHPX' not in accelerators and get_option('whpx').enabled()
  error('WHPX not available on this platform')
endif
if not have_xen_pci_passthrough and get_option('xen_pci_passthrough').enabled()
  if 'CONFIG_XEN' in accelerators
    error('Xen PCI passthrough not available on this platform')
  else
    error('Xen PCI passthrough requested but Xen not enabled')
  endif
endif
################
# Dependencies #
################

# The path to glib.h is added to all compilation commands.  This was
# grandfathered in from the QEMU Makefiles.
add_project_arguments(config_host['GLIB_CFLAGS'].split(),
                      native: false, language: ['c', 'cpp', 'objc'])
glib = declare_dependency(compile_args: config_host['GLIB_CFLAGS'].split(),
                          link_args: config_host['GLIB_LIBS'].split())
# override glib dep with the configure results (for subprojects)
meson.override_dependency('glib-2.0', glib)

gio = not_found
if 'CONFIG_GIO' in config_host
  gio = declare_dependency(compile_args: config_host['GIO_CFLAGS'].split(),
                           link_args: config_host['GIO_LIBS'].split())
endif
lttng = not_found
if 'CONFIG_TRACE_UST' in config_host
  lttng = declare_dependency(link_args: config_host['LTTNG_UST_LIBS'].split())
endif
urcubp = not_found
if 'CONFIG_TRACE_UST' in config_host
  urcubp = declare_dependency(link_args: config_host['URCU_BP_LIBS'].split())
endif
gcrypt = not_found
if 'CONFIG_GCRYPT' in config_host
  gcrypt = declare_dependency(compile_args: config_host['GCRYPT_CFLAGS'].split(),
                              link_args: config_host['GCRYPT_LIBS'].split())
endif
nettle = not_found
if 'CONFIG_NETTLE' in config_host
  nettle = declare_dependency(compile_args: config_host['NETTLE_CFLAGS'].split(),
                              link_args: config_host['NETTLE_LIBS'].split())
endif
gnutls = not_found
if 'CONFIG_GNUTLS' in config_host
  gnutls = declare_dependency(compile_args: config_host['GNUTLS_CFLAGS'].split(),
                              link_args: config_host['GNUTLS_LIBS'].split())
endif
pixman = not_found
if have_system or have_tools
  pixman = dependency('pixman-1', required: have_system, version:'>=0.21.8',
                      method: 'pkg-config', static: enable_static)
pam = not_found
if 'CONFIG_AUTH_PAM' in config_host
  pam = cc.find_library('pam')
endif
libaio = cc.find_library('aio', required: false)
zlib = dependency('zlib', required: true, static: enable_static)
linux_io_uring = not_found
if 'CONFIG_LINUX_IO_URING' in config_host
  linux_io_uring = declare_dependency(compile_args: config_host['LINUX_IO_URING_CFLAGS'].split(),
                                      link_args: config_host['LINUX_IO_URING_LIBS'].split())
endif
libxml2 = not_found
if 'CONFIG_LIBXML2' in config_host
  libxml2 = declare_dependency(compile_args: config_host['LIBXML2_CFLAGS'].split(),
                               link_args: config_host['LIBXML2_LIBS'].split())
endif
libnfs = not_found
Paolo Bonzini's avatar
Paolo Bonzini committed
if not get_option('libnfs').auto() or have_block
  libnfs = dependency('libnfs', version: '>=1.9.3',
                      required: get_option('libnfs'),
                      method: 'pkg-config', static: enable_static)
endif

libattr_test = '''
  #include <stddef.h>
  #include <sys/types.h>
  #ifdef CONFIG_LIBATTR
  #include <attr/xattr.h>
  #else
  #include <sys/xattr.h>
  #endif
  int main(void) { getxattr(NULL, NULL, NULL, 0); setxattr(NULL, NULL, NULL, 0, 0); return 0; }'''

libattr = not_found
have_old_libattr = false
if not get_option('attr').disabled()
  if cc.links(libattr_test)
    libattr = declare_dependency()
  else
    libattr = cc.find_library('attr', has_headers: ['attr/xattr.h'],
                              required: get_option('attr'),
                              static: enable_static)
    if libattr.found() and not \
      cc.links(libattr_test, dependencies: libattr, args: '-DCONFIG_LIBATTR')
      libattr = not_found
      if get_option('attr').enabled()
        error('could not link libattr')
      else
        warning('could not link libattr, disabling')
      endif
    else
      have_old_libattr = libattr.found()
    endif
  endif
cocoa = dependency('appleframeworks', modules: 'Cocoa', required: get_option('cocoa'))
if cocoa.found() and get_option('sdl').enabled()
  error('Cocoa and SDL cannot be enabled at the same time')
endif
if cocoa.found() and get_option('gtk').enabled()
  error('Cocoa and GTK+ cannot be enabled at the same time')
endif

seccomp = not_found
if not get_option('seccomp').auto() or have_system or have_tools
  seccomp = dependency('libseccomp', version: '>=2.3.0',
                       required: get_option('seccomp'),
                       method: 'pkg-config', static: enable_static)
libcap_ng = not_found
Paolo Bonzini's avatar
Paolo Bonzini committed
if not get_option('cap_ng').auto() or have_system or have_tools
  libcap_ng = cc.find_library('cap-ng', has_headers: ['cap-ng.h'],
                              required: get_option('cap_ng'),
                              static: enable_static)
endif
if libcap_ng.found() and not cc.links('''
   #include <cap-ng.h>
   int main(void)
   {
     capng_capability_to_name(CAPNG_EFFECTIVE);
     return 0;
   }''', dependencies: libcap_ng)
  libcap_ng = not_found
  if get_option('cap_ng').enabled()
    error('could not link libcap-ng')
  else
    warning('could not link libcap-ng, disabling')
  endif
if get_option('xkbcommon').auto() and not have_system and not have_tools
  xkbcommon = not_found
else
  xkbcommon = dependency('xkbcommon', required: get_option('xkbcommon'),
                         method: 'pkg-config', static: enable_static)
vde = not_found
if config_host.has_key('CONFIG_VDE')
  vde = declare_dependency(link_args: config_host['VDE_LIBS'].split())
endif
pulse = not_found
if 'CONFIG_LIBPULSE' in config_host
  pulse = declare_dependency(compile_args: config_host['PULSE_CFLAGS'].split(),
                             link_args: config_host['PULSE_LIBS'].split())
endif
alsa = not_found
if 'CONFIG_ALSA' in config_host
  alsa = declare_dependency(compile_args: config_host['ALSA_CFLAGS'].split(),
                            link_args: config_host['ALSA_LIBS'].split())
endif
jack = not_found
if 'CONFIG_LIBJACK' in config_host
  jack = declare_dependency(link_args: config_host['JACK_LIBS'].split())
endif
spice_headers = not_found
if 'CONFIG_SPICE' in config_host
  spice = declare_dependency(compile_args: config_host['SPICE_CFLAGS'].split(),
                             link_args: config_host['SPICE_LIBS'].split())
  spice_headers = declare_dependency(compile_args: config_host['SPICE_CFLAGS'].split())
rt = cc.find_library('rt', required: false)
libdl = not_found
if 'CONFIG_PLUGIN' in config_host
  libdl = cc.find_library('dl', required: true)
endif
libiscsi = not_found
if not get_option('libiscsi').auto() or have_block
  libiscsi = dependency('libiscsi', version: '>=1.9.0',
                         required: get_option('libiscsi'),
                         method: 'pkg-config', static: enable_static)
zstd = not_found
Paolo Bonzini's avatar
Paolo Bonzini committed
if not get_option('zstd').auto() or have_block
  zstd = dependency('libzstd', version: '>=1.4.0',
                    required: get_option('zstd'),
                    method: 'pkg-config', static: enable_static)
endif
gbm = not_found
if 'CONFIG_GBM' in config_host
  gbm = declare_dependency(compile_args: config_host['GBM_CFLAGS'].split(),
                           link_args: config_host['GBM_LIBS'].split())
endif
virgl = not_found
if 'CONFIG_VIRGL' in config_host
  virgl = declare_dependency(compile_args: config_host['VIRGL_CFLAGS'].split(),
                             link_args: config_host['VIRGL_LIBS'].split())
endif
curl = not_found
Paolo Bonzini's avatar
Paolo Bonzini committed
if not get_option('curl').auto() or have_block
  curl = dependency('libcurl', version: '>=7.29.0',
                    method: 'pkg-config',
                    required: get_option('curl'),
                    static: enable_static)
Paolo Bonzini's avatar
Paolo Bonzini committed
libudev = not_found
Paolo Bonzini's avatar
Paolo Bonzini committed
if targetos == 'linux' and (have_system or have_tools)
  libudev = dependency('libudev',
                       method: 'pkg-config',
                       required: get_option('libudev'),
                       static: enable_static)
endif

mpathlibs = [libudev]
mpathpersist = not_found
mpathpersist_new_api = false
if targetos == 'linux' and have_tools and not get_option('mpath').disabled()
  mpath_test_source_new = '''
    #include <libudev.h>
    #include <mpath_persist.h>
    unsigned mpath_mx_alloc_len = 1024;
    int logsink;
    static struct config *multipath_conf;
    extern struct udev *udev;
    extern struct config *get_multipath_config(void);
    extern void put_multipath_config(struct config *conf);
    struct udev *udev;
    struct config *get_multipath_config(void) { return multipath_conf; }
    void put_multipath_config(struct config *conf) { }
    int main(void) {
        udev = udev_new();
        multipath_conf = mpath_lib_init();
        return 0;
    }'''
  mpath_test_source_old = '''
      #include <libudev.h>
      #include <mpath_persist.h>
      unsigned mpath_mx_alloc_len = 1024;
      int logsink;
      int main(void) {
          struct udev *udev = udev_new();
          mpath_lib_init(udev);
          return 0;
      }'''
  libmpathpersist = cc.find_library('mpathpersist',
                                    required: get_option('mpath'),
                                    static: enable_static)
  if libmpathpersist.found()
    mpathlibs += libmpathpersist
    if enable_static
      mpathlibs += cc.find_library('devmapper',
                                     required: get_option('mpath'),
                                     static: enable_static)
    mpathlibs += cc.find_library('multipath',
                                 required: get_option('mpath'),
                                 static: enable_static)
    foreach lib: mpathlibs
      if not lib.found()
        mpathlibs = []
        break
      endif
    endforeach
    if mpathlibs.length() == 0
      msg = 'Dependencies missing for libmpathpersist'
    elif cc.links(mpath_test_source_new, dependencies: mpathlibs)
      mpathpersist = declare_dependency(dependencies: mpathlibs)
      mpathpersist_new_api = true
    elif cc.links(mpath_test_source_old, dependencies: mpathlibs)
      mpathpersist = declare_dependency(dependencies: mpathlibs)
    else
      msg = 'Cannot detect libmpathpersist API'
    endif
    if not mpathpersist.found()
      if get_option('mpath').enabled()
        warning(msg + ', disabling')
Paolo Bonzini's avatar
Paolo Bonzini committed
endif
if have_system and not get_option('curses').disabled()
  curses_test = '''
    #include <locale.h>
    #include <curses.h>
    #include <wchar.h>
    int main(void) {
      wchar_t wch = L'w';
      setlocale(LC_ALL, "");
      resize_term(0, 0);
      addwstr(L"wide chars\n");
      addnwstr(&wch, 1);
      add_wch(WACS_DEGREE);
      return 0;
    }'''

  curses_dep_list = targetos == 'windows' ? ['ncurses', 'ncursesw'] : ['ncursesw']
  foreach curses_dep : curses_dep_list
    if not curses.found()
      curses = dependency(curses_dep,
                          required: false,
                          method: 'pkg-config',
                          static: enable_static)
    endif
  endforeach
  msg = get_option('curses').enabled() ? 'curses library not found' : ''
  curses_compile_args = ['-DNCURSES_WIDECHAR']
  if curses.found()
    if cc.links(curses_test, args: curses_compile_args, dependencies: [curses])
      curses = declare_dependency(compile_args: curses_compile_args, dependencies: [curses])
    else
      msg = 'curses package not usable'
      curses = not_found
  if not curses.found()
    has_curses_h = cc.has_header('curses.h', args: curses_compile_args)
    if targetos != 'windows' and not has_curses_h
      message('Trying with /usr/include/ncursesw')
      curses_compile_args += ['-I/usr/include/ncursesw']
      has_curses_h = cc.has_header('curses.h', args: curses_compile_args)
    endif
    if has_curses_h
      curses_libname_list = (targetos == 'windows' ? ['pdcurses'] : ['ncursesw', 'cursesw'])
      foreach curses_libname : curses_libname_list
        libcurses = cc.find_library(curses_libname,
                                    required: false,
                                    static: enable_static)
        if libcurses.found()
          if cc.links(curses_test, args: curses_compile_args, dependencies: libcurses)
            curses = declare_dependency(compile_args: curses_compile_args,
                                        dependencies: [libcurses])
            break
          else
            msg = 'curses library not usable'
          endif
      endforeach
    endif
  endif
  if not get_option('iconv').disabled()
    foreach link_args : [ ['-liconv'], [] ]
      # Programs will be linked with glib and this will bring in libiconv on FreeBSD.
      # We need to use libiconv if available because mixing libiconv's headers with
      # the system libc does not work.
      # However, without adding glib to the dependencies -L/usr/local/lib will not be
      # included in the command line and libiconv will not be found.
      if cc.links('''
        #include <iconv.h>
        int main(void) {
          iconv_t conv = iconv_open("WCHAR_T", "UCS-2");
          return conv != (iconv_t) -1;
        }''', args: config_host['GLIB_CFLAGS'].split() + config_host['GLIB_LIBS'].split() + link_args)
        iconv = declare_dependency(link_args: link_args, dependencies: glib)
        break
    endforeach
  endif
  if curses.found() and not iconv.found()
    if get_option('iconv').enabled()
      error('iconv not available')
    endif
    msg = 'iconv required for curses UI but not available'
    curses = not_found
  endif
  if not curses.found() and msg != ''
    if get_option('curses').enabled()
      error(msg)
      warning(msg + ', disabling')
Paolo Bonzini's avatar
Paolo Bonzini committed
if not get_option('brlapi').auto() or have_system
  brlapi = cc.find_library('brlapi', has_headers: ['brlapi.h'],
                         required: get_option('brlapi'),
                         static: enable_static)
  if brlapi.found() and not cc.links('''
     #include <brlapi.h>
     #include <stddef.h>
     int main(void) { return brlapi__openConnection (NULL, NULL, NULL); }''', dependencies: brlapi)
    brlapi = not_found
    if get_option('brlapi').enabled()
      error('could not link brlapi')
    else
      warning('could not link brlapi, disabling')
    endif
  endif
if not get_option('sdl').auto() or (have_system and not cocoa.found())
  sdl = dependency('sdl2', required: get_option('sdl'), static: enable_static)
  sdl_image = not_found
endif
if sdl.found()
  # work around 2.0.8 bug
  sdl = declare_dependency(compile_args: '-Wno-undef',
                           dependencies: sdl)
  sdl_image = dependency('SDL2_image', required: get_option('sdl_image'),
                         method: 'pkg-config', static: enable_static)
else
  if get_option('sdl_image').enabled()
    error('sdl-image required, but SDL was @0@'.format(
          get_option('sdl').disabled() ? 'disabled' : 'not found'))
  endif
  sdl_image = not_found
rbd = not_found
Paolo Bonzini's avatar
Paolo Bonzini committed
if not get_option('rbd').auto() or have_block
  librados = cc.find_library('rados', required: get_option('rbd'),
                             static: enable_static)
  librbd = cc.find_library('rbd', has_headers: ['rbd/librbd.h'],
                           required: get_option('rbd'),
                           static: enable_static)
  if librados.found() and librbd.found() and cc.links('''
    #include <stdio.h>
    #include <rbd/librbd.h>
    int main(void) {
      rados_t cluster;
      rados_create(&cluster, NULL);
      return 0;
    }''', dependencies: [librbd, librados])
    rbd = declare_dependency(dependencies: [librbd, librados])
  endif
endif
glusterfs = not_found
glusterfs_ftruncate_has_stat = false
glusterfs_iocb_has_stat = false
if not get_option('glusterfs').auto() or have_block
  glusterfs = dependency('glusterfs-api', version: '>=3',
                         required: get_option('glusterfs'),
                         method: 'pkg-config', static: enable_static)
  if glusterfs.found()
    glusterfs_ftruncate_has_stat = cc.links('''
      #include <glusterfs/api/glfs.h>

      int
      main(void)
      {
          /* new glfs_ftruncate() passes two additional args */
          return glfs_ftruncate(NULL, 0, NULL, NULL);
      }
    ''', dependencies: glusterfs)
    glusterfs_iocb_has_stat = cc.links('''
      #include <glusterfs/api/glfs.h>

      /* new glfs_io_cbk() passes two additional glfs_stat structs */
      static void
      glusterfs_iocb(glfs_fd_t *fd, ssize_t ret, struct glfs_stat *prestat, struct glfs_stat *poststat, void *data)
      {}

      int
      main(void)
      {
          glfs_io_cbk iocb = &glusterfs_iocb;
          iocb(NULL, 0 , NULL, NULL, NULL);
          return 0;
      }
    ''', dependencies: glusterfs)
  endif
endif
libssh = not_found
if 'CONFIG_LIBSSH' in config_host
  libssh = declare_dependency(compile_args: config_host['LIBSSH_CFLAGS'].split(),
                              link_args: config_host['LIBSSH_LIBS'].split())
endif
libbzip2 = not_found
Paolo Bonzini's avatar
Paolo Bonzini committed
if not get_option('bzip2').auto() or have_block
  libbzip2 = cc.find_library('bz2', has_headers: ['bzlib.h'],
                             required: get_option('bzip2'),
                             static: enable_static)
  if libbzip2.found() and not cc.links('''
     #include <bzlib.h>
     int main(void) { BZ2_bzlibVersion(); return 0; }''', dependencies: libbzip2)
    libbzip2 = not_found
    if get_option('bzip2').enabled()
      error('could not link libbzip2')
    else
      warning('could not link libbzip2, disabling')
    endif
  endif
endif
liblzfse = not_found
Paolo Bonzini's avatar
Paolo Bonzini committed
if not get_option('lzfse').auto() or have_block
  liblzfse = cc.find_library('lzfse', has_headers: ['lzfse.h'],
                             required: get_option('lzfse'),
                             static: enable_static)
endif
if liblzfse.found() and not cc.links('''
   #include <lzfse.h>
   int main(void) { lzfse_decode_scratch_size(); return 0; }''', dependencies: liblzfse)
  liblzfse = not_found
  if get_option('lzfse').enabled()
    error('could not link liblzfse')
  else
    warning('could not link liblzfse, disabling')
  endif
endif
oss = not_found
if 'CONFIG_AUDIO_OSS' in config_host
  oss = declare_dependency(link_args: config_host['OSS_LIBS'].split())
endif
dsound = not_found
if 'CONFIG_AUDIO_DSOUND' in config_host
  dsound = declare_dependency(link_args: config_host['DSOUND_LIBS'].split())
endif
coreaudio = not_found
if 'CONFIG_AUDIO_COREAUDIO' in config_host
  coreaudio = declare_dependency(link_args: config_host['COREAUDIO_LIBS'].split())
endif
opengl = not_found
if 'CONFIG_OPENGL' in config_host
  opengl = declare_dependency(compile_args: config_host['OPENGL_CFLAGS'].split(),
                              link_args: config_host['OPENGL_LIBS'].split())
gtk = not_found
gtkx11 = not_found
if not get_option('gtk').auto() or (have_system and not cocoa.found())
  gtk = dependency('gtk+-3.0', version: '>=3.22.0',
                   method: 'pkg-config',
                   required: get_option('gtk'),
                   static: enable_static)
  if gtk.found()
    gtkx11 = dependency('gtk+-x11-3.0', version: '>=3.22.0',
                        method: 'pkg-config',
                        required: false,
                        static: enable_static)
    gtk = declare_dependency(dependencies: [gtk, gtkx11])
  endif
vte = not_found
if 'CONFIG_VTE' in config_host
  vte = declare_dependency(compile_args: config_host['VTE_CFLAGS'].split(),
                           link_args: config_host['VTE_LIBS'].split())
endif
x11 = not_found
if gtkx11.found() or 'lm32-softmmu' in target_dirs
  x11 = dependency('x11', method: 'pkg-config', required: gtkx11.found(),
                   static: enable_static)
png = not_found
jpeg = not_found
sasl = not_found
if get_option('vnc').enabled()
  vnc = declare_dependency() # dummy dependency
  png = dependency('libpng', required: get_option('vnc_png'),
                   method: 'pkg-config', static: enable_static)
  jpeg = dependency('libjpeg', required: get_option('vnc_jpeg'),
                    method: 'pkg-config', static: enable_static)
  sasl = cc.find_library('sasl2', has_headers: ['sasl/sasl.h'],
                         required: get_option('vnc_sasl'),
                         static: enable_static)
  if sasl.found()
    sasl = declare_dependency(dependencies: sasl,
                              compile_args: '-DSTRUCT_IOVEC_DEFINED')
  endif
snappy = not_found
Paolo Bonzini's avatar
Paolo Bonzini committed
if not get_option('snappy').auto() or have_system
  snappy = cc.find_library('snappy', has_headers: ['snappy-c.h'],
                           required: get_option('snappy'),
                           static: enable_static)
endif
if snappy.found() and not cc.links('''
   #include <snappy-c.h>
   int main(void) { snappy_max_compressed_length(4096); return 0; }''', dependencies: snappy)
  snappy = not_found
  if get_option('snappy').enabled()
    error('could not link libsnappy')
  else
    warning('could not link libsnappy, disabling')
  endif
endif
lzo = not_found
Paolo Bonzini's avatar
Paolo Bonzini committed
if not get_option('lzo').auto() or have_system
  lzo = cc.find_library('lzo2', has_headers: ['lzo/lzo1x.h'],
                        required: get_option('lzo'),
                        static: enable_static)
endif
if lzo.found() and not cc.links('''
   #include <lzo/lzo1x.h>
   int main(void) { lzo_version(); return 0; }''', dependencies: lzo)
  lzo = not_found
  if get_option('lzo').enabled()
    error('could not link liblzo2')
  else
    warning('could not link liblzo2, disabling')
  endif
endif
rdma = not_found
if 'CONFIG_RDMA' in config_host
  rdma = declare_dependency(link_args: config_host['RDMA_LIBS'].split())
endif
numa = not_found
if 'CONFIG_NUMA' in config_host
  numa = declare_dependency(link_args: config_host['NUMA_LIBS'].split())
endif
xen = not_found
if 'CONFIG_XEN_BACKEND' in config_host
  xen = declare_dependency(compile_args: config_host['XEN_CFLAGS'].split(),
                           link_args: config_host['XEN_LIBS'].split())
endif
Paolo Bonzini's avatar
Paolo Bonzini committed
cacard = not_found
if 'CONFIG_SMARTCARD' in config_host
  cacard = declare_dependency(compile_args: config_host['SMARTCARD_CFLAGS'].split(),
                              link_args: config_host['SMARTCARD_LIBS'].split())
endif
u2f = not_found
if have_system
  u2f = dependency('u2f-emu', required: get_option('u2f'),
                   method: 'pkg-config',
                   static: enable_static)
endif
Paolo Bonzini's avatar
Paolo Bonzini committed
usbredir = not_found
if 'CONFIG_USB_REDIR' in config_host
  usbredir = declare_dependency(compile_args: config_host['USB_REDIR_CFLAGS'].split(),
                                link_args: config_host['USB_REDIR_LIBS'].split())
endif
libusb = not_found
if 'CONFIG_USB_LIBUSB' in config_host
  libusb = declare_dependency(compile_args: config_host['LIBUSB_CFLAGS'].split(),
                              link_args: config_host['LIBUSB_LIBS'].split())
endif
Marc-André Lureau's avatar
Marc-André Lureau committed
libpmem = not_found
if 'CONFIG_LIBPMEM' in config_host
  libpmem = declare_dependency(compile_args: config_host['LIBPMEM_CFLAGS'].split(),
                               link_args: config_host['LIBPMEM_LIBS'].split())
endif
libdaxctl = not_found
if 'CONFIG_LIBDAXCTL' in config_host
  libdaxctl = declare_dependency(link_args: config_host['LIBDAXCTL_LIBS'].split())
endif
tasn1 = not_found
if 'CONFIG_TASN1' in config_host
  tasn1 = declare_dependency(compile_args: config_host['TASN1_CFLAGS'].split(),
                             link_args: config_host['TASN1_LIBS'].split())
endif
keyutils = dependency('libkeyutils', required: false,
                      method: 'pkg-config', static: enable_static)
has_gettid = cc.has_function('gettid')

# Malloc tests

malloc = []
if get_option('malloc') == 'system'
  has_malloc_trim = \
    not get_option('malloc_trim').disabled() and \
    cc.links('''#include <malloc.h>
                int main(void) { malloc_trim(0); return 0; }''')
else
  has_malloc_trim = false
  malloc = cc.find_library(get_option('malloc'), required: true)
endif
if not has_malloc_trim and get_option('malloc_trim').enabled()
  if get_option('malloc') == 'system'
    error('malloc_trim not available on this platform.')
  else
    error('malloc_trim not available with non-libc memory allocator')
  endif
endif

# Check whether the glibc provides statx()

statx_test = '''
  #ifndef _GNU_SOURCE
  #define _GNU_SOURCE
  #endif
  #include <sys/stat.h>
  int main(void) {
    struct statx statxbuf;
    statx(0, "", 0, STATX_BASIC_STATS, &statxbuf);
    return 0;
  }'''

has_statx = cc.links(statx_test)

have_vhost_user_blk_server = (targetos == 'linux' and
    'CONFIG_VHOST_USER' in config_host)

if get_option('vhost_user_blk_server').enabled()
    if targetos != 'linux'
        error('vhost_user_blk_server requires linux')
    elif 'CONFIG_VHOST_USER' not in config_host
        error('vhost_user_blk_server requires vhost-user support')
    endif
elif get_option('vhost_user_blk_server').disabled() or not have_system
    have_vhost_user_blk_server = false
endif

if get_option('fuse').disabled() and get_option('fuse_lseek').enabled()
  error('Cannot enable fuse-lseek while fuse is disabled')
endif

Hanna Reitz's avatar
Hanna Reitz committed
fuse = dependency('fuse3', required: get_option('fuse'),
                  version: '>=3.1', method: 'pkg-config',
                  static: enable_static)

fuse_lseek = not_found
if not get_option('fuse_lseek').disabled()
  if fuse.version().version_compare('>=3.8')
    # Dummy dependency
    fuse_lseek = declare_dependency()
  elif get_option('fuse_lseek').enabled()
    if fuse.found()
      error('fuse-lseek requires libfuse >=3.8, found ' + fuse.version())
    else
      error('fuse-lseek requires libfuse, which was not found')
    endif
  endif
endif

if get_option('cfi')
  cfi_flags=[]
  # Check for dependency on LTO
  if not get_option('b_lto')
    error('Selected Control-Flow Integrity but LTO is disabled')
  endif
  if config_host.has_key('CONFIG_MODULES')
    error('Selected Control-Flow Integrity is not compatible with modules')
  endif
  # Check for cfi flags. CFI requires LTO so we can't use
  # get_supported_arguments, but need a more complex "compiles" which allows
  # custom arguments
  if cc.compiles('int main () { return 0; }', name: '-fsanitize=cfi-icall',
                 args: ['-flto', '-fsanitize=cfi-icall'] )
    cfi_flags += '-fsanitize=cfi-icall'