xref: /openbmc/qemu/meson.build (revision ee17db83)
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/adc',
1708    'hw/alpha',
1709    'hw/arm',
1710    'hw/audio',
1711    'hw/block',
1712    'hw/block/dataplane',
1713    'hw/char',
1714    'hw/display',
1715    'hw/dma',
1716    'hw/hppa',
1717    'hw/hyperv',
1718    'hw/i2c',
1719    'hw/i386',
1720    'hw/i386/xen',
1721    'hw/ide',
1722    'hw/input',
1723    'hw/intc',
1724    'hw/isa',
1725    'hw/mem',
1726    'hw/mips',
1727    'hw/misc',
1728    'hw/misc/macio',
1729    'hw/net',
1730    'hw/net/can',
1731    'hw/nvram',
1732    'hw/pci',
1733    'hw/pci-host',
1734    'hw/ppc',
1735    'hw/rdma',
1736    'hw/rdma/vmw',
1737    'hw/rtc',
1738    'hw/s390x',
1739    'hw/scsi',
1740    'hw/sd',
1741    'hw/sparc',
1742    'hw/sparc64',
1743    'hw/ssi',
1744    'hw/timer',
1745    'hw/tpm',
1746    'hw/usb',
1747    'hw/vfio',
1748    'hw/virtio',
1749    'hw/watchdog',
1750    'hw/xen',
1751    'hw/gpio',
1752    'migration',
1753    'net',
1754    'softmmu',
1755    'ui',
1756  ]
1757endif
1758trace_events_subdirs += [
1759  'hw/core',
1760  'qapi',
1761  'qom',
1762  'target/arm',
1763  'target/hppa',
1764  'target/i386',
1765  'target/i386/kvm',
1766  'target/mips',
1767  'target/ppc',
1768  'target/riscv',
1769  'target/s390x',
1770  'target/sparc',
1771  'util',
1772]
1773
1774vhost_user = not_found
1775if 'CONFIG_VHOST_USER' in config_host
1776  libvhost_user = subproject('libvhost-user')
1777  vhost_user = libvhost_user.get_variable('vhost_user_dep')
1778endif
1779
1780subdir('qapi')
1781subdir('qobject')
1782subdir('stubs')
1783subdir('trace')
1784subdir('util')
1785subdir('qom')
1786subdir('authz')
1787subdir('crypto')
1788subdir('ui')
1789
1790
1791if enable_modules
1792  libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
1793  modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
1794endif
1795
1796stub_ss = stub_ss.apply(config_all, strict: false)
1797
1798util_ss.add_all(trace_ss)
1799util_ss = util_ss.apply(config_all, strict: false)
1800libqemuutil = static_library('qemuutil',
1801                             sources: util_ss.sources() + stub_ss.sources() + genh,
1802                             dependencies: [util_ss.dependencies(), m, glib, socket, malloc])
1803qemuutil = declare_dependency(link_with: libqemuutil,
1804                              sources: genh + version_res)
1805
1806decodetree = generator(find_program('scripts/decodetree.py'),
1807                       output: 'decode-@BASENAME@.c.inc',
1808                       arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
1809
1810subdir('audio')
1811subdir('io')
1812subdir('chardev')
1813subdir('fsdev')
1814subdir('libdecnumber')
1815subdir('target')
1816subdir('dump')
1817
1818block_ss.add(files(
1819  'block.c',
1820  'blockjob.c',
1821  'job.c',
1822  'qemu-io-cmds.c',
1823))
1824block_ss.add(when: 'CONFIG_REPLICATION', if_true: files('replication.c'))
1825
1826subdir('nbd')
1827subdir('scsi')
1828subdir('block')
1829
1830blockdev_ss.add(files(
1831  'blockdev.c',
1832  'blockdev-nbd.c',
1833  'iothread.c',
1834  'job-qmp.c',
1835), gnutls)
1836
1837# os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
1838# os-win32.c does not
1839blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c'))
1840softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')])
1841
1842common_ss.add(files('cpus-common.c'))
1843
1844subdir('softmmu')
1845
1846common_ss.add(capstone)
1847specific_ss.add(files('cpu.c', 'disas.c', 'gdbstub.c'), capstone)
1848specific_ss.add(files('exec-vary.c'))
1849specific_ss.add(when: 'CONFIG_TCG', if_true: files(
1850  'fpu/softfloat.c',
1851  'tcg/optimize.c',
1852  'tcg/tcg-common.c',
1853  'tcg/tcg-op-gvec.c',
1854  'tcg/tcg-op-vec.c',
1855  'tcg/tcg-op.c',
1856  'tcg/tcg.c',
1857))
1858specific_ss.add(when: 'CONFIG_TCG_INTERPRETER', if_true: files('disas/tci.c', 'tcg/tci.c'))
1859
1860subdir('backends')
1861subdir('disas')
1862subdir('migration')
1863subdir('monitor')
1864subdir('net')
1865subdir('replay')
1866subdir('hw')
1867subdir('accel')
1868subdir('plugins')
1869subdir('bsd-user')
1870subdir('linux-user')
1871
1872bsd_user_ss.add(files('gdbstub.c'))
1873specific_ss.add_all(when: 'CONFIG_BSD_USER', if_true: bsd_user_ss)
1874
1875linux_user_ss.add(files('gdbstub.c', 'thunk.c'))
1876specific_ss.add_all(when: 'CONFIG_LINUX_USER', if_true: linux_user_ss)
1877
1878# needed for fuzzing binaries
1879subdir('tests/qtest/libqos')
1880subdir('tests/qtest/fuzz')
1881
1882########################
1883# Library dependencies #
1884########################
1885
1886block_mods = []
1887softmmu_mods = []
1888foreach d, list : modules
1889  foreach m, module_ss : list
1890    if enable_modules and targetos != 'windows'
1891      module_ss = module_ss.apply(config_all, strict: false)
1892      sl = static_library(d + '-' + m, [genh, module_ss.sources()],
1893                          dependencies: [modulecommon, module_ss.dependencies()], pic: true)
1894      if d == 'block'
1895        block_mods += sl
1896      else
1897        softmmu_mods += sl
1898      endif
1899    else
1900      if d == 'block'
1901        block_ss.add_all(module_ss)
1902      else
1903        softmmu_ss.add_all(module_ss)
1904      endif
1905    endif
1906  endforeach
1907endforeach
1908
1909nm = find_program('nm')
1910undefsym = find_program('scripts/undefsym.py')
1911block_syms = custom_target('block.syms', output: 'block.syms',
1912                             input: [libqemuutil, block_mods],
1913                             capture: true,
1914                             command: [undefsym, nm, '@INPUT@'])
1915qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
1916                             input: [libqemuutil, softmmu_mods],
1917                             capture: true,
1918                             command: [undefsym, nm, '@INPUT@'])
1919
1920qom_ss = qom_ss.apply(config_host, strict: false)
1921libqom = static_library('qom', qom_ss.sources() + genh,
1922                        dependencies: [qom_ss.dependencies()],
1923                        name_suffix: 'fa')
1924
1925qom = declare_dependency(link_whole: libqom)
1926
1927authz_ss = authz_ss.apply(config_host, strict: false)
1928libauthz = static_library('authz', authz_ss.sources() + genh,
1929                          dependencies: [authz_ss.dependencies()],
1930                          name_suffix: 'fa',
1931                          build_by_default: false)
1932
1933authz = declare_dependency(link_whole: libauthz,
1934                           dependencies: qom)
1935
1936crypto_ss = crypto_ss.apply(config_host, strict: false)
1937libcrypto = static_library('crypto', crypto_ss.sources() + genh,
1938                           dependencies: [crypto_ss.dependencies()],
1939                           name_suffix: 'fa',
1940                           build_by_default: false)
1941
1942crypto = declare_dependency(link_whole: libcrypto,
1943                            dependencies: [authz, qom])
1944
1945io_ss = io_ss.apply(config_host, strict: false)
1946libio = static_library('io', io_ss.sources() + genh,
1947                       dependencies: [io_ss.dependencies()],
1948                       link_with: libqemuutil,
1949                       name_suffix: 'fa',
1950                       build_by_default: false)
1951
1952io = declare_dependency(link_whole: libio, dependencies: [crypto, qom])
1953
1954libmigration = static_library('migration', sources: migration_files + genh,
1955                              name_suffix: 'fa',
1956                              build_by_default: false)
1957migration = declare_dependency(link_with: libmigration,
1958                               dependencies: [zlib, qom, io])
1959softmmu_ss.add(migration)
1960
1961block_ss = block_ss.apply(config_host, strict: false)
1962libblock = static_library('block', block_ss.sources() + genh,
1963                          dependencies: block_ss.dependencies(),
1964                          link_depends: block_syms,
1965                          name_suffix: 'fa',
1966                          build_by_default: false)
1967
1968block = declare_dependency(link_whole: [libblock],
1969                           link_args: '@block.syms',
1970                           dependencies: [crypto, io])
1971
1972blockdev_ss = blockdev_ss.apply(config_host, strict: false)
1973libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
1974                             dependencies: blockdev_ss.dependencies(),
1975                             name_suffix: 'fa',
1976                             build_by_default: false)
1977
1978blockdev = declare_dependency(link_whole: [libblockdev],
1979                              dependencies: [block])
1980
1981qmp_ss = qmp_ss.apply(config_host, strict: false)
1982libqmp = static_library('qmp', qmp_ss.sources() + genh,
1983                        dependencies: qmp_ss.dependencies(),
1984                        name_suffix: 'fa',
1985                        build_by_default: false)
1986
1987qmp = declare_dependency(link_whole: [libqmp])
1988
1989libchardev = static_library('chardev', chardev_ss.sources() + genh,
1990                            name_suffix: 'fa',
1991                            dependencies: [gnutls],
1992                            build_by_default: false)
1993
1994chardev = declare_dependency(link_whole: libchardev)
1995
1996libhwcore = static_library('hwcore', sources: hwcore_files + genh,
1997                           name_suffix: 'fa',
1998                           build_by_default: false)
1999hwcore = declare_dependency(link_whole: libhwcore)
2000common_ss.add(hwcore)
2001
2002###########
2003# Targets #
2004###########
2005
2006foreach m : block_mods + softmmu_mods
2007  shared_module(m.name(),
2008                name_prefix: '',
2009                link_whole: m,
2010                install: true,
2011                install_dir: qemu_moddir)
2012endforeach
2013
2014softmmu_ss.add(authz, blockdev, chardev, crypto, io, qmp)
2015common_ss.add(qom, qemuutil)
2016
2017common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss])
2018common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
2019
2020common_all = common_ss.apply(config_all, strict: false)
2021common_all = static_library('common',
2022                            build_by_default: false,
2023                            sources: common_all.sources() + genh,
2024                            dependencies: common_all.dependencies(),
2025                            name_suffix: 'fa')
2026
2027feature_to_c = find_program('scripts/feature_to_c.sh')
2028
2029emulators = {}
2030foreach target : target_dirs
2031  config_target = config_target_mak[target]
2032  target_name = config_target['TARGET_NAME']
2033  arch = config_target['TARGET_BASE_ARCH']
2034  arch_srcs = [config_target_h[target]]
2035  arch_deps = []
2036  c_args = ['-DNEED_CPU_H',
2037            '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
2038            '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
2039  link_args = emulator_link_args
2040
2041  config_target += config_host
2042  target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
2043  if targetos == 'linux'
2044    target_inc += include_directories('linux-headers', is_system: true)
2045  endif
2046  if target.endswith('-softmmu')
2047    qemu_target_name = 'qemu-system-' + target_name
2048    target_type='system'
2049    t = target_softmmu_arch[arch].apply(config_target, strict: false)
2050    arch_srcs += t.sources()
2051    arch_deps += t.dependencies()
2052
2053    hw_dir = target_name == 'sparc64' ? 'sparc64' : arch
2054    hw = hw_arch[hw_dir].apply(config_target, strict: false)
2055    arch_srcs += hw.sources()
2056    arch_deps += hw.dependencies()
2057
2058    arch_srcs += config_devices_h[target]
2059    link_args += ['@block.syms', '@qemu.syms']
2060  else
2061    abi = config_target['TARGET_ABI_DIR']
2062    target_type='user'
2063    qemu_target_name = 'qemu-' + target_name
2064    if 'CONFIG_LINUX_USER' in config_target
2065      base_dir = 'linux-user'
2066      target_inc += include_directories('linux-user/host/' / config_host['ARCH'])
2067    else
2068      base_dir = 'bsd-user'
2069      target_inc += include_directories('bsd-user/freebsd')
2070    endif
2071    target_inc += include_directories(
2072      base_dir,
2073      base_dir / abi,
2074    )
2075    if 'CONFIG_LINUX_USER' in config_target
2076      dir = base_dir / abi
2077      arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
2078      if config_target.has_key('TARGET_SYSTBL_ABI')
2079        arch_srcs += \
2080          syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
2081                                             extra_args : config_target['TARGET_SYSTBL_ABI'])
2082      endif
2083    endif
2084  endif
2085
2086  if 'TARGET_XML_FILES' in config_target
2087    gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
2088                                output: target + '-gdbstub-xml.c',
2089                                input: files(config_target['TARGET_XML_FILES'].split()),
2090                                command: [feature_to_c, '@INPUT@'],
2091                                capture: true)
2092    arch_srcs += gdbstub_xml
2093  endif
2094
2095  t = target_arch[arch].apply(config_target, strict: false)
2096  arch_srcs += t.sources()
2097  arch_deps += t.dependencies()
2098
2099  target_common = common_ss.apply(config_target, strict: false)
2100  objects = common_all.extract_objects(target_common.sources())
2101  deps = target_common.dependencies()
2102
2103  target_specific = specific_ss.apply(config_target, strict: false)
2104  arch_srcs += target_specific.sources()
2105  arch_deps += target_specific.dependencies()
2106
2107  lib = static_library('qemu-' + target,
2108                 sources: arch_srcs + genh,
2109                 dependencies: arch_deps,
2110                 objects: objects,
2111                 include_directories: target_inc,
2112                 c_args: c_args,
2113                 build_by_default: false,
2114                 name_suffix: 'fa')
2115
2116  if target.endswith('-softmmu')
2117    execs = [{
2118      'name': 'qemu-system-' + target_name,
2119      'gui': false,
2120      'sources': files('softmmu/main.c'),
2121      'dependencies': []
2122    }]
2123    if targetos == 'windows' and (sdl.found() or gtk.found())
2124      execs += [{
2125        'name': 'qemu-system-' + target_name + 'w',
2126        'gui': true,
2127        'sources': files('softmmu/main.c'),
2128        'dependencies': []
2129      }]
2130    endif
2131    if config_host.has_key('CONFIG_FUZZ')
2132      specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
2133      execs += [{
2134        'name': 'qemu-fuzz-' + target_name,
2135        'gui': false,
2136        'sources': specific_fuzz.sources(),
2137        'dependencies': specific_fuzz.dependencies(),
2138      }]
2139    endif
2140  else
2141    execs = [{
2142      'name': 'qemu-' + target_name,
2143      'gui': false,
2144      'sources': [],
2145      'dependencies': []
2146    }]
2147  endif
2148  foreach exe: execs
2149    emulators += {exe['name']:
2150         executable(exe['name'], exe['sources'],
2151               install: true,
2152               c_args: c_args,
2153               dependencies: arch_deps + deps + exe['dependencies'],
2154               objects: lib.extract_all_objects(recursive: true),
2155               link_language: link_language,
2156               link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
2157               link_args: link_args,
2158               gui_app: exe['gui'])
2159    }
2160
2161    if 'CONFIG_TRACE_SYSTEMTAP' in config_host
2162      foreach stp: [
2163        {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
2164        {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
2165        {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
2166        {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
2167      ]
2168        custom_target(exe['name'] + stp['ext'],
2169                      input: trace_events_all,
2170                      output: exe['name'] + stp['ext'],
2171                      install: stp['install'],
2172                      install_dir: get_option('datadir') / 'systemtap/tapset',
2173                      command: [
2174                        tracetool, '--group=all', '--format=' + stp['fmt'],
2175                        '--binary=' + stp['bin'],
2176                        '--target-name=' + target_name,
2177                        '--target-type=' + target_type,
2178                        '--probe-prefix=qemu.' + target_type + '.' + target_name,
2179                        '@INPUT@', '@OUTPUT@'
2180                      ])
2181      endforeach
2182    endif
2183  endforeach
2184endforeach
2185
2186# Other build targets
2187
2188if 'CONFIG_PLUGIN' in config_host
2189  install_headers('include/qemu/qemu-plugin.h')
2190endif
2191
2192if 'CONFIG_GUEST_AGENT' in config_host
2193  subdir('qga')
2194endif
2195
2196# Don't build qemu-keymap if xkbcommon is not explicitly enabled
2197# when we don't build tools or system
2198if xkbcommon.found()
2199  # used for the update-keymaps target, so include rules even if !have_tools
2200  qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
2201                           dependencies: [qemuutil, xkbcommon], install: have_tools)
2202endif
2203
2204if have_tools
2205  qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
2206             dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
2207  qemu_io = executable('qemu-io', files('qemu-io.c'),
2208             dependencies: [block, qemuutil], install: true)
2209  qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
2210               dependencies: [blockdev, qemuutil, gnutls], install: true)
2211
2212  subdir('storage-daemon')
2213  subdir('contrib/rdmacm-mux')
2214  subdir('contrib/elf2dmp')
2215
2216  executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
2217             dependencies: qemuutil,
2218             install: true)
2219
2220  if 'CONFIG_VHOST_USER' in config_host
2221    subdir('contrib/vhost-user-blk')
2222    subdir('contrib/vhost-user-gpu')
2223    subdir('contrib/vhost-user-input')
2224    subdir('contrib/vhost-user-scsi')
2225  endif
2226
2227  if targetos == 'linux'
2228    executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
2229               dependencies: [qemuutil, libcap_ng],
2230               install: true,
2231               install_dir: get_option('libexecdir'))
2232
2233    executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
2234               dependencies: [authz, crypto, io, qom, qemuutil,
2235                              libcap_ng, mpathpersist],
2236               install: true)
2237  endif
2238
2239  if 'CONFIG_IVSHMEM' in config_host
2240    subdir('contrib/ivshmem-client')
2241    subdir('contrib/ivshmem-server')
2242  endif
2243endif
2244
2245subdir('scripts')
2246subdir('tools')
2247subdir('pc-bios')
2248subdir('docs')
2249subdir('tests')
2250if gtk.found()
2251  subdir('po')
2252endif
2253
2254if host_machine.system() == 'windows'
2255  nsis_cmd = [
2256    find_program('scripts/nsis.py'),
2257    '@OUTPUT@',
2258    get_option('prefix'),
2259    meson.current_source_dir(),
2260    host_machine.cpu(),
2261    '--',
2262    '-DDISPLAYVERSION=' + meson.project_version(),
2263  ]
2264  if build_docs
2265    nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
2266  endif
2267  if gtk.found()
2268    nsis_cmd += '-DCONFIG_GTK=y'
2269  endif
2270
2271  nsis = custom_target('nsis',
2272                       output: 'qemu-setup-' + meson.project_version() + '.exe',
2273                       input: files('qemu.nsi'),
2274                       build_always_stale: true,
2275                       command: nsis_cmd + ['@INPUT@'])
2276  alias_target('installer', nsis)
2277endif
2278
2279#########################
2280# Configuration summary #
2281#########################
2282
2283summary_info = {}
2284summary_info += {'Install prefix':    get_option('prefix')}
2285summary_info += {'BIOS directory':    qemu_datadir}
2286summary_info += {'firmware path':     get_option('qemu_firmwarepath')}
2287summary_info += {'binary directory':  get_option('bindir')}
2288summary_info += {'library directory': get_option('libdir')}
2289summary_info += {'module directory':  qemu_moddir}
2290summary_info += {'libexec directory': get_option('libexecdir')}
2291summary_info += {'include directory': get_option('includedir')}
2292summary_info += {'config directory':  get_option('sysconfdir')}
2293if targetos != 'windows'
2294  summary_info += {'local state directory': get_option('localstatedir')}
2295  summary_info += {'Manual directory':      get_option('mandir')}
2296else
2297  summary_info += {'local state directory': 'queried at runtime'}
2298endif
2299summary_info += {'Doc directory':     get_option('docdir')}
2300summary_info += {'Build directory':   meson.current_build_dir()}
2301summary_info += {'Source path':       meson.current_source_dir()}
2302summary_info += {'GIT binary':        config_host['GIT']}
2303summary_info += {'GIT submodules':    config_host['GIT_SUBMODULES']}
2304summary_info += {'C compiler':        meson.get_compiler('c').cmd_array()[0]}
2305summary_info += {'Host C compiler':   meson.get_compiler('c', native: true).cmd_array()[0]}
2306if link_language == 'cpp'
2307  summary_info += {'C++ compiler':      meson.get_compiler('cpp').cmd_array()[0]}
2308else
2309  summary_info += {'C++ compiler':      false}
2310endif
2311if targetos == 'darwin'
2312  summary_info += {'Objective-C compiler': meson.get_compiler('objc').cmd_array()[0]}
2313endif
2314summary_info += {'ARFLAGS':           config_host['ARFLAGS']}
2315summary_info += {'CFLAGS':            ' '.join(get_option('c_args')
2316                                               + ['-O' + get_option('optimization')]
2317                                               + (get_option('debug') ? ['-g'] : []))}
2318if link_language == 'cpp'
2319  summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args')
2320                                               + ['-O' + get_option('optimization')]
2321                                               + (get_option('debug') ? ['-g'] : []))}
2322endif
2323link_args = get_option(link_language + '_link_args')
2324if link_args.length() > 0
2325  summary_info += {'LDFLAGS':         ' '.join(link_args)}
2326endif
2327summary_info += {'QEMU_CFLAGS':       config_host['QEMU_CFLAGS']}
2328summary_info += {'QEMU_LDFLAGS':      config_host['QEMU_LDFLAGS']}
2329summary_info += {'make':              config_host['MAKE']}
2330summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
2331summary_info += {'sphinx-build':      sphinx_build.found()}
2332summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
2333# TODO: add back version
2334summary_info += {'slirp support':     slirp_opt == 'disabled' ? false : slirp_opt}
2335if slirp_opt != 'disabled'
2336  summary_info += {'smbd':            config_host['CONFIG_SMBD_COMMAND']}
2337endif
2338summary_info += {'module support':    config_host.has_key('CONFIG_MODULES')}
2339if config_host.has_key('CONFIG_MODULES')
2340  summary_info += {'alternative module path': config_host.has_key('CONFIG_MODULE_UPGRADES')}
2341endif
2342summary_info += {'host CPU':          cpu}
2343summary_info += {'host endianness':   build_machine.endian()}
2344summary_info += {'target list':       ' '.join(target_dirs)}
2345summary_info += {'gprof enabled':     config_host.has_key('CONFIG_GPROF')}
2346summary_info += {'sparse enabled':    sparse.found()}
2347summary_info += {'strip binaries':    get_option('strip')}
2348summary_info += {'profiler':          config_host.has_key('CONFIG_PROFILER')}
2349summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
2350summary_info += {'static build':      config_host.has_key('CONFIG_STATIC')}
2351if targetos == 'darwin'
2352  summary_info += {'Cocoa support':   cocoa.found()}
2353endif
2354# TODO: add back version
2355summary_info += {'SDL support':       sdl.found()}
2356summary_info += {'SDL image support': sdl_image.found()}
2357# TODO: add back version
2358summary_info += {'GTK support':       gtk.found()}
2359summary_info += {'pixman':            pixman.found()}
2360# TODO: add back version
2361summary_info += {'VTE support':       config_host.has_key('CONFIG_VTE')}
2362summary_info += {'TLS priority':      config_host['CONFIG_TLS_PRIORITY']}
2363summary_info += {'GNUTLS support':    config_host.has_key('CONFIG_GNUTLS')}
2364# TODO: add back version
2365summary_info += {'libgcrypt':         config_host.has_key('CONFIG_GCRYPT')}
2366if config_host.has_key('CONFIG_GCRYPT')
2367   summary_info += {'  hmac':            config_host.has_key('CONFIG_GCRYPT_HMAC')}
2368   summary_info += {'  XTS':             not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')}
2369endif
2370# TODO: add back version
2371summary_info += {'nettle':            config_host.has_key('CONFIG_NETTLE')}
2372if config_host.has_key('CONFIG_NETTLE')
2373   summary_info += {'  XTS':             not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')}
2374endif
2375summary_info += {'libtasn1':          config_host.has_key('CONFIG_TASN1')}
2376summary_info += {'PAM':               config_host.has_key('CONFIG_AUTH_PAM')}
2377summary_info += {'iconv support':     iconv.found()}
2378summary_info += {'curses support':    curses.found()}
2379# TODO: add back version
2380summary_info += {'virgl support':     config_host.has_key('CONFIG_VIRGL')}
2381summary_info += {'curl support':      curl.found()}
2382summary_info += {'mingw32 support':   targetos == 'windows'}
2383summary_info += {'Audio drivers':     config_host['CONFIG_AUDIO_DRIVERS']}
2384summary_info += {'Block whitelist (rw)': config_host['CONFIG_BDRV_RW_WHITELIST']}
2385summary_info += {'Block whitelist (ro)': config_host['CONFIG_BDRV_RO_WHITELIST']}
2386summary_info += {'VirtFS support':    have_virtfs}
2387summary_info += {'build virtiofs daemon': have_virtiofsd}
2388summary_info += {'Multipath support': mpathpersist.found()}
2389summary_info += {'VNC support':       vnc.found()}
2390if vnc.found()
2391  summary_info += {'VNC SASL support':  sasl.found()}
2392  summary_info += {'VNC JPEG support':  jpeg.found()}
2393  summary_info += {'VNC PNG support':   png.found()}
2394endif
2395summary_info += {'xen support':       config_host.has_key('CONFIG_XEN_BACKEND')}
2396if config_host.has_key('CONFIG_XEN_BACKEND')
2397  summary_info += {'xen ctrl version':  config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']}
2398endif
2399summary_info += {'brlapi support':    brlapi.found()}
2400summary_info += {'Documentation':     build_docs}
2401summary_info += {'PIE':               get_option('b_pie')}
2402summary_info += {'vde support':       config_host.has_key('CONFIG_VDE')}
2403summary_info += {'netmap support':    config_host.has_key('CONFIG_NETMAP')}
2404summary_info += {'Linux AIO support': config_host.has_key('CONFIG_LINUX_AIO')}
2405summary_info += {'Linux io_uring support': config_host.has_key('CONFIG_LINUX_IO_URING')}
2406summary_info += {'ATTR/XATTR support': libattr.found()}
2407summary_info += {'Install blobs':     get_option('install_blobs')}
2408summary_info += {'KVM support':       config_all.has_key('CONFIG_KVM')}
2409summary_info += {'HAX support':       config_all.has_key('CONFIG_HAX')}
2410summary_info += {'HVF support':       config_all.has_key('CONFIG_HVF')}
2411summary_info += {'WHPX support':      config_all.has_key('CONFIG_WHPX')}
2412summary_info += {'TCG support':       config_all.has_key('CONFIG_TCG')}
2413if config_all.has_key('CONFIG_TCG')
2414  summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')}
2415  summary_info += {'TCG interpreter':   config_host.has_key('CONFIG_TCG_INTERPRETER')}
2416endif
2417summary_info += {'malloc trim support': has_malloc_trim}
2418summary_info += {'RDMA support':      config_host.has_key('CONFIG_RDMA')}
2419summary_info += {'PVRDMA support':    config_host.has_key('CONFIG_PVRDMA')}
2420summary_info += {'fdt support':       fdt_opt == 'disabled' ? false : fdt_opt}
2421summary_info += {'membarrier':        config_host.has_key('CONFIG_MEMBARRIER')}
2422summary_info += {'preadv support':    config_host.has_key('CONFIG_PREADV')}
2423summary_info += {'fdatasync':         config_host.has_key('CONFIG_FDATASYNC')}
2424summary_info += {'madvise':           config_host.has_key('CONFIG_MADVISE')}
2425summary_info += {'posix_madvise':     config_host.has_key('CONFIG_POSIX_MADVISE')}
2426summary_info += {'posix_memalign':    config_host.has_key('CONFIG_POSIX_MEMALIGN')}
2427summary_info += {'libcap-ng support': libcap_ng.found()}
2428summary_info += {'vhost-kernel support': config_host.has_key('CONFIG_VHOST_KERNEL')}
2429summary_info += {'vhost-net support': config_host.has_key('CONFIG_VHOST_NET')}
2430summary_info += {'vhost-crypto support': config_host.has_key('CONFIG_VHOST_CRYPTO')}
2431summary_info += {'vhost-scsi support': config_host.has_key('CONFIG_VHOST_SCSI')}
2432summary_info += {'vhost-vsock support': config_host.has_key('CONFIG_VHOST_VSOCK')}
2433summary_info += {'vhost-user support': config_host.has_key('CONFIG_VHOST_USER')}
2434summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
2435summary_info += {'vhost-user-fs support': config_host.has_key('CONFIG_VHOST_USER_FS')}
2436summary_info += {'vhost-vdpa support': config_host.has_key('CONFIG_VHOST_VDPA')}
2437summary_info += {'Trace backends':    config_host['TRACE_BACKENDS']}
2438if config_host['TRACE_BACKENDS'].split().contains('simple')
2439  summary_info += {'Trace output file': config_host['CONFIG_TRACE_FILE'] + '-<pid>'}
2440endif
2441# TODO: add back protocol and server version
2442summary_info += {'spice support':     config_host.has_key('CONFIG_SPICE')}
2443summary_info += {'rbd support':       rbd.found()}
2444summary_info += {'xfsctl support':    config_host.has_key('CONFIG_XFS')}
2445summary_info += {'smartcard support': config_host.has_key('CONFIG_SMARTCARD')}
2446summary_info += {'U2F support':       u2f.found()}
2447summary_info += {'libusb':            config_host.has_key('CONFIG_USB_LIBUSB')}
2448summary_info += {'usb net redir':     config_host.has_key('CONFIG_USB_REDIR')}
2449summary_info += {'OpenGL support':    config_host.has_key('CONFIG_OPENGL')}
2450summary_info += {'OpenGL dmabufs':    config_host.has_key('CONFIG_OPENGL_DMABUF')}
2451summary_info += {'libiscsi support':  libiscsi.found()}
2452summary_info += {'libnfs support':    libnfs.found()}
2453summary_info += {'build guest agent': config_host.has_key('CONFIG_GUEST_AGENT')}
2454if targetos == 'windows'
2455  if 'WIN_SDK' in config_host
2456    summary_info += {'Windows SDK':       config_host['WIN_SDK']}
2457  endif
2458  summary_info += {'QGA VSS support':   config_host.has_key('CONFIG_QGA_VSS')}
2459  summary_info += {'QGA w32 disk info': config_host.has_key('CONFIG_QGA_NTDDSCSI')}
2460  summary_info += {'QGA MSI support':   config_host.has_key('CONFIG_QGA_MSI')}
2461endif
2462summary_info += {'seccomp support':   seccomp.found()}
2463summary_info += {'CFI support':       get_option('cfi')}
2464summary_info += {'CFI debug support': get_option('cfi_debug')}
2465summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']}
2466summary_info += {'coroutine pool':    config_host['CONFIG_COROUTINE_POOL'] == '1'}
2467summary_info += {'debug stack usage': config_host.has_key('CONFIG_DEBUG_STACK_USAGE')}
2468summary_info += {'mutex debugging':   config_host.has_key('CONFIG_DEBUG_MUTEX')}
2469summary_info += {'crypto afalg':      config_host.has_key('CONFIG_AF_ALG')}
2470summary_info += {'GlusterFS support': glusterfs.found()}
2471summary_info += {'gcov':              get_option('b_coverage')}
2472summary_info += {'TPM support':       config_host.has_key('CONFIG_TPM')}
2473summary_info += {'libssh support':    config_host.has_key('CONFIG_LIBSSH')}
2474summary_info += {'QOM debugging':     config_host.has_key('CONFIG_QOM_CAST_DEBUG')}
2475summary_info += {'Live block migration': config_host.has_key('CONFIG_LIVE_BLOCK_MIGRATION')}
2476summary_info += {'lzo support':       lzo.found()}
2477summary_info += {'snappy support':    snappy.found()}
2478summary_info += {'bzip2 support':     libbzip2.found()}
2479summary_info += {'lzfse support':     liblzfse.found()}
2480summary_info += {'zstd support':      zstd.found()}
2481summary_info += {'NUMA host support': config_host.has_key('CONFIG_NUMA')}
2482summary_info += {'libxml2':           config_host.has_key('CONFIG_LIBXML2')}
2483summary_info += {'memory allocator':  get_option('malloc')}
2484summary_info += {'avx2 optimization': config_host.has_key('CONFIG_AVX2_OPT')}
2485summary_info += {'avx512f optimization': config_host.has_key('CONFIG_AVX512F_OPT')}
2486summary_info += {'replication support': config_host.has_key('CONFIG_REPLICATION')}
2487summary_info += {'bochs support':     config_host.has_key('CONFIG_BOCHS')}
2488summary_info += {'cloop support':     config_host.has_key('CONFIG_CLOOP')}
2489summary_info += {'dmg support':       config_host.has_key('CONFIG_DMG')}
2490summary_info += {'qcow v1 support':   config_host.has_key('CONFIG_QCOW1')}
2491summary_info += {'vdi support':       config_host.has_key('CONFIG_VDI')}
2492summary_info += {'vvfat support':     config_host.has_key('CONFIG_VVFAT')}
2493summary_info += {'qed support':       config_host.has_key('CONFIG_QED')}
2494summary_info += {'parallels support': config_host.has_key('CONFIG_PARALLELS')}
2495summary_info += {'sheepdog support':  config_host.has_key('CONFIG_SHEEPDOG')}
2496summary_info += {'capstone':          capstone_opt == 'disabled' ? false : capstone_opt}
2497summary_info += {'libpmem support':   config_host.has_key('CONFIG_LIBPMEM')}
2498summary_info += {'libdaxctl support': config_host.has_key('CONFIG_LIBDAXCTL')}
2499summary_info += {'libudev':           libudev.found()}
2500summary_info += {'default devices':   get_option('default_devices')}
2501summary_info += {'plugin support':    config_host.has_key('CONFIG_PLUGIN')}
2502summary_info += {'fuzzing support':   config_host.has_key('CONFIG_FUZZ')}
2503if config_host.has_key('HAVE_GDB_BIN')
2504  summary_info += {'gdb':             config_host['HAVE_GDB_BIN']}
2505endif
2506summary_info += {'thread sanitizer':  config_host.has_key('CONFIG_TSAN')}
2507summary_info += {'rng-none':          config_host.has_key('CONFIG_RNG_NONE')}
2508summary_info += {'Linux keyring':     config_host.has_key('CONFIG_SECRET_KEYRING')}
2509summary_info += {'FUSE exports':      fuse.found()}
2510summary_info += {'FUSE lseek':        fuse_lseek.found()}
2511summary(summary_info, bool_yn: true)
2512
2513if not supported_cpus.contains(cpu)
2514  message()
2515  warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!')
2516  message()
2517  message('CPU host architecture ' + cpu + ' support is not currently maintained.')
2518  message('The QEMU project intends to remove support for this host CPU in')
2519  message('a future release if nobody volunteers to maintain it and to')
2520  message('provide a build host for our continuous integration setup.')
2521  message('configure has succeeded and you can continue to build, but')
2522  message('if you care about QEMU on this platform you should contact')
2523  message('us upstream at qemu-devel@nongnu.org.')
2524endif
2525
2526if not supported_oses.contains(targetos)
2527  message()
2528  warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!')
2529  message()
2530  message('Host OS ' + targetos + 'support is not currently maintained.')
2531  message('The QEMU project intends to remove support for this host OS in')
2532  message('a future release if nobody volunteers to maintain it and to')
2533  message('provide a build host for our continuous integration setup.')
2534  message('configure has succeeded and you can continue to build, but')
2535  message('if you care about QEMU on this platform you should contact')
2536  message('us upstream at qemu-devel@nongnu.org.')
2537endif
2538