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