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