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