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