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