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