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