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