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