xref: /openbmc/qemu/meson.build (revision 719f0f60)
1project('qemu', ['c'], meson_version: '>=0.55.0',
2        default_options: ['warning_level=1', 'c_std=gnu99', 'cpp_std=gnu++11', 'b_colorout=auto'] +
3                         (meson.version().version_compare('>=0.56.0') ? [ 'b_staticpic=false' ] : []),
4        version: run_command('head', meson.source_root() / 'VERSION').stdout().strip())
5
6not_found = dependency('', required: false)
7if meson.version().version_compare('>=0.56.0')
8  keyval = import('keyval')
9else
10  keyval = import('unstable-keyval')
11endif
12ss = import('sourceset')
13fs = import('fs')
14
15sh = find_program('sh')
16cc = meson.get_compiler('c')
17config_host = keyval.load(meson.current_build_dir() / 'config-host.mak')
18enable_modules = 'CONFIG_MODULES' in config_host
19enable_static = 'CONFIG_STATIC' in config_host
20
21# Allow both shared and static libraries unless --enable-static
22static_kwargs = enable_static ? {'static': true} : {}
23
24# Temporary directory used for files created while
25# configure runs. Since it is in the build directory
26# we can safely blow away any previous version of it
27# (and we need not jump through hoops to try to delete
28# it when configure exits.)
29tmpdir = meson.current_build_dir() / 'meson-private/temp'
30
31if get_option('qemu_suffix').startswith('/')
32  error('qemu_suffix cannot start with a /')
33endif
34
35qemu_confdir = get_option('sysconfdir') / get_option('qemu_suffix')
36qemu_datadir = get_option('datadir') / get_option('qemu_suffix')
37qemu_docdir = get_option('docdir') / get_option('qemu_suffix')
38qemu_moddir = get_option('libdir') / get_option('qemu_suffix')
39
40qemu_desktopdir = get_option('datadir') / 'applications'
41qemu_icondir = get_option('datadir') / 'icons'
42
43config_host_data = configuration_data()
44genh = []
45
46target_dirs = config_host['TARGET_DIRS'].split()
47have_user = false
48have_system = false
49foreach target : target_dirs
50  have_user = have_user or target.endswith('-user')
51  have_system = have_system or target.endswith('-softmmu')
52endforeach
53have_tools = 'CONFIG_TOOLS' in config_host
54have_block = have_system or have_tools
55
56python = import('python').find_installation()
57
58supported_oses = ['windows', 'freebsd', 'netbsd', 'openbsd', 'darwin', 'sunos', 'linux']
59supported_cpus = ['ppc', 'ppc64', 's390x', 'riscv32', 'riscv64', 'x86', 'x86_64',
60  'arm', 'aarch64', 'mips', 'mips64', 'sparc', 'sparc64']
61
62cpu = host_machine.cpu_family()
63targetos = host_machine.system()
64
65if cpu in ['x86', 'x86_64']
66  kvm_targets = ['i386-softmmu', 'x86_64-softmmu']
67elif cpu == 'aarch64'
68  kvm_targets = ['aarch64-softmmu']
69elif cpu == 's390x'
70  kvm_targets = ['s390x-softmmu']
71elif cpu in ['ppc', 'ppc64']
72  kvm_targets = ['ppc-softmmu', 'ppc64-softmmu']
73elif cpu in ['mips', 'mips64']
74  kvm_targets = ['mips-softmmu', 'mipsel-softmmu', 'mips64-softmmu', 'mips64el-softmmu']
75else
76  kvm_targets = []
77endif
78
79accelerator_targets = { 'CONFIG_KVM': kvm_targets }
80if cpu in ['x86', 'x86_64', 'arm', 'aarch64']
81  # i368 emulator provides xenpv machine type for multiple architectures
82  accelerator_targets += {
83    'CONFIG_XEN': ['i386-softmmu', 'x86_64-softmmu'],
84  }
85endif
86if cpu in ['x86', 'x86_64']
87  accelerator_targets += {
88    'CONFIG_HAX': ['i386-softmmu', 'x86_64-softmmu'],
89    'CONFIG_HVF': ['x86_64-softmmu'],
90    'CONFIG_NVMM': ['i386-softmmu', 'x86_64-softmmu'],
91    'CONFIG_WHPX': ['i386-softmmu', 'x86_64-softmmu'],
92  }
93endif
94
95edk2_targets = [ 'arm-softmmu', 'aarch64-softmmu', 'i386-softmmu', 'x86_64-softmmu' ]
96install_edk2_blobs = false
97if get_option('install_blobs')
98  foreach target : target_dirs
99    install_edk2_blobs = install_edk2_blobs or target in edk2_targets
100  endforeach
101endif
102
103bzip2 = find_program('bzip2', required: install_edk2_blobs)
104
105##################
106# Compiler flags #
107##################
108
109# Specify linker-script with add_project_link_arguments so that it is not placed
110# within a linker --start-group/--end-group pair
111if 'CONFIG_FUZZ' in config_host
112   add_project_link_arguments(['-Wl,-T,',
113                               (meson.current_source_dir() / 'tests/qtest/fuzz/fork_fuzz.ld')],
114                              native: false, language: ['c', 'cpp', 'objc'])
115endif
116
117add_global_arguments(config_host['QEMU_CFLAGS'].split(),
118                     native: false, language: ['c', 'objc'])
119add_global_arguments(config_host['QEMU_CXXFLAGS'].split(),
120                     native: false, language: 'cpp')
121add_global_link_arguments(config_host['QEMU_LDFLAGS'].split(),
122                          native: false, language: ['c', 'cpp', 'objc'])
123
124if targetos == 'linux'
125  add_project_arguments('-isystem', meson.current_source_dir() / 'linux-headers',
126                        '-isystem', 'linux-headers',
127                        language: ['c', 'cpp'])
128endif
129
130add_project_arguments('-iquote', '.',
131                      '-iquote', meson.current_source_dir(),
132                      '-iquote', meson.current_source_dir() / 'include',
133                      '-iquote', meson.current_source_dir() / 'disas/libvixl',
134                      language: ['c', 'cpp', 'objc'])
135
136link_language = meson.get_external_property('link_language', 'cpp')
137if link_language == 'cpp'
138  add_languages('cpp', required: true, native: false)
139endif
140if host_machine.system() == 'darwin'
141  add_languages('objc', required: false, native: false)
142endif
143
144sparse = find_program('cgcc', required: get_option('sparse'))
145if sparse.found()
146  run_target('sparse',
147             command: [find_program('scripts/check_sparse.py'),
148                       'compile_commands.json', sparse.full_path(), '-Wbitwise',
149                       '-Wno-transparent-union', '-Wno-old-initializer',
150                       '-Wno-non-pointer-null'])
151endif
152
153###########################################
154# Target-specific checks and dependencies #
155###########################################
156
157if targetos != 'linux' and get_option('mpath').enabled()
158  error('Multipath is supported only on Linux')
159endif
160
161if targetos != 'linux' and get_option('multiprocess').enabled()
162  error('Multiprocess QEMU is supported only on Linux')
163endif
164multiprocess_allowed = targetos == 'linux' and not get_option('multiprocess').disabled()
165
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)
1971specific_ss.add(when: 'CONFIG_TCG', if_true: files(
1972  'fpu/softfloat.c',
1973  'tcg/optimize.c',
1974  'tcg/tcg-common.c',
1975  'tcg/tcg-op-gvec.c',
1976  'tcg/tcg-op-vec.c',
1977  'tcg/tcg-op.c',
1978  'tcg/tcg.c',
1979))
1980specific_ss.add(when: 'CONFIG_TCG_INTERPRETER', if_true: files('tcg/tci.c'))
1981
1982# Work around a gcc bug/misfeature wherein constant propagation looks
1983# through an alias:
1984#   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99696
1985# to guess that a const variable is always zero.  Without lto, this is
1986# impossible, as the alias is restricted to page-vary-common.c.  Indeed,
1987# without lto, not even the alias is required -- we simply use different
1988# declarations in different compilation units.
1989pagevary = files('page-vary-common.c')
1990if get_option('b_lto')
1991  pagevary_flags = ['-fno-lto']
1992  if get_option('cfi')
1993    pagevary_flags += '-fno-sanitize=cfi-icall'
1994  endif
1995  pagevary = static_library('page-vary-common', sources: pagevary,
1996                            c_args: pagevary_flags)
1997  pagevary = declare_dependency(link_with: pagevary)
1998endif
1999common_ss.add(pagevary)
2000specific_ss.add(files('page-vary.c'))
2001
2002subdir('backends')
2003subdir('disas')
2004subdir('migration')
2005subdir('monitor')
2006subdir('net')
2007subdir('replay')
2008subdir('semihosting')
2009subdir('hw')
2010subdir('accel')
2011subdir('plugins')
2012subdir('bsd-user')
2013subdir('linux-user')
2014subdir('ebpf')
2015
2016common_ss.add(libbpf)
2017
2018bsd_user_ss.add(files('gdbstub.c'))
2019specific_ss.add_all(when: 'CONFIG_BSD_USER', if_true: bsd_user_ss)
2020
2021linux_user_ss.add(files('gdbstub.c', 'thunk.c'))
2022specific_ss.add_all(when: 'CONFIG_LINUX_USER', if_true: linux_user_ss)
2023
2024# needed for fuzzing binaries
2025subdir('tests/qtest/libqos')
2026subdir('tests/qtest/fuzz')
2027
2028########################
2029# Library dependencies #
2030########################
2031
2032block_mods = []
2033softmmu_mods = []
2034foreach d, list : modules
2035  foreach m, module_ss : list
2036    if enable_modules and targetos != 'windows'
2037      module_ss = module_ss.apply(config_all, strict: false)
2038      sl = static_library(d + '-' + m, [genh, module_ss.sources()],
2039                          dependencies: [modulecommon, module_ss.dependencies()], pic: true)
2040      if d == 'block'
2041        block_mods += sl
2042      else
2043        softmmu_mods += sl
2044      endif
2045    else
2046      if d == 'block'
2047        block_ss.add_all(module_ss)
2048      else
2049        softmmu_ss.add_all(module_ss)
2050      endif
2051    endif
2052  endforeach
2053endforeach
2054
2055nm = find_program('nm')
2056undefsym = find_program('scripts/undefsym.py')
2057block_syms = custom_target('block.syms', output: 'block.syms',
2058                             input: [libqemuutil, block_mods],
2059                             capture: true,
2060                             command: [undefsym, nm, '@INPUT@'])
2061qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
2062                             input: [libqemuutil, softmmu_mods],
2063                             capture: true,
2064                             command: [undefsym, nm, '@INPUT@'])
2065
2066qom_ss = qom_ss.apply(config_host, strict: false)
2067libqom = static_library('qom', qom_ss.sources() + genh,
2068                        dependencies: [qom_ss.dependencies()],
2069                        name_suffix: 'fa')
2070
2071qom = declare_dependency(link_whole: libqom)
2072
2073authz_ss = authz_ss.apply(config_host, strict: false)
2074libauthz = static_library('authz', authz_ss.sources() + genh,
2075                          dependencies: [authz_ss.dependencies()],
2076                          name_suffix: 'fa',
2077                          build_by_default: false)
2078
2079authz = declare_dependency(link_whole: libauthz,
2080                           dependencies: qom)
2081
2082crypto_ss = crypto_ss.apply(config_host, strict: false)
2083libcrypto = static_library('crypto', crypto_ss.sources() + genh,
2084                           dependencies: [crypto_ss.dependencies()],
2085                           name_suffix: 'fa',
2086                           build_by_default: false)
2087
2088crypto = declare_dependency(link_whole: libcrypto,
2089                            dependencies: [authz, qom])
2090
2091io_ss = io_ss.apply(config_host, strict: false)
2092libio = static_library('io', io_ss.sources() + genh,
2093                       dependencies: [io_ss.dependencies()],
2094                       link_with: libqemuutil,
2095                       name_suffix: 'fa',
2096                       build_by_default: false)
2097
2098io = declare_dependency(link_whole: libio, dependencies: [crypto, qom])
2099
2100libmigration = static_library('migration', sources: migration_files + genh,
2101                              name_suffix: 'fa',
2102                              build_by_default: false)
2103migration = declare_dependency(link_with: libmigration,
2104                               dependencies: [zlib, qom, io])
2105softmmu_ss.add(migration)
2106
2107block_ss = block_ss.apply(config_host, strict: false)
2108libblock = static_library('block', block_ss.sources() + genh,
2109                          dependencies: block_ss.dependencies(),
2110                          link_depends: block_syms,
2111                          name_suffix: 'fa',
2112                          build_by_default: false)
2113
2114block = declare_dependency(link_whole: [libblock],
2115                           link_args: '@block.syms',
2116                           dependencies: [crypto, io])
2117
2118blockdev_ss = blockdev_ss.apply(config_host, strict: false)
2119libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
2120                             dependencies: blockdev_ss.dependencies(),
2121                             name_suffix: 'fa',
2122                             build_by_default: false)
2123
2124blockdev = declare_dependency(link_whole: [libblockdev],
2125                              dependencies: [block])
2126
2127qmp_ss = qmp_ss.apply(config_host, strict: false)
2128libqmp = static_library('qmp', qmp_ss.sources() + genh,
2129                        dependencies: qmp_ss.dependencies(),
2130                        name_suffix: 'fa',
2131                        build_by_default: false)
2132
2133qmp = declare_dependency(link_whole: [libqmp])
2134
2135libchardev = static_library('chardev', chardev_ss.sources() + genh,
2136                            name_suffix: 'fa',
2137                            dependencies: [gnutls],
2138                            build_by_default: false)
2139
2140chardev = declare_dependency(link_whole: libchardev)
2141
2142libhwcore = static_library('hwcore', sources: hwcore_files + genh,
2143                           name_suffix: 'fa',
2144                           build_by_default: false)
2145hwcore = declare_dependency(link_whole: libhwcore)
2146common_ss.add(hwcore)
2147
2148###########
2149# Targets #
2150###########
2151
2152foreach m : block_mods + softmmu_mods
2153  shared_module(m.name(),
2154                name_prefix: '',
2155                link_whole: m,
2156                install: true,
2157                install_dir: qemu_moddir)
2158endforeach
2159
2160softmmu_ss.add(authz, blockdev, chardev, crypto, io, qmp)
2161common_ss.add(qom, qemuutil)
2162
2163common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss])
2164common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
2165
2166common_all = common_ss.apply(config_all, strict: false)
2167common_all = static_library('common',
2168                            build_by_default: false,
2169                            sources: common_all.sources() + genh,
2170                            implicit_include_directories: false,
2171                            dependencies: common_all.dependencies(),
2172                            name_suffix: 'fa')
2173
2174feature_to_c = find_program('scripts/feature_to_c.sh')
2175
2176emulators = {}
2177foreach target : target_dirs
2178  config_target = config_target_mak[target]
2179  target_name = config_target['TARGET_NAME']
2180  arch = config_target['TARGET_BASE_ARCH']
2181  arch_srcs = [config_target_h[target]]
2182  arch_deps = []
2183  c_args = ['-DNEED_CPU_H',
2184            '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
2185            '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
2186  link_args = emulator_link_args
2187
2188  config_target += config_host
2189  target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
2190  if targetos == 'linux'
2191    target_inc += include_directories('linux-headers', is_system: true)
2192  endif
2193  if target.endswith('-softmmu')
2194    qemu_target_name = 'qemu-system-' + target_name
2195    target_type='system'
2196    t = target_softmmu_arch[arch].apply(config_target, strict: false)
2197    arch_srcs += t.sources()
2198    arch_deps += t.dependencies()
2199
2200    hw_dir = target_name == 'sparc64' ? 'sparc64' : arch
2201    hw = hw_arch[hw_dir].apply(config_target, strict: false)
2202    arch_srcs += hw.sources()
2203    arch_deps += hw.dependencies()
2204
2205    arch_srcs += config_devices_h[target]
2206    link_args += ['@block.syms', '@qemu.syms']
2207  else
2208    abi = config_target['TARGET_ABI_DIR']
2209    target_type='user'
2210    qemu_target_name = 'qemu-' + target_name
2211    if arch in target_user_arch
2212      t = target_user_arch[arch].apply(config_target, strict: false)
2213      arch_srcs += t.sources()
2214      arch_deps += t.dependencies()
2215    endif
2216    if 'CONFIG_LINUX_USER' in config_target
2217      base_dir = 'linux-user'
2218      target_inc += include_directories('linux-user/host/' / config_host['ARCH'])
2219    else
2220      base_dir = 'bsd-user'
2221      target_inc += include_directories('bsd-user/freebsd')
2222    endif
2223    target_inc += include_directories(
2224      base_dir,
2225      base_dir / abi,
2226    )
2227    if 'CONFIG_LINUX_USER' in config_target
2228      dir = base_dir / abi
2229      arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
2230      if config_target.has_key('TARGET_SYSTBL_ABI')
2231        arch_srcs += \
2232          syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
2233                                             extra_args : config_target['TARGET_SYSTBL_ABI'])
2234      endif
2235    endif
2236  endif
2237
2238  if 'TARGET_XML_FILES' in config_target
2239    gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
2240                                output: target + '-gdbstub-xml.c',
2241                                input: files(config_target['TARGET_XML_FILES'].split()),
2242                                command: [feature_to_c, '@INPUT@'],
2243                                capture: true)
2244    arch_srcs += gdbstub_xml
2245  endif
2246
2247  t = target_arch[arch].apply(config_target, strict: false)
2248  arch_srcs += t.sources()
2249  arch_deps += t.dependencies()
2250
2251  target_common = common_ss.apply(config_target, strict: false)
2252  objects = common_all.extract_objects(target_common.sources())
2253  deps = target_common.dependencies()
2254
2255  target_specific = specific_ss.apply(config_target, strict: false)
2256  arch_srcs += target_specific.sources()
2257  arch_deps += target_specific.dependencies()
2258
2259  lib = static_library('qemu-' + target,
2260                 sources: arch_srcs + genh,
2261                 dependencies: arch_deps,
2262                 objects: objects,
2263                 include_directories: target_inc,
2264                 c_args: c_args,
2265                 build_by_default: false,
2266                 name_suffix: 'fa')
2267
2268  if target.endswith('-softmmu')
2269    execs = [{
2270      'name': 'qemu-system-' + target_name,
2271      'gui': false,
2272      'sources': files('softmmu/main.c'),
2273      'dependencies': []
2274    }]
2275    if targetos == 'windows' and (sdl.found() or gtk.found())
2276      execs += [{
2277        'name': 'qemu-system-' + target_name + 'w',
2278        'gui': true,
2279        'sources': files('softmmu/main.c'),
2280        'dependencies': []
2281      }]
2282    endif
2283    if config_host.has_key('CONFIG_FUZZ')
2284      specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
2285      execs += [{
2286        'name': 'qemu-fuzz-' + target_name,
2287        'gui': false,
2288        'sources': specific_fuzz.sources(),
2289        'dependencies': specific_fuzz.dependencies(),
2290      }]
2291    endif
2292  else
2293    execs = [{
2294      'name': 'qemu-' + target_name,
2295      'gui': false,
2296      'sources': [],
2297      'dependencies': []
2298    }]
2299  endif
2300  foreach exe: execs
2301    exe_name = exe['name']
2302    exe_sign = 'CONFIG_HVF' in config_target
2303    if exe_sign
2304      exe_name += '-unsigned'
2305    endif
2306
2307    emulator = executable(exe_name, exe['sources'],
2308               install: true,
2309               c_args: c_args,
2310               dependencies: arch_deps + deps + exe['dependencies'],
2311               objects: lib.extract_all_objects(recursive: true),
2312               link_language: link_language,
2313               link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
2314               link_args: link_args,
2315               gui_app: exe['gui'])
2316
2317    if exe_sign
2318      emulators += {exe['name'] : custom_target(exe['name'],
2319                   depends: emulator,
2320                   output: exe['name'],
2321                   command: [
2322                     meson.current_source_dir() / 'scripts/entitlement.sh',
2323                     meson.current_build_dir() / exe_name,
2324                     meson.current_build_dir() / exe['name'],
2325                     meson.current_source_dir() / 'accel/hvf/entitlements.plist'
2326                   ])
2327      }
2328
2329      meson.add_install_script('scripts/entitlement.sh', '--install',
2330                               get_option('bindir') / exe_name,
2331                               get_option('bindir') / exe['name'],
2332                               meson.current_source_dir() / 'accel/hvf/entitlements.plist')
2333    else
2334      emulators += {exe['name']: emulator}
2335    endif
2336
2337    if 'CONFIG_TRACE_SYSTEMTAP' in config_host
2338      foreach stp: [
2339        {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
2340        {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
2341        {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
2342        {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
2343      ]
2344        custom_target(exe['name'] + stp['ext'],
2345                      input: trace_events_all,
2346                      output: exe['name'] + stp['ext'],
2347                      install: stp['install'],
2348                      install_dir: get_option('datadir') / 'systemtap/tapset',
2349                      command: [
2350                        tracetool, '--group=all', '--format=' + stp['fmt'],
2351                        '--binary=' + stp['bin'],
2352                        '--target-name=' + target_name,
2353                        '--target-type=' + target_type,
2354                        '--probe-prefix=qemu.' + target_type + '.' + target_name,
2355                        '@INPUT@', '@OUTPUT@'
2356                      ],
2357                      depend_files: tracetool_depends)
2358      endforeach
2359    endif
2360  endforeach
2361endforeach
2362
2363# Other build targets
2364
2365if 'CONFIG_PLUGIN' in config_host
2366  install_headers('include/qemu/qemu-plugin.h')
2367endif
2368
2369if 'CONFIG_GUEST_AGENT' in config_host
2370  subdir('qga')
2371elif get_option('guest_agent_msi').enabled()
2372  error('Guest agent MSI requested, but the guest agent is not being built')
2373endif
2374
2375# Don't build qemu-keymap if xkbcommon is not explicitly enabled
2376# when we don't build tools or system
2377if xkbcommon.found()
2378  # used for the update-keymaps target, so include rules even if !have_tools
2379  qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
2380                           dependencies: [qemuutil, xkbcommon], install: have_tools)
2381endif
2382
2383if have_tools
2384  qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
2385             dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
2386  qemu_io = executable('qemu-io', files('qemu-io.c'),
2387             dependencies: [block, qemuutil], install: true)
2388  qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
2389               dependencies: [blockdev, qemuutil, gnutls], install: true)
2390
2391  subdir('storage-daemon')
2392  subdir('contrib/rdmacm-mux')
2393  subdir('contrib/elf2dmp')
2394
2395  executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
2396             dependencies: qemuutil,
2397             install: true)
2398
2399  if 'CONFIG_VHOST_USER' in config_host
2400    subdir('contrib/vhost-user-blk')
2401    subdir('contrib/vhost-user-gpu')
2402    subdir('contrib/vhost-user-input')
2403    subdir('contrib/vhost-user-scsi')
2404  endif
2405
2406  if targetos == 'linux'
2407    executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
2408               dependencies: [qemuutil, libcap_ng],
2409               install: true,
2410               install_dir: get_option('libexecdir'))
2411
2412    executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
2413               dependencies: [authz, crypto, io, qom, qemuutil,
2414                              libcap_ng, mpathpersist],
2415               install: true)
2416  endif
2417
2418  if 'CONFIG_IVSHMEM' in config_host
2419    subdir('contrib/ivshmem-client')
2420    subdir('contrib/ivshmem-server')
2421  endif
2422endif
2423
2424subdir('scripts')
2425subdir('tools')
2426subdir('pc-bios')
2427subdir('docs')
2428subdir('tests')
2429if gtk.found()
2430  subdir('po')
2431endif
2432
2433if host_machine.system() == 'windows'
2434  nsis_cmd = [
2435    find_program('scripts/nsis.py'),
2436    '@OUTPUT@',
2437    get_option('prefix'),
2438    meson.current_source_dir(),
2439    host_machine.cpu(),
2440    '--',
2441    '-DDISPLAYVERSION=' + meson.project_version(),
2442  ]
2443  if build_docs
2444    nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
2445  endif
2446  if gtk.found()
2447    nsis_cmd += '-DCONFIG_GTK=y'
2448  endif
2449
2450  nsis = custom_target('nsis',
2451                       output: 'qemu-setup-' + meson.project_version() + '.exe',
2452                       input: files('qemu.nsi'),
2453                       build_always_stale: true,
2454                       command: nsis_cmd + ['@INPUT@'])
2455  alias_target('installer', nsis)
2456endif
2457
2458#########################
2459# Configuration summary #
2460#########################
2461
2462# Directories
2463summary_info = {}
2464summary_info += {'Install prefix':    get_option('prefix')}
2465summary_info += {'BIOS directory':    qemu_datadir}
2466summary_info += {'firmware path':     get_option('qemu_firmwarepath')}
2467summary_info += {'binary directory':  get_option('bindir')}
2468summary_info += {'library directory': get_option('libdir')}
2469summary_info += {'module directory':  qemu_moddir}
2470summary_info += {'libexec directory': get_option('libexecdir')}
2471summary_info += {'include directory': get_option('includedir')}
2472summary_info += {'config directory':  get_option('sysconfdir')}
2473if targetos != 'windows'
2474  summary_info += {'local state directory': get_option('localstatedir')}
2475  summary_info += {'Manual directory':      get_option('mandir')}
2476else
2477  summary_info += {'local state directory': 'queried at runtime'}
2478endif
2479summary_info += {'Doc directory':     get_option('docdir')}
2480summary_info += {'Build directory':   meson.current_build_dir()}
2481summary_info += {'Source path':       meson.current_source_dir()}
2482summary_info += {'GIT submodules':    config_host['GIT_SUBMODULES']}
2483summary(summary_info, bool_yn: true, section: 'Directories')
2484
2485# Host binaries
2486summary_info = {}
2487summary_info += {'git':               config_host['GIT']}
2488summary_info += {'make':              config_host['MAKE']}
2489summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
2490summary_info += {'sphinx-build':      sphinx_build.found()}
2491if config_host.has_key('HAVE_GDB_BIN')
2492  summary_info += {'gdb':             config_host['HAVE_GDB_BIN']}
2493endif
2494summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
2495if targetos == 'windows' and config_host.has_key('CONFIG_GUEST_AGENT')
2496  summary_info += {'wixl':            wixl.found() ? wixl.full_path() : false}
2497endif
2498if slirp_opt != 'disabled' and 'CONFIG_SLIRP_SMBD' in config_host
2499  summary_info += {'smbd':            config_host['CONFIG_SMBD_COMMAND']}
2500endif
2501summary(summary_info, bool_yn: true, section: 'Host binaries')
2502
2503# Configurable features
2504summary_info = {}
2505summary_info += {'Documentation':     build_docs}
2506summary_info += {'system-mode emulation': have_system}
2507summary_info += {'user-mode emulation': have_user}
2508summary_info += {'block layer':       have_block}
2509summary_info += {'Install blobs':     get_option('install_blobs')}
2510summary_info += {'module support':    config_host.has_key('CONFIG_MODULES')}
2511if config_host.has_key('CONFIG_MODULES')
2512  summary_info += {'alternative module path': config_host.has_key('CONFIG_MODULE_UPGRADES')}
2513endif
2514summary_info += {'plugin support':    config_host.has_key('CONFIG_PLUGIN')}
2515summary_info += {'fuzzing support':   config_host.has_key('CONFIG_FUZZ')}
2516if have_system
2517  summary_info += {'Audio drivers':     config_host['CONFIG_AUDIO_DRIVERS']}
2518endif
2519summary_info += {'Trace backends':    config_host['TRACE_BACKENDS']}
2520if config_host['TRACE_BACKENDS'].split().contains('simple')
2521  summary_info += {'Trace output file': config_host['CONFIG_TRACE_FILE'] + '-<pid>'}
2522endif
2523summary_info += {'QOM debugging':     config_host.has_key('CONFIG_QOM_CAST_DEBUG')}
2524summary_info += {'vhost-kernel support': config_host.has_key('CONFIG_VHOST_KERNEL')}
2525summary_info += {'vhost-net support': config_host.has_key('CONFIG_VHOST_NET')}
2526summary_info += {'vhost-crypto support': config_host.has_key('CONFIG_VHOST_CRYPTO')}
2527summary_info += {'vhost-scsi support': config_host.has_key('CONFIG_VHOST_SCSI')}
2528summary_info += {'vhost-vsock support': config_host.has_key('CONFIG_VHOST_VSOCK')}
2529summary_info += {'vhost-user support': config_host.has_key('CONFIG_VHOST_USER')}
2530summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
2531summary_info += {'vhost-user-fs support': config_host.has_key('CONFIG_VHOST_USER_FS')}
2532summary_info += {'vhost-vdpa support': config_host.has_key('CONFIG_VHOST_VDPA')}
2533summary_info += {'build guest agent': config_host.has_key('CONFIG_GUEST_AGENT')}
2534summary(summary_info, bool_yn: true, section: 'Configurable features')
2535
2536# Compilation information
2537summary_info = {}
2538summary_info += {'host CPU':          cpu}
2539summary_info += {'host endianness':   build_machine.endian()}
2540summary_info += {'C compiler':        ' '.join(meson.get_compiler('c').cmd_array())}
2541summary_info += {'Host C compiler':   ' '.join(meson.get_compiler('c', native: true).cmd_array())}
2542if link_language == 'cpp'
2543  summary_info += {'C++ compiler':    ' '.join(meson.get_compiler('cpp').cmd_array())}
2544else
2545  summary_info += {'C++ compiler':      false}
2546endif
2547if targetos == 'darwin'
2548  summary_info += {'Objective-C compiler': ' '.join(meson.get_compiler('objc').cmd_array())}
2549endif
2550if targetos == 'windows'
2551  if 'WIN_SDK' in config_host
2552    summary_info += {'Windows SDK':   config_host['WIN_SDK']}
2553  endif
2554endif
2555summary_info += {'ARFLAGS':           config_host['ARFLAGS']}
2556summary_info += {'CFLAGS':            ' '.join(get_option('c_args')
2557                                               + ['-O' + get_option('optimization')]
2558                                               + (get_option('debug') ? ['-g'] : []))}
2559if link_language == 'cpp'
2560  summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args')
2561                                               + ['-O' + get_option('optimization')]
2562                                               + (get_option('debug') ? ['-g'] : []))}
2563endif
2564link_args = get_option(link_language + '_link_args')
2565if link_args.length() > 0
2566  summary_info += {'LDFLAGS':         ' '.join(link_args)}
2567endif
2568summary_info += {'QEMU_CFLAGS':       config_host['QEMU_CFLAGS']}
2569summary_info += {'QEMU_LDFLAGS':      config_host['QEMU_LDFLAGS']}
2570summary_info += {'profiler':          config_host.has_key('CONFIG_PROFILER')}
2571summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
2572summary_info += {'PIE':               get_option('b_pie')}
2573summary_info += {'static build':      config_host.has_key('CONFIG_STATIC')}
2574summary_info += {'malloc trim support': has_malloc_trim}
2575summary_info += {'membarrier':        config_host.has_key('CONFIG_MEMBARRIER')}
2576summary_info += {'preadv support':    config_host_data.get('CONFIG_PREADV')}
2577summary_info += {'fdatasync':         config_host.has_key('CONFIG_FDATASYNC')}
2578summary_info += {'madvise':           config_host.has_key('CONFIG_MADVISE')}
2579summary_info += {'posix_madvise':     config_host.has_key('CONFIG_POSIX_MADVISE')}
2580summary_info += {'posix_memalign':    config_host.has_key('CONFIG_POSIX_MEMALIGN')}
2581summary_info += {'debug stack usage': config_host.has_key('CONFIG_DEBUG_STACK_USAGE')}
2582summary_info += {'mutex debugging':   config_host.has_key('CONFIG_DEBUG_MUTEX')}
2583summary_info += {'memory allocator':  get_option('malloc')}
2584summary_info += {'avx2 optimization': config_host.has_key('CONFIG_AVX2_OPT')}
2585summary_info += {'avx512f optimization': config_host.has_key('CONFIG_AVX512F_OPT')}
2586summary_info += {'gprof enabled':     config_host.has_key('CONFIG_GPROF')}
2587summary_info += {'gcov':              get_option('b_coverage')}
2588summary_info += {'thread sanitizer':  config_host.has_key('CONFIG_TSAN')}
2589summary_info += {'CFI support':       get_option('cfi')}
2590if get_option('cfi')
2591  summary_info += {'CFI debug support': get_option('cfi_debug')}
2592endif
2593summary_info += {'strip binaries':    get_option('strip')}
2594summary_info += {'sparse':            sparse.found() ? sparse.full_path() : false}
2595summary_info += {'mingw32 support':   targetos == 'windows'}
2596
2597# snarf the cross-compilation information for tests
2598foreach target: target_dirs
2599  tcg_mak = meson.current_build_dir() / 'tests/tcg' / 'config-' + target + '.mak'
2600  if fs.exists(tcg_mak)
2601    config_cross_tcg = keyval.load(tcg_mak)
2602    target = config_cross_tcg['TARGET_NAME']
2603    compiler = ''
2604    if 'DOCKER_CROSS_CC_GUEST' in config_cross_tcg
2605      summary_info += {target + ' tests': config_cross_tcg['DOCKER_CROSS_CC_GUEST'] +
2606                                          ' via ' + config_cross_tcg['DOCKER_IMAGE']}
2607    elif 'CROSS_CC_GUEST' in config_cross_tcg
2608      summary_info += {target + ' tests'
2609                                : config_cross_tcg['CROSS_CC_GUEST'] }
2610    endif
2611   endif
2612endforeach
2613
2614summary(summary_info, bool_yn: true, section: 'Compilation')
2615
2616# Targets and accelerators
2617summary_info = {}
2618if have_system
2619  summary_info += {'KVM support':       config_all.has_key('CONFIG_KVM')}
2620  summary_info += {'HAX support':       config_all.has_key('CONFIG_HAX')}
2621  summary_info += {'HVF support':       config_all.has_key('CONFIG_HVF')}
2622  summary_info += {'WHPX support':      config_all.has_key('CONFIG_WHPX')}
2623  summary_info += {'NVMM support':      config_all.has_key('CONFIG_NVMM')}
2624  summary_info += {'Xen support':       config_host.has_key('CONFIG_XEN_BACKEND')}
2625  if config_host.has_key('CONFIG_XEN_BACKEND')
2626    summary_info += {'xen ctrl version':  config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']}
2627  endif
2628endif
2629summary_info += {'TCG support':       config_all.has_key('CONFIG_TCG')}
2630if config_all.has_key('CONFIG_TCG')
2631  if get_option('tcg_interpreter')
2632    summary_info += {'TCG backend':   'TCI (TCG with bytecode interpreter, experimental and slow)'}
2633  else
2634    summary_info += {'TCG backend':   'native (@0@)'.format(cpu)}
2635  endif
2636  summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')}
2637endif
2638summary_info += {'target list':       ' '.join(target_dirs)}
2639if have_system
2640  summary_info += {'default devices':   get_option('default_devices')}
2641  summary_info += {'out of process emulation': multiprocess_allowed}
2642endif
2643summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
2644
2645# Block layer
2646summary_info = {}
2647summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']}
2648summary_info += {'coroutine pool':    config_host['CONFIG_COROUTINE_POOL'] == '1'}
2649if have_block
2650  summary_info += {'Block whitelist (rw)': config_host['CONFIG_BDRV_RW_WHITELIST']}
2651  summary_info += {'Block whitelist (ro)': config_host['CONFIG_BDRV_RO_WHITELIST']}
2652  summary_info += {'VirtFS support':    have_virtfs}
2653  summary_info += {'build virtiofs daemon': have_virtiofsd}
2654  summary_info += {'Live block migration': config_host.has_key('CONFIG_LIVE_BLOCK_MIGRATION')}
2655  summary_info += {'replication support': config_host.has_key('CONFIG_REPLICATION')}
2656  summary_info += {'bochs support':     config_host.has_key('CONFIG_BOCHS')}
2657  summary_info += {'cloop support':     config_host.has_key('CONFIG_CLOOP')}
2658  summary_info += {'dmg support':       config_host.has_key('CONFIG_DMG')}
2659  summary_info += {'qcow v1 support':   config_host.has_key('CONFIG_QCOW1')}
2660  summary_info += {'vdi support':       config_host.has_key('CONFIG_VDI')}
2661  summary_info += {'vvfat support':     config_host.has_key('CONFIG_VVFAT')}
2662  summary_info += {'qed support':       config_host.has_key('CONFIG_QED')}
2663  summary_info += {'parallels support': config_host.has_key('CONFIG_PARALLELS')}
2664  summary_info += {'FUSE exports':      fuse.found()}
2665endif
2666summary(summary_info, bool_yn: true, section: 'Block layer support')
2667
2668# Crypto
2669summary_info = {}
2670summary_info += {'TLS priority':      config_host['CONFIG_TLS_PRIORITY']}
2671summary_info += {'GNUTLS support':    config_host.has_key('CONFIG_GNUTLS')}
2672# TODO: add back version
2673summary_info += {'libgcrypt':         config_host.has_key('CONFIG_GCRYPT')}
2674if config_host.has_key('CONFIG_GCRYPT')
2675   summary_info += {'  hmac':            config_host.has_key('CONFIG_GCRYPT_HMAC')}
2676   summary_info += {'  XTS':             not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')}
2677endif
2678# TODO: add back version
2679summary_info += {'nettle':            config_host.has_key('CONFIG_NETTLE')}
2680if config_host.has_key('CONFIG_NETTLE')
2681   summary_info += {'  XTS':             not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')}
2682endif
2683summary_info += {'crypto afalg':      config_host.has_key('CONFIG_AF_ALG')}
2684summary_info += {'rng-none':          config_host.has_key('CONFIG_RNG_NONE')}
2685summary_info += {'Linux keyring':     config_host.has_key('CONFIG_SECRET_KEYRING')}
2686summary(summary_info, bool_yn: true, section: 'Crypto')
2687
2688# Libraries
2689summary_info = {}
2690if targetos == 'darwin'
2691  summary_info += {'Cocoa support':   cocoa.found()}
2692endif
2693# TODO: add back version
2694summary_info += {'SDL support':       sdl.found()}
2695summary_info += {'SDL image support': sdl_image.found()}
2696# TODO: add back version
2697summary_info += {'GTK support':       gtk.found()}
2698summary_info += {'pixman':            pixman.found()}
2699# TODO: add back version
2700summary_info += {'VTE support':       config_host.has_key('CONFIG_VTE')}
2701# TODO: add back version
2702summary_info += {'slirp support':     slirp_opt == 'disabled' ? false : slirp_opt}
2703summary_info += {'libtasn1':          config_host.has_key('CONFIG_TASN1')}
2704summary_info += {'PAM':               config_host.has_key('CONFIG_AUTH_PAM')}
2705summary_info += {'iconv support':     iconv.found()}
2706summary_info += {'curses support':    curses.found()}
2707# TODO: add back version
2708summary_info += {'virgl support':     config_host.has_key('CONFIG_VIRGL')}
2709summary_info += {'curl support':      curl.found()}
2710summary_info += {'Multipath support': mpathpersist.found()}
2711summary_info += {'VNC support':       vnc.found()}
2712if vnc.found()
2713  summary_info += {'VNC SASL support':  sasl.found()}
2714  summary_info += {'VNC JPEG support':  jpeg.found()}
2715  summary_info += {'VNC PNG support':   png.found()}
2716endif
2717summary_info += {'brlapi support':    brlapi.found()}
2718summary_info += {'vde support':       config_host.has_key('CONFIG_VDE')}
2719summary_info += {'netmap support':    config_host.has_key('CONFIG_NETMAP')}
2720summary_info += {'Linux AIO support': config_host.has_key('CONFIG_LINUX_AIO')}
2721summary_info += {'Linux io_uring support': config_host.has_key('CONFIG_LINUX_IO_URING')}
2722summary_info += {'ATTR/XATTR support': libattr.found()}
2723summary_info += {'RDMA support':      config_host.has_key('CONFIG_RDMA')}
2724summary_info += {'PVRDMA support':    config_host.has_key('CONFIG_PVRDMA')}
2725summary_info += {'fdt support':       fdt_opt == 'disabled' ? false : fdt_opt}
2726summary_info += {'libcap-ng support': libcap_ng.found()}
2727summary_info += {'bpf support': libbpf.found()}
2728# TODO: add back protocol and server version
2729summary_info += {'spice support':     config_host.has_key('CONFIG_SPICE')}
2730summary_info += {'rbd support':       rbd.found()}
2731summary_info += {'xfsctl support':    config_host.has_key('CONFIG_XFS')}
2732summary_info += {'smartcard support': config_host.has_key('CONFIG_SMARTCARD')}
2733summary_info += {'U2F support':       u2f.found()}
2734summary_info += {'libusb':            config_host.has_key('CONFIG_USB_LIBUSB')}
2735summary_info += {'usb net redir':     config_host.has_key('CONFIG_USB_REDIR')}
2736summary_info += {'OpenGL support':    config_host.has_key('CONFIG_OPENGL')}
2737summary_info += {'GBM':               config_host.has_key('CONFIG_GBM')}
2738summary_info += {'libiscsi support':  libiscsi.found()}
2739summary_info += {'libnfs support':    libnfs.found()}
2740if targetos == 'windows'
2741  if config_host.has_key('CONFIG_GUEST_AGENT')
2742    summary_info += {'QGA VSS support':   config_host.has_key('CONFIG_QGA_VSS')}
2743    summary_info += {'QGA w32 disk info': config_host.has_key('CONFIG_QGA_NTDDSCSI')}
2744  endif
2745endif
2746summary_info += {'seccomp support':   seccomp.found()}
2747summary_info += {'GlusterFS support': glusterfs.found()}
2748summary_info += {'TPM support':       config_host.has_key('CONFIG_TPM')}
2749summary_info += {'libssh support':    config_host.has_key('CONFIG_LIBSSH')}
2750summary_info += {'lzo support':       lzo.found()}
2751summary_info += {'snappy support':    snappy.found()}
2752summary_info += {'bzip2 support':     libbzip2.found()}
2753summary_info += {'lzfse support':     liblzfse.found()}
2754summary_info += {'zstd support':      zstd.found()}
2755summary_info += {'NUMA host support': config_host.has_key('CONFIG_NUMA')}
2756summary_info += {'libxml2':           config_host.has_key('CONFIG_LIBXML2')}
2757summary_info += {'capstone':          capstone_opt == 'disabled' ? false : capstone_opt}
2758summary_info += {'libpmem support':   config_host.has_key('CONFIG_LIBPMEM')}
2759summary_info += {'libdaxctl support': config_host.has_key('CONFIG_LIBDAXCTL')}
2760summary_info += {'libudev':           libudev.found()}
2761summary_info += {'FUSE lseek':        fuse_lseek.found()}
2762summary(summary_info, bool_yn: true, section: 'Dependencies')
2763
2764if not supported_cpus.contains(cpu)
2765  message()
2766  warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!')
2767  message()
2768  message('CPU host architecture ' + cpu + ' support is not currently maintained.')
2769  message('The QEMU project intends to remove support for this host CPU in')
2770  message('a future release if nobody volunteers to maintain it and to')
2771  message('provide a build host for our continuous integration setup.')
2772  message('configure has succeeded and you can continue to build, but')
2773  message('if you care about QEMU on this platform you should contact')
2774  message('us upstream at qemu-devel@nongnu.org.')
2775endif
2776
2777if not supported_oses.contains(targetos)
2778  message()
2779  warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!')
2780  message()
2781  message('Host OS ' + targetos + 'support is not currently maintained.')
2782  message('The QEMU project intends to remove support for this host OS in')
2783  message('a future release if nobody volunteers to maintain it and to')
2784  message('provide a build host for our continuous integration setup.')
2785  message('configure has succeeded and you can continue to build, but')
2786  message('if you care about QEMU on this platform you should contact')
2787  message('us upstream at qemu-devel@nongnu.org.')
2788endif
2789