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