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