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