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