xref: /openbmc/qemu/meson.build (revision 2182e405)
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  'hexagon' : ['CONFIG_HEXAGON_DIS'],
1192  'hppa' : ['CONFIG_HPPA_DIS'],
1193  'i386' : ['CONFIG_I386_DIS'],
1194  'x86_64' : ['CONFIG_I386_DIS'],
1195  'x32' : ['CONFIG_I386_DIS'],
1196  'lm32' : ['CONFIG_LM32_DIS'],
1197  'm68k' : ['CONFIG_M68K_DIS'],
1198  'microblaze' : ['CONFIG_MICROBLAZE_DIS'],
1199  'mips' : ['CONFIG_MIPS_DIS'],
1200  'moxie' : ['CONFIG_MOXIE_DIS'],
1201  'nios2' : ['CONFIG_NIOS2_DIS'],
1202  'or1k' : ['CONFIG_OPENRISC_DIS'],
1203  'ppc' : ['CONFIG_PPC_DIS'],
1204  'riscv' : ['CONFIG_RISCV_DIS'],
1205  'rx' : ['CONFIG_RX_DIS'],
1206  's390' : ['CONFIG_S390_DIS'],
1207  'sh4' : ['CONFIG_SH4_DIS'],
1208  'sparc' : ['CONFIG_SPARC_DIS'],
1209  'xtensa' : ['CONFIG_XTENSA_DIS'],
1210}
1211if link_language == 'cpp'
1212  disassemblers += {
1213    'aarch64' : [ 'CONFIG_ARM_A64_DIS'],
1214    'arm' : [ 'CONFIG_ARM_DIS', 'CONFIG_ARM_A64_DIS'],
1215    'mips' : [ 'CONFIG_MIPS_DIS', 'CONFIG_NANOMIPS_DIS'],
1216  }
1217endif
1218
1219host_kconfig = \
1220  ('CONFIG_TPM' in config_host ? ['CONFIG_TPM=y'] : []) + \
1221  ('CONFIG_SPICE' in config_host ? ['CONFIG_SPICE=y'] : []) + \
1222  ('CONFIG_IVSHMEM' in config_host ? ['CONFIG_IVSHMEM=y'] : []) + \
1223  ('CONFIG_OPENGL' in config_host ? ['CONFIG_OPENGL=y'] : []) + \
1224  (x11.found() ? ['CONFIG_X11=y'] : []) + \
1225  ('CONFIG_VHOST_USER' in config_host ? ['CONFIG_VHOST_USER=y'] : []) + \
1226  ('CONFIG_VHOST_VDPA' in config_host ? ['CONFIG_VHOST_VDPA=y'] : []) + \
1227  ('CONFIG_VHOST_KERNEL' in config_host ? ['CONFIG_VHOST_KERNEL=y'] : []) + \
1228  (have_virtfs ? ['CONFIG_VIRTFS=y'] : []) + \
1229  ('CONFIG_LINUX' in config_host ? ['CONFIG_LINUX=y'] : []) + \
1230  ('CONFIG_PVRDMA' in config_host ? ['CONFIG_PVRDMA=y'] : []) + \
1231  ('CONFIG_MULTIPROCESS_ALLOWED' in config_host ? ['CONFIG_MULTIPROCESS_ALLOWED=y'] : [])
1232
1233ignored = [ 'TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_ARCH' ]
1234
1235default_targets = 'CONFIG_DEFAULT_TARGETS' in config_host
1236actual_target_dirs = []
1237fdt_required = []
1238foreach target : target_dirs
1239  config_target = { 'TARGET_NAME': target.split('-')[0] }
1240  if target.endswith('linux-user')
1241    if targetos != 'linux'
1242      if default_targets
1243        continue
1244      endif
1245      error('Target @0@ is only available on a Linux host'.format(target))
1246    endif
1247    config_target += { 'CONFIG_LINUX_USER': 'y' }
1248  elif target.endswith('bsd-user')
1249    if 'CONFIG_BSD' not in config_host
1250      if default_targets
1251        continue
1252      endif
1253      error('Target @0@ is only available on a BSD host'.format(target))
1254    endif
1255    config_target += { 'CONFIG_BSD_USER': 'y' }
1256  elif target.endswith('softmmu')
1257    config_target += { 'CONFIG_SOFTMMU': 'y' }
1258  endif
1259  if target.endswith('-user')
1260    config_target += {
1261      'CONFIG_USER_ONLY': 'y',
1262      'CONFIG_QEMU_INTERP_PREFIX':
1263        config_host['CONFIG_QEMU_INTERP_PREFIX'].format(config_target['TARGET_NAME'])
1264    }
1265  endif
1266
1267  accel_kconfig = []
1268  foreach sym: accelerators
1269    if sym == 'CONFIG_TCG' or target in accelerator_targets.get(sym, [])
1270      config_target += { sym: 'y' }
1271      config_all += { sym: 'y' }
1272      if sym == 'CONFIG_TCG' and tcg_arch == 'tci'
1273        config_target += { 'CONFIG_TCG_INTERPRETER': 'y' }
1274      elif sym == 'CONFIG_XEN' and have_xen_pci_passthrough
1275        config_target += { 'CONFIG_XEN_PCI_PASSTHROUGH': 'y' }
1276      endif
1277      accel_kconfig += [ sym + '=y' ]
1278    endif
1279  endforeach
1280  if accel_kconfig.length() == 0
1281    if default_targets
1282      continue
1283    endif
1284    error('No accelerator available for target @0@'.format(target))
1285  endif
1286
1287  actual_target_dirs += target
1288  config_target += keyval.load('default-configs/targets' / target + '.mak')
1289  config_target += { 'TARGET_' + config_target['TARGET_ARCH'].to_upper(): 'y' }
1290
1291  if 'TARGET_NEED_FDT' in config_target
1292    fdt_required += target
1293  endif
1294
1295  # Add default keys
1296  if 'TARGET_BASE_ARCH' not in config_target
1297    config_target += {'TARGET_BASE_ARCH': config_target['TARGET_ARCH']}
1298  endif
1299  if 'TARGET_ABI_DIR' not in config_target
1300    config_target += {'TARGET_ABI_DIR': config_target['TARGET_ARCH']}
1301  endif
1302
1303  foreach k, v: disassemblers
1304    if config_host['ARCH'].startswith(k) or config_target['TARGET_BASE_ARCH'].startswith(k)
1305      foreach sym: v
1306        config_target += { sym: 'y' }
1307        config_all_disas += { sym: 'y' }
1308      endforeach
1309    endif
1310  endforeach
1311
1312  config_target_data = configuration_data()
1313  foreach k, v: config_target
1314    if not k.startswith('TARGET_') and not k.startswith('CONFIG_')
1315      # do nothing
1316    elif ignored.contains(k)
1317      # do nothing
1318    elif k == 'TARGET_BASE_ARCH'
1319      # Note that TARGET_BASE_ARCH ends up in config-target.h but it is
1320      # not used to select files from sourcesets.
1321      config_target_data.set('TARGET_' + v.to_upper(), 1)
1322    elif k == 'TARGET_NAME' or k == 'CONFIG_QEMU_INTERP_PREFIX'
1323      config_target_data.set_quoted(k, v)
1324    elif v == 'y'
1325      config_target_data.set(k, 1)
1326    else
1327      config_target_data.set(k, v)
1328    endif
1329  endforeach
1330  config_target_h += {target: configure_file(output: target + '-config-target.h',
1331                                               configuration: config_target_data)}
1332
1333  if target.endswith('-softmmu')
1334    config_devices_mak = target + '-config-devices.mak'
1335    config_devices_mak = configure_file(
1336      input: ['default-configs/devices' / target + '.mak', 'Kconfig'],
1337      output: config_devices_mak,
1338      depfile: config_devices_mak + '.d',
1339      capture: true,
1340      command: [minikconf,
1341                get_option('default_devices') ? '--defconfig' : '--allnoconfig',
1342                config_devices_mak, '@DEPFILE@', '@INPUT@',
1343                host_kconfig, accel_kconfig])
1344
1345    config_devices_data = configuration_data()
1346    config_devices = keyval.load(config_devices_mak)
1347    foreach k, v: config_devices
1348      config_devices_data.set(k, 1)
1349    endforeach
1350    config_devices_mak_list += config_devices_mak
1351    config_devices_h += {target: configure_file(output: target + '-config-devices.h',
1352                                                configuration: config_devices_data)}
1353    config_target += config_devices
1354    config_all_devices += config_devices
1355  endif
1356  config_target_mak += {target: config_target}
1357endforeach
1358target_dirs = actual_target_dirs
1359
1360# This configuration is used to build files that are shared by
1361# multiple binaries, and then extracted out of the "common"
1362# static_library target.
1363#
1364# We do not use all_sources()/all_dependencies(), because it would
1365# build literally all source files, including devices only used by
1366# targets that are not built for this compilation.  The CONFIG_ALL
1367# pseudo symbol replaces it.
1368
1369config_all += config_all_devices
1370config_all += config_host
1371config_all += config_all_disas
1372config_all += {
1373  'CONFIG_XEN': config_host.has_key('CONFIG_XEN_BACKEND'),
1374  'CONFIG_SOFTMMU': have_system,
1375  'CONFIG_USER_ONLY': have_user,
1376  'CONFIG_ALL': true,
1377}
1378
1379##############
1380# Submodules #
1381##############
1382
1383capstone = not_found
1384capstone_opt = get_option('capstone')
1385if capstone_opt in ['enabled', 'auto', 'system']
1386  have_internal = fs.exists(meson.current_source_dir() / 'capstone/Makefile')
1387  capstone = dependency('capstone', version: '>=4.0',
1388                        kwargs: static_kwargs, method: 'pkg-config',
1389                        required: capstone_opt == 'system' or
1390                                  capstone_opt == 'enabled' and not have_internal)
1391  if capstone.found()
1392    capstone_opt = 'system'
1393  elif have_internal
1394    capstone_opt = 'internal'
1395  else
1396    capstone_opt = 'disabled'
1397  endif
1398endif
1399if capstone_opt == 'internal'
1400  capstone_data = configuration_data()
1401  capstone_data.set('CAPSTONE_USE_SYS_DYN_MEM', '1')
1402
1403  capstone_files = files(
1404    'capstone/cs.c',
1405    'capstone/MCInst.c',
1406    'capstone/MCInstrDesc.c',
1407    'capstone/MCRegisterInfo.c',
1408    'capstone/SStream.c',
1409    'capstone/utils.c'
1410  )
1411
1412  if 'CONFIG_ARM_DIS' in config_all_disas
1413    capstone_data.set('CAPSTONE_HAS_ARM', '1')
1414    capstone_files += files(
1415      'capstone/arch/ARM/ARMDisassembler.c',
1416      'capstone/arch/ARM/ARMInstPrinter.c',
1417      'capstone/arch/ARM/ARMMapping.c',
1418      'capstone/arch/ARM/ARMModule.c'
1419    )
1420  endif
1421
1422  # FIXME: This config entry currently depends on a c++ compiler.
1423  # Which is needed for building libvixl, but not for capstone.
1424  if 'CONFIG_ARM_A64_DIS' in config_all_disas
1425    capstone_data.set('CAPSTONE_HAS_ARM64', '1')
1426    capstone_files += files(
1427      'capstone/arch/AArch64/AArch64BaseInfo.c',
1428      'capstone/arch/AArch64/AArch64Disassembler.c',
1429      'capstone/arch/AArch64/AArch64InstPrinter.c',
1430      'capstone/arch/AArch64/AArch64Mapping.c',
1431      'capstone/arch/AArch64/AArch64Module.c'
1432    )
1433  endif
1434
1435  if 'CONFIG_PPC_DIS' in config_all_disas
1436    capstone_data.set('CAPSTONE_HAS_POWERPC', '1')
1437    capstone_files += files(
1438      'capstone/arch/PowerPC/PPCDisassembler.c',
1439      'capstone/arch/PowerPC/PPCInstPrinter.c',
1440      'capstone/arch/PowerPC/PPCMapping.c',
1441      'capstone/arch/PowerPC/PPCModule.c'
1442    )
1443  endif
1444
1445  if 'CONFIG_S390_DIS' in config_all_disas
1446    capstone_data.set('CAPSTONE_HAS_SYSZ', '1')
1447    capstone_files += files(
1448      'capstone/arch/SystemZ/SystemZDisassembler.c',
1449      'capstone/arch/SystemZ/SystemZInstPrinter.c',
1450      'capstone/arch/SystemZ/SystemZMapping.c',
1451      'capstone/arch/SystemZ/SystemZModule.c',
1452      'capstone/arch/SystemZ/SystemZMCTargetDesc.c'
1453    )
1454  endif
1455
1456  if 'CONFIG_I386_DIS' in config_all_disas
1457    capstone_data.set('CAPSTONE_HAS_X86', 1)
1458    capstone_files += files(
1459      'capstone/arch/X86/X86Disassembler.c',
1460      'capstone/arch/X86/X86DisassemblerDecoder.c',
1461      'capstone/arch/X86/X86ATTInstPrinter.c',
1462      'capstone/arch/X86/X86IntelInstPrinter.c',
1463      'capstone/arch/X86/X86InstPrinterCommon.c',
1464      'capstone/arch/X86/X86Mapping.c',
1465      'capstone/arch/X86/X86Module.c'
1466    )
1467  endif
1468
1469  configure_file(output: 'capstone-defs.h', configuration: capstone_data)
1470
1471  capstone_cargs = [
1472    # FIXME: There does not seem to be a way to completely replace the c_args
1473    # that come from add_project_arguments() -- we can only add to them.
1474    # So: disable all warnings with a big hammer.
1475    '-Wno-error', '-w',
1476
1477    # Include all configuration defines via a header file, which will wind up
1478    # as a dependency on the object file, and thus changes here will result
1479    # in a rebuild.
1480    '-include', 'capstone-defs.h'
1481  ]
1482
1483  libcapstone = static_library('capstone',
1484                               build_by_default: false,
1485                               sources: capstone_files,
1486                               c_args: capstone_cargs,
1487                               include_directories: 'capstone/include')
1488  capstone = declare_dependency(link_with: libcapstone,
1489                                include_directories: 'capstone/include/capstone')
1490endif
1491
1492slirp = not_found
1493slirp_opt = 'disabled'
1494if have_system
1495  slirp_opt = get_option('slirp')
1496  if slirp_opt in ['enabled', 'auto', 'system']
1497    have_internal = fs.exists(meson.current_source_dir() / 'slirp/meson.build')
1498    slirp = dependency('slirp', kwargs: static_kwargs,
1499                       method: 'pkg-config',
1500                       required: slirp_opt == 'system' or
1501                                 slirp_opt == 'enabled' and not have_internal)
1502    if slirp.found()
1503      slirp_opt = 'system'
1504    elif have_internal
1505      slirp_opt = 'internal'
1506    else
1507      slirp_opt = 'disabled'
1508    endif
1509  endif
1510  if slirp_opt == 'internal'
1511    slirp_deps = []
1512    if targetos == 'windows'
1513      slirp_deps = cc.find_library('iphlpapi')
1514    endif
1515    slirp_conf = configuration_data()
1516    slirp_conf.set('SLIRP_MAJOR_VERSION', meson.project_version().split('.')[0])
1517    slirp_conf.set('SLIRP_MINOR_VERSION', meson.project_version().split('.')[1])
1518    slirp_conf.set('SLIRP_MICRO_VERSION', meson.project_version().split('.')[2])
1519    slirp_conf.set_quoted('SLIRP_VERSION_STRING', meson.project_version())
1520    slirp_cargs = ['-DG_LOG_DOMAIN="Slirp"']
1521    slirp_files = [
1522      'slirp/src/arp_table.c',
1523      'slirp/src/bootp.c',
1524      'slirp/src/cksum.c',
1525      'slirp/src/dhcpv6.c',
1526      'slirp/src/dnssearch.c',
1527      'slirp/src/if.c',
1528      'slirp/src/ip6_icmp.c',
1529      'slirp/src/ip6_input.c',
1530      'slirp/src/ip6_output.c',
1531      'slirp/src/ip_icmp.c',
1532      'slirp/src/ip_input.c',
1533      'slirp/src/ip_output.c',
1534      'slirp/src/mbuf.c',
1535      'slirp/src/misc.c',
1536      'slirp/src/ncsi.c',
1537      'slirp/src/ndp_table.c',
1538      'slirp/src/sbuf.c',
1539      'slirp/src/slirp.c',
1540      'slirp/src/socket.c',
1541      'slirp/src/state.c',
1542      'slirp/src/stream.c',
1543      'slirp/src/tcp_input.c',
1544      'slirp/src/tcp_output.c',
1545      'slirp/src/tcp_subr.c',
1546      'slirp/src/tcp_timer.c',
1547      'slirp/src/tftp.c',
1548      'slirp/src/udp.c',
1549      'slirp/src/udp6.c',
1550      'slirp/src/util.c',
1551      'slirp/src/version.c',
1552      'slirp/src/vmstate.c',
1553    ]
1554
1555    configure_file(
1556      input : 'slirp/src/libslirp-version.h.in',
1557      output : 'libslirp-version.h',
1558      configuration: slirp_conf)
1559
1560    slirp_inc = include_directories('slirp', 'slirp/src')
1561    libslirp = static_library('slirp',
1562                              build_by_default: false,
1563                              sources: slirp_files,
1564                              c_args: slirp_cargs,
1565                              include_directories: slirp_inc)
1566    slirp = declare_dependency(link_with: libslirp,
1567                               dependencies: slirp_deps,
1568                               include_directories: slirp_inc)
1569  endif
1570endif
1571
1572fdt = not_found
1573fdt_opt = get_option('fdt')
1574if have_system
1575  if fdt_opt in ['enabled', 'auto', 'system']
1576    have_internal = fs.exists(meson.current_source_dir() / 'dtc/libfdt/Makefile.libfdt')
1577    fdt = cc.find_library('fdt', kwargs: static_kwargs,
1578                          required: fdt_opt == 'system' or
1579                                    fdt_opt == 'enabled' and not have_internal)
1580    if fdt.found() and cc.links('''
1581       #include <libfdt.h>
1582       #include <libfdt_env.h>
1583       int main(void) { fdt_check_full(NULL, 0); return 0; }''',
1584         dependencies: fdt)
1585      fdt_opt = 'system'
1586    elif have_internal
1587      fdt_opt = 'internal'
1588    else
1589      fdt_opt = 'disabled'
1590    endif
1591  endif
1592  if fdt_opt == 'internal'
1593    fdt_files = files(
1594      'dtc/libfdt/fdt.c',
1595      'dtc/libfdt/fdt_ro.c',
1596      'dtc/libfdt/fdt_wip.c',
1597      'dtc/libfdt/fdt_sw.c',
1598      'dtc/libfdt/fdt_rw.c',
1599      'dtc/libfdt/fdt_strerror.c',
1600      'dtc/libfdt/fdt_empty_tree.c',
1601      'dtc/libfdt/fdt_addresses.c',
1602      'dtc/libfdt/fdt_overlay.c',
1603      'dtc/libfdt/fdt_check.c',
1604    )
1605
1606    fdt_inc = include_directories('dtc/libfdt')
1607    libfdt = static_library('fdt',
1608                            build_by_default: false,
1609                            sources: fdt_files,
1610                            include_directories: fdt_inc)
1611    fdt = declare_dependency(link_with: libfdt,
1612                             include_directories: fdt_inc)
1613  endif
1614endif
1615if not fdt.found() and fdt_required.length() > 0
1616  error('fdt not available but required by targets ' + ', '.join(fdt_required))
1617endif
1618
1619config_host_data.set('CONFIG_CAPSTONE', capstone.found())
1620config_host_data.set('CONFIG_FDT', fdt.found())
1621config_host_data.set('CONFIG_SLIRP', slirp.found())
1622
1623#####################
1624# Generated sources #
1625#####################
1626
1627genh += configure_file(output: 'config-host.h', configuration: config_host_data)
1628
1629hxtool = find_program('scripts/hxtool')
1630shaderinclude = find_program('scripts/shaderinclude.pl')
1631qapi_gen = find_program('scripts/qapi-gen.py')
1632qapi_gen_depends = [ meson.source_root() / 'scripts/qapi/__init__.py',
1633                     meson.source_root() / 'scripts/qapi/commands.py',
1634                     meson.source_root() / 'scripts/qapi/common.py',
1635                     meson.source_root() / 'scripts/qapi/error.py',
1636                     meson.source_root() / 'scripts/qapi/events.py',
1637                     meson.source_root() / 'scripts/qapi/expr.py',
1638                     meson.source_root() / 'scripts/qapi/gen.py',
1639                     meson.source_root() / 'scripts/qapi/introspect.py',
1640                     meson.source_root() / 'scripts/qapi/parser.py',
1641                     meson.source_root() / 'scripts/qapi/schema.py',
1642                     meson.source_root() / 'scripts/qapi/source.py',
1643                     meson.source_root() / 'scripts/qapi/types.py',
1644                     meson.source_root() / 'scripts/qapi/visit.py',
1645                     meson.source_root() / 'scripts/qapi/common.py',
1646                     meson.source_root() / 'scripts/qapi-gen.py'
1647]
1648
1649tracetool = [
1650  python, files('scripts/tracetool.py'),
1651   '--backend=' + config_host['TRACE_BACKENDS']
1652]
1653tracetool_depends = files(
1654  'scripts/tracetool/backend/log.py',
1655  'scripts/tracetool/backend/__init__.py',
1656  'scripts/tracetool/backend/dtrace.py',
1657  'scripts/tracetool/backend/ftrace.py',
1658  'scripts/tracetool/backend/simple.py',
1659  'scripts/tracetool/backend/syslog.py',
1660  'scripts/tracetool/backend/ust.py',
1661  'scripts/tracetool/format/tcg_h.py',
1662  'scripts/tracetool/format/ust_events_c.py',
1663  'scripts/tracetool/format/ust_events_h.py',
1664  'scripts/tracetool/format/__init__.py',
1665  'scripts/tracetool/format/d.py',
1666  'scripts/tracetool/format/tcg_helper_c.py',
1667  'scripts/tracetool/format/simpletrace_stap.py',
1668  'scripts/tracetool/format/c.py',
1669  'scripts/tracetool/format/h.py',
1670  'scripts/tracetool/format/tcg_helper_h.py',
1671  'scripts/tracetool/format/log_stap.py',
1672  'scripts/tracetool/format/stap.py',
1673  'scripts/tracetool/format/tcg_helper_wrapper_h.py',
1674  'scripts/tracetool/__init__.py',
1675  'scripts/tracetool/transform.py',
1676  'scripts/tracetool/vcpu.py'
1677)
1678
1679qemu_version_cmd = [find_program('scripts/qemu-version.sh'),
1680                    meson.current_source_dir(),
1681                    config_host['PKGVERSION'], meson.project_version()]
1682qemu_version = custom_target('qemu-version.h',
1683                             output: 'qemu-version.h',
1684                             command: qemu_version_cmd,
1685                             capture: true,
1686                             build_by_default: true,
1687                             build_always_stale: true)
1688genh += qemu_version
1689
1690hxdep = []
1691hx_headers = [
1692  ['qemu-options.hx', 'qemu-options.def'],
1693  ['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
1694]
1695if have_system
1696  hx_headers += [
1697    ['hmp-commands.hx', 'hmp-commands.h'],
1698    ['hmp-commands-info.hx', 'hmp-commands-info.h'],
1699  ]
1700endif
1701foreach d : hx_headers
1702  hxdep += custom_target(d[1],
1703                input: files(d[0]),
1704                output: d[1],
1705                capture: true,
1706                build_by_default: true, # to be removed when added to a target
1707                command: [hxtool, '-h', '@INPUT0@'])
1708endforeach
1709genh += hxdep
1710
1711###################
1712# Collect sources #
1713###################
1714
1715authz_ss = ss.source_set()
1716blockdev_ss = ss.source_set()
1717block_ss = ss.source_set()
1718bsd_user_ss = ss.source_set()
1719chardev_ss = ss.source_set()
1720common_ss = ss.source_set()
1721crypto_ss = ss.source_set()
1722io_ss = ss.source_set()
1723linux_user_ss = ss.source_set()
1724qmp_ss = ss.source_set()
1725qom_ss = ss.source_set()
1726softmmu_ss = ss.source_set()
1727specific_fuzz_ss = ss.source_set()
1728specific_ss = ss.source_set()
1729stub_ss = ss.source_set()
1730trace_ss = ss.source_set()
1731user_ss = ss.source_set()
1732util_ss = ss.source_set()
1733
1734modules = {}
1735hw_arch = {}
1736target_arch = {}
1737target_softmmu_arch = {}
1738
1739###############
1740# Trace files #
1741###############
1742
1743# TODO: add each directory to the subdirs from its own meson.build, once
1744# we have those
1745trace_events_subdirs = [
1746  'crypto',
1747  'qapi',
1748  'qom',
1749  'monitor',
1750  'util',
1751]
1752if have_user
1753  trace_events_subdirs += [ 'linux-user' ]
1754endif
1755if have_block
1756  trace_events_subdirs += [
1757    'authz',
1758    'block',
1759    'io',
1760    'nbd',
1761    'scsi',
1762  ]
1763endif
1764if have_system
1765  trace_events_subdirs += [
1766    'accel/kvm',
1767    'audio',
1768    'backends',
1769    'backends/tpm',
1770    'chardev',
1771    'hw/9pfs',
1772    'hw/acpi',
1773    'hw/adc',
1774    'hw/alpha',
1775    'hw/arm',
1776    'hw/audio',
1777    'hw/block',
1778    'hw/block/dataplane',
1779    'hw/char',
1780    'hw/display',
1781    'hw/dma',
1782    'hw/hppa',
1783    'hw/hyperv',
1784    'hw/i2c',
1785    'hw/i386',
1786    'hw/i386/xen',
1787    'hw/ide',
1788    'hw/input',
1789    'hw/intc',
1790    'hw/isa',
1791    'hw/mem',
1792    'hw/mips',
1793    'hw/misc',
1794    'hw/misc/macio',
1795    'hw/net',
1796    'hw/net/can',
1797    'hw/nvram',
1798    'hw/pci',
1799    'hw/pci-host',
1800    'hw/ppc',
1801    'hw/rdma',
1802    'hw/rdma/vmw',
1803    'hw/rtc',
1804    'hw/s390x',
1805    'hw/scsi',
1806    'hw/sd',
1807    'hw/sparc',
1808    'hw/sparc64',
1809    'hw/ssi',
1810    'hw/timer',
1811    'hw/tpm',
1812    'hw/usb',
1813    'hw/vfio',
1814    'hw/virtio',
1815    'hw/watchdog',
1816    'hw/xen',
1817    'hw/gpio',
1818    'migration',
1819    'net',
1820    'softmmu',
1821    'ui',
1822    'hw/remote',
1823  ]
1824endif
1825if have_system or have_user
1826  trace_events_subdirs += [
1827    'accel/tcg',
1828    'hw/core',
1829    'target/arm',
1830    'target/hppa',
1831    'target/i386',
1832    'target/i386/kvm',
1833    'target/mips',
1834    'target/ppc',
1835    'target/riscv',
1836    'target/s390x',
1837    'target/sparc',
1838  ]
1839endif
1840
1841vhost_user = not_found
1842if 'CONFIG_VHOST_USER' in config_host
1843  libvhost_user = subproject('libvhost-user')
1844  vhost_user = libvhost_user.get_variable('vhost_user_dep')
1845endif
1846
1847subdir('qapi')
1848subdir('qobject')
1849subdir('stubs')
1850subdir('trace')
1851subdir('util')
1852subdir('qom')
1853subdir('authz')
1854subdir('crypto')
1855subdir('ui')
1856
1857
1858if enable_modules
1859  libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
1860  modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
1861endif
1862
1863stub_ss = stub_ss.apply(config_all, strict: false)
1864
1865util_ss.add_all(trace_ss)
1866util_ss = util_ss.apply(config_all, strict: false)
1867libqemuutil = static_library('qemuutil',
1868                             sources: util_ss.sources() + stub_ss.sources() + genh,
1869                             dependencies: [util_ss.dependencies(), m, glib, socket, malloc])
1870qemuutil = declare_dependency(link_with: libqemuutil,
1871                              sources: genh + version_res)
1872
1873if have_system or have_user
1874  decodetree = generator(find_program('scripts/decodetree.py'),
1875                         output: 'decode-@BASENAME@.c.inc',
1876                         arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
1877  subdir('libdecnumber')
1878  subdir('target')
1879endif
1880
1881subdir('audio')
1882subdir('io')
1883subdir('chardev')
1884subdir('fsdev')
1885subdir('dump')
1886
1887if have_block
1888  block_ss.add(files(
1889    'block.c',
1890    'blockjob.c',
1891    'job.c',
1892    'qemu-io-cmds.c',
1893  ))
1894  block_ss.add(when: 'CONFIG_REPLICATION', if_true: files('replication.c'))
1895
1896  subdir('nbd')
1897  subdir('scsi')
1898  subdir('block')
1899
1900  blockdev_ss.add(files(
1901    'blockdev.c',
1902    'blockdev-nbd.c',
1903    'iothread.c',
1904    'job-qmp.c',
1905  ), gnutls)
1906
1907  # os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
1908  # os-win32.c does not
1909  blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c'))
1910  softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')])
1911endif
1912
1913common_ss.add(files('cpus-common.c'))
1914
1915subdir('softmmu')
1916
1917common_ss.add(capstone)
1918specific_ss.add(files('cpu.c', 'disas.c', 'gdbstub.c'), capstone)
1919specific_ss.add(files('exec-vary.c'))
1920specific_ss.add(when: 'CONFIG_TCG', if_true: files(
1921  'fpu/softfloat.c',
1922  'tcg/optimize.c',
1923  'tcg/tcg-common.c',
1924  'tcg/tcg-op-gvec.c',
1925  'tcg/tcg-op-vec.c',
1926  'tcg/tcg-op.c',
1927  'tcg/tcg.c',
1928))
1929specific_ss.add(when: 'CONFIG_TCG_INTERPRETER', if_true: files('disas/tci.c', 'tcg/tci.c'))
1930
1931subdir('backends')
1932subdir('disas')
1933subdir('migration')
1934subdir('monitor')
1935subdir('net')
1936subdir('replay')
1937subdir('hw')
1938subdir('accel')
1939subdir('plugins')
1940subdir('bsd-user')
1941subdir('linux-user')
1942
1943bsd_user_ss.add(files('gdbstub.c'))
1944specific_ss.add_all(when: 'CONFIG_BSD_USER', if_true: bsd_user_ss)
1945
1946linux_user_ss.add(files('gdbstub.c', 'thunk.c'))
1947specific_ss.add_all(when: 'CONFIG_LINUX_USER', if_true: linux_user_ss)
1948
1949# needed for fuzzing binaries
1950subdir('tests/qtest/libqos')
1951subdir('tests/qtest/fuzz')
1952
1953########################
1954# Library dependencies #
1955########################
1956
1957block_mods = []
1958softmmu_mods = []
1959foreach d, list : modules
1960  foreach m, module_ss : list
1961    if enable_modules and targetos != 'windows'
1962      module_ss = module_ss.apply(config_all, strict: false)
1963      sl = static_library(d + '-' + m, [genh, module_ss.sources()],
1964                          dependencies: [modulecommon, module_ss.dependencies()], pic: true)
1965      if d == 'block'
1966        block_mods += sl
1967      else
1968        softmmu_mods += sl
1969      endif
1970    else
1971      if d == 'block'
1972        block_ss.add_all(module_ss)
1973      else
1974        softmmu_ss.add_all(module_ss)
1975      endif
1976    endif
1977  endforeach
1978endforeach
1979
1980nm = find_program('nm')
1981undefsym = find_program('scripts/undefsym.py')
1982block_syms = custom_target('block.syms', output: 'block.syms',
1983                             input: [libqemuutil, block_mods],
1984                             capture: true,
1985                             command: [undefsym, nm, '@INPUT@'])
1986qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
1987                             input: [libqemuutil, softmmu_mods],
1988                             capture: true,
1989                             command: [undefsym, nm, '@INPUT@'])
1990
1991qom_ss = qom_ss.apply(config_host, strict: false)
1992libqom = static_library('qom', qom_ss.sources() + genh,
1993                        dependencies: [qom_ss.dependencies()],
1994                        name_suffix: 'fa')
1995
1996qom = declare_dependency(link_whole: libqom)
1997
1998authz_ss = authz_ss.apply(config_host, strict: false)
1999libauthz = static_library('authz', authz_ss.sources() + genh,
2000                          dependencies: [authz_ss.dependencies()],
2001                          name_suffix: 'fa',
2002                          build_by_default: false)
2003
2004authz = declare_dependency(link_whole: libauthz,
2005                           dependencies: qom)
2006
2007crypto_ss = crypto_ss.apply(config_host, strict: false)
2008libcrypto = static_library('crypto', crypto_ss.sources() + genh,
2009                           dependencies: [crypto_ss.dependencies()],
2010                           name_suffix: 'fa',
2011                           build_by_default: false)
2012
2013crypto = declare_dependency(link_whole: libcrypto,
2014                            dependencies: [authz, qom])
2015
2016io_ss = io_ss.apply(config_host, strict: false)
2017libio = static_library('io', io_ss.sources() + genh,
2018                       dependencies: [io_ss.dependencies()],
2019                       link_with: libqemuutil,
2020                       name_suffix: 'fa',
2021                       build_by_default: false)
2022
2023io = declare_dependency(link_whole: libio, dependencies: [crypto, qom])
2024
2025libmigration = static_library('migration', sources: migration_files + genh,
2026                              name_suffix: 'fa',
2027                              build_by_default: false)
2028migration = declare_dependency(link_with: libmigration,
2029                               dependencies: [zlib, qom, io])
2030softmmu_ss.add(migration)
2031
2032block_ss = block_ss.apply(config_host, strict: false)
2033libblock = static_library('block', block_ss.sources() + genh,
2034                          dependencies: block_ss.dependencies(),
2035                          link_depends: block_syms,
2036                          name_suffix: 'fa',
2037                          build_by_default: false)
2038
2039block = declare_dependency(link_whole: [libblock],
2040                           link_args: '@block.syms',
2041                           dependencies: [crypto, io])
2042
2043blockdev_ss = blockdev_ss.apply(config_host, strict: false)
2044libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
2045                             dependencies: blockdev_ss.dependencies(),
2046                             name_suffix: 'fa',
2047                             build_by_default: false)
2048
2049blockdev = declare_dependency(link_whole: [libblockdev],
2050                              dependencies: [block])
2051
2052qmp_ss = qmp_ss.apply(config_host, strict: false)
2053libqmp = static_library('qmp', qmp_ss.sources() + genh,
2054                        dependencies: qmp_ss.dependencies(),
2055                        name_suffix: 'fa',
2056                        build_by_default: false)
2057
2058qmp = declare_dependency(link_whole: [libqmp])
2059
2060libchardev = static_library('chardev', chardev_ss.sources() + genh,
2061                            name_suffix: 'fa',
2062                            dependencies: [gnutls],
2063                            build_by_default: false)
2064
2065chardev = declare_dependency(link_whole: libchardev)
2066
2067libhwcore = static_library('hwcore', sources: hwcore_files + genh,
2068                           name_suffix: 'fa',
2069                           build_by_default: false)
2070hwcore = declare_dependency(link_whole: libhwcore)
2071common_ss.add(hwcore)
2072
2073###########
2074# Targets #
2075###########
2076
2077foreach m : block_mods + softmmu_mods
2078  shared_module(m.name(),
2079                name_prefix: '',
2080                link_whole: m,
2081                install: true,
2082                install_dir: qemu_moddir)
2083endforeach
2084
2085softmmu_ss.add(authz, blockdev, chardev, crypto, io, qmp)
2086common_ss.add(qom, qemuutil)
2087
2088common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss])
2089common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
2090
2091common_all = common_ss.apply(config_all, strict: false)
2092common_all = static_library('common',
2093                            build_by_default: false,
2094                            sources: common_all.sources() + genh,
2095                            dependencies: common_all.dependencies(),
2096                            name_suffix: 'fa')
2097
2098feature_to_c = find_program('scripts/feature_to_c.sh')
2099
2100emulators = {}
2101foreach target : target_dirs
2102  config_target = config_target_mak[target]
2103  target_name = config_target['TARGET_NAME']
2104  arch = config_target['TARGET_BASE_ARCH']
2105  arch_srcs = [config_target_h[target]]
2106  arch_deps = []
2107  c_args = ['-DNEED_CPU_H',
2108            '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
2109            '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
2110  link_args = emulator_link_args
2111
2112  config_target += config_host
2113  target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
2114  if targetos == 'linux'
2115    target_inc += include_directories('linux-headers', is_system: true)
2116  endif
2117  if target.endswith('-softmmu')
2118    qemu_target_name = 'qemu-system-' + target_name
2119    target_type='system'
2120    t = target_softmmu_arch[arch].apply(config_target, strict: false)
2121    arch_srcs += t.sources()
2122    arch_deps += t.dependencies()
2123
2124    hw_dir = target_name == 'sparc64' ? 'sparc64' : arch
2125    hw = hw_arch[hw_dir].apply(config_target, strict: false)
2126    arch_srcs += hw.sources()
2127    arch_deps += hw.dependencies()
2128
2129    arch_srcs += config_devices_h[target]
2130    link_args += ['@block.syms', '@qemu.syms']
2131  else
2132    abi = config_target['TARGET_ABI_DIR']
2133    target_type='user'
2134    qemu_target_name = 'qemu-' + target_name
2135    if 'CONFIG_LINUX_USER' in config_target
2136      base_dir = 'linux-user'
2137      target_inc += include_directories('linux-user/host/' / config_host['ARCH'])
2138    else
2139      base_dir = 'bsd-user'
2140      target_inc += include_directories('bsd-user/freebsd')
2141    endif
2142    target_inc += include_directories(
2143      base_dir,
2144      base_dir / abi,
2145    )
2146    if 'CONFIG_LINUX_USER' in config_target
2147      dir = base_dir / abi
2148      arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
2149      if config_target.has_key('TARGET_SYSTBL_ABI')
2150        arch_srcs += \
2151          syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
2152                                             extra_args : config_target['TARGET_SYSTBL_ABI'])
2153      endif
2154    endif
2155  endif
2156
2157  if 'TARGET_XML_FILES' in config_target
2158    gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
2159                                output: target + '-gdbstub-xml.c',
2160                                input: files(config_target['TARGET_XML_FILES'].split()),
2161                                command: [feature_to_c, '@INPUT@'],
2162                                capture: true)
2163    arch_srcs += gdbstub_xml
2164  endif
2165
2166  t = target_arch[arch].apply(config_target, strict: false)
2167  arch_srcs += t.sources()
2168  arch_deps += t.dependencies()
2169
2170  target_common = common_ss.apply(config_target, strict: false)
2171  objects = common_all.extract_objects(target_common.sources())
2172  deps = target_common.dependencies()
2173
2174  target_specific = specific_ss.apply(config_target, strict: false)
2175  arch_srcs += target_specific.sources()
2176  arch_deps += target_specific.dependencies()
2177
2178  lib = static_library('qemu-' + target,
2179                 sources: arch_srcs + genh,
2180                 dependencies: arch_deps,
2181                 objects: objects,
2182                 include_directories: target_inc,
2183                 c_args: c_args,
2184                 build_by_default: false,
2185                 name_suffix: 'fa')
2186
2187  if target.endswith('-softmmu')
2188    execs = [{
2189      'name': 'qemu-system-' + target_name,
2190      'gui': false,
2191      'sources': files('softmmu/main.c'),
2192      'dependencies': []
2193    }]
2194    if targetos == 'windows' and (sdl.found() or gtk.found())
2195      execs += [{
2196        'name': 'qemu-system-' + target_name + 'w',
2197        'gui': true,
2198        'sources': files('softmmu/main.c'),
2199        'dependencies': []
2200      }]
2201    endif
2202    if config_host.has_key('CONFIG_FUZZ')
2203      specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
2204      execs += [{
2205        'name': 'qemu-fuzz-' + target_name,
2206        'gui': false,
2207        'sources': specific_fuzz.sources(),
2208        'dependencies': specific_fuzz.dependencies(),
2209      }]
2210    endif
2211  else
2212    execs = [{
2213      'name': 'qemu-' + target_name,
2214      'gui': false,
2215      'sources': [],
2216      'dependencies': []
2217    }]
2218  endif
2219  foreach exe: execs
2220    exe_name = exe['name']
2221    exe_sign = 'CONFIG_HVF' in config_target
2222    if exe_sign
2223      exe_name += '-unsigned'
2224    endif
2225
2226    emulator = executable(exe_name, exe['sources'],
2227               install: not exe_sign,
2228               c_args: c_args,
2229               dependencies: arch_deps + deps + exe['dependencies'],
2230               objects: lib.extract_all_objects(recursive: true),
2231               link_language: link_language,
2232               link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
2233               link_args: link_args,
2234               gui_app: exe['gui'])
2235
2236    if exe_sign
2237      emulators += {exe['name'] : custom_target(exe['name'],
2238                   install: true,
2239                   install_dir: get_option('bindir'),
2240                   depends: emulator,
2241                   output: exe['name'],
2242                   command: [
2243                     meson.current_source_dir() / 'scripts/entitlement.sh',
2244                     meson.current_build_dir() / exe_name,
2245                     meson.current_build_dir() / exe['name'],
2246                     meson.current_source_dir() / 'accel/hvf/entitlements.plist'
2247                   ])
2248      }
2249    else
2250      emulators += {exe['name']: emulator}
2251    endif
2252
2253    if 'CONFIG_TRACE_SYSTEMTAP' in config_host
2254      foreach stp: [
2255        {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
2256        {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
2257        {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
2258        {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
2259      ]
2260        custom_target(exe['name'] + stp['ext'],
2261                      input: trace_events_all,
2262                      output: exe['name'] + stp['ext'],
2263                      install: stp['install'],
2264                      install_dir: get_option('datadir') / 'systemtap/tapset',
2265                      command: [
2266                        tracetool, '--group=all', '--format=' + stp['fmt'],
2267                        '--binary=' + stp['bin'],
2268                        '--target-name=' + target_name,
2269                        '--target-type=' + target_type,
2270                        '--probe-prefix=qemu.' + target_type + '.' + target_name,
2271                        '@INPUT@', '@OUTPUT@'
2272                      ],
2273                      depend_files: tracetool_depends)
2274      endforeach
2275    endif
2276  endforeach
2277endforeach
2278
2279# Other build targets
2280
2281if 'CONFIG_PLUGIN' in config_host
2282  install_headers('include/qemu/qemu-plugin.h')
2283endif
2284
2285if 'CONFIG_GUEST_AGENT' in config_host
2286  subdir('qga')
2287elif get_option('guest_agent_msi').enabled()
2288  error('Guest agent MSI requested, but the guest agent is not being built')
2289endif
2290
2291# Don't build qemu-keymap if xkbcommon is not explicitly enabled
2292# when we don't build tools or system
2293if xkbcommon.found()
2294  # used for the update-keymaps target, so include rules even if !have_tools
2295  qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
2296                           dependencies: [qemuutil, xkbcommon], install: have_tools)
2297endif
2298
2299if have_tools
2300  qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
2301             dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
2302  qemu_io = executable('qemu-io', files('qemu-io.c'),
2303             dependencies: [block, qemuutil], install: true)
2304  qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
2305               dependencies: [blockdev, qemuutil, gnutls], install: true)
2306
2307  subdir('storage-daemon')
2308  subdir('contrib/rdmacm-mux')
2309  subdir('contrib/elf2dmp')
2310
2311  executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
2312             dependencies: qemuutil,
2313             install: true)
2314
2315  if 'CONFIG_VHOST_USER' in config_host
2316    subdir('contrib/vhost-user-blk')
2317    subdir('contrib/vhost-user-gpu')
2318    subdir('contrib/vhost-user-input')
2319    subdir('contrib/vhost-user-scsi')
2320  endif
2321
2322  if targetos == 'linux'
2323    executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
2324               dependencies: [qemuutil, libcap_ng],
2325               install: true,
2326               install_dir: get_option('libexecdir'))
2327
2328    executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
2329               dependencies: [authz, crypto, io, qom, qemuutil,
2330                              libcap_ng, mpathpersist],
2331               install: true)
2332  endif
2333
2334  if 'CONFIG_IVSHMEM' in config_host
2335    subdir('contrib/ivshmem-client')
2336    subdir('contrib/ivshmem-server')
2337  endif
2338endif
2339
2340subdir('scripts')
2341subdir('tools')
2342subdir('pc-bios')
2343subdir('docs')
2344subdir('tests')
2345if gtk.found()
2346  subdir('po')
2347endif
2348
2349if host_machine.system() == 'windows'
2350  nsis_cmd = [
2351    find_program('scripts/nsis.py'),
2352    '@OUTPUT@',
2353    get_option('prefix'),
2354    meson.current_source_dir(),
2355    host_machine.cpu(),
2356    '--',
2357    '-DDISPLAYVERSION=' + meson.project_version(),
2358  ]
2359  if build_docs
2360    nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
2361  endif
2362  if gtk.found()
2363    nsis_cmd += '-DCONFIG_GTK=y'
2364  endif
2365
2366  nsis = custom_target('nsis',
2367                       output: 'qemu-setup-' + meson.project_version() + '.exe',
2368                       input: files('qemu.nsi'),
2369                       build_always_stale: true,
2370                       command: nsis_cmd + ['@INPUT@'])
2371  alias_target('installer', nsis)
2372endif
2373
2374#########################
2375# Configuration summary #
2376#########################
2377
2378# Directories
2379summary_info = {}
2380summary_info += {'Install prefix':    get_option('prefix')}
2381summary_info += {'BIOS directory':    qemu_datadir}
2382summary_info += {'firmware path':     get_option('qemu_firmwarepath')}
2383summary_info += {'binary directory':  get_option('bindir')}
2384summary_info += {'library directory': get_option('libdir')}
2385summary_info += {'module directory':  qemu_moddir}
2386summary_info += {'libexec directory': get_option('libexecdir')}
2387summary_info += {'include directory': get_option('includedir')}
2388summary_info += {'config directory':  get_option('sysconfdir')}
2389if targetos != 'windows'
2390  summary_info += {'local state directory': get_option('localstatedir')}
2391  summary_info += {'Manual directory':      get_option('mandir')}
2392else
2393  summary_info += {'local state directory': 'queried at runtime'}
2394endif
2395summary_info += {'Doc directory':     get_option('docdir')}
2396summary_info += {'Build directory':   meson.current_build_dir()}
2397summary_info += {'Source path':       meson.current_source_dir()}
2398summary_info += {'GIT submodules':    config_host['GIT_SUBMODULES']}
2399summary(summary_info, bool_yn: true, section: 'Directories')
2400
2401# Host binaries
2402summary_info = {}
2403summary_info += {'git':               config_host['GIT']}
2404summary_info += {'make':              config_host['MAKE']}
2405summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
2406summary_info += {'sphinx-build':      sphinx_build.found()}
2407if config_host.has_key('HAVE_GDB_BIN')
2408  summary_info += {'gdb':             config_host['HAVE_GDB_BIN']}
2409endif
2410summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
2411if targetos == 'windows' and config_host.has_key('CONFIG_GUEST_AGENT')
2412  summary_info += {'wixl':            wixl.found() ? wixl.full_path() : false}
2413endif
2414if slirp_opt != 'disabled'
2415  summary_info += {'smbd':            config_host['CONFIG_SMBD_COMMAND']}
2416endif
2417summary(summary_info, bool_yn: true, section: 'Host binaries')
2418
2419# Configurable features
2420summary_info = {}
2421summary_info += {'Documentation':     build_docs}
2422summary_info += {'system-mode emulation': have_system}
2423summary_info += {'user-mode emulation': have_user}
2424summary_info += {'block layer':       have_block}
2425summary_info += {'Install blobs':     get_option('install_blobs')}
2426summary_info += {'module support':    config_host.has_key('CONFIG_MODULES')}
2427if config_host.has_key('CONFIG_MODULES')
2428  summary_info += {'alternative module path': config_host.has_key('CONFIG_MODULE_UPGRADES')}
2429endif
2430summary_info += {'plugin support':    config_host.has_key('CONFIG_PLUGIN')}
2431summary_info += {'fuzzing support':   config_host.has_key('CONFIG_FUZZ')}
2432if have_system
2433  summary_info += {'Audio drivers':     config_host['CONFIG_AUDIO_DRIVERS']}
2434endif
2435summary_info += {'Trace backends':    config_host['TRACE_BACKENDS']}
2436if config_host['TRACE_BACKENDS'].split().contains('simple')
2437  summary_info += {'Trace output file': config_host['CONFIG_TRACE_FILE'] + '-<pid>'}
2438endif
2439summary_info += {'QOM debugging':     config_host.has_key('CONFIG_QOM_CAST_DEBUG')}
2440summary_info += {'vhost-kernel support': config_host.has_key('CONFIG_VHOST_KERNEL')}
2441summary_info += {'vhost-net support': config_host.has_key('CONFIG_VHOST_NET')}
2442summary_info += {'vhost-crypto support': config_host.has_key('CONFIG_VHOST_CRYPTO')}
2443summary_info += {'vhost-scsi support': config_host.has_key('CONFIG_VHOST_SCSI')}
2444summary_info += {'vhost-vsock support': config_host.has_key('CONFIG_VHOST_VSOCK')}
2445summary_info += {'vhost-user support': config_host.has_key('CONFIG_VHOST_USER')}
2446summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
2447summary_info += {'vhost-user-fs support': config_host.has_key('CONFIG_VHOST_USER_FS')}
2448summary_info += {'vhost-vdpa support': config_host.has_key('CONFIG_VHOST_VDPA')}
2449summary_info += {'build guest agent': config_host.has_key('CONFIG_GUEST_AGENT')}
2450summary(summary_info, bool_yn: true, section: 'Configurable features')
2451
2452# Compilation information
2453summary_info = {}
2454summary_info += {'host CPU':          cpu}
2455summary_info += {'host endianness':   build_machine.endian()}
2456summary_info += {'C compiler':        meson.get_compiler('c').cmd_array()[0]}
2457summary_info += {'Host C compiler':   meson.get_compiler('c', native: true).cmd_array()[0]}
2458if link_language == 'cpp'
2459  summary_info += {'C++ compiler':      meson.get_compiler('cpp').cmd_array()[0]}
2460else
2461  summary_info += {'C++ compiler':      false}
2462endif
2463if targetos == 'darwin'
2464  summary_info += {'Objective-C compiler': meson.get_compiler('objc').cmd_array()[0]}
2465endif
2466if targetos == 'windows'
2467  if 'WIN_SDK' in config_host
2468    summary_info += {'Windows SDK':   config_host['WIN_SDK']}
2469  endif
2470endif
2471summary_info += {'ARFLAGS':           config_host['ARFLAGS']}
2472summary_info += {'CFLAGS':            ' '.join(get_option('c_args')
2473                                               + ['-O' + get_option('optimization')]
2474                                               + (get_option('debug') ? ['-g'] : []))}
2475if link_language == 'cpp'
2476  summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args')
2477                                               + ['-O' + get_option('optimization')]
2478                                               + (get_option('debug') ? ['-g'] : []))}
2479endif
2480link_args = get_option(link_language + '_link_args')
2481if link_args.length() > 0
2482  summary_info += {'LDFLAGS':         ' '.join(link_args)}
2483endif
2484summary_info += {'QEMU_CFLAGS':       config_host['QEMU_CFLAGS']}
2485summary_info += {'QEMU_LDFLAGS':      config_host['QEMU_LDFLAGS']}
2486summary_info += {'profiler':          config_host.has_key('CONFIG_PROFILER')}
2487summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
2488summary_info += {'PIE':               get_option('b_pie')}
2489summary_info += {'static build':      config_host.has_key('CONFIG_STATIC')}
2490summary_info += {'malloc trim support': has_malloc_trim}
2491summary_info += {'membarrier':        config_host.has_key('CONFIG_MEMBARRIER')}
2492summary_info += {'preadv support':    config_host_data.get('CONFIG_PREADV')}
2493summary_info += {'fdatasync':         config_host.has_key('CONFIG_FDATASYNC')}
2494summary_info += {'madvise':           config_host.has_key('CONFIG_MADVISE')}
2495summary_info += {'posix_madvise':     config_host.has_key('CONFIG_POSIX_MADVISE')}
2496summary_info += {'posix_memalign':    config_host.has_key('CONFIG_POSIX_MEMALIGN')}
2497summary_info += {'debug stack usage': config_host.has_key('CONFIG_DEBUG_STACK_USAGE')}
2498summary_info += {'mutex debugging':   config_host.has_key('CONFIG_DEBUG_MUTEX')}
2499summary_info += {'memory allocator':  get_option('malloc')}
2500summary_info += {'avx2 optimization': config_host.has_key('CONFIG_AVX2_OPT')}
2501summary_info += {'avx512f optimization': config_host.has_key('CONFIG_AVX512F_OPT')}
2502summary_info += {'gprof enabled':     config_host.has_key('CONFIG_GPROF')}
2503summary_info += {'gcov':              get_option('b_coverage')}
2504summary_info += {'thread sanitizer':  config_host.has_key('CONFIG_TSAN')}
2505summary_info += {'CFI support':       get_option('cfi')}
2506if get_option('cfi')
2507  summary_info += {'CFI debug support': get_option('cfi_debug')}
2508endif
2509summary_info += {'strip binaries':    get_option('strip')}
2510summary_info += {'sparse':            sparse.found() ? sparse.full_path() : false}
2511summary_info += {'mingw32 support':   targetos == 'windows'}
2512summary(summary_info, bool_yn: true, section: 'Compilation')
2513
2514# Targets and accelerators
2515summary_info = {}
2516if have_system
2517  summary_info += {'KVM support':       config_all.has_key('CONFIG_KVM')}
2518  summary_info += {'HAX support':       config_all.has_key('CONFIG_HAX')}
2519  summary_info += {'HVF support':       config_all.has_key('CONFIG_HVF')}
2520  summary_info += {'WHPX support':      config_all.has_key('CONFIG_WHPX')}
2521  summary_info += {'Xen support':       config_host.has_key('CONFIG_XEN_BACKEND')}
2522  if config_host.has_key('CONFIG_XEN_BACKEND')
2523    summary_info += {'xen ctrl version':  config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']}
2524  endif
2525endif
2526summary_info += {'TCG support':       config_all.has_key('CONFIG_TCG')}
2527if config_all.has_key('CONFIG_TCG')
2528  if get_option('tcg_interpreter')
2529    summary_info += {'TCG backend':   'TCI (TCG with bytecode interpreter, experimental and slow)'}
2530  else
2531    summary_info += {'TCG backend':   'native (@0@)'.format(cpu)}
2532  endif
2533  summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')}
2534endif
2535summary_info += {'target list':       ' '.join(target_dirs)}
2536if have_system
2537  summary_info += {'default devices':   get_option('default_devices')}
2538endif
2539summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
2540
2541# Block layer
2542summary_info = {}
2543summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']}
2544summary_info += {'coroutine pool':    config_host['CONFIG_COROUTINE_POOL'] == '1'}
2545if have_block
2546  summary_info += {'Block whitelist (rw)': config_host['CONFIG_BDRV_RW_WHITELIST']}
2547  summary_info += {'Block whitelist (ro)': config_host['CONFIG_BDRV_RO_WHITELIST']}
2548  summary_info += {'VirtFS support':    have_virtfs}
2549  summary_info += {'build virtiofs daemon': have_virtiofsd}
2550  summary_info += {'Live block migration': config_host.has_key('CONFIG_LIVE_BLOCK_MIGRATION')}
2551  summary_info += {'replication support': config_host.has_key('CONFIG_REPLICATION')}
2552  summary_info += {'bochs support':     config_host.has_key('CONFIG_BOCHS')}
2553  summary_info += {'cloop support':     config_host.has_key('CONFIG_CLOOP')}
2554  summary_info += {'dmg support':       config_host.has_key('CONFIG_DMG')}
2555  summary_info += {'qcow v1 support':   config_host.has_key('CONFIG_QCOW1')}
2556  summary_info += {'vdi support':       config_host.has_key('CONFIG_VDI')}
2557  summary_info += {'vvfat support':     config_host.has_key('CONFIG_VVFAT')}
2558  summary_info += {'qed support':       config_host.has_key('CONFIG_QED')}
2559  summary_info += {'parallels support': config_host.has_key('CONFIG_PARALLELS')}
2560  summary_info += {'sheepdog support':  config_host.has_key('CONFIG_SHEEPDOG')}
2561  summary_info += {'FUSE exports':      fuse.found()}
2562endif
2563summary(summary_info, bool_yn: true, section: 'Block layer support')
2564
2565# Crypto
2566summary_info = {}
2567summary_info += {'TLS priority':      config_host['CONFIG_TLS_PRIORITY']}
2568summary_info += {'GNUTLS support':    config_host.has_key('CONFIG_GNUTLS')}
2569# TODO: add back version
2570summary_info += {'libgcrypt':         config_host.has_key('CONFIG_GCRYPT')}
2571if config_host.has_key('CONFIG_GCRYPT')
2572   summary_info += {'  hmac':            config_host.has_key('CONFIG_GCRYPT_HMAC')}
2573   summary_info += {'  XTS':             not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')}
2574endif
2575# TODO: add back version
2576summary_info += {'nettle':            config_host.has_key('CONFIG_NETTLE')}
2577if config_host.has_key('CONFIG_NETTLE')
2578   summary_info += {'  XTS':             not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')}
2579endif
2580summary_info += {'crypto afalg':      config_host.has_key('CONFIG_AF_ALG')}
2581summary_info += {'rng-none':          config_host.has_key('CONFIG_RNG_NONE')}
2582summary_info += {'Linux keyring':     config_host.has_key('CONFIG_SECRET_KEYRING')}
2583summary(summary_info, bool_yn: true, section: 'Crypto')
2584
2585# Libraries
2586summary_info = {}
2587if targetos == 'darwin'
2588  summary_info += {'Cocoa support':   cocoa.found()}
2589endif
2590# TODO: add back version
2591summary_info += {'SDL support':       sdl.found()}
2592summary_info += {'SDL image support': sdl_image.found()}
2593# TODO: add back version
2594summary_info += {'GTK support':       gtk.found()}
2595summary_info += {'pixman':            pixman.found()}
2596# TODO: add back version
2597summary_info += {'VTE support':       config_host.has_key('CONFIG_VTE')}
2598# TODO: add back version
2599summary_info += {'slirp support':     slirp_opt == 'disabled' ? false : slirp_opt}
2600summary_info += {'libtasn1':          config_host.has_key('CONFIG_TASN1')}
2601summary_info += {'PAM':               config_host.has_key('CONFIG_AUTH_PAM')}
2602summary_info += {'iconv support':     iconv.found()}
2603summary_info += {'curses support':    curses.found()}
2604# TODO: add back version
2605summary_info += {'virgl support':     config_host.has_key('CONFIG_VIRGL')}
2606summary_info += {'curl support':      curl.found()}
2607summary_info += {'Multipath support': mpathpersist.found()}
2608summary_info += {'VNC support':       vnc.found()}
2609if vnc.found()
2610  summary_info += {'VNC SASL support':  sasl.found()}
2611  summary_info += {'VNC JPEG support':  jpeg.found()}
2612  summary_info += {'VNC PNG support':   png.found()}
2613endif
2614summary_info += {'brlapi support':    brlapi.found()}
2615summary_info += {'vde support':       config_host.has_key('CONFIG_VDE')}
2616summary_info += {'netmap support':    config_host.has_key('CONFIG_NETMAP')}
2617summary_info += {'Linux AIO support': config_host.has_key('CONFIG_LINUX_AIO')}
2618summary_info += {'Linux io_uring support': config_host.has_key('CONFIG_LINUX_IO_URING')}
2619summary_info += {'ATTR/XATTR support': libattr.found()}
2620summary_info += {'RDMA support':      config_host.has_key('CONFIG_RDMA')}
2621summary_info += {'PVRDMA support':    config_host.has_key('CONFIG_PVRDMA')}
2622summary_info += {'fdt support':       fdt_opt == 'disabled' ? false : fdt_opt}
2623summary_info += {'libcap-ng support': libcap_ng.found()}
2624# TODO: add back protocol and server version
2625summary_info += {'spice support':     config_host.has_key('CONFIG_SPICE')}
2626summary_info += {'rbd support':       rbd.found()}
2627summary_info += {'xfsctl support':    config_host.has_key('CONFIG_XFS')}
2628summary_info += {'smartcard support': config_host.has_key('CONFIG_SMARTCARD')}
2629summary_info += {'U2F support':       u2f.found()}
2630summary_info += {'libusb':            config_host.has_key('CONFIG_USB_LIBUSB')}
2631summary_info += {'usb net redir':     config_host.has_key('CONFIG_USB_REDIR')}
2632summary_info += {'OpenGL support':    config_host.has_key('CONFIG_OPENGL')}
2633summary_info += {'OpenGL dmabufs':    config_host.has_key('CONFIG_OPENGL_DMABUF')}
2634summary_info += {'libiscsi support':  libiscsi.found()}
2635summary_info += {'libnfs support':    libnfs.found()}
2636if targetos == 'windows'
2637  if config_host.has_key('CONFIG_GUEST_AGENT')
2638    summary_info += {'QGA VSS support':   config_host.has_key('CONFIG_QGA_VSS')}
2639    summary_info += {'QGA w32 disk info': config_host.has_key('CONFIG_QGA_NTDDSCSI')}
2640  endif
2641endif
2642summary_info += {'seccomp support':   seccomp.found()}
2643summary_info += {'GlusterFS support': glusterfs.found()}
2644summary_info += {'TPM support':       config_host.has_key('CONFIG_TPM')}
2645summary_info += {'libssh support':    config_host.has_key('CONFIG_LIBSSH')}
2646summary_info += {'lzo support':       lzo.found()}
2647summary_info += {'snappy support':    snappy.found()}
2648summary_info += {'bzip2 support':     libbzip2.found()}
2649summary_info += {'lzfse support':     liblzfse.found()}
2650summary_info += {'zstd support':      zstd.found()}
2651summary_info += {'NUMA host support': config_host.has_key('CONFIG_NUMA')}
2652summary_info += {'libxml2':           config_host.has_key('CONFIG_LIBXML2')}
2653summary_info += {'capstone':          capstone_opt == 'disabled' ? false : capstone_opt}
2654summary_info += {'libpmem support':   config_host.has_key('CONFIG_LIBPMEM')}
2655summary_info += {'libdaxctl support': config_host.has_key('CONFIG_LIBDAXCTL')}
2656summary_info += {'libudev':           libudev.found()}
2657summary_info += {'FUSE lseek':        fuse_lseek.found()}
2658summary_info += {'Multiprocess QEMU': config_host.has_key('CONFIG_MULTIPROCESS_ALLOWED')}
2659summary(summary_info, bool_yn: true, section: 'Dependencies')
2660
2661if not supported_cpus.contains(cpu)
2662  message()
2663  warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!')
2664  message()
2665  message('CPU host architecture ' + cpu + ' support is not currently maintained.')
2666  message('The QEMU project intends to remove support for this host CPU in')
2667  message('a future release if nobody volunteers to maintain it and to')
2668  message('provide a build host for our continuous integration setup.')
2669  message('configure has succeeded and you can continue to build, but')
2670  message('if you care about QEMU on this platform you should contact')
2671  message('us upstream at qemu-devel@nongnu.org.')
2672endif
2673
2674if not supported_oses.contains(targetos)
2675  message()
2676  warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!')
2677  message()
2678  message('Host OS ' + targetos + 'support is not currently maintained.')
2679  message('The QEMU project intends to remove support for this host OS in')
2680  message('a future release if nobody volunteers to maintain it and to')
2681  message('provide a build host for our continuous integration setup.')
2682  message('configure has succeeded and you can continue to build, but')
2683  message('if you care about QEMU on this platform you should contact')
2684  message('us upstream at qemu-devel@nongnu.org.')
2685endif
2686