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