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