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