xref: /openbmc/qemu/meson.build (revision b9188f9c)
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' ]
109unpack_edk2_blobs = false
110foreach target : edk2_targets
111  if target in target_dirs
112    bzip2 = find_program('bzip2', required: get_option('install_blobs'))
113    unpack_edk2_blobs = bzip2.found()
114    break
115  endif
116endforeach
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'))
1377config_host_data.set('HAVE_IPPROTO_MPTCP',
1378                     cc.has_header_symbol('netinet/in.h', 'IPPROTO_MPTCP'))
1379
1380# has_member
1381config_host_data.set('HAVE_SIGEV_NOTIFY_THREAD_ID',
1382                     cc.has_member('struct sigevent', 'sigev_notify_thread_id',
1383                                   prefix: '#include <signal.h>'))
1384config_host_data.set('HAVE_STRUCT_STAT_ST_ATIM',
1385                     cc.has_member('struct stat', 'st_atim',
1386                                   prefix: '#include <sys/stat.h>'))
1387
1388config_host_data.set('CONFIG_EVENTFD', cc.links('''
1389  #include <sys/eventfd.h>
1390  int main(void) { return eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); }'''))
1391config_host_data.set('CONFIG_FDATASYNC', cc.links(gnu_source_prefix + '''
1392  #include <unistd.h>
1393  int main(void) {
1394  #if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
1395  return fdatasync(0);
1396  #else
1397  #error Not supported
1398  #endif
1399  }'''))
1400config_host_data.set('CONFIG_MADVISE', cc.links(gnu_source_prefix + '''
1401  #include <sys/types.h>
1402  #include <sys/mman.h>
1403  #include <stddef.h>
1404  int main(void) { return madvise(NULL, 0, MADV_DONTNEED); }'''))
1405config_host_data.set('CONFIG_MEMFD', cc.links(gnu_source_prefix + '''
1406  #include <sys/mman.h>
1407  int main(void) { return memfd_create("foo", MFD_ALLOW_SEALING); }'''))
1408config_host_data.set('CONFIG_OPEN_BY_HANDLE', cc.links(gnu_source_prefix + '''
1409  #include <fcntl.h>
1410  #if !defined(AT_EMPTY_PATH)
1411  # error missing definition
1412  #else
1413  int main(void) { struct file_handle fh; return open_by_handle_at(0, &fh, 0); }
1414  #endif'''))
1415config_host_data.set('CONFIG_PIPE2', cc.links(gnu_source_prefix + '''
1416  #include <unistd.h>
1417  #include <fcntl.h>
1418
1419  int main(void)
1420  {
1421      int pipefd[2];
1422      return pipe2(pipefd, O_CLOEXEC);
1423  }'''))
1424config_host_data.set('CONFIG_POSIX_MADVISE', cc.links(gnu_source_prefix + '''
1425  #include <sys/mman.h>
1426  #include <stddef.h>
1427  int main(void) { return posix_madvise(NULL, 0, POSIX_MADV_DONTNEED); }'''))
1428config_host_data.set('CONFIG_SIGNALFD', cc.links(gnu_source_prefix + '''
1429  #include <unistd.h>
1430  #include <sys/syscall.h>
1431  #include <signal.h>
1432  int main(void) { return syscall(SYS_signalfd, -1, NULL, _NSIG / 8); }'''))
1433config_host_data.set('CONFIG_SPLICE', cc.links(gnu_source_prefix + '''
1434  #include <unistd.h>
1435  #include <fcntl.h>
1436  #include <limits.h>
1437
1438  int main(void)
1439  {
1440    int len, fd = 0;
1441    len = tee(STDIN_FILENO, STDOUT_FILENO, INT_MAX, SPLICE_F_NONBLOCK);
1442    splice(STDIN_FILENO, NULL, fd, NULL, len, SPLICE_F_MOVE);
1443    return 0;
1444  }'''))
1445
1446# Some versions of Mac OS X incorrectly define SIZE_MAX
1447config_host_data.set('HAVE_BROKEN_SIZE_MAX', not cc.compiles('''
1448    #include <stdint.h>
1449    #include <stdio.h>
1450    int main(int argc, char *argv[]) {
1451        return printf("%zu", SIZE_MAX);
1452    }''', args: ['-Werror']))
1453
1454
1455ignored = ['CONFIG_QEMU_INTERP_PREFIX'] # actually per-target
1456arrays = ['CONFIG_AUDIO_DRIVERS', 'CONFIG_BDRV_RW_WHITELIST', 'CONFIG_BDRV_RO_WHITELIST']
1457strings = ['HOST_DSOSUF', 'CONFIG_IASL']
1458foreach k, v: config_host
1459  if ignored.contains(k)
1460    # do nothing
1461  elif arrays.contains(k)
1462    if v != ''
1463      v = '"' + '", "'.join(v.split()) + '", '
1464    endif
1465    config_host_data.set(k, v)
1466  elif k == 'ARCH'
1467    config_host_data.set('HOST_' + v.to_upper(), 1)
1468  elif strings.contains(k)
1469    if not k.startswith('CONFIG_')
1470      k = 'CONFIG_' + k.to_upper()
1471    endif
1472    config_host_data.set_quoted(k, v)
1473  elif k.startswith('CONFIG_') or k.startswith('HAVE_') or k.startswith('HOST_')
1474    config_host_data.set(k, v == 'y' ? 1 : v)
1475  endif
1476endforeach
1477
1478########################
1479# Target configuration #
1480########################
1481
1482minikconf = find_program('scripts/minikconf.py')
1483config_all = {}
1484config_all_devices = {}
1485config_all_disas = {}
1486config_devices_mak_list = []
1487config_devices_h = {}
1488config_target_h = {}
1489config_target_mak = {}
1490
1491disassemblers = {
1492  'alpha' : ['CONFIG_ALPHA_DIS'],
1493  'arm' : ['CONFIG_ARM_DIS'],
1494  'avr' : ['CONFIG_AVR_DIS'],
1495  'cris' : ['CONFIG_CRIS_DIS'],
1496  'hexagon' : ['CONFIG_HEXAGON_DIS'],
1497  'hppa' : ['CONFIG_HPPA_DIS'],
1498  'i386' : ['CONFIG_I386_DIS'],
1499  'x86_64' : ['CONFIG_I386_DIS'],
1500  'x32' : ['CONFIG_I386_DIS'],
1501  'm68k' : ['CONFIG_M68K_DIS'],
1502  'microblaze' : ['CONFIG_MICROBLAZE_DIS'],
1503  'mips' : ['CONFIG_MIPS_DIS'],
1504  'nios2' : ['CONFIG_NIOS2_DIS'],
1505  'or1k' : ['CONFIG_OPENRISC_DIS'],
1506  'ppc' : ['CONFIG_PPC_DIS'],
1507  'riscv' : ['CONFIG_RISCV_DIS'],
1508  'rx' : ['CONFIG_RX_DIS'],
1509  's390' : ['CONFIG_S390_DIS'],
1510  'sh4' : ['CONFIG_SH4_DIS'],
1511  'sparc' : ['CONFIG_SPARC_DIS'],
1512  'xtensa' : ['CONFIG_XTENSA_DIS'],
1513}
1514if link_language == 'cpp'
1515  disassemblers += {
1516    'aarch64' : [ 'CONFIG_ARM_A64_DIS'],
1517    'arm' : [ 'CONFIG_ARM_DIS', 'CONFIG_ARM_A64_DIS'],
1518    'mips' : [ 'CONFIG_MIPS_DIS', 'CONFIG_NANOMIPS_DIS'],
1519  }
1520endif
1521
1522have_ivshmem = config_host_data.get('CONFIG_EVENTFD')
1523host_kconfig = \
1524  ('CONFIG_TPM' in config_host ? ['CONFIG_TPM=y'] : []) + \
1525  ('CONFIG_SPICE' in config_host ? ['CONFIG_SPICE=y'] : []) + \
1526  (have_ivshmem ? ['CONFIG_IVSHMEM=y'] : []) + \
1527  ('CONFIG_OPENGL' in config_host ? ['CONFIG_OPENGL=y'] : []) + \
1528  (x11.found() ? ['CONFIG_X11=y'] : []) + \
1529  ('CONFIG_VHOST_USER' in config_host ? ['CONFIG_VHOST_USER=y'] : []) + \
1530  ('CONFIG_VHOST_VDPA' in config_host ? ['CONFIG_VHOST_VDPA=y'] : []) + \
1531  ('CONFIG_VHOST_KERNEL' in config_host ? ['CONFIG_VHOST_KERNEL=y'] : []) + \
1532  (have_virtfs ? ['CONFIG_VIRTFS=y'] : []) + \
1533  ('CONFIG_LINUX' in config_host ? ['CONFIG_LINUX=y'] : []) + \
1534  ('CONFIG_PVRDMA' in config_host ? ['CONFIG_PVRDMA=y'] : []) + \
1535  (multiprocess_allowed ? ['CONFIG_MULTIPROCESS_ALLOWED=y'] : [])
1536
1537ignored = [ 'TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_ARCH' ]
1538
1539default_targets = 'CONFIG_DEFAULT_TARGETS' in config_host
1540actual_target_dirs = []
1541fdt_required = []
1542foreach target : target_dirs
1543  config_target = { 'TARGET_NAME': target.split('-')[0] }
1544  if target.endswith('linux-user')
1545    if targetos != 'linux'
1546      if default_targets
1547        continue
1548      endif
1549      error('Target @0@ is only available on a Linux host'.format(target))
1550    endif
1551    config_target += { 'CONFIG_LINUX_USER': 'y' }
1552  elif target.endswith('bsd-user')
1553    if 'CONFIG_BSD' not in config_host
1554      if default_targets
1555        continue
1556      endif
1557      error('Target @0@ is only available on a BSD host'.format(target))
1558    endif
1559    config_target += { 'CONFIG_BSD_USER': 'y' }
1560  elif target.endswith('softmmu')
1561    config_target += { 'CONFIG_SOFTMMU': 'y' }
1562  endif
1563  if target.endswith('-user')
1564    config_target += {
1565      'CONFIG_USER_ONLY': 'y',
1566      'CONFIG_QEMU_INTERP_PREFIX':
1567        config_host['CONFIG_QEMU_INTERP_PREFIX'].format(config_target['TARGET_NAME'])
1568    }
1569  endif
1570
1571  accel_kconfig = []
1572  foreach sym: accelerators
1573    if sym == 'CONFIG_TCG' or target in accelerator_targets.get(sym, [])
1574      config_target += { sym: 'y' }
1575      config_all += { sym: 'y' }
1576      if sym == 'CONFIG_TCG' and tcg_arch == 'tci'
1577        config_target += { 'CONFIG_TCG_INTERPRETER': 'y' }
1578      elif sym == 'CONFIG_XEN' and have_xen_pci_passthrough
1579        config_target += { 'CONFIG_XEN_PCI_PASSTHROUGH': 'y' }
1580      endif
1581      if target in modular_tcg
1582        config_target += { 'CONFIG_TCG_MODULAR': 'y' }
1583      else
1584        config_target += { 'CONFIG_TCG_BUILTIN': 'y' }
1585      endif
1586      accel_kconfig += [ sym + '=y' ]
1587    endif
1588  endforeach
1589  if accel_kconfig.length() == 0
1590    if default_targets
1591      continue
1592    endif
1593    error('No accelerator available for target @0@'.format(target))
1594  endif
1595
1596  actual_target_dirs += target
1597  config_target += keyval.load('configs/targets' / target + '.mak')
1598  config_target += { 'TARGET_' + config_target['TARGET_ARCH'].to_upper(): 'y' }
1599
1600  if 'TARGET_NEED_FDT' in config_target
1601    fdt_required += target
1602  endif
1603
1604  # Add default keys
1605  if 'TARGET_BASE_ARCH' not in config_target
1606    config_target += {'TARGET_BASE_ARCH': config_target['TARGET_ARCH']}
1607  endif
1608  if 'TARGET_ABI_DIR' not in config_target
1609    config_target += {'TARGET_ABI_DIR': config_target['TARGET_ARCH']}
1610  endif
1611
1612  foreach k, v: disassemblers
1613    if config_host['ARCH'].startswith(k) or config_target['TARGET_BASE_ARCH'].startswith(k)
1614      foreach sym: v
1615        config_target += { sym: 'y' }
1616        config_all_disas += { sym: 'y' }
1617      endforeach
1618    endif
1619  endforeach
1620
1621  config_target_data = configuration_data()
1622  foreach k, v: config_target
1623    if not k.startswith('TARGET_') and not k.startswith('CONFIG_')
1624      # do nothing
1625    elif ignored.contains(k)
1626      # do nothing
1627    elif k == 'TARGET_BASE_ARCH'
1628      # Note that TARGET_BASE_ARCH ends up in config-target.h but it is
1629      # not used to select files from sourcesets.
1630      config_target_data.set('TARGET_' + v.to_upper(), 1)
1631    elif k == 'TARGET_NAME' or k == 'CONFIG_QEMU_INTERP_PREFIX'
1632      config_target_data.set_quoted(k, v)
1633    elif v == 'y'
1634      config_target_data.set(k, 1)
1635    else
1636      config_target_data.set(k, v)
1637    endif
1638  endforeach
1639  config_target_data.set('QEMU_ARCH',
1640                         'QEMU_ARCH_' + config_target['TARGET_BASE_ARCH'].to_upper())
1641  config_target_h += {target: configure_file(output: target + '-config-target.h',
1642                                               configuration: config_target_data)}
1643
1644  if target.endswith('-softmmu')
1645    config_input = meson.get_external_property(target, 'default')
1646    config_devices_mak = target + '-config-devices.mak'
1647    config_devices_mak = configure_file(
1648      input: ['configs/devices' / target / config_input + '.mak', 'Kconfig'],
1649      output: config_devices_mak,
1650      depfile: config_devices_mak + '.d',
1651      capture: true,
1652      command: [minikconf,
1653                get_option('default_devices') ? '--defconfig' : '--allnoconfig',
1654                config_devices_mak, '@DEPFILE@', '@INPUT@',
1655                host_kconfig, accel_kconfig,
1656                'CONFIG_' + config_target['TARGET_ARCH'].to_upper() + '=y'])
1657
1658    config_devices_data = configuration_data()
1659    config_devices = keyval.load(config_devices_mak)
1660    foreach k, v: config_devices
1661      config_devices_data.set(k, 1)
1662    endforeach
1663    config_devices_mak_list += config_devices_mak
1664    config_devices_h += {target: configure_file(output: target + '-config-devices.h',
1665                                                configuration: config_devices_data)}
1666    config_target += config_devices
1667    config_all_devices += config_devices
1668  endif
1669  config_target_mak += {target: config_target}
1670endforeach
1671target_dirs = actual_target_dirs
1672
1673# This configuration is used to build files that are shared by
1674# multiple binaries, and then extracted out of the "common"
1675# static_library target.
1676#
1677# We do not use all_sources()/all_dependencies(), because it would
1678# build literally all source files, including devices only used by
1679# targets that are not built for this compilation.  The CONFIG_ALL
1680# pseudo symbol replaces it.
1681
1682config_all += config_all_devices
1683config_all += config_host
1684config_all += config_all_disas
1685config_all += {
1686  'CONFIG_XEN': config_host.has_key('CONFIG_XEN_BACKEND'),
1687  'CONFIG_SOFTMMU': have_system,
1688  'CONFIG_USER_ONLY': have_user,
1689  'CONFIG_ALL': true,
1690}
1691
1692##############
1693# Submodules #
1694##############
1695
1696capstone = not_found
1697capstone_opt = get_option('capstone')
1698if capstone_opt in ['enabled', 'auto', 'system']
1699  have_internal = fs.exists(meson.current_source_dir() / 'capstone/Makefile')
1700  capstone = dependency('capstone', version: '>=4.0',
1701                        kwargs: static_kwargs, method: 'pkg-config',
1702                        required: capstone_opt == 'system' or
1703                                  capstone_opt == 'enabled' and not have_internal)
1704
1705  # Some versions of capstone have broken pkg-config file
1706  # that reports a wrong -I path, causing the #include to
1707  # fail later. If the system has such a broken version
1708  # do not use it.
1709  if capstone.found() and not cc.compiles('#include <capstone.h>',
1710                                          dependencies: [capstone])
1711    capstone = not_found
1712    if capstone_opt == 'system'
1713      error('system capstone requested, it does not appear to work')
1714    endif
1715  endif
1716
1717  if capstone.found()
1718    capstone_opt = 'system'
1719  elif have_internal
1720    capstone_opt = 'internal'
1721  else
1722    capstone_opt = 'disabled'
1723  endif
1724endif
1725if capstone_opt == 'internal'
1726  capstone_data = configuration_data()
1727  capstone_data.set('CAPSTONE_USE_SYS_DYN_MEM', '1')
1728
1729  capstone_files = files(
1730    'capstone/cs.c',
1731    'capstone/MCInst.c',
1732    'capstone/MCInstrDesc.c',
1733    'capstone/MCRegisterInfo.c',
1734    'capstone/SStream.c',
1735    'capstone/utils.c'
1736  )
1737
1738  if 'CONFIG_ARM_DIS' in config_all_disas
1739    capstone_data.set('CAPSTONE_HAS_ARM', '1')
1740    capstone_files += files(
1741      'capstone/arch/ARM/ARMDisassembler.c',
1742      'capstone/arch/ARM/ARMInstPrinter.c',
1743      'capstone/arch/ARM/ARMMapping.c',
1744      'capstone/arch/ARM/ARMModule.c'
1745    )
1746  endif
1747
1748  # FIXME: This config entry currently depends on a c++ compiler.
1749  # Which is needed for building libvixl, but not for capstone.
1750  if 'CONFIG_ARM_A64_DIS' in config_all_disas
1751    capstone_data.set('CAPSTONE_HAS_ARM64', '1')
1752    capstone_files += files(
1753      'capstone/arch/AArch64/AArch64BaseInfo.c',
1754      'capstone/arch/AArch64/AArch64Disassembler.c',
1755      'capstone/arch/AArch64/AArch64InstPrinter.c',
1756      'capstone/arch/AArch64/AArch64Mapping.c',
1757      'capstone/arch/AArch64/AArch64Module.c'
1758    )
1759  endif
1760
1761  if 'CONFIG_PPC_DIS' in config_all_disas
1762    capstone_data.set('CAPSTONE_HAS_POWERPC', '1')
1763    capstone_files += files(
1764      'capstone/arch/PowerPC/PPCDisassembler.c',
1765      'capstone/arch/PowerPC/PPCInstPrinter.c',
1766      'capstone/arch/PowerPC/PPCMapping.c',
1767      'capstone/arch/PowerPC/PPCModule.c'
1768    )
1769  endif
1770
1771  if 'CONFIG_S390_DIS' in config_all_disas
1772    capstone_data.set('CAPSTONE_HAS_SYSZ', '1')
1773    capstone_files += files(
1774      'capstone/arch/SystemZ/SystemZDisassembler.c',
1775      'capstone/arch/SystemZ/SystemZInstPrinter.c',
1776      'capstone/arch/SystemZ/SystemZMapping.c',
1777      'capstone/arch/SystemZ/SystemZModule.c',
1778      'capstone/arch/SystemZ/SystemZMCTargetDesc.c'
1779    )
1780  endif
1781
1782  if 'CONFIG_I386_DIS' in config_all_disas
1783    capstone_data.set('CAPSTONE_HAS_X86', 1)
1784    capstone_files += files(
1785      'capstone/arch/X86/X86Disassembler.c',
1786      'capstone/arch/X86/X86DisassemblerDecoder.c',
1787      'capstone/arch/X86/X86ATTInstPrinter.c',
1788      'capstone/arch/X86/X86IntelInstPrinter.c',
1789      'capstone/arch/X86/X86InstPrinterCommon.c',
1790      'capstone/arch/X86/X86Mapping.c',
1791      'capstone/arch/X86/X86Module.c'
1792    )
1793  endif
1794
1795  configure_file(output: 'capstone-defs.h', configuration: capstone_data)
1796
1797  capstone_cargs = [
1798    # FIXME: There does not seem to be a way to completely replace the c_args
1799    # that come from add_project_arguments() -- we can only add to them.
1800    # So: disable all warnings with a big hammer.
1801    '-Wno-error', '-w',
1802
1803    # Include all configuration defines via a header file, which will wind up
1804    # as a dependency on the object file, and thus changes here will result
1805    # in a rebuild.
1806    '-include', 'capstone-defs.h'
1807  ]
1808
1809  libcapstone = static_library('capstone',
1810                               build_by_default: false,
1811                               sources: capstone_files,
1812                               c_args: capstone_cargs,
1813                               include_directories: 'capstone/include')
1814  capstone = declare_dependency(link_with: libcapstone,
1815                                include_directories: 'capstone/include/capstone')
1816endif
1817
1818slirp = not_found
1819slirp_opt = 'disabled'
1820if have_system
1821  slirp_opt = get_option('slirp')
1822  if slirp_opt in ['enabled', 'auto', 'system']
1823    have_internal = fs.exists(meson.current_source_dir() / 'slirp/meson.build')
1824    slirp = dependency('slirp', kwargs: static_kwargs,
1825                       method: 'pkg-config',
1826                       required: slirp_opt == 'system' or
1827                                 slirp_opt == 'enabled' and not have_internal)
1828    if slirp.found()
1829      slirp_opt = 'system'
1830    elif have_internal
1831      slirp_opt = 'internal'
1832    else
1833      slirp_opt = 'disabled'
1834    endif
1835  endif
1836  if slirp_opt == 'internal'
1837    slirp_deps = []
1838    if targetos == 'windows'
1839      slirp_deps = cc.find_library('iphlpapi')
1840    elif targetos == 'darwin'
1841      slirp_deps = cc.find_library('resolv')
1842    endif
1843    slirp_conf = configuration_data()
1844    slirp_conf.set('SLIRP_MAJOR_VERSION', meson.project_version().split('.')[0])
1845    slirp_conf.set('SLIRP_MINOR_VERSION', meson.project_version().split('.')[1])
1846    slirp_conf.set('SLIRP_MICRO_VERSION', meson.project_version().split('.')[2])
1847    slirp_conf.set_quoted('SLIRP_VERSION_STRING', meson.project_version())
1848    slirp_cargs = ['-DG_LOG_DOMAIN="Slirp"']
1849    slirp_files = [
1850      'slirp/src/arp_table.c',
1851      'slirp/src/bootp.c',
1852      'slirp/src/cksum.c',
1853      'slirp/src/dhcpv6.c',
1854      'slirp/src/dnssearch.c',
1855      'slirp/src/if.c',
1856      'slirp/src/ip6_icmp.c',
1857      'slirp/src/ip6_input.c',
1858      'slirp/src/ip6_output.c',
1859      'slirp/src/ip_icmp.c',
1860      'slirp/src/ip_input.c',
1861      'slirp/src/ip_output.c',
1862      'slirp/src/mbuf.c',
1863      'slirp/src/misc.c',
1864      'slirp/src/ncsi.c',
1865      'slirp/src/ndp_table.c',
1866      'slirp/src/sbuf.c',
1867      'slirp/src/slirp.c',
1868      'slirp/src/socket.c',
1869      'slirp/src/state.c',
1870      'slirp/src/stream.c',
1871      'slirp/src/tcp_input.c',
1872      'slirp/src/tcp_output.c',
1873      'slirp/src/tcp_subr.c',
1874      'slirp/src/tcp_timer.c',
1875      'slirp/src/tftp.c',
1876      'slirp/src/udp.c',
1877      'slirp/src/udp6.c',
1878      'slirp/src/util.c',
1879      'slirp/src/version.c',
1880      'slirp/src/vmstate.c',
1881    ]
1882
1883    configure_file(
1884      input : 'slirp/src/libslirp-version.h.in',
1885      output : 'libslirp-version.h',
1886      configuration: slirp_conf)
1887
1888    slirp_inc = include_directories('slirp', 'slirp/src')
1889    libslirp = static_library('slirp',
1890                              build_by_default: false,
1891                              sources: slirp_files,
1892                              c_args: slirp_cargs,
1893                              include_directories: slirp_inc)
1894    slirp = declare_dependency(link_with: libslirp,
1895                               dependencies: slirp_deps,
1896                               include_directories: slirp_inc)
1897  endif
1898endif
1899
1900# For CFI, we need to compile slirp as a static library together with qemu.
1901# This is because we register slirp functions as callbacks for QEMU Timers.
1902# When using a system-wide shared libslirp, the type information for the
1903# callback is missing and the timer call produces a false positive with CFI.
1904#
1905# Now that slirp_opt has been defined, check if the selected slirp is compatible
1906# with control-flow integrity.
1907if get_option('cfi') and slirp_opt == 'system'
1908  error('Control-Flow Integrity is not compatible with system-wide slirp.' \
1909         + ' Please configure with --enable-slirp=git')
1910endif
1911
1912fdt = not_found
1913fdt_opt = get_option('fdt')
1914if have_system
1915  if fdt_opt in ['enabled', 'auto', 'system']
1916    have_internal = fs.exists(meson.current_source_dir() / 'dtc/libfdt/Makefile.libfdt')
1917    fdt = cc.find_library('fdt', kwargs: static_kwargs,
1918                          required: fdt_opt == 'system' or
1919                                    fdt_opt == 'enabled' and not have_internal)
1920    if fdt.found() and cc.links('''
1921       #include <libfdt.h>
1922       #include <libfdt_env.h>
1923       int main(void) { fdt_check_full(NULL, 0); return 0; }''',
1924         dependencies: fdt)
1925      fdt_opt = 'system'
1926    elif fdt_opt == 'system'
1927       error('system libfdt requested, but it is too old (1.5.1 or newer required)')
1928    elif have_internal
1929      fdt_opt = 'internal'
1930    else
1931      fdt_opt = 'disabled'
1932      fdt = not_found
1933    endif
1934  endif
1935  if fdt_opt == 'internal'
1936    fdt_files = files(
1937      'dtc/libfdt/fdt.c',
1938      'dtc/libfdt/fdt_ro.c',
1939      'dtc/libfdt/fdt_wip.c',
1940      'dtc/libfdt/fdt_sw.c',
1941      'dtc/libfdt/fdt_rw.c',
1942      'dtc/libfdt/fdt_strerror.c',
1943      'dtc/libfdt/fdt_empty_tree.c',
1944      'dtc/libfdt/fdt_addresses.c',
1945      'dtc/libfdt/fdt_overlay.c',
1946      'dtc/libfdt/fdt_check.c',
1947    )
1948
1949    fdt_inc = include_directories('dtc/libfdt')
1950    libfdt = static_library('fdt',
1951                            build_by_default: false,
1952                            sources: fdt_files,
1953                            include_directories: fdt_inc)
1954    fdt = declare_dependency(link_with: libfdt,
1955                             include_directories: fdt_inc)
1956  endif
1957endif
1958if not fdt.found() and fdt_required.length() > 0
1959  error('fdt not available but required by targets ' + ', '.join(fdt_required))
1960endif
1961
1962config_host_data.set('CONFIG_CAPSTONE', capstone.found())
1963config_host_data.set('CONFIG_FDT', fdt.found())
1964config_host_data.set('CONFIG_SLIRP', slirp.found())
1965
1966#####################
1967# Generated sources #
1968#####################
1969
1970genh += configure_file(output: 'config-host.h', configuration: config_host_data)
1971
1972hxtool = find_program('scripts/hxtool')
1973shaderinclude = find_program('scripts/shaderinclude.pl')
1974qapi_gen = find_program('scripts/qapi-gen.py')
1975qapi_gen_depends = [ meson.source_root() / 'scripts/qapi/__init__.py',
1976                     meson.source_root() / 'scripts/qapi/commands.py',
1977                     meson.source_root() / 'scripts/qapi/common.py',
1978                     meson.source_root() / 'scripts/qapi/error.py',
1979                     meson.source_root() / 'scripts/qapi/events.py',
1980                     meson.source_root() / 'scripts/qapi/expr.py',
1981                     meson.source_root() / 'scripts/qapi/gen.py',
1982                     meson.source_root() / 'scripts/qapi/introspect.py',
1983                     meson.source_root() / 'scripts/qapi/parser.py',
1984                     meson.source_root() / 'scripts/qapi/schema.py',
1985                     meson.source_root() / 'scripts/qapi/source.py',
1986                     meson.source_root() / 'scripts/qapi/types.py',
1987                     meson.source_root() / 'scripts/qapi/visit.py',
1988                     meson.source_root() / 'scripts/qapi/common.py',
1989                     meson.source_root() / 'scripts/qapi-gen.py'
1990]
1991
1992tracetool = [
1993  python, files('scripts/tracetool.py'),
1994   '--backend=' + config_host['TRACE_BACKENDS']
1995]
1996tracetool_depends = files(
1997  'scripts/tracetool/backend/log.py',
1998  'scripts/tracetool/backend/__init__.py',
1999  'scripts/tracetool/backend/dtrace.py',
2000  'scripts/tracetool/backend/ftrace.py',
2001  'scripts/tracetool/backend/simple.py',
2002  'scripts/tracetool/backend/syslog.py',
2003  'scripts/tracetool/backend/ust.py',
2004  'scripts/tracetool/format/tcg_h.py',
2005  'scripts/tracetool/format/ust_events_c.py',
2006  'scripts/tracetool/format/ust_events_h.py',
2007  'scripts/tracetool/format/__init__.py',
2008  'scripts/tracetool/format/d.py',
2009  'scripts/tracetool/format/tcg_helper_c.py',
2010  'scripts/tracetool/format/simpletrace_stap.py',
2011  'scripts/tracetool/format/c.py',
2012  'scripts/tracetool/format/h.py',
2013  'scripts/tracetool/format/tcg_helper_h.py',
2014  'scripts/tracetool/format/log_stap.py',
2015  'scripts/tracetool/format/stap.py',
2016  'scripts/tracetool/format/tcg_helper_wrapper_h.py',
2017  'scripts/tracetool/__init__.py',
2018  'scripts/tracetool/transform.py',
2019  'scripts/tracetool/vcpu.py'
2020)
2021
2022qemu_version_cmd = [find_program('scripts/qemu-version.sh'),
2023                    meson.current_source_dir(),
2024                    config_host['PKGVERSION'], meson.project_version()]
2025qemu_version = custom_target('qemu-version.h',
2026                             output: 'qemu-version.h',
2027                             command: qemu_version_cmd,
2028                             capture: true,
2029                             build_by_default: true,
2030                             build_always_stale: true)
2031genh += qemu_version
2032
2033hxdep = []
2034hx_headers = [
2035  ['qemu-options.hx', 'qemu-options.def'],
2036  ['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
2037]
2038if have_system
2039  hx_headers += [
2040    ['hmp-commands.hx', 'hmp-commands.h'],
2041    ['hmp-commands-info.hx', 'hmp-commands-info.h'],
2042  ]
2043endif
2044foreach d : hx_headers
2045  hxdep += custom_target(d[1],
2046                input: files(d[0]),
2047                output: d[1],
2048                capture: true,
2049                build_by_default: true, # to be removed when added to a target
2050                command: [hxtool, '-h', '@INPUT0@'])
2051endforeach
2052genh += hxdep
2053
2054###################
2055# Collect sources #
2056###################
2057
2058authz_ss = ss.source_set()
2059blockdev_ss = ss.source_set()
2060block_ss = ss.source_set()
2061bsd_user_ss = ss.source_set()
2062chardev_ss = ss.source_set()
2063common_ss = ss.source_set()
2064crypto_ss = ss.source_set()
2065io_ss = ss.source_set()
2066linux_user_ss = ss.source_set()
2067qmp_ss = ss.source_set()
2068qom_ss = ss.source_set()
2069softmmu_ss = ss.source_set()
2070specific_fuzz_ss = ss.source_set()
2071specific_ss = ss.source_set()
2072stub_ss = ss.source_set()
2073trace_ss = ss.source_set()
2074user_ss = ss.source_set()
2075util_ss = ss.source_set()
2076
2077# accel modules
2078qtest_module_ss = ss.source_set()
2079tcg_module_ss = ss.source_set()
2080
2081modules = {}
2082target_modules = {}
2083hw_arch = {}
2084target_arch = {}
2085target_softmmu_arch = {}
2086target_user_arch = {}
2087
2088###############
2089# Trace files #
2090###############
2091
2092# TODO: add each directory to the subdirs from its own meson.build, once
2093# we have those
2094trace_events_subdirs = [
2095  'crypto',
2096  'qapi',
2097  'qom',
2098  'monitor',
2099  'util',
2100]
2101if have_user
2102  trace_events_subdirs += [ 'linux-user' ]
2103endif
2104if have_block
2105  trace_events_subdirs += [
2106    'authz',
2107    'block',
2108    'io',
2109    'nbd',
2110    'scsi',
2111  ]
2112endif
2113if have_system
2114  trace_events_subdirs += [
2115    'accel/kvm',
2116    'audio',
2117    'backends',
2118    'backends/tpm',
2119    'chardev',
2120    'ebpf',
2121    'hw/9pfs',
2122    'hw/acpi',
2123    'hw/adc',
2124    'hw/alpha',
2125    'hw/arm',
2126    'hw/audio',
2127    'hw/block',
2128    'hw/block/dataplane',
2129    'hw/char',
2130    'hw/display',
2131    'hw/dma',
2132    'hw/hppa',
2133    'hw/hyperv',
2134    'hw/i2c',
2135    'hw/i386',
2136    'hw/i386/xen',
2137    'hw/ide',
2138    'hw/input',
2139    'hw/intc',
2140    'hw/isa',
2141    'hw/mem',
2142    'hw/mips',
2143    'hw/misc',
2144    'hw/misc/macio',
2145    'hw/net',
2146    'hw/net/can',
2147    'hw/nubus',
2148    'hw/nvme',
2149    'hw/nvram',
2150    'hw/pci',
2151    'hw/pci-host',
2152    'hw/ppc',
2153    'hw/rdma',
2154    'hw/rdma/vmw',
2155    'hw/rtc',
2156    'hw/s390x',
2157    'hw/scsi',
2158    'hw/sd',
2159    'hw/sparc',
2160    'hw/sparc64',
2161    'hw/ssi',
2162    'hw/timer',
2163    'hw/tpm',
2164    'hw/usb',
2165    'hw/vfio',
2166    'hw/virtio',
2167    'hw/watchdog',
2168    'hw/xen',
2169    'hw/gpio',
2170    'migration',
2171    'net',
2172    'softmmu',
2173    'ui',
2174    'hw/remote',
2175  ]
2176endif
2177if have_system or have_user
2178  trace_events_subdirs += [
2179    'accel/tcg',
2180    'hw/core',
2181    'target/arm',
2182    'target/arm/hvf',
2183    'target/hppa',
2184    'target/i386',
2185    'target/i386/kvm',
2186    'target/mips/tcg',
2187    'target/ppc',
2188    'target/riscv',
2189    'target/s390x',
2190    'target/s390x/kvm',
2191    'target/sparc',
2192  ]
2193endif
2194
2195vhost_user = not_found
2196if 'CONFIG_VHOST_USER' in config_host
2197  libvhost_user = subproject('libvhost-user')
2198  vhost_user = libvhost_user.get_variable('vhost_user_dep')
2199endif
2200
2201subdir('qapi')
2202subdir('qobject')
2203subdir('stubs')
2204subdir('trace')
2205subdir('util')
2206subdir('qom')
2207subdir('authz')
2208subdir('crypto')
2209subdir('ui')
2210
2211
2212if enable_modules
2213  libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
2214  modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
2215endif
2216
2217stub_ss = stub_ss.apply(config_all, strict: false)
2218
2219util_ss.add_all(trace_ss)
2220util_ss = util_ss.apply(config_all, strict: false)
2221libqemuutil = static_library('qemuutil',
2222                             sources: util_ss.sources() + stub_ss.sources() + genh,
2223                             dependencies: [util_ss.dependencies(), libm, threads, glib, socket, malloc, pixman])
2224qemuutil = declare_dependency(link_with: libqemuutil,
2225                              sources: genh + version_res)
2226
2227if have_system or have_user
2228  decodetree = generator(find_program('scripts/decodetree.py'),
2229                         output: 'decode-@BASENAME@.c.inc',
2230                         arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
2231  subdir('libdecnumber')
2232  subdir('target')
2233endif
2234
2235subdir('audio')
2236subdir('io')
2237subdir('chardev')
2238subdir('fsdev')
2239subdir('dump')
2240
2241if have_block
2242  block_ss.add(files(
2243    'block.c',
2244    'blockjob.c',
2245    'job.c',
2246    'qemu-io-cmds.c',
2247  ))
2248  block_ss.add(when: 'CONFIG_REPLICATION', if_true: files('replication.c'))
2249
2250  subdir('nbd')
2251  subdir('scsi')
2252  subdir('block')
2253
2254  blockdev_ss.add(files(
2255    'blockdev.c',
2256    'blockdev-nbd.c',
2257    'iothread.c',
2258    'job-qmp.c',
2259  ), gnutls)
2260
2261  # os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
2262  # os-win32.c does not
2263  blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c'))
2264  softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')])
2265endif
2266
2267common_ss.add(files('cpus-common.c'))
2268
2269subdir('softmmu')
2270
2271common_ss.add(capstone)
2272specific_ss.add(files('cpu.c', 'disas.c', 'gdbstub.c'), capstone)
2273
2274# Work around a gcc bug/misfeature wherein constant propagation looks
2275# through an alias:
2276#   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99696
2277# to guess that a const variable is always zero.  Without lto, this is
2278# impossible, as the alias is restricted to page-vary-common.c.  Indeed,
2279# without lto, not even the alias is required -- we simply use different
2280# declarations in different compilation units.
2281pagevary = files('page-vary-common.c')
2282if get_option('b_lto')
2283  pagevary_flags = ['-fno-lto']
2284  if get_option('cfi')
2285    pagevary_flags += '-fno-sanitize=cfi-icall'
2286  endif
2287  pagevary = static_library('page-vary-common', sources: pagevary,
2288                            c_args: pagevary_flags)
2289  pagevary = declare_dependency(link_with: pagevary)
2290endif
2291common_ss.add(pagevary)
2292specific_ss.add(files('page-vary.c'))
2293
2294subdir('backends')
2295subdir('disas')
2296subdir('migration')
2297subdir('monitor')
2298subdir('net')
2299subdir('replay')
2300subdir('semihosting')
2301subdir('hw')
2302subdir('tcg')
2303subdir('fpu')
2304subdir('accel')
2305subdir('plugins')
2306subdir('bsd-user')
2307subdir('linux-user')
2308subdir('ebpf')
2309
2310common_ss.add(libbpf)
2311
2312bsd_user_ss.add(files('gdbstub.c'))
2313specific_ss.add_all(when: 'CONFIG_BSD_USER', if_true: bsd_user_ss)
2314
2315linux_user_ss.add(files('gdbstub.c', 'thunk.c'))
2316specific_ss.add_all(when: 'CONFIG_LINUX_USER', if_true: linux_user_ss)
2317
2318# needed for fuzzing binaries
2319subdir('tests/qtest/libqos')
2320subdir('tests/qtest/fuzz')
2321
2322# accel modules
2323tcg_real_module_ss = ss.source_set()
2324tcg_real_module_ss.add_all(when: 'CONFIG_TCG_MODULAR', if_true: tcg_module_ss)
2325specific_ss.add_all(when: 'CONFIG_TCG_BUILTIN', if_true: tcg_module_ss)
2326target_modules += { 'accel' : { 'qtest': qtest_module_ss,
2327                                'tcg': tcg_real_module_ss }}
2328
2329########################
2330# Library dependencies #
2331########################
2332
2333modinfo_collect = find_program('scripts/modinfo-collect.py')
2334modinfo_generate = find_program('scripts/modinfo-generate.py')
2335modinfo_files = []
2336
2337block_mods = []
2338softmmu_mods = []
2339foreach d, list : modules
2340  foreach m, module_ss : list
2341    if enable_modules and targetos != 'windows'
2342      module_ss = module_ss.apply(config_all, strict: false)
2343      sl = static_library(d + '-' + m, [genh, module_ss.sources()],
2344                          dependencies: [modulecommon, module_ss.dependencies()], pic: true)
2345      if d == 'block'
2346        block_mods += sl
2347      else
2348        softmmu_mods += sl
2349      endif
2350      if module_ss.sources() != []
2351        # FIXME: Should use sl.extract_all_objects(recursive: true) as
2352        # input. Sources can be used multiple times but objects are
2353        # unique when it comes to lookup in compile_commands.json.
2354        # Depnds on a mesion version with
2355        # https://github.com/mesonbuild/meson/pull/8900
2356        modinfo_files += custom_target(d + '-' + m + '.modinfo',
2357                                       output: d + '-' + m + '.modinfo',
2358                                       input: module_ss.sources() + genh,
2359                                       capture: true,
2360                                       command: [modinfo_collect, module_ss.sources()])
2361      endif
2362    else
2363      if d == 'block'
2364        block_ss.add_all(module_ss)
2365      else
2366        softmmu_ss.add_all(module_ss)
2367      endif
2368    endif
2369  endforeach
2370endforeach
2371
2372foreach d, list : target_modules
2373  foreach m, module_ss : list
2374    if enable_modules and targetos != 'windows'
2375      foreach target : target_dirs
2376        if target.endswith('-softmmu')
2377          config_target = config_target_mak[target]
2378          config_target += config_host
2379          target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
2380          c_args = ['-DNEED_CPU_H',
2381                    '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
2382                    '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
2383          target_module_ss = module_ss.apply(config_target, strict: false)
2384          if target_module_ss.sources() != []
2385            module_name = d + '-' + m + '-' + config_target['TARGET_NAME']
2386            sl = static_library(module_name,
2387                                [genh, target_module_ss.sources()],
2388                                dependencies: [modulecommon, target_module_ss.dependencies()],
2389                                include_directories: target_inc,
2390                                c_args: c_args,
2391                                pic: true)
2392            softmmu_mods += sl
2393            # FIXME: Should use sl.extract_all_objects(recursive: true) too.
2394            modinfo_files += custom_target(module_name + '.modinfo',
2395                                           output: module_name + '.modinfo',
2396                                           input: target_module_ss.sources() + genh,
2397                                           capture: true,
2398                                           command: [modinfo_collect, '--target', target, target_module_ss.sources()])
2399          endif
2400        endif
2401      endforeach
2402    else
2403      specific_ss.add_all(module_ss)
2404    endif
2405  endforeach
2406endforeach
2407
2408if enable_modules
2409  modinfo_src = custom_target('modinfo.c',
2410                              output: 'modinfo.c',
2411                              input: modinfo_files,
2412                              command: [modinfo_generate, '@INPUT@'],
2413                              capture: true)
2414  modinfo_lib = static_library('modinfo', modinfo_src)
2415  modinfo_dep = declare_dependency(link_whole: modinfo_lib)
2416  softmmu_ss.add(modinfo_dep)
2417endif
2418
2419nm = find_program('nm')
2420undefsym = find_program('scripts/undefsym.py')
2421block_syms = custom_target('block.syms', output: 'block.syms',
2422                             input: [libqemuutil, block_mods],
2423                             capture: true,
2424                             command: [undefsym, nm, '@INPUT@'])
2425qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
2426                             input: [libqemuutil, softmmu_mods],
2427                             capture: true,
2428                             command: [undefsym, nm, '@INPUT@'])
2429
2430qom_ss = qom_ss.apply(config_host, strict: false)
2431libqom = static_library('qom', qom_ss.sources() + genh,
2432                        dependencies: [qom_ss.dependencies()],
2433                        name_suffix: 'fa')
2434
2435qom = declare_dependency(link_whole: libqom)
2436
2437authz_ss = authz_ss.apply(config_host, strict: false)
2438libauthz = static_library('authz', authz_ss.sources() + genh,
2439                          dependencies: [authz_ss.dependencies()],
2440                          name_suffix: 'fa',
2441                          build_by_default: false)
2442
2443authz = declare_dependency(link_whole: libauthz,
2444                           dependencies: qom)
2445
2446crypto_ss = crypto_ss.apply(config_host, strict: false)
2447libcrypto = static_library('crypto', crypto_ss.sources() + genh,
2448                           dependencies: [crypto_ss.dependencies()],
2449                           name_suffix: 'fa',
2450                           build_by_default: false)
2451
2452crypto = declare_dependency(link_whole: libcrypto,
2453                            dependencies: [authz, qom])
2454
2455io_ss = io_ss.apply(config_host, strict: false)
2456libio = static_library('io', io_ss.sources() + genh,
2457                       dependencies: [io_ss.dependencies()],
2458                       link_with: libqemuutil,
2459                       name_suffix: 'fa',
2460                       build_by_default: false)
2461
2462io = declare_dependency(link_whole: libio, dependencies: [crypto, qom])
2463
2464libmigration = static_library('migration', sources: migration_files + genh,
2465                              name_suffix: 'fa',
2466                              build_by_default: false)
2467migration = declare_dependency(link_with: libmigration,
2468                               dependencies: [zlib, qom, io])
2469softmmu_ss.add(migration)
2470
2471block_ss = block_ss.apply(config_host, strict: false)
2472libblock = static_library('block', block_ss.sources() + genh,
2473                          dependencies: block_ss.dependencies(),
2474                          link_depends: block_syms,
2475                          name_suffix: 'fa',
2476                          build_by_default: false)
2477
2478block = declare_dependency(link_whole: [libblock],
2479                           link_args: '@block.syms',
2480                           dependencies: [crypto, io])
2481
2482blockdev_ss = blockdev_ss.apply(config_host, strict: false)
2483libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
2484                             dependencies: blockdev_ss.dependencies(),
2485                             name_suffix: 'fa',
2486                             build_by_default: false)
2487
2488blockdev = declare_dependency(link_whole: [libblockdev],
2489                              dependencies: [block])
2490
2491qmp_ss = qmp_ss.apply(config_host, strict: false)
2492libqmp = static_library('qmp', qmp_ss.sources() + genh,
2493                        dependencies: qmp_ss.dependencies(),
2494                        name_suffix: 'fa',
2495                        build_by_default: false)
2496
2497qmp = declare_dependency(link_whole: [libqmp])
2498
2499libchardev = static_library('chardev', chardev_ss.sources() + genh,
2500                            name_suffix: 'fa',
2501                            dependencies: [gnutls],
2502                            build_by_default: false)
2503
2504chardev = declare_dependency(link_whole: libchardev)
2505
2506libhwcore = static_library('hwcore', sources: hwcore_files + genh,
2507                           name_suffix: 'fa',
2508                           build_by_default: false)
2509hwcore = declare_dependency(link_whole: libhwcore)
2510common_ss.add(hwcore)
2511
2512###########
2513# Targets #
2514###########
2515
2516foreach m : block_mods + softmmu_mods
2517  shared_module(m.name(),
2518                name_prefix: '',
2519                link_whole: m,
2520                install: true,
2521                install_dir: qemu_moddir)
2522endforeach
2523
2524softmmu_ss.add(authz, blockdev, chardev, crypto, io, qmp)
2525common_ss.add(qom, qemuutil)
2526
2527common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss])
2528common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
2529
2530common_all = common_ss.apply(config_all, strict: false)
2531common_all = static_library('common',
2532                            build_by_default: false,
2533                            sources: common_all.sources() + genh,
2534                            implicit_include_directories: false,
2535                            dependencies: common_all.dependencies(),
2536                            name_suffix: 'fa')
2537
2538feature_to_c = find_program('scripts/feature_to_c.sh')
2539
2540emulators = {}
2541foreach target : target_dirs
2542  config_target = config_target_mak[target]
2543  target_name = config_target['TARGET_NAME']
2544  arch = config_target['TARGET_BASE_ARCH']
2545  arch_srcs = [config_target_h[target]]
2546  arch_deps = []
2547  c_args = ['-DNEED_CPU_H',
2548            '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
2549            '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
2550  link_args = emulator_link_args
2551
2552  config_target += config_host
2553  target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
2554  if targetos == 'linux'
2555    target_inc += include_directories('linux-headers', is_system: true)
2556  endif
2557  if target.endswith('-softmmu')
2558    qemu_target_name = 'qemu-system-' + target_name
2559    target_type='system'
2560    t = target_softmmu_arch[arch].apply(config_target, strict: false)
2561    arch_srcs += t.sources()
2562    arch_deps += t.dependencies()
2563
2564    hw_dir = target_name == 'sparc64' ? 'sparc64' : arch
2565    hw = hw_arch[hw_dir].apply(config_target, strict: false)
2566    arch_srcs += hw.sources()
2567    arch_deps += hw.dependencies()
2568
2569    arch_srcs += config_devices_h[target]
2570    link_args += ['@block.syms', '@qemu.syms']
2571  else
2572    abi = config_target['TARGET_ABI_DIR']
2573    target_type='user'
2574    qemu_target_name = 'qemu-' + target_name
2575    if arch in target_user_arch
2576      t = target_user_arch[arch].apply(config_target, strict: false)
2577      arch_srcs += t.sources()
2578      arch_deps += t.dependencies()
2579    endif
2580    if 'CONFIG_LINUX_USER' in config_target
2581      base_dir = 'linux-user'
2582      target_inc += include_directories('linux-user/host/' / config_host['ARCH'])
2583    endif
2584    if 'CONFIG_BSD_USER' in config_target
2585      base_dir = 'bsd-user'
2586      target_inc += include_directories('bsd-user/' / targetos)
2587      dir = base_dir / abi
2588      arch_srcs += files(dir / 'target_arch_cpu.c')
2589    endif
2590    target_inc += include_directories(
2591      base_dir,
2592      base_dir / abi,
2593    )
2594    if 'CONFIG_LINUX_USER' in config_target
2595      dir = base_dir / abi
2596      arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
2597      if config_target.has_key('TARGET_SYSTBL_ABI')
2598        arch_srcs += \
2599          syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
2600                                             extra_args : config_target['TARGET_SYSTBL_ABI'])
2601      endif
2602    endif
2603  endif
2604
2605  if 'TARGET_XML_FILES' in config_target
2606    gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
2607                                output: target + '-gdbstub-xml.c',
2608                                input: files(config_target['TARGET_XML_FILES'].split()),
2609                                command: [feature_to_c, '@INPUT@'],
2610                                capture: true)
2611    arch_srcs += gdbstub_xml
2612  endif
2613
2614  t = target_arch[arch].apply(config_target, strict: false)
2615  arch_srcs += t.sources()
2616  arch_deps += t.dependencies()
2617
2618  target_common = common_ss.apply(config_target, strict: false)
2619  objects = common_all.extract_objects(target_common.sources())
2620  deps = target_common.dependencies()
2621
2622  target_specific = specific_ss.apply(config_target, strict: false)
2623  arch_srcs += target_specific.sources()
2624  arch_deps += target_specific.dependencies()
2625
2626  lib = static_library('qemu-' + target,
2627                 sources: arch_srcs + genh,
2628                 dependencies: arch_deps,
2629                 objects: objects,
2630                 include_directories: target_inc,
2631                 c_args: c_args,
2632                 build_by_default: false,
2633                 name_suffix: 'fa')
2634
2635  if target.endswith('-softmmu')
2636    execs = [{
2637      'name': 'qemu-system-' + target_name,
2638      'gui': false,
2639      'sources': files('softmmu/main.c'),
2640      'dependencies': []
2641    }]
2642    if targetos == 'windows' and (sdl.found() or gtk.found())
2643      execs += [{
2644        'name': 'qemu-system-' + target_name + 'w',
2645        'gui': true,
2646        'sources': files('softmmu/main.c'),
2647        'dependencies': []
2648      }]
2649    endif
2650    if config_host.has_key('CONFIG_FUZZ')
2651      specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
2652      execs += [{
2653        'name': 'qemu-fuzz-' + target_name,
2654        'gui': false,
2655        'sources': specific_fuzz.sources(),
2656        'dependencies': specific_fuzz.dependencies(),
2657      }]
2658    endif
2659  else
2660    execs = [{
2661      'name': 'qemu-' + target_name,
2662      'gui': false,
2663      'sources': [],
2664      'dependencies': []
2665    }]
2666  endif
2667  foreach exe: execs
2668    exe_name = exe['name']
2669    if targetos == 'darwin'
2670      exe_name += '-unsigned'
2671    endif
2672
2673    emulator = executable(exe_name, exe['sources'],
2674               install: true,
2675               c_args: c_args,
2676               dependencies: arch_deps + deps + exe['dependencies'],
2677               objects: lib.extract_all_objects(recursive: true),
2678               link_language: link_language,
2679               link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
2680               link_args: link_args,
2681               gui_app: exe['gui'])
2682
2683    if targetos == 'darwin'
2684      icon = 'pc-bios/qemu.rsrc'
2685      build_input = [emulator, files(icon)]
2686      install_input = [
2687        get_option('bindir') / exe_name,
2688        meson.current_source_dir() / icon
2689      ]
2690      if 'CONFIG_HVF' in config_target
2691        entitlements = 'accel/hvf/entitlements.plist'
2692        build_input += files(entitlements)
2693        install_input += meson.current_source_dir() / entitlements
2694      endif
2695
2696      emulators += {exe['name'] : custom_target(exe['name'],
2697                   input: build_input,
2698                   output: exe['name'],
2699                   command: [
2700                     files('scripts/entitlement.sh'),
2701                     '@OUTPUT@',
2702                     '@INPUT@'
2703                   ])
2704      }
2705
2706      meson.add_install_script('scripts/entitlement.sh', '--install',
2707                               get_option('bindir') / exe['name'],
2708                               install_input)
2709    else
2710      emulators += {exe['name']: emulator}
2711    endif
2712
2713    if 'CONFIG_TRACE_SYSTEMTAP' in config_host
2714      foreach stp: [
2715        {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
2716        {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
2717        {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
2718        {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
2719      ]
2720        custom_target(exe['name'] + stp['ext'],
2721                      input: trace_events_all,
2722                      output: exe['name'] + stp['ext'],
2723                      install: stp['install'],
2724                      install_dir: get_option('datadir') / 'systemtap/tapset',
2725                      command: [
2726                        tracetool, '--group=all', '--format=' + stp['fmt'],
2727                        '--binary=' + stp['bin'],
2728                        '--target-name=' + target_name,
2729                        '--target-type=' + target_type,
2730                        '--probe-prefix=qemu.' + target_type + '.' + target_name,
2731                        '@INPUT@', '@OUTPUT@'
2732                      ],
2733                      depend_files: tracetool_depends)
2734      endforeach
2735    endif
2736  endforeach
2737endforeach
2738
2739# Other build targets
2740
2741if 'CONFIG_PLUGIN' in config_host
2742  install_headers('include/qemu/qemu-plugin.h')
2743endif
2744
2745if 'CONFIG_GUEST_AGENT' in config_host
2746  subdir('qga')
2747elif get_option('guest_agent_msi').enabled()
2748  error('Guest agent MSI requested, but the guest agent is not being built')
2749endif
2750
2751# Don't build qemu-keymap if xkbcommon is not explicitly enabled
2752# when we don't build tools or system
2753if xkbcommon.found()
2754  # used for the update-keymaps target, so include rules even if !have_tools
2755  qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
2756                           dependencies: [qemuutil, xkbcommon], install: have_tools)
2757endif
2758
2759if have_tools
2760  qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
2761             dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
2762  qemu_io = executable('qemu-io', files('qemu-io.c'),
2763             dependencies: [block, qemuutil], install: true)
2764  qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
2765               dependencies: [blockdev, qemuutil, gnutls], install: true)
2766
2767  subdir('storage-daemon')
2768  subdir('contrib/rdmacm-mux')
2769  subdir('contrib/elf2dmp')
2770
2771  executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
2772             dependencies: qemuutil,
2773             install: true)
2774
2775  if 'CONFIG_VHOST_USER' in config_host
2776    subdir('contrib/vhost-user-blk')
2777    subdir('contrib/vhost-user-gpu')
2778    subdir('contrib/vhost-user-input')
2779    subdir('contrib/vhost-user-scsi')
2780  endif
2781
2782  if targetos == 'linux'
2783    executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
2784               dependencies: [qemuutil, libcap_ng],
2785               install: true,
2786               install_dir: get_option('libexecdir'))
2787
2788    executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
2789               dependencies: [authz, crypto, io, qom, qemuutil,
2790                              libcap_ng, mpathpersist],
2791               install: true)
2792  endif
2793
2794  if have_ivshmem
2795    subdir('contrib/ivshmem-client')
2796    subdir('contrib/ivshmem-server')
2797  endif
2798endif
2799
2800subdir('scripts')
2801subdir('tools')
2802subdir('pc-bios')
2803subdir('docs')
2804subdir('tests')
2805if gtk.found()
2806  subdir('po')
2807endif
2808
2809if host_machine.system() == 'windows'
2810  nsis_cmd = [
2811    find_program('scripts/nsis.py'),
2812    '@OUTPUT@',
2813    get_option('prefix'),
2814    meson.current_source_dir(),
2815    host_machine.cpu(),
2816    '--',
2817    '-DDISPLAYVERSION=' + meson.project_version(),
2818  ]
2819  if build_docs
2820    nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
2821  endif
2822  if gtk.found()
2823    nsis_cmd += '-DCONFIG_GTK=y'
2824  endif
2825
2826  nsis = custom_target('nsis',
2827                       output: 'qemu-setup-' + meson.project_version() + '.exe',
2828                       input: files('qemu.nsi'),
2829                       build_always_stale: true,
2830                       command: nsis_cmd + ['@INPUT@'])
2831  alias_target('installer', nsis)
2832endif
2833
2834#########################
2835# Configuration summary #
2836#########################
2837
2838# Directories
2839summary_info = {}
2840summary_info += {'Install prefix':    get_option('prefix')}
2841summary_info += {'BIOS directory':    qemu_datadir}
2842summary_info += {'firmware path':     get_option('qemu_firmwarepath')}
2843summary_info += {'binary directory':  get_option('bindir')}
2844summary_info += {'library directory': get_option('libdir')}
2845summary_info += {'module directory':  qemu_moddir}
2846summary_info += {'libexec directory': get_option('libexecdir')}
2847summary_info += {'include directory': get_option('includedir')}
2848summary_info += {'config directory':  get_option('sysconfdir')}
2849if targetos != 'windows'
2850  summary_info += {'local state directory': get_option('localstatedir')}
2851  summary_info += {'Manual directory':      get_option('mandir')}
2852else
2853  summary_info += {'local state directory': 'queried at runtime'}
2854endif
2855summary_info += {'Doc directory':     get_option('docdir')}
2856summary_info += {'Build directory':   meson.current_build_dir()}
2857summary_info += {'Source path':       meson.current_source_dir()}
2858summary_info += {'GIT submodules':    config_host['GIT_SUBMODULES']}
2859summary(summary_info, bool_yn: true, section: 'Directories')
2860
2861# Host binaries
2862summary_info = {}
2863summary_info += {'git':               config_host['GIT']}
2864summary_info += {'make':              config_host['MAKE']}
2865summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
2866summary_info += {'sphinx-build':      sphinx_build.found()}
2867if config_host.has_key('HAVE_GDB_BIN')
2868  summary_info += {'gdb':             config_host['HAVE_GDB_BIN']}
2869endif
2870summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
2871if targetos == 'windows' and config_host.has_key('CONFIG_GUEST_AGENT')
2872  summary_info += {'wixl':            wixl.found() ? wixl.full_path() : false}
2873endif
2874if slirp_opt != 'disabled' and 'CONFIG_SLIRP_SMBD' in config_host
2875  summary_info += {'smbd':            config_host['CONFIG_SMBD_COMMAND']}
2876endif
2877summary(summary_info, bool_yn: true, section: 'Host binaries')
2878
2879# Configurable features
2880summary_info = {}
2881summary_info += {'Documentation':     build_docs}
2882summary_info += {'system-mode emulation': have_system}
2883summary_info += {'user-mode emulation': have_user}
2884summary_info += {'block layer':       have_block}
2885summary_info += {'Install blobs':     get_option('install_blobs')}
2886summary_info += {'module support':    config_host.has_key('CONFIG_MODULES')}
2887if config_host.has_key('CONFIG_MODULES')
2888  summary_info += {'alternative module path': config_host.has_key('CONFIG_MODULE_UPGRADES')}
2889endif
2890summary_info += {'fuzzing support':   config_host.has_key('CONFIG_FUZZ')}
2891if have_system
2892  summary_info += {'Audio drivers':     config_host['CONFIG_AUDIO_DRIVERS']}
2893endif
2894summary_info += {'Trace backends':    config_host['TRACE_BACKENDS']}
2895if config_host['TRACE_BACKENDS'].split().contains('simple')
2896  summary_info += {'Trace output file': config_host['CONFIG_TRACE_FILE'] + '-<pid>'}
2897endif
2898summary_info += {'QOM debugging':     config_host.has_key('CONFIG_QOM_CAST_DEBUG')}
2899summary_info += {'vhost-kernel support': config_host.has_key('CONFIG_VHOST_KERNEL')}
2900summary_info += {'vhost-net support': config_host.has_key('CONFIG_VHOST_NET')}
2901summary_info += {'vhost-crypto support': config_host.has_key('CONFIG_VHOST_CRYPTO')}
2902summary_info += {'vhost-scsi support': config_host.has_key('CONFIG_VHOST_SCSI')}
2903summary_info += {'vhost-vsock support': config_host.has_key('CONFIG_VHOST_VSOCK')}
2904summary_info += {'vhost-user support': config_host.has_key('CONFIG_VHOST_USER')}
2905summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
2906summary_info += {'vhost-user-fs support': config_host.has_key('CONFIG_VHOST_USER_FS')}
2907summary_info += {'vhost-vdpa support': config_host.has_key('CONFIG_VHOST_VDPA')}
2908summary_info += {'build guest agent': config_host.has_key('CONFIG_GUEST_AGENT')}
2909summary(summary_info, bool_yn: true, section: 'Configurable features')
2910
2911# Compilation information
2912summary_info = {}
2913summary_info += {'host CPU':          cpu}
2914summary_info += {'host endianness':   build_machine.endian()}
2915summary_info += {'C compiler':        ' '.join(meson.get_compiler('c').cmd_array())}
2916summary_info += {'Host C compiler':   ' '.join(meson.get_compiler('c', native: true).cmd_array())}
2917if link_language == 'cpp'
2918  summary_info += {'C++ compiler':    ' '.join(meson.get_compiler('cpp').cmd_array())}
2919else
2920  summary_info += {'C++ compiler':      false}
2921endif
2922if targetos == 'darwin'
2923  summary_info += {'Objective-C compiler': ' '.join(meson.get_compiler('objc').cmd_array())}
2924endif
2925if targetos == 'windows'
2926  if 'WIN_SDK' in config_host
2927    summary_info += {'Windows SDK':   config_host['WIN_SDK']}
2928  endif
2929endif
2930summary_info += {'CFLAGS':            ' '.join(get_option('c_args')
2931                                               + ['-O' + get_option('optimization')]
2932                                               + (get_option('debug') ? ['-g'] : []))}
2933if link_language == 'cpp'
2934  summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args')
2935                                               + ['-O' + get_option('optimization')]
2936                                               + (get_option('debug') ? ['-g'] : []))}
2937endif
2938link_args = get_option(link_language + '_link_args')
2939if link_args.length() > 0
2940  summary_info += {'LDFLAGS':         ' '.join(link_args)}
2941endif
2942summary_info += {'QEMU_CFLAGS':       config_host['QEMU_CFLAGS']}
2943summary_info += {'QEMU_LDFLAGS':      config_host['QEMU_LDFLAGS']}
2944summary_info += {'profiler':          config_host.has_key('CONFIG_PROFILER')}
2945summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
2946summary_info += {'PIE':               get_option('b_pie')}
2947summary_info += {'static build':      config_host.has_key('CONFIG_STATIC')}
2948summary_info += {'malloc trim support': has_malloc_trim}
2949summary_info += {'membarrier':        config_host.has_key('CONFIG_MEMBARRIER')}
2950summary_info += {'debug stack usage': config_host.has_key('CONFIG_DEBUG_STACK_USAGE')}
2951summary_info += {'mutex debugging':   config_host.has_key('CONFIG_DEBUG_MUTEX')}
2952summary_info += {'memory allocator':  get_option('malloc')}
2953summary_info += {'avx2 optimization': config_host.has_key('CONFIG_AVX2_OPT')}
2954summary_info += {'avx512f optimization': config_host.has_key('CONFIG_AVX512F_OPT')}
2955summary_info += {'gprof enabled':     config_host.has_key('CONFIG_GPROF')}
2956summary_info += {'gcov':              get_option('b_coverage')}
2957summary_info += {'thread sanitizer':  config_host.has_key('CONFIG_TSAN')}
2958summary_info += {'CFI support':       get_option('cfi')}
2959if get_option('cfi')
2960  summary_info += {'CFI debug support': get_option('cfi_debug')}
2961endif
2962summary_info += {'strip binaries':    get_option('strip')}
2963summary_info += {'sparse':            sparse.found() ? sparse.full_path() : false}
2964summary_info += {'mingw32 support':   targetos == 'windows'}
2965
2966# snarf the cross-compilation information for tests
2967foreach target: target_dirs
2968  tcg_mak = meson.current_build_dir() / 'tests/tcg' / 'config-' + target + '.mak'
2969  if fs.exists(tcg_mak)
2970    config_cross_tcg = keyval.load(tcg_mak)
2971    target = config_cross_tcg['TARGET_NAME']
2972    compiler = ''
2973    if 'DOCKER_CROSS_CC_GUEST' in config_cross_tcg
2974      summary_info += {target + ' tests': config_cross_tcg['DOCKER_CROSS_CC_GUEST'] +
2975                                          ' via ' + config_cross_tcg['DOCKER_IMAGE']}
2976    elif 'CROSS_CC_GUEST' in config_cross_tcg
2977      summary_info += {target + ' tests'
2978                                : config_cross_tcg['CROSS_CC_GUEST'] }
2979    endif
2980   endif
2981endforeach
2982
2983summary(summary_info, bool_yn: true, section: 'Compilation')
2984
2985# Targets and accelerators
2986summary_info = {}
2987if have_system
2988  summary_info += {'KVM support':       config_all.has_key('CONFIG_KVM')}
2989  summary_info += {'HAX support':       config_all.has_key('CONFIG_HAX')}
2990  summary_info += {'HVF support':       config_all.has_key('CONFIG_HVF')}
2991  summary_info += {'WHPX support':      config_all.has_key('CONFIG_WHPX')}
2992  summary_info += {'NVMM support':      config_all.has_key('CONFIG_NVMM')}
2993  summary_info += {'Xen support':       config_host.has_key('CONFIG_XEN_BACKEND')}
2994  if config_host.has_key('CONFIG_XEN_BACKEND')
2995    summary_info += {'xen ctrl version':  config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']}
2996  endif
2997endif
2998summary_info += {'TCG support':       config_all.has_key('CONFIG_TCG')}
2999if config_all.has_key('CONFIG_TCG')
3000  if get_option('tcg_interpreter')
3001    summary_info += {'TCG backend':   'TCI (TCG with bytecode interpreter, experimental and slow)'}
3002  else
3003    summary_info += {'TCG backend':   'native (@0@)'.format(cpu)}
3004  endif
3005  summary_info += {'TCG plugins': config_host.has_key('CONFIG_PLUGIN')}
3006  summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')}
3007endif
3008summary_info += {'target list':       ' '.join(target_dirs)}
3009if have_system
3010  summary_info += {'default devices':   get_option('default_devices')}
3011  summary_info += {'out of process emulation': multiprocess_allowed}
3012endif
3013summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
3014
3015# Block layer
3016summary_info = {}
3017summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']}
3018summary_info += {'coroutine pool':    config_host['CONFIG_COROUTINE_POOL'] == '1'}
3019if have_block
3020  summary_info += {'Block whitelist (rw)': config_host['CONFIG_BDRV_RW_WHITELIST']}
3021  summary_info += {'Block whitelist (ro)': config_host['CONFIG_BDRV_RO_WHITELIST']}
3022  summary_info += {'Use block whitelist in tools': config_host.has_key('CONFIG_BDRV_WHITELIST_TOOLS')}
3023  summary_info += {'VirtFS support':    have_virtfs}
3024  summary_info += {'build virtiofs daemon': have_virtiofsd}
3025  summary_info += {'Live block migration': config_host.has_key('CONFIG_LIVE_BLOCK_MIGRATION')}
3026  summary_info += {'replication support': config_host.has_key('CONFIG_REPLICATION')}
3027  summary_info += {'bochs support':     config_host.has_key('CONFIG_BOCHS')}
3028  summary_info += {'cloop support':     config_host.has_key('CONFIG_CLOOP')}
3029  summary_info += {'dmg support':       config_host.has_key('CONFIG_DMG')}
3030  summary_info += {'qcow v1 support':   config_host.has_key('CONFIG_QCOW1')}
3031  summary_info += {'vdi support':       config_host.has_key('CONFIG_VDI')}
3032  summary_info += {'vvfat support':     config_host.has_key('CONFIG_VVFAT')}
3033  summary_info += {'qed support':       config_host.has_key('CONFIG_QED')}
3034  summary_info += {'parallels support': config_host.has_key('CONFIG_PARALLELS')}
3035  summary_info += {'FUSE exports':      fuse.found()}
3036endif
3037summary(summary_info, bool_yn: true, section: 'Block layer support')
3038
3039# Crypto
3040summary_info = {}
3041summary_info += {'TLS priority':      config_host['CONFIG_TLS_PRIORITY']}
3042summary_info += {'GNUTLS support':    gnutls.found()}
3043summary_info += {'GNUTLS crypto':     gnutls_crypto.found()}
3044# TODO: add back version
3045summary_info += {'libgcrypt':         gcrypt.found()}
3046# TODO: add back version
3047summary_info += {'nettle':            nettle.found()}
3048if nettle.found()
3049   summary_info += {'  XTS':             xts != 'private'}
3050endif
3051summary_info += {'crypto afalg':      config_host.has_key('CONFIG_AF_ALG')}
3052summary_info += {'rng-none':          config_host.has_key('CONFIG_RNG_NONE')}
3053summary_info += {'Linux keyring':     config_host.has_key('CONFIG_SECRET_KEYRING')}
3054summary(summary_info, bool_yn: true, section: 'Crypto')
3055
3056# Libraries
3057summary_info = {}
3058if targetos == 'darwin'
3059  summary_info += {'Cocoa support':   cocoa.found()}
3060endif
3061# TODO: add back version
3062summary_info += {'SDL support':       sdl.found()}
3063summary_info += {'SDL image support': sdl_image.found()}
3064# TODO: add back version
3065summary_info += {'GTK support':       gtk.found()}
3066summary_info += {'pixman':            pixman.found()}
3067# TODO: add back version
3068summary_info += {'VTE support':       vte.found()}
3069# TODO: add back version
3070summary_info += {'slirp support':     slirp_opt == 'disabled' ? false : slirp_opt}
3071summary_info += {'libtasn1':          tasn1.found()}
3072summary_info += {'PAM':               pam.found()}
3073summary_info += {'iconv support':     iconv.found()}
3074summary_info += {'curses support':    curses.found()}
3075# TODO: add back version
3076summary_info += {'virgl support':     virgl.found()}
3077summary_info += {'curl support':      curl.found()}
3078summary_info += {'Multipath support': mpathpersist.found()}
3079summary_info += {'VNC support':       vnc.found()}
3080if vnc.found()
3081  summary_info += {'VNC SASL support':  sasl.found()}
3082  summary_info += {'VNC JPEG support':  jpeg.found()}
3083  summary_info += {'VNC PNG support':   png.found()}
3084endif
3085summary_info += {'brlapi support':    brlapi.found()}
3086summary_info += {'vde support':       config_host.has_key('CONFIG_VDE')}
3087summary_info += {'netmap support':    config_host.has_key('CONFIG_NETMAP')}
3088summary_info += {'Linux AIO support': config_host.has_key('CONFIG_LINUX_AIO')}
3089summary_info += {'Linux io_uring support': linux_io_uring.found()}
3090summary_info += {'ATTR/XATTR support': libattr.found()}
3091summary_info += {'RDMA support':      config_host.has_key('CONFIG_RDMA')}
3092summary_info += {'PVRDMA support':    config_host.has_key('CONFIG_PVRDMA')}
3093summary_info += {'fdt support':       fdt_opt == 'disabled' ? false : fdt_opt}
3094summary_info += {'libcap-ng support': libcap_ng.found()}
3095summary_info += {'bpf support': libbpf.found()}
3096# TODO: add back protocol and server version
3097summary_info += {'spice support':     config_host.has_key('CONFIG_SPICE')}
3098summary_info += {'rbd support':       rbd.found()}
3099summary_info += {'xfsctl support':    config_host.has_key('CONFIG_XFS')}
3100summary_info += {'smartcard support': cacard.found()}
3101summary_info += {'U2F support':       u2f.found()}
3102summary_info += {'libusb':            libusb.found()}
3103summary_info += {'usb net redir':     usbredir.found()}
3104summary_info += {'OpenGL support':    config_host.has_key('CONFIG_OPENGL')}
3105summary_info += {'GBM':               gbm.found()}
3106summary_info += {'libiscsi support':  libiscsi.found()}
3107summary_info += {'libnfs support':    libnfs.found()}
3108if targetos == 'windows'
3109  if config_host.has_key('CONFIG_GUEST_AGENT')
3110    summary_info += {'QGA VSS support':   config_host.has_key('CONFIG_QGA_VSS')}
3111    summary_info += {'QGA w32 disk info': config_host.has_key('CONFIG_QGA_NTDDSCSI')}
3112  endif
3113endif
3114summary_info += {'seccomp support':   seccomp.found()}
3115summary_info += {'GlusterFS support': glusterfs.found()}
3116summary_info += {'TPM support':       config_host.has_key('CONFIG_TPM')}
3117summary_info += {'libssh support':    config_host.has_key('CONFIG_LIBSSH')}
3118summary_info += {'lzo support':       lzo.found()}
3119summary_info += {'snappy support':    snappy.found()}
3120summary_info += {'bzip2 support':     libbzip2.found()}
3121summary_info += {'lzfse support':     liblzfse.found()}
3122summary_info += {'zstd support':      zstd.found()}
3123summary_info += {'NUMA host support': config_host.has_key('CONFIG_NUMA')}
3124summary_info += {'libxml2':           libxml2.found()}
3125summary_info += {'capstone':          capstone_opt == 'disabled' ? false : capstone_opt}
3126summary_info += {'libpmem support':   libpmem.found()}
3127summary_info += {'libdaxctl support': libdaxctl.found()}
3128summary_info += {'libudev':           libudev.found()}
3129summary_info += {'FUSE lseek':        fuse_lseek.found()}
3130summary(summary_info, bool_yn: true, section: 'Dependencies')
3131
3132if not supported_cpus.contains(cpu)
3133  message()
3134  warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!')
3135  message()
3136  message('CPU host architecture ' + cpu + ' support is not currently maintained.')
3137  message('The QEMU project intends to remove support for this host CPU in')
3138  message('a future release if nobody volunteers to maintain it and to')
3139  message('provide a build host for our continuous integration setup.')
3140  message('configure has succeeded and you can continue to build, but')
3141  message('if you care about QEMU on this platform you should contact')
3142  message('us upstream at qemu-devel@nongnu.org.')
3143endif
3144
3145if not supported_oses.contains(targetos)
3146  message()
3147  warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!')
3148  message()
3149  message('Host OS ' + targetos + 'support is not currently maintained.')
3150  message('The QEMU project intends to remove support for this host OS in')
3151  message('a future release if nobody volunteers to maintain it and to')
3152  message('provide a build host for our continuous integration setup.')
3153  message('configure has succeeded and you can continue to build, but')
3154  message('if you care about QEMU on this platform you should contact')
3155  message('us upstream at qemu-devel@nongnu.org.')
3156endif
3157