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