xref: /openbmc/qemu/meson.build (revision 875bb7e35b78c609252187dc7bd68d90bf742da9)
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  'nios2' : ['CONFIG_NIOS2_DIS'],
1218  'or1k' : ['CONFIG_OPENRISC_DIS'],
1219  'ppc' : ['CONFIG_PPC_DIS'],
1220  'riscv' : ['CONFIG_RISCV_DIS'],
1221  'rx' : ['CONFIG_RX_DIS'],
1222  's390' : ['CONFIG_S390_DIS'],
1223  'sh4' : ['CONFIG_SH4_DIS'],
1224  'sparc' : ['CONFIG_SPARC_DIS'],
1225  'xtensa' : ['CONFIG_XTENSA_DIS'],
1226}
1227if link_language == 'cpp'
1228  disassemblers += {
1229    'aarch64' : [ 'CONFIG_ARM_A64_DIS'],
1230    'arm' : [ 'CONFIG_ARM_DIS', 'CONFIG_ARM_A64_DIS'],
1231    'mips' : [ 'CONFIG_MIPS_DIS', 'CONFIG_NANOMIPS_DIS'],
1232  }
1233endif
1234
1235host_kconfig = \
1236  ('CONFIG_TPM' in config_host ? ['CONFIG_TPM=y'] : []) + \
1237  ('CONFIG_SPICE' in config_host ? ['CONFIG_SPICE=y'] : []) + \
1238  ('CONFIG_IVSHMEM' in config_host ? ['CONFIG_IVSHMEM=y'] : []) + \
1239  ('CONFIG_OPENGL' in config_host ? ['CONFIG_OPENGL=y'] : []) + \
1240  (x11.found() ? ['CONFIG_X11=y'] : []) + \
1241  ('CONFIG_VHOST_USER' in config_host ? ['CONFIG_VHOST_USER=y'] : []) + \
1242  ('CONFIG_VHOST_VDPA' in config_host ? ['CONFIG_VHOST_VDPA=y'] : []) + \
1243  ('CONFIG_VHOST_KERNEL' in config_host ? ['CONFIG_VHOST_KERNEL=y'] : []) + \
1244  (have_virtfs ? ['CONFIG_VIRTFS=y'] : []) + \
1245  ('CONFIG_LINUX' in config_host ? ['CONFIG_LINUX=y'] : []) + \
1246  ('CONFIG_PVRDMA' in config_host ? ['CONFIG_PVRDMA=y'] : []) + \
1247  (multiprocess_allowed ? ['CONFIG_MULTIPROCESS_ALLOWED=y'] : [])
1248
1249ignored = [ 'TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_ARCH' ]
1250
1251default_targets = 'CONFIG_DEFAULT_TARGETS' in config_host
1252actual_target_dirs = []
1253fdt_required = []
1254foreach target : target_dirs
1255  config_target = { 'TARGET_NAME': target.split('-')[0] }
1256  if target.endswith('linux-user')
1257    if targetos != 'linux'
1258      if default_targets
1259        continue
1260      endif
1261      error('Target @0@ is only available on a Linux host'.format(target))
1262    endif
1263    config_target += { 'CONFIG_LINUX_USER': 'y' }
1264  elif target.endswith('bsd-user')
1265    if 'CONFIG_BSD' not in config_host
1266      if default_targets
1267        continue
1268      endif
1269      error('Target @0@ is only available on a BSD host'.format(target))
1270    endif
1271    config_target += { 'CONFIG_BSD_USER': 'y' }
1272  elif target.endswith('softmmu')
1273    config_target += { 'CONFIG_SOFTMMU': 'y' }
1274  endif
1275  if target.endswith('-user')
1276    config_target += {
1277      'CONFIG_USER_ONLY': 'y',
1278      'CONFIG_QEMU_INTERP_PREFIX':
1279        config_host['CONFIG_QEMU_INTERP_PREFIX'].format(config_target['TARGET_NAME'])
1280    }
1281  endif
1282
1283  accel_kconfig = []
1284  foreach sym: accelerators
1285    if sym == 'CONFIG_TCG' or target in accelerator_targets.get(sym, [])
1286      config_target += { sym: 'y' }
1287      config_all += { sym: 'y' }
1288      if sym == 'CONFIG_TCG' and tcg_arch == 'tci'
1289        config_target += { 'CONFIG_TCG_INTERPRETER': 'y' }
1290      elif sym == 'CONFIG_XEN' and have_xen_pci_passthrough
1291        config_target += { 'CONFIG_XEN_PCI_PASSTHROUGH': 'y' }
1292      endif
1293      accel_kconfig += [ sym + '=y' ]
1294    endif
1295  endforeach
1296  if accel_kconfig.length() == 0
1297    if default_targets
1298      continue
1299    endif
1300    error('No accelerator available for target @0@'.format(target))
1301  endif
1302
1303  actual_target_dirs += target
1304  config_target += keyval.load('default-configs/targets' / target + '.mak')
1305  config_target += { 'TARGET_' + config_target['TARGET_ARCH'].to_upper(): 'y' }
1306
1307  if 'TARGET_NEED_FDT' in config_target
1308    fdt_required += target
1309  endif
1310
1311  # Add default keys
1312  if 'TARGET_BASE_ARCH' not in config_target
1313    config_target += {'TARGET_BASE_ARCH': config_target['TARGET_ARCH']}
1314  endif
1315  if 'TARGET_ABI_DIR' not in config_target
1316    config_target += {'TARGET_ABI_DIR': config_target['TARGET_ARCH']}
1317  endif
1318
1319  foreach k, v: disassemblers
1320    if config_host['ARCH'].startswith(k) or config_target['TARGET_BASE_ARCH'].startswith(k)
1321      foreach sym: v
1322        config_target += { sym: 'y' }
1323        config_all_disas += { sym: 'y' }
1324      endforeach
1325    endif
1326  endforeach
1327
1328  config_target_data = configuration_data()
1329  foreach k, v: config_target
1330    if not k.startswith('TARGET_') and not k.startswith('CONFIG_')
1331      # do nothing
1332    elif ignored.contains(k)
1333      # do nothing
1334    elif k == 'TARGET_BASE_ARCH'
1335      # Note that TARGET_BASE_ARCH ends up in config-target.h but it is
1336      # not used to select files from sourcesets.
1337      config_target_data.set('TARGET_' + v.to_upper(), 1)
1338    elif k == 'TARGET_NAME' or k == 'CONFIG_QEMU_INTERP_PREFIX'
1339      config_target_data.set_quoted(k, v)
1340    elif v == 'y'
1341      config_target_data.set(k, 1)
1342    else
1343      config_target_data.set(k, v)
1344    endif
1345  endforeach
1346  config_target_h += {target: configure_file(output: target + '-config-target.h',
1347                                               configuration: config_target_data)}
1348
1349  if target.endswith('-softmmu')
1350    config_devices_mak = target + '-config-devices.mak'
1351    config_devices_mak = configure_file(
1352      input: ['default-configs/devices' / target + '.mak', 'Kconfig'],
1353      output: config_devices_mak,
1354      depfile: config_devices_mak + '.d',
1355      capture: true,
1356      command: [minikconf,
1357                get_option('default_devices') ? '--defconfig' : '--allnoconfig',
1358                config_devices_mak, '@DEPFILE@', '@INPUT@',
1359                host_kconfig, accel_kconfig])
1360
1361    config_devices_data = configuration_data()
1362    config_devices = keyval.load(config_devices_mak)
1363    foreach k, v: config_devices
1364      config_devices_data.set(k, 1)
1365    endforeach
1366    config_devices_mak_list += config_devices_mak
1367    config_devices_h += {target: configure_file(output: target + '-config-devices.h',
1368                                                configuration: config_devices_data)}
1369    config_target += config_devices
1370    config_all_devices += config_devices
1371  endif
1372  config_target_mak += {target: config_target}
1373endforeach
1374target_dirs = actual_target_dirs
1375
1376# This configuration is used to build files that are shared by
1377# multiple binaries, and then extracted out of the "common"
1378# static_library target.
1379#
1380# We do not use all_sources()/all_dependencies(), because it would
1381# build literally all source files, including devices only used by
1382# targets that are not built for this compilation.  The CONFIG_ALL
1383# pseudo symbol replaces it.
1384
1385config_all += config_all_devices
1386config_all += config_host
1387config_all += config_all_disas
1388config_all += {
1389  'CONFIG_XEN': config_host.has_key('CONFIG_XEN_BACKEND'),
1390  'CONFIG_SOFTMMU': have_system,
1391  'CONFIG_USER_ONLY': have_user,
1392  'CONFIG_ALL': true,
1393}
1394
1395##############
1396# Submodules #
1397##############
1398
1399capstone = not_found
1400capstone_opt = get_option('capstone')
1401if capstone_opt in ['enabled', 'auto', 'system']
1402  have_internal = fs.exists(meson.current_source_dir() / 'capstone/Makefile')
1403  capstone = dependency('capstone', version: '>=4.0',
1404                        kwargs: static_kwargs, method: 'pkg-config',
1405                        required: capstone_opt == 'system' or
1406                                  capstone_opt == 'enabled' and not have_internal)
1407  if capstone.found()
1408    capstone_opt = 'system'
1409  elif have_internal
1410    capstone_opt = 'internal'
1411  else
1412    capstone_opt = 'disabled'
1413  endif
1414endif
1415if capstone_opt == 'internal'
1416  capstone_data = configuration_data()
1417  capstone_data.set('CAPSTONE_USE_SYS_DYN_MEM', '1')
1418
1419  capstone_files = files(
1420    'capstone/cs.c',
1421    'capstone/MCInst.c',
1422    'capstone/MCInstrDesc.c',
1423    'capstone/MCRegisterInfo.c',
1424    'capstone/SStream.c',
1425    'capstone/utils.c'
1426  )
1427
1428  if 'CONFIG_ARM_DIS' in config_all_disas
1429    capstone_data.set('CAPSTONE_HAS_ARM', '1')
1430    capstone_files += files(
1431      'capstone/arch/ARM/ARMDisassembler.c',
1432      'capstone/arch/ARM/ARMInstPrinter.c',
1433      'capstone/arch/ARM/ARMMapping.c',
1434      'capstone/arch/ARM/ARMModule.c'
1435    )
1436  endif
1437
1438  # FIXME: This config entry currently depends on a c++ compiler.
1439  # Which is needed for building libvixl, but not for capstone.
1440  if 'CONFIG_ARM_A64_DIS' in config_all_disas
1441    capstone_data.set('CAPSTONE_HAS_ARM64', '1')
1442    capstone_files += files(
1443      'capstone/arch/AArch64/AArch64BaseInfo.c',
1444      'capstone/arch/AArch64/AArch64Disassembler.c',
1445      'capstone/arch/AArch64/AArch64InstPrinter.c',
1446      'capstone/arch/AArch64/AArch64Mapping.c',
1447      'capstone/arch/AArch64/AArch64Module.c'
1448    )
1449  endif
1450
1451  if 'CONFIG_PPC_DIS' in config_all_disas
1452    capstone_data.set('CAPSTONE_HAS_POWERPC', '1')
1453    capstone_files += files(
1454      'capstone/arch/PowerPC/PPCDisassembler.c',
1455      'capstone/arch/PowerPC/PPCInstPrinter.c',
1456      'capstone/arch/PowerPC/PPCMapping.c',
1457      'capstone/arch/PowerPC/PPCModule.c'
1458    )
1459  endif
1460
1461  if 'CONFIG_S390_DIS' in config_all_disas
1462    capstone_data.set('CAPSTONE_HAS_SYSZ', '1')
1463    capstone_files += files(
1464      'capstone/arch/SystemZ/SystemZDisassembler.c',
1465      'capstone/arch/SystemZ/SystemZInstPrinter.c',
1466      'capstone/arch/SystemZ/SystemZMapping.c',
1467      'capstone/arch/SystemZ/SystemZModule.c',
1468      'capstone/arch/SystemZ/SystemZMCTargetDesc.c'
1469    )
1470  endif
1471
1472  if 'CONFIG_I386_DIS' in config_all_disas
1473    capstone_data.set('CAPSTONE_HAS_X86', 1)
1474    capstone_files += files(
1475      'capstone/arch/X86/X86Disassembler.c',
1476      'capstone/arch/X86/X86DisassemblerDecoder.c',
1477      'capstone/arch/X86/X86ATTInstPrinter.c',
1478      'capstone/arch/X86/X86IntelInstPrinter.c',
1479      'capstone/arch/X86/X86InstPrinterCommon.c',
1480      'capstone/arch/X86/X86Mapping.c',
1481      'capstone/arch/X86/X86Module.c'
1482    )
1483  endif
1484
1485  configure_file(output: 'capstone-defs.h', configuration: capstone_data)
1486
1487  capstone_cargs = [
1488    # FIXME: There does not seem to be a way to completely replace the c_args
1489    # that come from add_project_arguments() -- we can only add to them.
1490    # So: disable all warnings with a big hammer.
1491    '-Wno-error', '-w',
1492
1493    # Include all configuration defines via a header file, which will wind up
1494    # as a dependency on the object file, and thus changes here will result
1495    # in a rebuild.
1496    '-include', 'capstone-defs.h'
1497  ]
1498
1499  libcapstone = static_library('capstone',
1500                               build_by_default: false,
1501                               sources: capstone_files,
1502                               c_args: capstone_cargs,
1503                               include_directories: 'capstone/include')
1504  capstone = declare_dependency(link_with: libcapstone,
1505                                include_directories: 'capstone/include/capstone')
1506endif
1507
1508slirp = not_found
1509slirp_opt = 'disabled'
1510if have_system
1511  slirp_opt = get_option('slirp')
1512  if slirp_opt in ['enabled', 'auto', 'system']
1513    have_internal = fs.exists(meson.current_source_dir() / 'slirp/meson.build')
1514    slirp = dependency('slirp', kwargs: static_kwargs,
1515                       method: 'pkg-config',
1516                       required: slirp_opt == 'system' or
1517                                 slirp_opt == 'enabled' and not have_internal)
1518    if slirp.found()
1519      slirp_opt = 'system'
1520    elif have_internal
1521      slirp_opt = 'internal'
1522    else
1523      slirp_opt = 'disabled'
1524    endif
1525  endif
1526  if slirp_opt == 'internal'
1527    slirp_deps = []
1528    if targetos == 'windows'
1529      slirp_deps = cc.find_library('iphlpapi')
1530    endif
1531    slirp_conf = configuration_data()
1532    slirp_conf.set('SLIRP_MAJOR_VERSION', meson.project_version().split('.')[0])
1533    slirp_conf.set('SLIRP_MINOR_VERSION', meson.project_version().split('.')[1])
1534    slirp_conf.set('SLIRP_MICRO_VERSION', meson.project_version().split('.')[2])
1535    slirp_conf.set_quoted('SLIRP_VERSION_STRING', meson.project_version())
1536    slirp_cargs = ['-DG_LOG_DOMAIN="Slirp"']
1537    slirp_files = [
1538      'slirp/src/arp_table.c',
1539      'slirp/src/bootp.c',
1540      'slirp/src/cksum.c',
1541      'slirp/src/dhcpv6.c',
1542      'slirp/src/dnssearch.c',
1543      'slirp/src/if.c',
1544      'slirp/src/ip6_icmp.c',
1545      'slirp/src/ip6_input.c',
1546      'slirp/src/ip6_output.c',
1547      'slirp/src/ip_icmp.c',
1548      'slirp/src/ip_input.c',
1549      'slirp/src/ip_output.c',
1550      'slirp/src/mbuf.c',
1551      'slirp/src/misc.c',
1552      'slirp/src/ncsi.c',
1553      'slirp/src/ndp_table.c',
1554      'slirp/src/sbuf.c',
1555      'slirp/src/slirp.c',
1556      'slirp/src/socket.c',
1557      'slirp/src/state.c',
1558      'slirp/src/stream.c',
1559      'slirp/src/tcp_input.c',
1560      'slirp/src/tcp_output.c',
1561      'slirp/src/tcp_subr.c',
1562      'slirp/src/tcp_timer.c',
1563      'slirp/src/tftp.c',
1564      'slirp/src/udp.c',
1565      'slirp/src/udp6.c',
1566      'slirp/src/util.c',
1567      'slirp/src/version.c',
1568      'slirp/src/vmstate.c',
1569    ]
1570
1571    configure_file(
1572      input : 'slirp/src/libslirp-version.h.in',
1573      output : 'libslirp-version.h',
1574      configuration: slirp_conf)
1575
1576    slirp_inc = include_directories('slirp', 'slirp/src')
1577    libslirp = static_library('slirp',
1578                              build_by_default: false,
1579                              sources: slirp_files,
1580                              c_args: slirp_cargs,
1581                              include_directories: slirp_inc)
1582    slirp = declare_dependency(link_with: libslirp,
1583                               dependencies: slirp_deps,
1584                               include_directories: slirp_inc)
1585  endif
1586endif
1587
1588# For CFI, we need to compile slirp as a static library together with qemu.
1589# This is because we register slirp functions as callbacks for QEMU Timers.
1590# When using a system-wide shared libslirp, the type information for the
1591# callback is missing and the timer call produces a false positive with CFI.
1592#
1593# Now that slirp_opt has been defined, check if the selected slirp is compatible
1594# with control-flow integrity.
1595if get_option('cfi') and slirp_opt == 'system'
1596  error('Control-Flow Integrity is not compatible with system-wide slirp.' \
1597         + ' Please configure with --enable-slirp=git')
1598endif
1599
1600fdt = not_found
1601fdt_opt = get_option('fdt')
1602if have_system
1603  if fdt_opt in ['enabled', 'auto', 'system']
1604    have_internal = fs.exists(meson.current_source_dir() / 'dtc/libfdt/Makefile.libfdt')
1605    fdt = cc.find_library('fdt', kwargs: static_kwargs,
1606                          required: fdt_opt == 'system' or
1607                                    fdt_opt == 'enabled' and not have_internal)
1608    if fdt.found() and cc.links('''
1609       #include <libfdt.h>
1610       #include <libfdt_env.h>
1611       int main(void) { fdt_check_full(NULL, 0); return 0; }''',
1612         dependencies: fdt)
1613      fdt_opt = 'system'
1614    elif have_internal
1615      fdt_opt = 'internal'
1616    else
1617      fdt_opt = 'disabled'
1618    endif
1619  endif
1620  if fdt_opt == 'internal'
1621    fdt_files = files(
1622      'dtc/libfdt/fdt.c',
1623      'dtc/libfdt/fdt_ro.c',
1624      'dtc/libfdt/fdt_wip.c',
1625      'dtc/libfdt/fdt_sw.c',
1626      'dtc/libfdt/fdt_rw.c',
1627      'dtc/libfdt/fdt_strerror.c',
1628      'dtc/libfdt/fdt_empty_tree.c',
1629      'dtc/libfdt/fdt_addresses.c',
1630      'dtc/libfdt/fdt_overlay.c',
1631      'dtc/libfdt/fdt_check.c',
1632    )
1633
1634    fdt_inc = include_directories('dtc/libfdt')
1635    libfdt = static_library('fdt',
1636                            build_by_default: false,
1637                            sources: fdt_files,
1638                            include_directories: fdt_inc)
1639    fdt = declare_dependency(link_with: libfdt,
1640                             include_directories: fdt_inc)
1641  endif
1642endif
1643if not fdt.found() and fdt_required.length() > 0
1644  error('fdt not available but required by targets ' + ', '.join(fdt_required))
1645endif
1646
1647config_host_data.set('CONFIG_CAPSTONE', capstone.found())
1648config_host_data.set('CONFIG_FDT', fdt.found())
1649config_host_data.set('CONFIG_SLIRP', slirp.found())
1650
1651#####################
1652# Generated sources #
1653#####################
1654
1655genh += configure_file(output: 'config-host.h', configuration: config_host_data)
1656
1657hxtool = find_program('scripts/hxtool')
1658shaderinclude = find_program('scripts/shaderinclude.pl')
1659qapi_gen = find_program('scripts/qapi-gen.py')
1660qapi_gen_depends = [ meson.source_root() / 'scripts/qapi/__init__.py',
1661                     meson.source_root() / 'scripts/qapi/commands.py',
1662                     meson.source_root() / 'scripts/qapi/common.py',
1663                     meson.source_root() / 'scripts/qapi/error.py',
1664                     meson.source_root() / 'scripts/qapi/events.py',
1665                     meson.source_root() / 'scripts/qapi/expr.py',
1666                     meson.source_root() / 'scripts/qapi/gen.py',
1667                     meson.source_root() / 'scripts/qapi/introspect.py',
1668                     meson.source_root() / 'scripts/qapi/parser.py',
1669                     meson.source_root() / 'scripts/qapi/schema.py',
1670                     meson.source_root() / 'scripts/qapi/source.py',
1671                     meson.source_root() / 'scripts/qapi/types.py',
1672                     meson.source_root() / 'scripts/qapi/visit.py',
1673                     meson.source_root() / 'scripts/qapi/common.py',
1674                     meson.source_root() / 'scripts/qapi-gen.py'
1675]
1676
1677tracetool = [
1678  python, files('scripts/tracetool.py'),
1679   '--backend=' + config_host['TRACE_BACKENDS']
1680]
1681tracetool_depends = files(
1682  'scripts/tracetool/backend/log.py',
1683  'scripts/tracetool/backend/__init__.py',
1684  'scripts/tracetool/backend/dtrace.py',
1685  'scripts/tracetool/backend/ftrace.py',
1686  'scripts/tracetool/backend/simple.py',
1687  'scripts/tracetool/backend/syslog.py',
1688  'scripts/tracetool/backend/ust.py',
1689  'scripts/tracetool/format/tcg_h.py',
1690  'scripts/tracetool/format/ust_events_c.py',
1691  'scripts/tracetool/format/ust_events_h.py',
1692  'scripts/tracetool/format/__init__.py',
1693  'scripts/tracetool/format/d.py',
1694  'scripts/tracetool/format/tcg_helper_c.py',
1695  'scripts/tracetool/format/simpletrace_stap.py',
1696  'scripts/tracetool/format/c.py',
1697  'scripts/tracetool/format/h.py',
1698  'scripts/tracetool/format/tcg_helper_h.py',
1699  'scripts/tracetool/format/log_stap.py',
1700  'scripts/tracetool/format/stap.py',
1701  'scripts/tracetool/format/tcg_helper_wrapper_h.py',
1702  'scripts/tracetool/__init__.py',
1703  'scripts/tracetool/transform.py',
1704  'scripts/tracetool/vcpu.py'
1705)
1706
1707qemu_version_cmd = [find_program('scripts/qemu-version.sh'),
1708                    meson.current_source_dir(),
1709                    config_host['PKGVERSION'], meson.project_version()]
1710qemu_version = custom_target('qemu-version.h',
1711                             output: 'qemu-version.h',
1712                             command: qemu_version_cmd,
1713                             capture: true,
1714                             build_by_default: true,
1715                             build_always_stale: true)
1716genh += qemu_version
1717
1718hxdep = []
1719hx_headers = [
1720  ['qemu-options.hx', 'qemu-options.def'],
1721  ['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
1722]
1723if have_system
1724  hx_headers += [
1725    ['hmp-commands.hx', 'hmp-commands.h'],
1726    ['hmp-commands-info.hx', 'hmp-commands-info.h'],
1727  ]
1728endif
1729foreach d : hx_headers
1730  hxdep += custom_target(d[1],
1731                input: files(d[0]),
1732                output: d[1],
1733                capture: true,
1734                build_by_default: true, # to be removed when added to a target
1735                command: [hxtool, '-h', '@INPUT0@'])
1736endforeach
1737genh += hxdep
1738
1739###################
1740# Collect sources #
1741###################
1742
1743authz_ss = ss.source_set()
1744blockdev_ss = ss.source_set()
1745block_ss = ss.source_set()
1746bsd_user_ss = ss.source_set()
1747chardev_ss = ss.source_set()
1748common_ss = ss.source_set()
1749crypto_ss = ss.source_set()
1750io_ss = ss.source_set()
1751linux_user_ss = ss.source_set()
1752qmp_ss = ss.source_set()
1753qom_ss = ss.source_set()
1754softmmu_ss = ss.source_set()
1755specific_fuzz_ss = ss.source_set()
1756specific_ss = ss.source_set()
1757stub_ss = ss.source_set()
1758trace_ss = ss.source_set()
1759user_ss = ss.source_set()
1760util_ss = ss.source_set()
1761
1762modules = {}
1763hw_arch = {}
1764target_arch = {}
1765target_softmmu_arch = {}
1766target_user_arch = {}
1767
1768###############
1769# Trace files #
1770###############
1771
1772# TODO: add each directory to the subdirs from its own meson.build, once
1773# we have those
1774trace_events_subdirs = [
1775  'crypto',
1776  'qapi',
1777  'qom',
1778  'monitor',
1779  'util',
1780]
1781if have_user
1782  trace_events_subdirs += [ 'linux-user' ]
1783endif
1784if have_block
1785  trace_events_subdirs += [
1786    'authz',
1787    'block',
1788    'io',
1789    'nbd',
1790    'scsi',
1791  ]
1792endif
1793if have_system
1794  trace_events_subdirs += [
1795    'accel/kvm',
1796    'audio',
1797    'backends',
1798    'backends/tpm',
1799    'chardev',
1800    'hw/9pfs',
1801    'hw/acpi',
1802    'hw/adc',
1803    'hw/alpha',
1804    'hw/arm',
1805    'hw/audio',
1806    'hw/block',
1807    'hw/block/dataplane',
1808    'hw/char',
1809    'hw/display',
1810    'hw/dma',
1811    'hw/hppa',
1812    'hw/hyperv',
1813    'hw/i2c',
1814    'hw/i386',
1815    'hw/i386/xen',
1816    'hw/ide',
1817    'hw/input',
1818    'hw/intc',
1819    'hw/isa',
1820    'hw/mem',
1821    'hw/mips',
1822    'hw/misc',
1823    'hw/misc/macio',
1824    'hw/net',
1825    'hw/net/can',
1826    'hw/nvram',
1827    'hw/pci',
1828    'hw/pci-host',
1829    'hw/ppc',
1830    'hw/rdma',
1831    'hw/rdma/vmw',
1832    'hw/rtc',
1833    'hw/s390x',
1834    'hw/scsi',
1835    'hw/sd',
1836    'hw/sparc',
1837    'hw/sparc64',
1838    'hw/ssi',
1839    'hw/timer',
1840    'hw/tpm',
1841    'hw/usb',
1842    'hw/vfio',
1843    'hw/virtio',
1844    'hw/watchdog',
1845    'hw/xen',
1846    'hw/gpio',
1847    'migration',
1848    'net',
1849    'softmmu',
1850    'ui',
1851    'hw/remote',
1852  ]
1853endif
1854if have_system or have_user
1855  trace_events_subdirs += [
1856    'accel/tcg',
1857    'hw/core',
1858    'target/arm',
1859    'target/hppa',
1860    'target/i386',
1861    'target/i386/kvm',
1862    'target/mips',
1863    'target/ppc',
1864    'target/riscv',
1865    'target/s390x',
1866    'target/sparc',
1867  ]
1868endif
1869
1870vhost_user = not_found
1871if 'CONFIG_VHOST_USER' in config_host
1872  libvhost_user = subproject('libvhost-user')
1873  vhost_user = libvhost_user.get_variable('vhost_user_dep')
1874endif
1875
1876subdir('qapi')
1877subdir('qobject')
1878subdir('stubs')
1879subdir('trace')
1880subdir('util')
1881subdir('qom')
1882subdir('authz')
1883subdir('crypto')
1884subdir('ui')
1885
1886
1887if enable_modules
1888  libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
1889  modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
1890endif
1891
1892stub_ss = stub_ss.apply(config_all, strict: false)
1893
1894util_ss.add_all(trace_ss)
1895util_ss = util_ss.apply(config_all, strict: false)
1896libqemuutil = static_library('qemuutil',
1897                             sources: util_ss.sources() + stub_ss.sources() + genh,
1898                             dependencies: [util_ss.dependencies(), m, glib, socket, malloc])
1899qemuutil = declare_dependency(link_with: libqemuutil,
1900                              sources: genh + version_res)
1901
1902if have_system or have_user
1903  decodetree = generator(find_program('scripts/decodetree.py'),
1904                         output: 'decode-@BASENAME@.c.inc',
1905                         arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
1906  subdir('libdecnumber')
1907  subdir('target')
1908endif
1909
1910subdir('audio')
1911subdir('io')
1912subdir('chardev')
1913subdir('fsdev')
1914subdir('dump')
1915
1916if have_block
1917  block_ss.add(files(
1918    'block.c',
1919    'blockjob.c',
1920    'job.c',
1921    'qemu-io-cmds.c',
1922  ))
1923  block_ss.add(when: 'CONFIG_REPLICATION', if_true: files('replication.c'))
1924
1925  subdir('nbd')
1926  subdir('scsi')
1927  subdir('block')
1928
1929  blockdev_ss.add(files(
1930    'blockdev.c',
1931    'blockdev-nbd.c',
1932    'iothread.c',
1933    'job-qmp.c',
1934  ), gnutls)
1935
1936  # os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
1937  # os-win32.c does not
1938  blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c'))
1939  softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')])
1940endif
1941
1942common_ss.add(files('cpus-common.c'))
1943
1944subdir('softmmu')
1945
1946common_ss.add(capstone)
1947specific_ss.add(files('cpu.c', 'disas.c', 'gdbstub.c'), capstone)
1948specific_ss.add(when: 'CONFIG_TCG', if_true: files(
1949  'fpu/softfloat.c',
1950  'tcg/optimize.c',
1951  'tcg/tcg-common.c',
1952  'tcg/tcg-op-gvec.c',
1953  'tcg/tcg-op-vec.c',
1954  'tcg/tcg-op.c',
1955  'tcg/tcg.c',
1956))
1957specific_ss.add(when: 'CONFIG_TCG_INTERPRETER', if_true: files('tcg/tci.c'))
1958
1959# Work around a gcc bug/misfeature wherein constant propagation looks
1960# through an alias:
1961#   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99696
1962# to guess that a const variable is always zero.  Without lto, this is
1963# impossible, as the alias is restricted to page-vary-common.c.  Indeed,
1964# without lto, not even the alias is required -- we simply use different
1965# declarations in different compilation units.
1966pagevary = files('page-vary-common.c')
1967if get_option('b_lto')
1968  pagevary_flags = ['-fno-lto']
1969  if get_option('cfi')
1970    pagevary_flags += '-fno-sanitize=cfi-icall'
1971  endif
1972  pagevary = static_library('page-vary-common', sources: pagevary,
1973                            c_args: pagevary_flags)
1974  pagevary = declare_dependency(link_with: pagevary)
1975endif
1976common_ss.add(pagevary)
1977specific_ss.add(files('page-vary.c'))
1978
1979subdir('backends')
1980subdir('disas')
1981subdir('migration')
1982subdir('monitor')
1983subdir('net')
1984subdir('replay')
1985subdir('semihosting')
1986subdir('hw')
1987subdir('accel')
1988subdir('plugins')
1989subdir('bsd-user')
1990subdir('linux-user')
1991
1992bsd_user_ss.add(files('gdbstub.c'))
1993specific_ss.add_all(when: 'CONFIG_BSD_USER', if_true: bsd_user_ss)
1994
1995linux_user_ss.add(files('gdbstub.c', 'thunk.c'))
1996specific_ss.add_all(when: 'CONFIG_LINUX_USER', if_true: linux_user_ss)
1997
1998# needed for fuzzing binaries
1999subdir('tests/qtest/libqos')
2000subdir('tests/qtest/fuzz')
2001
2002########################
2003# Library dependencies #
2004########################
2005
2006block_mods = []
2007softmmu_mods = []
2008foreach d, list : modules
2009  foreach m, module_ss : list
2010    if enable_modules and targetos != 'windows'
2011      module_ss = module_ss.apply(config_all, strict: false)
2012      sl = static_library(d + '-' + m, [genh, module_ss.sources()],
2013                          dependencies: [modulecommon, module_ss.dependencies()], pic: true)
2014      if d == 'block'
2015        block_mods += sl
2016      else
2017        softmmu_mods += sl
2018      endif
2019    else
2020      if d == 'block'
2021        block_ss.add_all(module_ss)
2022      else
2023        softmmu_ss.add_all(module_ss)
2024      endif
2025    endif
2026  endforeach
2027endforeach
2028
2029nm = find_program('nm')
2030undefsym = find_program('scripts/undefsym.py')
2031block_syms = custom_target('block.syms', output: 'block.syms',
2032                             input: [libqemuutil, block_mods],
2033                             capture: true,
2034                             command: [undefsym, nm, '@INPUT@'])
2035qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
2036                             input: [libqemuutil, softmmu_mods],
2037                             capture: true,
2038                             command: [undefsym, nm, '@INPUT@'])
2039
2040qom_ss = qom_ss.apply(config_host, strict: false)
2041libqom = static_library('qom', qom_ss.sources() + genh,
2042                        dependencies: [qom_ss.dependencies()],
2043                        name_suffix: 'fa')
2044
2045qom = declare_dependency(link_whole: libqom)
2046
2047authz_ss = authz_ss.apply(config_host, strict: false)
2048libauthz = static_library('authz', authz_ss.sources() + genh,
2049                          dependencies: [authz_ss.dependencies()],
2050                          name_suffix: 'fa',
2051                          build_by_default: false)
2052
2053authz = declare_dependency(link_whole: libauthz,
2054                           dependencies: qom)
2055
2056crypto_ss = crypto_ss.apply(config_host, strict: false)
2057libcrypto = static_library('crypto', crypto_ss.sources() + genh,
2058                           dependencies: [crypto_ss.dependencies()],
2059                           name_suffix: 'fa',
2060                           build_by_default: false)
2061
2062crypto = declare_dependency(link_whole: libcrypto,
2063                            dependencies: [authz, qom])
2064
2065io_ss = io_ss.apply(config_host, strict: false)
2066libio = static_library('io', io_ss.sources() + genh,
2067                       dependencies: [io_ss.dependencies()],
2068                       link_with: libqemuutil,
2069                       name_suffix: 'fa',
2070                       build_by_default: false)
2071
2072io = declare_dependency(link_whole: libio, dependencies: [crypto, qom])
2073
2074libmigration = static_library('migration', sources: migration_files + genh,
2075                              name_suffix: 'fa',
2076                              build_by_default: false)
2077migration = declare_dependency(link_with: libmigration,
2078                               dependencies: [zlib, qom, io])
2079softmmu_ss.add(migration)
2080
2081block_ss = block_ss.apply(config_host, strict: false)
2082libblock = static_library('block', block_ss.sources() + genh,
2083                          dependencies: block_ss.dependencies(),
2084                          link_depends: block_syms,
2085                          name_suffix: 'fa',
2086                          build_by_default: false)
2087
2088block = declare_dependency(link_whole: [libblock],
2089                           link_args: '@block.syms',
2090                           dependencies: [crypto, io])
2091
2092blockdev_ss = blockdev_ss.apply(config_host, strict: false)
2093libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
2094                             dependencies: blockdev_ss.dependencies(),
2095                             name_suffix: 'fa',
2096                             build_by_default: false)
2097
2098blockdev = declare_dependency(link_whole: [libblockdev],
2099                              dependencies: [block])
2100
2101qmp_ss = qmp_ss.apply(config_host, strict: false)
2102libqmp = static_library('qmp', qmp_ss.sources() + genh,
2103                        dependencies: qmp_ss.dependencies(),
2104                        name_suffix: 'fa',
2105                        build_by_default: false)
2106
2107qmp = declare_dependency(link_whole: [libqmp])
2108
2109libchardev = static_library('chardev', chardev_ss.sources() + genh,
2110                            name_suffix: 'fa',
2111                            dependencies: [gnutls],
2112                            build_by_default: false)
2113
2114chardev = declare_dependency(link_whole: libchardev)
2115
2116libhwcore = static_library('hwcore', sources: hwcore_files + genh,
2117                           name_suffix: 'fa',
2118                           build_by_default: false)
2119hwcore = declare_dependency(link_whole: libhwcore)
2120common_ss.add(hwcore)
2121
2122###########
2123# Targets #
2124###########
2125
2126foreach m : block_mods + softmmu_mods
2127  shared_module(m.name(),
2128                name_prefix: '',
2129                link_whole: m,
2130                install: true,
2131                install_dir: qemu_moddir)
2132endforeach
2133
2134softmmu_ss.add(authz, blockdev, chardev, crypto, io, qmp)
2135common_ss.add(qom, qemuutil)
2136
2137common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss])
2138common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
2139
2140common_all = common_ss.apply(config_all, strict: false)
2141common_all = static_library('common',
2142                            build_by_default: false,
2143                            sources: common_all.sources() + genh,
2144                            dependencies: common_all.dependencies(),
2145                            name_suffix: 'fa')
2146
2147feature_to_c = find_program('scripts/feature_to_c.sh')
2148
2149emulators = {}
2150foreach target : target_dirs
2151  config_target = config_target_mak[target]
2152  target_name = config_target['TARGET_NAME']
2153  arch = config_target['TARGET_BASE_ARCH']
2154  arch_srcs = [config_target_h[target]]
2155  arch_deps = []
2156  c_args = ['-DNEED_CPU_H',
2157            '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
2158            '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
2159  link_args = emulator_link_args
2160
2161  config_target += config_host
2162  target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
2163  if targetos == 'linux'
2164    target_inc += include_directories('linux-headers', is_system: true)
2165  endif
2166  if target.endswith('-softmmu')
2167    qemu_target_name = 'qemu-system-' + target_name
2168    target_type='system'
2169    t = target_softmmu_arch[arch].apply(config_target, strict: false)
2170    arch_srcs += t.sources()
2171    arch_deps += t.dependencies()
2172
2173    hw_dir = target_name == 'sparc64' ? 'sparc64' : arch
2174    hw = hw_arch[hw_dir].apply(config_target, strict: false)
2175    arch_srcs += hw.sources()
2176    arch_deps += hw.dependencies()
2177
2178    arch_srcs += config_devices_h[target]
2179    link_args += ['@block.syms', '@qemu.syms']
2180  else
2181    abi = config_target['TARGET_ABI_DIR']
2182    target_type='user'
2183    qemu_target_name = 'qemu-' + target_name
2184    if arch in target_user_arch
2185      t = target_user_arch[arch].apply(config_target, strict: false)
2186      arch_srcs += t.sources()
2187      arch_deps += t.dependencies()
2188    endif
2189    if 'CONFIG_LINUX_USER' in config_target
2190      base_dir = 'linux-user'
2191      target_inc += include_directories('linux-user/host/' / config_host['ARCH'])
2192    else
2193      base_dir = 'bsd-user'
2194      target_inc += include_directories('bsd-user/freebsd')
2195    endif
2196    target_inc += include_directories(
2197      base_dir,
2198      base_dir / abi,
2199    )
2200    if 'CONFIG_LINUX_USER' in config_target
2201      dir = base_dir / abi
2202      arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
2203      if config_target.has_key('TARGET_SYSTBL_ABI')
2204        arch_srcs += \
2205          syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
2206                                             extra_args : config_target['TARGET_SYSTBL_ABI'])
2207      endif
2208    endif
2209  endif
2210
2211  if 'TARGET_XML_FILES' in config_target
2212    gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
2213                                output: target + '-gdbstub-xml.c',
2214                                input: files(config_target['TARGET_XML_FILES'].split()),
2215                                command: [feature_to_c, '@INPUT@'],
2216                                capture: true)
2217    arch_srcs += gdbstub_xml
2218  endif
2219
2220  t = target_arch[arch].apply(config_target, strict: false)
2221  arch_srcs += t.sources()
2222  arch_deps += t.dependencies()
2223
2224  target_common = common_ss.apply(config_target, strict: false)
2225  objects = common_all.extract_objects(target_common.sources())
2226  deps = target_common.dependencies()
2227
2228  target_specific = specific_ss.apply(config_target, strict: false)
2229  arch_srcs += target_specific.sources()
2230  arch_deps += target_specific.dependencies()
2231
2232  lib = static_library('qemu-' + target,
2233                 sources: arch_srcs + genh,
2234                 dependencies: arch_deps,
2235                 objects: objects,
2236                 include_directories: target_inc,
2237                 c_args: c_args,
2238                 build_by_default: false,
2239                 name_suffix: 'fa')
2240
2241  if target.endswith('-softmmu')
2242    execs = [{
2243      'name': 'qemu-system-' + target_name,
2244      'gui': false,
2245      'sources': files('softmmu/main.c'),
2246      'dependencies': []
2247    }]
2248    if targetos == 'windows' and (sdl.found() or gtk.found())
2249      execs += [{
2250        'name': 'qemu-system-' + target_name + 'w',
2251        'gui': true,
2252        'sources': files('softmmu/main.c'),
2253        'dependencies': []
2254      }]
2255    endif
2256    if config_host.has_key('CONFIG_FUZZ')
2257      specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
2258      execs += [{
2259        'name': 'qemu-fuzz-' + target_name,
2260        'gui': false,
2261        'sources': specific_fuzz.sources(),
2262        'dependencies': specific_fuzz.dependencies(),
2263      }]
2264    endif
2265  else
2266    execs = [{
2267      'name': 'qemu-' + target_name,
2268      'gui': false,
2269      'sources': [],
2270      'dependencies': []
2271    }]
2272  endif
2273  foreach exe: execs
2274    exe_name = exe['name']
2275    exe_sign = 'CONFIG_HVF' in config_target
2276    if exe_sign
2277      exe_name += '-unsigned'
2278    endif
2279
2280    emulator = executable(exe_name, exe['sources'],
2281               install: true,
2282               c_args: c_args,
2283               dependencies: arch_deps + deps + exe['dependencies'],
2284               objects: lib.extract_all_objects(recursive: true),
2285               link_language: link_language,
2286               link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
2287               link_args: link_args,
2288               gui_app: exe['gui'])
2289
2290    if exe_sign
2291      emulators += {exe['name'] : custom_target(exe['name'],
2292                   depends: emulator,
2293                   output: exe['name'],
2294                   command: [
2295                     meson.current_source_dir() / 'scripts/entitlement.sh',
2296                     meson.current_build_dir() / exe_name,
2297                     meson.current_build_dir() / exe['name'],
2298                     meson.current_source_dir() / 'accel/hvf/entitlements.plist'
2299                   ])
2300      }
2301
2302      meson.add_install_script('scripts/entitlement.sh', '--install',
2303                               get_option('bindir') / exe_name,
2304                               get_option('bindir') / exe['name'],
2305                               meson.current_source_dir() / 'accel/hvf/entitlements.plist')
2306    else
2307      emulators += {exe['name']: emulator}
2308    endif
2309
2310    if 'CONFIG_TRACE_SYSTEMTAP' in config_host
2311      foreach stp: [
2312        {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
2313        {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
2314        {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
2315        {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
2316      ]
2317        custom_target(exe['name'] + stp['ext'],
2318                      input: trace_events_all,
2319                      output: exe['name'] + stp['ext'],
2320                      install: stp['install'],
2321                      install_dir: get_option('datadir') / 'systemtap/tapset',
2322                      command: [
2323                        tracetool, '--group=all', '--format=' + stp['fmt'],
2324                        '--binary=' + stp['bin'],
2325                        '--target-name=' + target_name,
2326                        '--target-type=' + target_type,
2327                        '--probe-prefix=qemu.' + target_type + '.' + target_name,
2328                        '@INPUT@', '@OUTPUT@'
2329                      ],
2330                      depend_files: tracetool_depends)
2331      endforeach
2332    endif
2333  endforeach
2334endforeach
2335
2336# Other build targets
2337
2338if 'CONFIG_PLUGIN' in config_host
2339  install_headers('include/qemu/qemu-plugin.h')
2340endif
2341
2342if 'CONFIG_GUEST_AGENT' in config_host
2343  subdir('qga')
2344elif get_option('guest_agent_msi').enabled()
2345  error('Guest agent MSI requested, but the guest agent is not being built')
2346endif
2347
2348# Don't build qemu-keymap if xkbcommon is not explicitly enabled
2349# when we don't build tools or system
2350if xkbcommon.found()
2351  # used for the update-keymaps target, so include rules even if !have_tools
2352  qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
2353                           dependencies: [qemuutil, xkbcommon], install: have_tools)
2354endif
2355
2356if have_tools
2357  qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
2358             dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
2359  qemu_io = executable('qemu-io', files('qemu-io.c'),
2360             dependencies: [block, qemuutil], install: true)
2361  qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
2362               dependencies: [blockdev, qemuutil, gnutls], install: true)
2363
2364  subdir('storage-daemon')
2365  subdir('contrib/rdmacm-mux')
2366  subdir('contrib/elf2dmp')
2367
2368  executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
2369             dependencies: qemuutil,
2370             install: true)
2371
2372  if 'CONFIG_VHOST_USER' in config_host
2373    subdir('contrib/vhost-user-blk')
2374    subdir('contrib/vhost-user-gpu')
2375    subdir('contrib/vhost-user-input')
2376    subdir('contrib/vhost-user-scsi')
2377  endif
2378
2379  if targetos == 'linux'
2380    executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
2381               dependencies: [qemuutil, libcap_ng],
2382               install: true,
2383               install_dir: get_option('libexecdir'))
2384
2385    executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
2386               dependencies: [authz, crypto, io, qom, qemuutil,
2387                              libcap_ng, mpathpersist],
2388               install: true)
2389  endif
2390
2391  if 'CONFIG_IVSHMEM' in config_host
2392    subdir('contrib/ivshmem-client')
2393    subdir('contrib/ivshmem-server')
2394  endif
2395endif
2396
2397subdir('scripts')
2398subdir('tools')
2399subdir('pc-bios')
2400subdir('docs')
2401subdir('tests')
2402if gtk.found()
2403  subdir('po')
2404endif
2405
2406if host_machine.system() == 'windows'
2407  nsis_cmd = [
2408    find_program('scripts/nsis.py'),
2409    '@OUTPUT@',
2410    get_option('prefix'),
2411    meson.current_source_dir(),
2412    host_machine.cpu(),
2413    '--',
2414    '-DDISPLAYVERSION=' + meson.project_version(),
2415  ]
2416  if build_docs
2417    nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
2418  endif
2419  if gtk.found()
2420    nsis_cmd += '-DCONFIG_GTK=y'
2421  endif
2422
2423  nsis = custom_target('nsis',
2424                       output: 'qemu-setup-' + meson.project_version() + '.exe',
2425                       input: files('qemu.nsi'),
2426                       build_always_stale: true,
2427                       command: nsis_cmd + ['@INPUT@'])
2428  alias_target('installer', nsis)
2429endif
2430
2431#########################
2432# Configuration summary #
2433#########################
2434
2435# Directories
2436summary_info = {}
2437summary_info += {'Install prefix':    get_option('prefix')}
2438summary_info += {'BIOS directory':    qemu_datadir}
2439summary_info += {'firmware path':     get_option('qemu_firmwarepath')}
2440summary_info += {'binary directory':  get_option('bindir')}
2441summary_info += {'library directory': get_option('libdir')}
2442summary_info += {'module directory':  qemu_moddir}
2443summary_info += {'libexec directory': get_option('libexecdir')}
2444summary_info += {'include directory': get_option('includedir')}
2445summary_info += {'config directory':  get_option('sysconfdir')}
2446if targetos != 'windows'
2447  summary_info += {'local state directory': get_option('localstatedir')}
2448  summary_info += {'Manual directory':      get_option('mandir')}
2449else
2450  summary_info += {'local state directory': 'queried at runtime'}
2451endif
2452summary_info += {'Doc directory':     get_option('docdir')}
2453summary_info += {'Build directory':   meson.current_build_dir()}
2454summary_info += {'Source path':       meson.current_source_dir()}
2455summary_info += {'GIT submodules':    config_host['GIT_SUBMODULES']}
2456summary(summary_info, bool_yn: true, section: 'Directories')
2457
2458# Host binaries
2459summary_info = {}
2460summary_info += {'git':               config_host['GIT']}
2461summary_info += {'make':              config_host['MAKE']}
2462summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
2463summary_info += {'sphinx-build':      sphinx_build.found()}
2464if config_host.has_key('HAVE_GDB_BIN')
2465  summary_info += {'gdb':             config_host['HAVE_GDB_BIN']}
2466endif
2467summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
2468if targetos == 'windows' and config_host.has_key('CONFIG_GUEST_AGENT')
2469  summary_info += {'wixl':            wixl.found() ? wixl.full_path() : false}
2470endif
2471if slirp_opt != 'disabled' and 'CONFIG_SLIRP_SMBD' in config_host
2472  summary_info += {'smbd':            config_host['CONFIG_SMBD_COMMAND']}
2473endif
2474summary(summary_info, bool_yn: true, section: 'Host binaries')
2475
2476# Configurable features
2477summary_info = {}
2478summary_info += {'Documentation':     build_docs}
2479summary_info += {'system-mode emulation': have_system}
2480summary_info += {'user-mode emulation': have_user}
2481summary_info += {'block layer':       have_block}
2482summary_info += {'Install blobs':     get_option('install_blobs')}
2483summary_info += {'module support':    config_host.has_key('CONFIG_MODULES')}
2484if config_host.has_key('CONFIG_MODULES')
2485  summary_info += {'alternative module path': config_host.has_key('CONFIG_MODULE_UPGRADES')}
2486endif
2487summary_info += {'plugin support':    config_host.has_key('CONFIG_PLUGIN')}
2488summary_info += {'fuzzing support':   config_host.has_key('CONFIG_FUZZ')}
2489if have_system
2490  summary_info += {'Audio drivers':     config_host['CONFIG_AUDIO_DRIVERS']}
2491endif
2492summary_info += {'Trace backends':    config_host['TRACE_BACKENDS']}
2493if config_host['TRACE_BACKENDS'].split().contains('simple')
2494  summary_info += {'Trace output file': config_host['CONFIG_TRACE_FILE'] + '-<pid>'}
2495endif
2496summary_info += {'QOM debugging':     config_host.has_key('CONFIG_QOM_CAST_DEBUG')}
2497summary_info += {'vhost-kernel support': config_host.has_key('CONFIG_VHOST_KERNEL')}
2498summary_info += {'vhost-net support': config_host.has_key('CONFIG_VHOST_NET')}
2499summary_info += {'vhost-crypto support': config_host.has_key('CONFIG_VHOST_CRYPTO')}
2500summary_info += {'vhost-scsi support': config_host.has_key('CONFIG_VHOST_SCSI')}
2501summary_info += {'vhost-vsock support': config_host.has_key('CONFIG_VHOST_VSOCK')}
2502summary_info += {'vhost-user support': config_host.has_key('CONFIG_VHOST_USER')}
2503summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
2504summary_info += {'vhost-user-fs support': config_host.has_key('CONFIG_VHOST_USER_FS')}
2505summary_info += {'vhost-vdpa support': config_host.has_key('CONFIG_VHOST_VDPA')}
2506summary_info += {'build guest agent': config_host.has_key('CONFIG_GUEST_AGENT')}
2507summary(summary_info, bool_yn: true, section: 'Configurable features')
2508
2509# Compilation information
2510summary_info = {}
2511summary_info += {'host CPU':          cpu}
2512summary_info += {'host endianness':   build_machine.endian()}
2513summary_info += {'C compiler':        meson.get_compiler('c').cmd_array()[0]}
2514summary_info += {'Host C compiler':   meson.get_compiler('c', native: true).cmd_array()[0]}
2515if link_language == 'cpp'
2516  summary_info += {'C++ compiler':      meson.get_compiler('cpp').cmd_array()[0]}
2517else
2518  summary_info += {'C++ compiler':      false}
2519endif
2520if targetos == 'darwin'
2521  summary_info += {'Objective-C compiler': meson.get_compiler('objc').cmd_array()[0]}
2522endif
2523if targetos == 'windows'
2524  if 'WIN_SDK' in config_host
2525    summary_info += {'Windows SDK':   config_host['WIN_SDK']}
2526  endif
2527endif
2528summary_info += {'ARFLAGS':           config_host['ARFLAGS']}
2529summary_info += {'CFLAGS':            ' '.join(get_option('c_args')
2530                                               + ['-O' + get_option('optimization')]
2531                                               + (get_option('debug') ? ['-g'] : []))}
2532if link_language == 'cpp'
2533  summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args')
2534                                               + ['-O' + get_option('optimization')]
2535                                               + (get_option('debug') ? ['-g'] : []))}
2536endif
2537link_args = get_option(link_language + '_link_args')
2538if link_args.length() > 0
2539  summary_info += {'LDFLAGS':         ' '.join(link_args)}
2540endif
2541summary_info += {'QEMU_CFLAGS':       config_host['QEMU_CFLAGS']}
2542summary_info += {'QEMU_LDFLAGS':      config_host['QEMU_LDFLAGS']}
2543summary_info += {'profiler':          config_host.has_key('CONFIG_PROFILER')}
2544summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
2545summary_info += {'PIE':               get_option('b_pie')}
2546summary_info += {'static build':      config_host.has_key('CONFIG_STATIC')}
2547summary_info += {'malloc trim support': has_malloc_trim}
2548summary_info += {'membarrier':        config_host.has_key('CONFIG_MEMBARRIER')}
2549summary_info += {'preadv support':    config_host_data.get('CONFIG_PREADV')}
2550summary_info += {'fdatasync':         config_host.has_key('CONFIG_FDATASYNC')}
2551summary_info += {'madvise':           config_host.has_key('CONFIG_MADVISE')}
2552summary_info += {'posix_madvise':     config_host.has_key('CONFIG_POSIX_MADVISE')}
2553summary_info += {'posix_memalign':    config_host.has_key('CONFIG_POSIX_MEMALIGN')}
2554summary_info += {'debug stack usage': config_host.has_key('CONFIG_DEBUG_STACK_USAGE')}
2555summary_info += {'mutex debugging':   config_host.has_key('CONFIG_DEBUG_MUTEX')}
2556summary_info += {'memory allocator':  get_option('malloc')}
2557summary_info += {'avx2 optimization': config_host.has_key('CONFIG_AVX2_OPT')}
2558summary_info += {'avx512f optimization': config_host.has_key('CONFIG_AVX512F_OPT')}
2559summary_info += {'gprof enabled':     config_host.has_key('CONFIG_GPROF')}
2560summary_info += {'gcov':              get_option('b_coverage')}
2561summary_info += {'thread sanitizer':  config_host.has_key('CONFIG_TSAN')}
2562summary_info += {'CFI support':       get_option('cfi')}
2563if get_option('cfi')
2564  summary_info += {'CFI debug support': get_option('cfi_debug')}
2565endif
2566summary_info += {'strip binaries':    get_option('strip')}
2567summary_info += {'sparse':            sparse.found() ? sparse.full_path() : false}
2568summary_info += {'mingw32 support':   targetos == 'windows'}
2569
2570# snarf the cross-compilation information for tests
2571foreach target: target_dirs
2572  tcg_mak = meson.current_build_dir() / 'tests/tcg' / 'config-' + target + '.mak'
2573  if fs.exists(tcg_mak)
2574    config_cross_tcg = keyval.load(tcg_mak)
2575    target = config_cross_tcg['TARGET_NAME']
2576    compiler = ''
2577    if 'DOCKER_CROSS_CC_GUEST' in config_cross_tcg
2578      summary_info += {target + ' tests': config_cross_tcg['DOCKER_CROSS_CC_GUEST'] +
2579                                          ' via ' + config_cross_tcg['DOCKER_IMAGE']}
2580    elif 'CROSS_CC_GUEST' in config_cross_tcg
2581      summary_info += {target + ' tests'
2582                                : config_cross_tcg['CROSS_CC_GUEST'] }
2583    endif
2584   endif
2585endforeach
2586
2587summary(summary_info, bool_yn: true, section: 'Compilation')
2588
2589# Targets and accelerators
2590summary_info = {}
2591if have_system
2592  summary_info += {'KVM support':       config_all.has_key('CONFIG_KVM')}
2593  summary_info += {'HAX support':       config_all.has_key('CONFIG_HAX')}
2594  summary_info += {'HVF support':       config_all.has_key('CONFIG_HVF')}
2595  summary_info += {'WHPX support':      config_all.has_key('CONFIG_WHPX')}
2596  summary_info += {'NVMM support':      config_all.has_key('CONFIG_NVMM')}
2597  summary_info += {'Xen support':       config_host.has_key('CONFIG_XEN_BACKEND')}
2598  if config_host.has_key('CONFIG_XEN_BACKEND')
2599    summary_info += {'xen ctrl version':  config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']}
2600  endif
2601endif
2602summary_info += {'TCG support':       config_all.has_key('CONFIG_TCG')}
2603if config_all.has_key('CONFIG_TCG')
2604  if get_option('tcg_interpreter')
2605    summary_info += {'TCG backend':   'TCI (TCG with bytecode interpreter, experimental and slow)'}
2606  else
2607    summary_info += {'TCG backend':   'native (@0@)'.format(cpu)}
2608  endif
2609  summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')}
2610endif
2611summary_info += {'target list':       ' '.join(target_dirs)}
2612if have_system
2613  summary_info += {'default devices':   get_option('default_devices')}
2614  summary_info += {'out of process emulation': multiprocess_allowed}
2615endif
2616summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
2617
2618# Block layer
2619summary_info = {}
2620summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']}
2621summary_info += {'coroutine pool':    config_host['CONFIG_COROUTINE_POOL'] == '1'}
2622if have_block
2623  summary_info += {'Block whitelist (rw)': config_host['CONFIG_BDRV_RW_WHITELIST']}
2624  summary_info += {'Block whitelist (ro)': config_host['CONFIG_BDRV_RO_WHITELIST']}
2625  summary_info += {'VirtFS support':    have_virtfs}
2626  summary_info += {'build virtiofs daemon': have_virtiofsd}
2627  summary_info += {'Live block migration': config_host.has_key('CONFIG_LIVE_BLOCK_MIGRATION')}
2628  summary_info += {'replication support': config_host.has_key('CONFIG_REPLICATION')}
2629  summary_info += {'bochs support':     config_host.has_key('CONFIG_BOCHS')}
2630  summary_info += {'cloop support':     config_host.has_key('CONFIG_CLOOP')}
2631  summary_info += {'dmg support':       config_host.has_key('CONFIG_DMG')}
2632  summary_info += {'qcow v1 support':   config_host.has_key('CONFIG_QCOW1')}
2633  summary_info += {'vdi support':       config_host.has_key('CONFIG_VDI')}
2634  summary_info += {'vvfat support':     config_host.has_key('CONFIG_VVFAT')}
2635  summary_info += {'qed support':       config_host.has_key('CONFIG_QED')}
2636  summary_info += {'parallels support': config_host.has_key('CONFIG_PARALLELS')}
2637  summary_info += {'sheepdog support':  config_host.has_key('CONFIG_SHEEPDOG')}
2638  summary_info += {'FUSE exports':      fuse.found()}
2639endif
2640summary(summary_info, bool_yn: true, section: 'Block layer support')
2641
2642# Crypto
2643summary_info = {}
2644summary_info += {'TLS priority':      config_host['CONFIG_TLS_PRIORITY']}
2645summary_info += {'GNUTLS support':    config_host.has_key('CONFIG_GNUTLS')}
2646# TODO: add back version
2647summary_info += {'libgcrypt':         config_host.has_key('CONFIG_GCRYPT')}
2648if config_host.has_key('CONFIG_GCRYPT')
2649   summary_info += {'  hmac':            config_host.has_key('CONFIG_GCRYPT_HMAC')}
2650   summary_info += {'  XTS':             not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')}
2651endif
2652# TODO: add back version
2653summary_info += {'nettle':            config_host.has_key('CONFIG_NETTLE')}
2654if config_host.has_key('CONFIG_NETTLE')
2655   summary_info += {'  XTS':             not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')}
2656endif
2657summary_info += {'crypto afalg':      config_host.has_key('CONFIG_AF_ALG')}
2658summary_info += {'rng-none':          config_host.has_key('CONFIG_RNG_NONE')}
2659summary_info += {'Linux keyring':     config_host.has_key('CONFIG_SECRET_KEYRING')}
2660summary(summary_info, bool_yn: true, section: 'Crypto')
2661
2662# Libraries
2663summary_info = {}
2664if targetos == 'darwin'
2665  summary_info += {'Cocoa support':   cocoa.found()}
2666endif
2667# TODO: add back version
2668summary_info += {'SDL support':       sdl.found()}
2669summary_info += {'SDL image support': sdl_image.found()}
2670# TODO: add back version
2671summary_info += {'GTK support':       gtk.found()}
2672summary_info += {'pixman':            pixman.found()}
2673# TODO: add back version
2674summary_info += {'VTE support':       config_host.has_key('CONFIG_VTE')}
2675# TODO: add back version
2676summary_info += {'slirp support':     slirp_opt == 'disabled' ? false : slirp_opt}
2677summary_info += {'libtasn1':          config_host.has_key('CONFIG_TASN1')}
2678summary_info += {'PAM':               config_host.has_key('CONFIG_AUTH_PAM')}
2679summary_info += {'iconv support':     iconv.found()}
2680summary_info += {'curses support':    curses.found()}
2681# TODO: add back version
2682summary_info += {'virgl support':     config_host.has_key('CONFIG_VIRGL')}
2683summary_info += {'curl support':      curl.found()}
2684summary_info += {'Multipath support': mpathpersist.found()}
2685summary_info += {'VNC support':       vnc.found()}
2686if vnc.found()
2687  summary_info += {'VNC SASL support':  sasl.found()}
2688  summary_info += {'VNC JPEG support':  jpeg.found()}
2689  summary_info += {'VNC PNG support':   png.found()}
2690endif
2691summary_info += {'brlapi support':    brlapi.found()}
2692summary_info += {'vde support':       config_host.has_key('CONFIG_VDE')}
2693summary_info += {'netmap support':    config_host.has_key('CONFIG_NETMAP')}
2694summary_info += {'Linux AIO support': config_host.has_key('CONFIG_LINUX_AIO')}
2695summary_info += {'Linux io_uring support': config_host.has_key('CONFIG_LINUX_IO_URING')}
2696summary_info += {'ATTR/XATTR support': libattr.found()}
2697summary_info += {'RDMA support':      config_host.has_key('CONFIG_RDMA')}
2698summary_info += {'PVRDMA support':    config_host.has_key('CONFIG_PVRDMA')}
2699summary_info += {'fdt support':       fdt_opt == 'disabled' ? false : fdt_opt}
2700summary_info += {'libcap-ng support': libcap_ng.found()}
2701# TODO: add back protocol and server version
2702summary_info += {'spice support':     config_host.has_key('CONFIG_SPICE')}
2703summary_info += {'rbd support':       rbd.found()}
2704summary_info += {'xfsctl support':    config_host.has_key('CONFIG_XFS')}
2705summary_info += {'smartcard support': config_host.has_key('CONFIG_SMARTCARD')}
2706summary_info += {'U2F support':       u2f.found()}
2707summary_info += {'libusb':            config_host.has_key('CONFIG_USB_LIBUSB')}
2708summary_info += {'usb net redir':     config_host.has_key('CONFIG_USB_REDIR')}
2709summary_info += {'OpenGL support':    config_host.has_key('CONFIG_OPENGL')}
2710summary_info += {'GBM':               config_host.has_key('CONFIG_GBM')}
2711summary_info += {'libiscsi support':  libiscsi.found()}
2712summary_info += {'libnfs support':    libnfs.found()}
2713if targetos == 'windows'
2714  if config_host.has_key('CONFIG_GUEST_AGENT')
2715    summary_info += {'QGA VSS support':   config_host.has_key('CONFIG_QGA_VSS')}
2716    summary_info += {'QGA w32 disk info': config_host.has_key('CONFIG_QGA_NTDDSCSI')}
2717  endif
2718endif
2719summary_info += {'seccomp support':   seccomp.found()}
2720summary_info += {'GlusterFS support': glusterfs.found()}
2721summary_info += {'TPM support':       config_host.has_key('CONFIG_TPM')}
2722summary_info += {'libssh support':    config_host.has_key('CONFIG_LIBSSH')}
2723summary_info += {'lzo support':       lzo.found()}
2724summary_info += {'snappy support':    snappy.found()}
2725summary_info += {'bzip2 support':     libbzip2.found()}
2726summary_info += {'lzfse support':     liblzfse.found()}
2727summary_info += {'zstd support':      zstd.found()}
2728summary_info += {'NUMA host support': config_host.has_key('CONFIG_NUMA')}
2729summary_info += {'libxml2':           config_host.has_key('CONFIG_LIBXML2')}
2730summary_info += {'capstone':          capstone_opt == 'disabled' ? false : capstone_opt}
2731summary_info += {'libpmem support':   config_host.has_key('CONFIG_LIBPMEM')}
2732summary_info += {'libdaxctl support': config_host.has_key('CONFIG_LIBDAXCTL')}
2733summary_info += {'libudev':           libudev.found()}
2734summary_info += {'FUSE lseek':        fuse_lseek.found()}
2735summary(summary_info, bool_yn: true, section: 'Dependencies')
2736
2737if not supported_cpus.contains(cpu)
2738  message()
2739  warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!')
2740  message()
2741  message('CPU host architecture ' + cpu + ' support is not currently maintained.')
2742  message('The QEMU project intends to remove support for this host CPU in')
2743  message('a future release if nobody volunteers to maintain it and to')
2744  message('provide a build host for our continuous integration setup.')
2745  message('configure has succeeded and you can continue to build, but')
2746  message('if you care about QEMU on this platform you should contact')
2747  message('us upstream at qemu-devel@nongnu.org.')
2748endif
2749
2750if not supported_oses.contains(targetos)
2751  message()
2752  warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!')
2753  message()
2754  message('Host OS ' + targetos + 'support is not currently maintained.')
2755  message('The QEMU project intends to remove support for this host OS in')
2756  message('a future release if nobody volunteers to maintain it and to')
2757  message('provide a build host for our continuous integration setup.')
2758  message('configure has succeeded and you can continue to build, but')
2759  message('if you care about QEMU on this platform you should contact')
2760  message('us upstream at qemu-devel@nongnu.org.')
2761endif
2762