xref: /openbmc/qemu/meson.build (revision b306e26c)
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/s390x/kvm',
2123    'target/sparc',
2124  ]
2125endif
2126
2127vhost_user = not_found
2128if 'CONFIG_VHOST_USER' in config_host
2129  libvhost_user = subproject('libvhost-user')
2130  vhost_user = libvhost_user.get_variable('vhost_user_dep')
2131endif
2132
2133subdir('qapi')
2134subdir('qobject')
2135subdir('stubs')
2136subdir('trace')
2137subdir('util')
2138subdir('qom')
2139subdir('authz')
2140subdir('crypto')
2141subdir('ui')
2142
2143
2144if enable_modules
2145  libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
2146  modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
2147endif
2148
2149stub_ss = stub_ss.apply(config_all, strict: false)
2150
2151util_ss.add_all(trace_ss)
2152util_ss = util_ss.apply(config_all, strict: false)
2153libqemuutil = static_library('qemuutil',
2154                             sources: util_ss.sources() + stub_ss.sources() + genh,
2155                             dependencies: [util_ss.dependencies(), libm, threads, glib, socket, malloc, pixman])
2156qemuutil = declare_dependency(link_with: libqemuutil,
2157                              sources: genh + version_res)
2158
2159if have_system or have_user
2160  decodetree = generator(find_program('scripts/decodetree.py'),
2161                         output: 'decode-@BASENAME@.c.inc',
2162                         arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
2163  subdir('libdecnumber')
2164  subdir('target')
2165endif
2166
2167subdir('audio')
2168subdir('io')
2169subdir('chardev')
2170subdir('fsdev')
2171subdir('dump')
2172
2173if have_block
2174  block_ss.add(files(
2175    'block.c',
2176    'blockjob.c',
2177    'job.c',
2178    'qemu-io-cmds.c',
2179  ))
2180  block_ss.add(when: 'CONFIG_REPLICATION', if_true: files('replication.c'))
2181
2182  subdir('nbd')
2183  subdir('scsi')
2184  subdir('block')
2185
2186  blockdev_ss.add(files(
2187    'blockdev.c',
2188    'blockdev-nbd.c',
2189    'iothread.c',
2190    'job-qmp.c',
2191  ), gnutls)
2192
2193  # os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
2194  # os-win32.c does not
2195  blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c'))
2196  softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')])
2197endif
2198
2199common_ss.add(files('cpus-common.c'))
2200
2201subdir('softmmu')
2202
2203common_ss.add(capstone)
2204specific_ss.add(files('cpu.c', 'disas.c', 'gdbstub.c'), capstone)
2205
2206# Work around a gcc bug/misfeature wherein constant propagation looks
2207# through an alias:
2208#   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99696
2209# to guess that a const variable is always zero.  Without lto, this is
2210# impossible, as the alias is restricted to page-vary-common.c.  Indeed,
2211# without lto, not even the alias is required -- we simply use different
2212# declarations in different compilation units.
2213pagevary = files('page-vary-common.c')
2214if get_option('b_lto')
2215  pagevary_flags = ['-fno-lto']
2216  if get_option('cfi')
2217    pagevary_flags += '-fno-sanitize=cfi-icall'
2218  endif
2219  pagevary = static_library('page-vary-common', sources: pagevary,
2220                            c_args: pagevary_flags)
2221  pagevary = declare_dependency(link_with: pagevary)
2222endif
2223common_ss.add(pagevary)
2224specific_ss.add(files('page-vary.c'))
2225
2226subdir('backends')
2227subdir('disas')
2228subdir('migration')
2229subdir('monitor')
2230subdir('net')
2231subdir('replay')
2232subdir('semihosting')
2233subdir('hw')
2234subdir('tcg')
2235subdir('fpu')
2236subdir('accel')
2237subdir('plugins')
2238subdir('bsd-user')
2239subdir('linux-user')
2240subdir('ebpf')
2241
2242common_ss.add(libbpf)
2243
2244bsd_user_ss.add(files('gdbstub.c'))
2245specific_ss.add_all(when: 'CONFIG_BSD_USER', if_true: bsd_user_ss)
2246
2247linux_user_ss.add(files('gdbstub.c', 'thunk.c'))
2248specific_ss.add_all(when: 'CONFIG_LINUX_USER', if_true: linux_user_ss)
2249
2250# needed for fuzzing binaries
2251subdir('tests/qtest/libqos')
2252subdir('tests/qtest/fuzz')
2253
2254# accel modules
2255tcg_real_module_ss = ss.source_set()
2256tcg_real_module_ss.add_all(when: 'CONFIG_TCG_MODULAR', if_true: tcg_module_ss)
2257specific_ss.add_all(when: 'CONFIG_TCG_BUILTIN', if_true: tcg_module_ss)
2258target_modules += { 'accel' : { 'qtest': qtest_module_ss,
2259                                'tcg': tcg_real_module_ss }}
2260
2261########################
2262# Library dependencies #
2263########################
2264
2265modinfo_collect = find_program('scripts/modinfo-collect.py')
2266modinfo_generate = find_program('scripts/modinfo-generate.py')
2267modinfo_files = []
2268
2269block_mods = []
2270softmmu_mods = []
2271foreach d, list : modules
2272  foreach m, module_ss : list
2273    if enable_modules and targetos != 'windows'
2274      module_ss = module_ss.apply(config_all, strict: false)
2275      sl = static_library(d + '-' + m, [genh, module_ss.sources()],
2276                          dependencies: [modulecommon, module_ss.dependencies()], pic: true)
2277      if d == 'block'
2278        block_mods += sl
2279      else
2280        softmmu_mods += sl
2281      endif
2282      if module_ss.sources() != []
2283        # FIXME: Should use sl.extract_all_objects(recursive: true) as
2284        # input. Sources can be used multiple times but objects are
2285        # unique when it comes to lookup in compile_commands.json.
2286        # Depnds on a mesion version with
2287        # https://github.com/mesonbuild/meson/pull/8900
2288        modinfo_files += custom_target(d + '-' + m + '.modinfo',
2289                                       output: d + '-' + m + '.modinfo',
2290                                       input: module_ss.sources(),
2291                                       capture: true,
2292                                       command: [modinfo_collect, '@INPUT@'])
2293      endif
2294    else
2295      if d == 'block'
2296        block_ss.add_all(module_ss)
2297      else
2298        softmmu_ss.add_all(module_ss)
2299      endif
2300    endif
2301  endforeach
2302endforeach
2303
2304foreach d, list : target_modules
2305  foreach m, module_ss : list
2306    if enable_modules and targetos != 'windows'
2307      foreach target : target_dirs
2308        if target.endswith('-softmmu')
2309          config_target = config_target_mak[target]
2310          config_target += config_host
2311          target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
2312          c_args = ['-DNEED_CPU_H',
2313                    '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
2314                    '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
2315          target_module_ss = module_ss.apply(config_target, strict: false)
2316          if target_module_ss.sources() != []
2317            module_name = d + '-' + m + '-' + config_target['TARGET_NAME']
2318            sl = static_library(module_name,
2319                                [genh, target_module_ss.sources()],
2320                                dependencies: [modulecommon, target_module_ss.dependencies()],
2321                                include_directories: target_inc,
2322                                c_args: c_args,
2323                                pic: true)
2324            softmmu_mods += sl
2325            # FIXME: Should use sl.extract_all_objects(recursive: true) too.
2326            modinfo_files += custom_target(module_name + '.modinfo',
2327                                           output: module_name + '.modinfo',
2328                                           input: target_module_ss.sources(),
2329                                           capture: true,
2330                                           command: [modinfo_collect, '--target', target, '@INPUT@'])
2331          endif
2332        endif
2333      endforeach
2334    else
2335      specific_ss.add_all(module_ss)
2336    endif
2337  endforeach
2338endforeach
2339
2340if enable_modules
2341  modinfo_src = custom_target('modinfo.c',
2342                              output: 'modinfo.c',
2343                              input: modinfo_files,
2344                              command: [modinfo_generate, '@INPUT@'],
2345                              capture: true)
2346  modinfo_lib = static_library('modinfo', modinfo_src)
2347  modinfo_dep = declare_dependency(link_whole: modinfo_lib)
2348  softmmu_ss.add(modinfo_dep)
2349endif
2350
2351nm = find_program('nm')
2352undefsym = find_program('scripts/undefsym.py')
2353block_syms = custom_target('block.syms', output: 'block.syms',
2354                             input: [libqemuutil, block_mods],
2355                             capture: true,
2356                             command: [undefsym, nm, '@INPUT@'])
2357qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
2358                             input: [libqemuutil, softmmu_mods],
2359                             capture: true,
2360                             command: [undefsym, nm, '@INPUT@'])
2361
2362qom_ss = qom_ss.apply(config_host, strict: false)
2363libqom = static_library('qom', qom_ss.sources() + genh,
2364                        dependencies: [qom_ss.dependencies()],
2365                        name_suffix: 'fa')
2366
2367qom = declare_dependency(link_whole: libqom)
2368
2369authz_ss = authz_ss.apply(config_host, strict: false)
2370libauthz = static_library('authz', authz_ss.sources() + genh,
2371                          dependencies: [authz_ss.dependencies()],
2372                          name_suffix: 'fa',
2373                          build_by_default: false)
2374
2375authz = declare_dependency(link_whole: libauthz,
2376                           dependencies: qom)
2377
2378crypto_ss = crypto_ss.apply(config_host, strict: false)
2379libcrypto = static_library('crypto', crypto_ss.sources() + genh,
2380                           dependencies: [crypto_ss.dependencies()],
2381                           name_suffix: 'fa',
2382                           build_by_default: false)
2383
2384crypto = declare_dependency(link_whole: libcrypto,
2385                            dependencies: [authz, qom])
2386
2387io_ss = io_ss.apply(config_host, strict: false)
2388libio = static_library('io', io_ss.sources() + genh,
2389                       dependencies: [io_ss.dependencies()],
2390                       link_with: libqemuutil,
2391                       name_suffix: 'fa',
2392                       build_by_default: false)
2393
2394io = declare_dependency(link_whole: libio, dependencies: [crypto, qom])
2395
2396libmigration = static_library('migration', sources: migration_files + genh,
2397                              name_suffix: 'fa',
2398                              build_by_default: false)
2399migration = declare_dependency(link_with: libmigration,
2400                               dependencies: [zlib, qom, io])
2401softmmu_ss.add(migration)
2402
2403block_ss = block_ss.apply(config_host, strict: false)
2404libblock = static_library('block', block_ss.sources() + genh,
2405                          dependencies: block_ss.dependencies(),
2406                          link_depends: block_syms,
2407                          name_suffix: 'fa',
2408                          build_by_default: false)
2409
2410block = declare_dependency(link_whole: [libblock],
2411                           link_args: '@block.syms',
2412                           dependencies: [crypto, io])
2413
2414blockdev_ss = blockdev_ss.apply(config_host, strict: false)
2415libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
2416                             dependencies: blockdev_ss.dependencies(),
2417                             name_suffix: 'fa',
2418                             build_by_default: false)
2419
2420blockdev = declare_dependency(link_whole: [libblockdev],
2421                              dependencies: [block])
2422
2423qmp_ss = qmp_ss.apply(config_host, strict: false)
2424libqmp = static_library('qmp', qmp_ss.sources() + genh,
2425                        dependencies: qmp_ss.dependencies(),
2426                        name_suffix: 'fa',
2427                        build_by_default: false)
2428
2429qmp = declare_dependency(link_whole: [libqmp])
2430
2431libchardev = static_library('chardev', chardev_ss.sources() + genh,
2432                            name_suffix: 'fa',
2433                            dependencies: [gnutls],
2434                            build_by_default: false)
2435
2436chardev = declare_dependency(link_whole: libchardev)
2437
2438libhwcore = static_library('hwcore', sources: hwcore_files + genh,
2439                           name_suffix: 'fa',
2440                           build_by_default: false)
2441hwcore = declare_dependency(link_whole: libhwcore)
2442common_ss.add(hwcore)
2443
2444###########
2445# Targets #
2446###########
2447
2448foreach m : block_mods + softmmu_mods
2449  shared_module(m.name(),
2450                name_prefix: '',
2451                link_whole: m,
2452                install: true,
2453                install_dir: qemu_moddir)
2454endforeach
2455
2456softmmu_ss.add(authz, blockdev, chardev, crypto, io, qmp)
2457common_ss.add(qom, qemuutil)
2458
2459common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss])
2460common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
2461
2462common_all = common_ss.apply(config_all, strict: false)
2463common_all = static_library('common',
2464                            build_by_default: false,
2465                            sources: common_all.sources() + genh,
2466                            implicit_include_directories: false,
2467                            dependencies: common_all.dependencies(),
2468                            name_suffix: 'fa')
2469
2470feature_to_c = find_program('scripts/feature_to_c.sh')
2471
2472emulators = {}
2473foreach target : target_dirs
2474  config_target = config_target_mak[target]
2475  target_name = config_target['TARGET_NAME']
2476  arch = config_target['TARGET_BASE_ARCH']
2477  arch_srcs = [config_target_h[target]]
2478  arch_deps = []
2479  c_args = ['-DNEED_CPU_H',
2480            '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
2481            '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
2482  link_args = emulator_link_args
2483
2484  config_target += config_host
2485  target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
2486  if targetos == 'linux'
2487    target_inc += include_directories('linux-headers', is_system: true)
2488  endif
2489  if target.endswith('-softmmu')
2490    qemu_target_name = 'qemu-system-' + target_name
2491    target_type='system'
2492    t = target_softmmu_arch[arch].apply(config_target, strict: false)
2493    arch_srcs += t.sources()
2494    arch_deps += t.dependencies()
2495
2496    hw_dir = target_name == 'sparc64' ? 'sparc64' : arch
2497    hw = hw_arch[hw_dir].apply(config_target, strict: false)
2498    arch_srcs += hw.sources()
2499    arch_deps += hw.dependencies()
2500
2501    arch_srcs += config_devices_h[target]
2502    link_args += ['@block.syms', '@qemu.syms']
2503  else
2504    abi = config_target['TARGET_ABI_DIR']
2505    target_type='user'
2506    qemu_target_name = 'qemu-' + target_name
2507    if arch in target_user_arch
2508      t = target_user_arch[arch].apply(config_target, strict: false)
2509      arch_srcs += t.sources()
2510      arch_deps += t.dependencies()
2511    endif
2512    if 'CONFIG_LINUX_USER' in config_target
2513      base_dir = 'linux-user'
2514      target_inc += include_directories('linux-user/host/' / config_host['ARCH'])
2515    else
2516      base_dir = 'bsd-user'
2517      target_inc += include_directories('bsd-user/freebsd')
2518    endif
2519    target_inc += include_directories(
2520      base_dir,
2521      base_dir / abi,
2522    )
2523    if 'CONFIG_LINUX_USER' in config_target
2524      dir = base_dir / abi
2525      arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
2526      if config_target.has_key('TARGET_SYSTBL_ABI')
2527        arch_srcs += \
2528          syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
2529                                             extra_args : config_target['TARGET_SYSTBL_ABI'])
2530      endif
2531    endif
2532  endif
2533
2534  if 'TARGET_XML_FILES' in config_target
2535    gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
2536                                output: target + '-gdbstub-xml.c',
2537                                input: files(config_target['TARGET_XML_FILES'].split()),
2538                                command: [feature_to_c, '@INPUT@'],
2539                                capture: true)
2540    arch_srcs += gdbstub_xml
2541  endif
2542
2543  t = target_arch[arch].apply(config_target, strict: false)
2544  arch_srcs += t.sources()
2545  arch_deps += t.dependencies()
2546
2547  target_common = common_ss.apply(config_target, strict: false)
2548  objects = common_all.extract_objects(target_common.sources())
2549  deps = target_common.dependencies()
2550
2551  target_specific = specific_ss.apply(config_target, strict: false)
2552  arch_srcs += target_specific.sources()
2553  arch_deps += target_specific.dependencies()
2554
2555  lib = static_library('qemu-' + target,
2556                 sources: arch_srcs + genh,
2557                 dependencies: arch_deps,
2558                 objects: objects,
2559                 include_directories: target_inc,
2560                 c_args: c_args,
2561                 build_by_default: false,
2562                 name_suffix: 'fa')
2563
2564  if target.endswith('-softmmu')
2565    execs = [{
2566      'name': 'qemu-system-' + target_name,
2567      'gui': false,
2568      'sources': files('softmmu/main.c'),
2569      'dependencies': []
2570    }]
2571    if targetos == 'windows' and (sdl.found() or gtk.found())
2572      execs += [{
2573        'name': 'qemu-system-' + target_name + 'w',
2574        'gui': true,
2575        'sources': files('softmmu/main.c'),
2576        'dependencies': []
2577      }]
2578    endif
2579    if config_host.has_key('CONFIG_FUZZ')
2580      specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
2581      execs += [{
2582        'name': 'qemu-fuzz-' + target_name,
2583        'gui': false,
2584        'sources': specific_fuzz.sources(),
2585        'dependencies': specific_fuzz.dependencies(),
2586      }]
2587    endif
2588  else
2589    execs = [{
2590      'name': 'qemu-' + target_name,
2591      'gui': false,
2592      'sources': [],
2593      'dependencies': []
2594    }]
2595  endif
2596  foreach exe: execs
2597    exe_name = exe['name']
2598    if targetos == 'darwin'
2599      exe_name += '-unsigned'
2600    endif
2601
2602    emulator = executable(exe_name, exe['sources'],
2603               install: true,
2604               c_args: c_args,
2605               dependencies: arch_deps + deps + exe['dependencies'],
2606               objects: lib.extract_all_objects(recursive: true),
2607               link_language: link_language,
2608               link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
2609               link_args: link_args,
2610               gui_app: exe['gui'])
2611
2612    if targetos == 'darwin'
2613      icon = 'pc-bios/qemu.rsrc'
2614      build_input = [emulator, files(icon)]
2615      install_input = [
2616        get_option('bindir') / exe_name,
2617        meson.current_source_dir() / icon
2618      ]
2619      if 'CONFIG_HVF' in config_target
2620        entitlements = 'accel/hvf/entitlements.plist'
2621        build_input += files(entitlements)
2622        install_input += meson.current_source_dir() / entitlements
2623      endif
2624
2625      emulators += {exe['name'] : custom_target(exe['name'],
2626                   input: build_input,
2627                   output: exe['name'],
2628                   command: [
2629                     files('scripts/entitlement.sh'),
2630                     '@OUTPUT@',
2631                     '@INPUT@'
2632                   ])
2633      }
2634
2635      meson.add_install_script('scripts/entitlement.sh', '--install',
2636                               get_option('bindir') / exe['name'],
2637                               install_input)
2638    else
2639      emulators += {exe['name']: emulator}
2640    endif
2641
2642    if 'CONFIG_TRACE_SYSTEMTAP' in config_host
2643      foreach stp: [
2644        {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
2645        {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
2646        {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
2647        {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
2648      ]
2649        custom_target(exe['name'] + stp['ext'],
2650                      input: trace_events_all,
2651                      output: exe['name'] + stp['ext'],
2652                      install: stp['install'],
2653                      install_dir: get_option('datadir') / 'systemtap/tapset',
2654                      command: [
2655                        tracetool, '--group=all', '--format=' + stp['fmt'],
2656                        '--binary=' + stp['bin'],
2657                        '--target-name=' + target_name,
2658                        '--target-type=' + target_type,
2659                        '--probe-prefix=qemu.' + target_type + '.' + target_name,
2660                        '@INPUT@', '@OUTPUT@'
2661                      ],
2662                      depend_files: tracetool_depends)
2663      endforeach
2664    endif
2665  endforeach
2666endforeach
2667
2668# Other build targets
2669
2670if 'CONFIG_PLUGIN' in config_host
2671  install_headers('include/qemu/qemu-plugin.h')
2672endif
2673
2674if 'CONFIG_GUEST_AGENT' in config_host
2675  subdir('qga')
2676elif get_option('guest_agent_msi').enabled()
2677  error('Guest agent MSI requested, but the guest agent is not being built')
2678endif
2679
2680# Don't build qemu-keymap if xkbcommon is not explicitly enabled
2681# when we don't build tools or system
2682if xkbcommon.found()
2683  # used for the update-keymaps target, so include rules even if !have_tools
2684  qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
2685                           dependencies: [qemuutil, xkbcommon], install: have_tools)
2686endif
2687
2688if have_tools
2689  qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
2690             dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
2691  qemu_io = executable('qemu-io', files('qemu-io.c'),
2692             dependencies: [block, qemuutil], install: true)
2693  qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
2694               dependencies: [blockdev, qemuutil, gnutls], install: true)
2695
2696  subdir('storage-daemon')
2697  subdir('contrib/rdmacm-mux')
2698  subdir('contrib/elf2dmp')
2699
2700  executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
2701             dependencies: qemuutil,
2702             install: true)
2703
2704  if 'CONFIG_VHOST_USER' in config_host
2705    subdir('contrib/vhost-user-blk')
2706    subdir('contrib/vhost-user-gpu')
2707    subdir('contrib/vhost-user-input')
2708    subdir('contrib/vhost-user-scsi')
2709  endif
2710
2711  if targetos == 'linux'
2712    executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
2713               dependencies: [qemuutil, libcap_ng],
2714               install: true,
2715               install_dir: get_option('libexecdir'))
2716
2717    executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
2718               dependencies: [authz, crypto, io, qom, qemuutil,
2719                              libcap_ng, mpathpersist],
2720               install: true)
2721  endif
2722
2723  if have_ivshmem
2724    subdir('contrib/ivshmem-client')
2725    subdir('contrib/ivshmem-server')
2726  endif
2727endif
2728
2729subdir('scripts')
2730subdir('tools')
2731subdir('pc-bios')
2732subdir('docs')
2733subdir('tests')
2734if gtk.found()
2735  subdir('po')
2736endif
2737
2738if host_machine.system() == 'windows'
2739  nsis_cmd = [
2740    find_program('scripts/nsis.py'),
2741    '@OUTPUT@',
2742    get_option('prefix'),
2743    meson.current_source_dir(),
2744    host_machine.cpu(),
2745    '--',
2746    '-DDISPLAYVERSION=' + meson.project_version(),
2747  ]
2748  if build_docs
2749    nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
2750  endif
2751  if gtk.found()
2752    nsis_cmd += '-DCONFIG_GTK=y'
2753  endif
2754
2755  nsis = custom_target('nsis',
2756                       output: 'qemu-setup-' + meson.project_version() + '.exe',
2757                       input: files('qemu.nsi'),
2758                       build_always_stale: true,
2759                       command: nsis_cmd + ['@INPUT@'])
2760  alias_target('installer', nsis)
2761endif
2762
2763#########################
2764# Configuration summary #
2765#########################
2766
2767# Directories
2768summary_info = {}
2769summary_info += {'Install prefix':    get_option('prefix')}
2770summary_info += {'BIOS directory':    qemu_datadir}
2771summary_info += {'firmware path':     get_option('qemu_firmwarepath')}
2772summary_info += {'binary directory':  get_option('bindir')}
2773summary_info += {'library directory': get_option('libdir')}
2774summary_info += {'module directory':  qemu_moddir}
2775summary_info += {'libexec directory': get_option('libexecdir')}
2776summary_info += {'include directory': get_option('includedir')}
2777summary_info += {'config directory':  get_option('sysconfdir')}
2778if targetos != 'windows'
2779  summary_info += {'local state directory': get_option('localstatedir')}
2780  summary_info += {'Manual directory':      get_option('mandir')}
2781else
2782  summary_info += {'local state directory': 'queried at runtime'}
2783endif
2784summary_info += {'Doc directory':     get_option('docdir')}
2785summary_info += {'Build directory':   meson.current_build_dir()}
2786summary_info += {'Source path':       meson.current_source_dir()}
2787summary_info += {'GIT submodules':    config_host['GIT_SUBMODULES']}
2788summary(summary_info, bool_yn: true, section: 'Directories')
2789
2790# Host binaries
2791summary_info = {}
2792summary_info += {'git':               config_host['GIT']}
2793summary_info += {'make':              config_host['MAKE']}
2794summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
2795summary_info += {'sphinx-build':      sphinx_build.found()}
2796if config_host.has_key('HAVE_GDB_BIN')
2797  summary_info += {'gdb':             config_host['HAVE_GDB_BIN']}
2798endif
2799summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
2800if targetos == 'windows' and config_host.has_key('CONFIG_GUEST_AGENT')
2801  summary_info += {'wixl':            wixl.found() ? wixl.full_path() : false}
2802endif
2803if slirp_opt != 'disabled' and 'CONFIG_SLIRP_SMBD' in config_host
2804  summary_info += {'smbd':            config_host['CONFIG_SMBD_COMMAND']}
2805endif
2806summary(summary_info, bool_yn: true, section: 'Host binaries')
2807
2808# Configurable features
2809summary_info = {}
2810summary_info += {'Documentation':     build_docs}
2811summary_info += {'system-mode emulation': have_system}
2812summary_info += {'user-mode emulation': have_user}
2813summary_info += {'block layer':       have_block}
2814summary_info += {'Install blobs':     get_option('install_blobs')}
2815summary_info += {'module support':    config_host.has_key('CONFIG_MODULES')}
2816if config_host.has_key('CONFIG_MODULES')
2817  summary_info += {'alternative module path': config_host.has_key('CONFIG_MODULE_UPGRADES')}
2818endif
2819summary_info += {'plugin support':    config_host.has_key('CONFIG_PLUGIN')}
2820summary_info += {'fuzzing support':   config_host.has_key('CONFIG_FUZZ')}
2821if have_system
2822  summary_info += {'Audio drivers':     config_host['CONFIG_AUDIO_DRIVERS']}
2823endif
2824summary_info += {'Trace backends':    config_host['TRACE_BACKENDS']}
2825if config_host['TRACE_BACKENDS'].split().contains('simple')
2826  summary_info += {'Trace output file': config_host['CONFIG_TRACE_FILE'] + '-<pid>'}
2827endif
2828summary_info += {'QOM debugging':     config_host.has_key('CONFIG_QOM_CAST_DEBUG')}
2829summary_info += {'vhost-kernel support': config_host.has_key('CONFIG_VHOST_KERNEL')}
2830summary_info += {'vhost-net support': config_host.has_key('CONFIG_VHOST_NET')}
2831summary_info += {'vhost-crypto support': config_host.has_key('CONFIG_VHOST_CRYPTO')}
2832summary_info += {'vhost-scsi support': config_host.has_key('CONFIG_VHOST_SCSI')}
2833summary_info += {'vhost-vsock support': config_host.has_key('CONFIG_VHOST_VSOCK')}
2834summary_info += {'vhost-user support': config_host.has_key('CONFIG_VHOST_USER')}
2835summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
2836summary_info += {'vhost-user-fs support': config_host.has_key('CONFIG_VHOST_USER_FS')}
2837summary_info += {'vhost-vdpa support': config_host.has_key('CONFIG_VHOST_VDPA')}
2838summary_info += {'build guest agent': config_host.has_key('CONFIG_GUEST_AGENT')}
2839summary(summary_info, bool_yn: true, section: 'Configurable features')
2840
2841# Compilation information
2842summary_info = {}
2843summary_info += {'host CPU':          cpu}
2844summary_info += {'host endianness':   build_machine.endian()}
2845summary_info += {'C compiler':        ' '.join(meson.get_compiler('c').cmd_array())}
2846summary_info += {'Host C compiler':   ' '.join(meson.get_compiler('c', native: true).cmd_array())}
2847if link_language == 'cpp'
2848  summary_info += {'C++ compiler':    ' '.join(meson.get_compiler('cpp').cmd_array())}
2849else
2850  summary_info += {'C++ compiler':      false}
2851endif
2852if targetos == 'darwin'
2853  summary_info += {'Objective-C compiler': ' '.join(meson.get_compiler('objc').cmd_array())}
2854endif
2855if targetos == 'windows'
2856  if 'WIN_SDK' in config_host
2857    summary_info += {'Windows SDK':   config_host['WIN_SDK']}
2858  endif
2859endif
2860summary_info += {'CFLAGS':            ' '.join(get_option('c_args')
2861                                               + ['-O' + get_option('optimization')]
2862                                               + (get_option('debug') ? ['-g'] : []))}
2863if link_language == 'cpp'
2864  summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args')
2865                                               + ['-O' + get_option('optimization')]
2866                                               + (get_option('debug') ? ['-g'] : []))}
2867endif
2868link_args = get_option(link_language + '_link_args')
2869if link_args.length() > 0
2870  summary_info += {'LDFLAGS':         ' '.join(link_args)}
2871endif
2872summary_info += {'QEMU_CFLAGS':       config_host['QEMU_CFLAGS']}
2873summary_info += {'QEMU_LDFLAGS':      config_host['QEMU_LDFLAGS']}
2874summary_info += {'profiler':          config_host.has_key('CONFIG_PROFILER')}
2875summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
2876summary_info += {'PIE':               get_option('b_pie')}
2877summary_info += {'static build':      config_host.has_key('CONFIG_STATIC')}
2878summary_info += {'malloc trim support': has_malloc_trim}
2879summary_info += {'membarrier':        config_host.has_key('CONFIG_MEMBARRIER')}
2880summary_info += {'debug stack usage': config_host.has_key('CONFIG_DEBUG_STACK_USAGE')}
2881summary_info += {'mutex debugging':   config_host.has_key('CONFIG_DEBUG_MUTEX')}
2882summary_info += {'memory allocator':  get_option('malloc')}
2883summary_info += {'avx2 optimization': config_host.has_key('CONFIG_AVX2_OPT')}
2884summary_info += {'avx512f optimization': config_host.has_key('CONFIG_AVX512F_OPT')}
2885summary_info += {'gprof enabled':     config_host.has_key('CONFIG_GPROF')}
2886summary_info += {'gcov':              get_option('b_coverage')}
2887summary_info += {'thread sanitizer':  config_host.has_key('CONFIG_TSAN')}
2888summary_info += {'CFI support':       get_option('cfi')}
2889if get_option('cfi')
2890  summary_info += {'CFI debug support': get_option('cfi_debug')}
2891endif
2892summary_info += {'strip binaries':    get_option('strip')}
2893summary_info += {'sparse':            sparse.found() ? sparse.full_path() : false}
2894summary_info += {'mingw32 support':   targetos == 'windows'}
2895
2896# snarf the cross-compilation information for tests
2897foreach target: target_dirs
2898  tcg_mak = meson.current_build_dir() / 'tests/tcg' / 'config-' + target + '.mak'
2899  if fs.exists(tcg_mak)
2900    config_cross_tcg = keyval.load(tcg_mak)
2901    target = config_cross_tcg['TARGET_NAME']
2902    compiler = ''
2903    if 'DOCKER_CROSS_CC_GUEST' in config_cross_tcg
2904      summary_info += {target + ' tests': config_cross_tcg['DOCKER_CROSS_CC_GUEST'] +
2905                                          ' via ' + config_cross_tcg['DOCKER_IMAGE']}
2906    elif 'CROSS_CC_GUEST' in config_cross_tcg
2907      summary_info += {target + ' tests'
2908                                : config_cross_tcg['CROSS_CC_GUEST'] }
2909    endif
2910   endif
2911endforeach
2912
2913summary(summary_info, bool_yn: true, section: 'Compilation')
2914
2915# Targets and accelerators
2916summary_info = {}
2917if have_system
2918  summary_info += {'KVM support':       config_all.has_key('CONFIG_KVM')}
2919  summary_info += {'HAX support':       config_all.has_key('CONFIG_HAX')}
2920  summary_info += {'HVF support':       config_all.has_key('CONFIG_HVF')}
2921  summary_info += {'WHPX support':      config_all.has_key('CONFIG_WHPX')}
2922  summary_info += {'NVMM support':      config_all.has_key('CONFIG_NVMM')}
2923  summary_info += {'Xen support':       config_host.has_key('CONFIG_XEN_BACKEND')}
2924  if config_host.has_key('CONFIG_XEN_BACKEND')
2925    summary_info += {'xen ctrl version':  config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']}
2926  endif
2927endif
2928summary_info += {'TCG support':       config_all.has_key('CONFIG_TCG')}
2929if config_all.has_key('CONFIG_TCG')
2930  if get_option('tcg_interpreter')
2931    summary_info += {'TCG backend':   'TCI (TCG with bytecode interpreter, experimental and slow)'}
2932  else
2933    summary_info += {'TCG backend':   'native (@0@)'.format(cpu)}
2934  endif
2935  summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')}
2936endif
2937summary_info += {'target list':       ' '.join(target_dirs)}
2938if have_system
2939  summary_info += {'default devices':   get_option('default_devices')}
2940  summary_info += {'out of process emulation': multiprocess_allowed}
2941endif
2942summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
2943
2944# Block layer
2945summary_info = {}
2946summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']}
2947summary_info += {'coroutine pool':    config_host['CONFIG_COROUTINE_POOL'] == '1'}
2948if have_block
2949  summary_info += {'Block whitelist (rw)': config_host['CONFIG_BDRV_RW_WHITELIST']}
2950  summary_info += {'Block whitelist (ro)': config_host['CONFIG_BDRV_RO_WHITELIST']}
2951  summary_info += {'VirtFS support':    have_virtfs}
2952  summary_info += {'build virtiofs daemon': have_virtiofsd}
2953  summary_info += {'Live block migration': config_host.has_key('CONFIG_LIVE_BLOCK_MIGRATION')}
2954  summary_info += {'replication support': config_host.has_key('CONFIG_REPLICATION')}
2955  summary_info += {'bochs support':     config_host.has_key('CONFIG_BOCHS')}
2956  summary_info += {'cloop support':     config_host.has_key('CONFIG_CLOOP')}
2957  summary_info += {'dmg support':       config_host.has_key('CONFIG_DMG')}
2958  summary_info += {'qcow v1 support':   config_host.has_key('CONFIG_QCOW1')}
2959  summary_info += {'vdi support':       config_host.has_key('CONFIG_VDI')}
2960  summary_info += {'vvfat support':     config_host.has_key('CONFIG_VVFAT')}
2961  summary_info += {'qed support':       config_host.has_key('CONFIG_QED')}
2962  summary_info += {'parallels support': config_host.has_key('CONFIG_PARALLELS')}
2963  summary_info += {'FUSE exports':      fuse.found()}
2964endif
2965summary(summary_info, bool_yn: true, section: 'Block layer support')
2966
2967# Crypto
2968summary_info = {}
2969summary_info += {'TLS priority':      config_host['CONFIG_TLS_PRIORITY']}
2970summary_info += {'GNUTLS support':    gnutls.found()}
2971# TODO: add back version
2972summary_info += {'libgcrypt':         gcrypt.found()}
2973if gcrypt.found()
2974   summary_info += {'  XTS':             xts != 'private'}
2975endif
2976# TODO: add back version
2977summary_info += {'nettle':            nettle.found()}
2978if nettle.found()
2979   summary_info += {'  XTS':             xts != 'private'}
2980endif
2981summary_info += {'crypto afalg':      config_host.has_key('CONFIG_AF_ALG')}
2982summary_info += {'rng-none':          config_host.has_key('CONFIG_RNG_NONE')}
2983summary_info += {'Linux keyring':     config_host.has_key('CONFIG_SECRET_KEYRING')}
2984summary(summary_info, bool_yn: true, section: 'Crypto')
2985
2986# Libraries
2987summary_info = {}
2988if targetos == 'darwin'
2989  summary_info += {'Cocoa support':   cocoa.found()}
2990endif
2991# TODO: add back version
2992summary_info += {'SDL support':       sdl.found()}
2993summary_info += {'SDL image support': sdl_image.found()}
2994# TODO: add back version
2995summary_info += {'GTK support':       gtk.found()}
2996summary_info += {'pixman':            pixman.found()}
2997# TODO: add back version
2998summary_info += {'VTE support':       vte.found()}
2999# TODO: add back version
3000summary_info += {'slirp support':     slirp_opt == 'disabled' ? false : slirp_opt}
3001summary_info += {'libtasn1':          tasn1.found()}
3002summary_info += {'PAM':               pam.found()}
3003summary_info += {'iconv support':     iconv.found()}
3004summary_info += {'curses support':    curses.found()}
3005# TODO: add back version
3006summary_info += {'virgl support':     virgl.found()}
3007summary_info += {'curl support':      curl.found()}
3008summary_info += {'Multipath support': mpathpersist.found()}
3009summary_info += {'VNC support':       vnc.found()}
3010if vnc.found()
3011  summary_info += {'VNC SASL support':  sasl.found()}
3012  summary_info += {'VNC JPEG support':  jpeg.found()}
3013  summary_info += {'VNC PNG support':   png.found()}
3014endif
3015summary_info += {'brlapi support':    brlapi.found()}
3016summary_info += {'vde support':       config_host.has_key('CONFIG_VDE')}
3017summary_info += {'netmap support':    config_host.has_key('CONFIG_NETMAP')}
3018summary_info += {'Linux AIO support': config_host.has_key('CONFIG_LINUX_AIO')}
3019summary_info += {'Linux io_uring support': linux_io_uring.found()}
3020summary_info += {'ATTR/XATTR support': libattr.found()}
3021summary_info += {'RDMA support':      config_host.has_key('CONFIG_RDMA')}
3022summary_info += {'PVRDMA support':    config_host.has_key('CONFIG_PVRDMA')}
3023summary_info += {'fdt support':       fdt_opt == 'disabled' ? false : fdt_opt}
3024summary_info += {'libcap-ng support': libcap_ng.found()}
3025summary_info += {'bpf support': libbpf.found()}
3026# TODO: add back protocol and server version
3027summary_info += {'spice support':     config_host.has_key('CONFIG_SPICE')}
3028summary_info += {'rbd support':       rbd.found()}
3029summary_info += {'xfsctl support':    config_host.has_key('CONFIG_XFS')}
3030summary_info += {'smartcard support': cacard.found()}
3031summary_info += {'U2F support':       u2f.found()}
3032summary_info += {'libusb':            libusb.found()}
3033summary_info += {'usb net redir':     usbredir.found()}
3034summary_info += {'OpenGL support':    config_host.has_key('CONFIG_OPENGL')}
3035summary_info += {'GBM':               config_host.has_key('CONFIG_GBM')}
3036summary_info += {'libiscsi support':  libiscsi.found()}
3037summary_info += {'libnfs support':    libnfs.found()}
3038if targetos == 'windows'
3039  if config_host.has_key('CONFIG_GUEST_AGENT')
3040    summary_info += {'QGA VSS support':   config_host.has_key('CONFIG_QGA_VSS')}
3041    summary_info += {'QGA w32 disk info': config_host.has_key('CONFIG_QGA_NTDDSCSI')}
3042  endif
3043endif
3044summary_info += {'seccomp support':   seccomp.found()}
3045summary_info += {'GlusterFS support': glusterfs.found()}
3046summary_info += {'TPM support':       config_host.has_key('CONFIG_TPM')}
3047summary_info += {'libssh support':    config_host.has_key('CONFIG_LIBSSH')}
3048summary_info += {'lzo support':       lzo.found()}
3049summary_info += {'snappy support':    snappy.found()}
3050summary_info += {'bzip2 support':     libbzip2.found()}
3051summary_info += {'lzfse support':     liblzfse.found()}
3052summary_info += {'zstd support':      zstd.found()}
3053summary_info += {'NUMA host support': config_host.has_key('CONFIG_NUMA')}
3054summary_info += {'libxml2':           libxml2.found()}
3055summary_info += {'capstone':          capstone_opt == 'disabled' ? false : capstone_opt}
3056summary_info += {'libpmem support':   libpmem.found()}
3057summary_info += {'libdaxctl support': libdaxctl.found()}
3058summary_info += {'libudev':           libudev.found()}
3059summary_info += {'FUSE lseek':        fuse_lseek.found()}
3060summary(summary_info, bool_yn: true, section: 'Dependencies')
3061
3062if not supported_cpus.contains(cpu)
3063  message()
3064  warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!')
3065  message()
3066  message('CPU host architecture ' + cpu + ' support is not currently maintained.')
3067  message('The QEMU project intends to remove support for this host CPU in')
3068  message('a future release if nobody volunteers to maintain it and to')
3069  message('provide a build host for our continuous integration setup.')
3070  message('configure has succeeded and you can continue to build, but')
3071  message('if you care about QEMU on this platform you should contact')
3072  message('us upstream at qemu-devel@nongnu.org.')
3073endif
3074
3075if not supported_oses.contains(targetos)
3076  message()
3077  warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!')
3078  message()
3079  message('Host OS ' + targetos + 'support is not currently maintained.')
3080  message('The QEMU project intends to remove support for this host OS in')
3081  message('a future release if nobody volunteers to maintain it and to')
3082  message('provide a build host for our continuous integration setup.')
3083  message('configure has succeeded and you can continue to build, but')
3084  message('if you care about QEMU on this platform you should contact')
3085  message('us upstream at qemu-devel@nongnu.org.')
3086endif
3087