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