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