xref: /openbmc/qemu/meson.build (revision 1abaec9a)
1project('qemu', ['c'], meson_version: '>=0.59.3',
2        default_options: ['warning_level=1', 'c_std=gnu11', 'cpp_std=gnu++11', 'b_colorout=auto',
3                          'b_staticpic=false', 'stdsplit=false', 'optimization=2', 'b_pie=true'],
4        version: files('VERSION'))
5
6add_test_setup('quick', exclude_suites: ['slow', 'thorough'], is_default: true)
7add_test_setup('slow', exclude_suites: ['thorough'], env: ['G_TEST_SLOW=1', 'SPEED=slow'])
8add_test_setup('thorough', env: ['G_TEST_SLOW=1', 'SPEED=thorough'])
9
10not_found = dependency('', required: false)
11keyval = import('keyval')
12ss = import('sourceset')
13fs = import('fs')
14
15sh = find_program('sh')
16cc = meson.get_compiler('c')
17config_host = keyval.load(meson.current_build_dir() / 'config-host.mak')
18enable_modules = 'CONFIG_MODULES' in config_host
19enable_static = 'CONFIG_STATIC' in config_host
20
21# Allow both shared and static libraries unless --enable-static
22static_kwargs = enable_static ? {'static': true} : {}
23
24# Temporary directory used for files created while
25# configure runs. Since it is in the build directory
26# we can safely blow away any previous version of it
27# (and we need not jump through hoops to try to delete
28# it when configure exits.)
29tmpdir = meson.current_build_dir() / 'meson-private/temp'
30
31if get_option('qemu_suffix').startswith('/')
32  error('qemu_suffix cannot start with a /')
33endif
34
35qemu_confdir = get_option('sysconfdir') / get_option('qemu_suffix')
36qemu_datadir = get_option('datadir') / get_option('qemu_suffix')
37qemu_docdir = get_option('docdir') / get_option('qemu_suffix')
38qemu_moddir = get_option('libdir') / get_option('qemu_suffix')
39
40qemu_desktopdir = get_option('datadir') / 'applications'
41qemu_icondir = get_option('datadir') / 'icons'
42
43config_host_data = configuration_data()
44genh = []
45qapi_trace_events = []
46
47bsd_oses = ['gnu/kfreebsd', 'freebsd', 'netbsd', 'openbsd', 'dragonfly', 'darwin']
48supported_oses = ['windows', 'freebsd', 'netbsd', 'openbsd', 'darwin', 'sunos', 'linux']
49supported_cpus = ['ppc', 'ppc64', 's390x', 'riscv', 'x86', 'x86_64',
50  'arm', 'aarch64', 'loongarch64', 'mips', 'mips64', 'sparc', 'sparc64']
51
52cpu = host_machine.cpu_family()
53
54# Unify riscv* to a single family.
55if cpu in ['riscv32', 'riscv64']
56  cpu = 'riscv'
57endif
58
59targetos = host_machine.system()
60
61target_dirs = config_host['TARGET_DIRS'].split()
62have_linux_user = false
63have_bsd_user = false
64have_system = false
65foreach target : target_dirs
66  have_linux_user = have_linux_user or target.endswith('linux-user')
67  have_bsd_user = have_bsd_user or target.endswith('bsd-user')
68  have_system = have_system or target.endswith('-softmmu')
69endforeach
70have_user = have_linux_user or have_bsd_user
71have_tools = get_option('tools') \
72  .disable_auto_if(not have_system) \
73  .allowed()
74have_ga = get_option('guest_agent') \
75  .disable_auto_if(not have_system and not have_tools) \
76  .require(targetos in ['sunos', 'linux', 'windows'],
77           error_message: 'unsupported OS for QEMU guest agent') \
78  .allowed()
79have_block = have_system or have_tools
80
81python = import('python').find_installation()
82
83if cpu not in supported_cpus
84  host_arch = 'unknown'
85elif cpu == 'x86'
86  host_arch = 'i386'
87elif cpu == 'mips64'
88  host_arch = 'mips'
89else
90  host_arch = cpu
91endif
92
93if cpu in ['x86', 'x86_64']
94  kvm_targets = ['i386-softmmu', 'x86_64-softmmu']
95elif cpu == 'aarch64'
96  kvm_targets = ['aarch64-softmmu']
97elif cpu == 's390x'
98  kvm_targets = ['s390x-softmmu']
99elif cpu in ['ppc', 'ppc64']
100  kvm_targets = ['ppc-softmmu', 'ppc64-softmmu']
101elif cpu in ['mips', 'mips64']
102  kvm_targets = ['mips-softmmu', 'mipsel-softmmu', 'mips64-softmmu', 'mips64el-softmmu']
103elif cpu in ['riscv']
104  kvm_targets = ['riscv32-softmmu', 'riscv64-softmmu']
105else
106  kvm_targets = []
107endif
108
109kvm_targets_c = '""'
110if get_option('kvm').allowed() and targetos == 'linux'
111  kvm_targets_c = '"' + '" ,"'.join(kvm_targets) + '"'
112endif
113config_host_data.set('CONFIG_KVM_TARGETS', kvm_targets_c)
114
115accelerator_targets = { 'CONFIG_KVM': kvm_targets }
116
117if cpu in ['aarch64']
118  accelerator_targets += {
119    'CONFIG_HVF': ['aarch64-softmmu']
120  }
121endif
122
123if cpu in ['x86', 'x86_64', 'arm', 'aarch64']
124  # i386 emulator provides xenpv machine type for multiple architectures
125  accelerator_targets += {
126    'CONFIG_XEN': ['i386-softmmu', 'x86_64-softmmu'],
127  }
128endif
129if cpu in ['x86', 'x86_64']
130  accelerator_targets += {
131    'CONFIG_HAX': ['i386-softmmu', 'x86_64-softmmu'],
132    'CONFIG_HVF': ['x86_64-softmmu'],
133    'CONFIG_NVMM': ['i386-softmmu', 'x86_64-softmmu'],
134    'CONFIG_WHPX': ['i386-softmmu', 'x86_64-softmmu'],
135  }
136endif
137
138modular_tcg = []
139# Darwin does not support references to thread-local variables in modules
140if targetos != 'darwin'
141  modular_tcg = ['i386-softmmu', 'x86_64-softmmu']
142endif
143
144edk2_targets = [ 'arm-softmmu', 'aarch64-softmmu', 'i386-softmmu', 'x86_64-softmmu' ]
145unpack_edk2_blobs = false
146foreach target : edk2_targets
147  if target in target_dirs
148    bzip2 = find_program('bzip2', required: get_option('install_blobs'))
149    unpack_edk2_blobs = bzip2.found()
150    break
151  endif
152endforeach
153
154dtrace = not_found
155stap = not_found
156if 'dtrace' in get_option('trace_backends')
157  dtrace = find_program('dtrace', required: true)
158  stap = find_program('stap', required: false)
159  if stap.found()
160    # Workaround to avoid dtrace(1) producing a file with 'hidden' symbol
161    # visibility. Define STAP_SDT_V2 to produce 'default' symbol visibility
162    # instead. QEMU --enable-modules depends on this because the SystemTap
163    # semaphores are linked into the main binary and not the module's shared
164    # object.
165    add_global_arguments('-DSTAP_SDT_V2',
166                         native: false, language: ['c', 'cpp', 'objc'])
167  endif
168endif
169
170if get_option('iasl') == ''
171  iasl = find_program('iasl', required: false)
172else
173  iasl = find_program(get_option('iasl'), required: true)
174endif
175
176##################
177# Compiler flags #
178##################
179
180qemu_cflags = config_host['QEMU_CFLAGS'].split()
181qemu_cxxflags = config_host['QEMU_CXXFLAGS'].split()
182qemu_objcflags = config_host['QEMU_OBJCFLAGS'].split()
183qemu_ldflags = config_host['QEMU_LDFLAGS'].split()
184
185if targetos == 'windows'
186  qemu_ldflags += cc.get_supported_link_arguments('-Wl,--no-seh', '-Wl,--nxcompat')
187  # Disable ASLR for debug builds to allow debugging with gdb
188  if get_option('optimization') == '0'
189    qemu_ldflags += cc.get_supported_link_arguments('-Wl,--dynamicbase')
190  endif
191endif
192
193if get_option('gprof')
194  qemu_cflags += ['-p']
195  qemu_cxxflags += ['-p']
196  qemu_objcflags += ['-p']
197  qemu_ldflags += ['-p']
198endif
199
200# Specify linker-script with add_project_link_arguments so that it is not placed
201# within a linker --start-group/--end-group pair
202if get_option('fuzzing')
203  add_project_link_arguments(['-Wl,-T,',
204                              (meson.current_source_dir() / 'tests/qtest/fuzz/fork_fuzz.ld')],
205                             native: false, language: ['c', 'cpp', 'objc'])
206
207  # Specify a filter to only instrument code that is directly related to
208  # virtual-devices.
209  configure_file(output: 'instrumentation-filter',
210                 input: 'scripts/oss-fuzz/instrumentation-filter-template',
211                 copy: true)
212
213  if cc.compiles('int main () { return 0; }',
214                  name: '-fsanitize-coverage-allowlist=/dev/null',
215                 args: ['-fsanitize-coverage-allowlist=/dev/null'] )
216    add_global_arguments('-fsanitize-coverage-allowlist=instrumentation-filter',
217                         native: false, language: ['c', 'cpp', 'objc'])
218  endif
219
220  if get_option('fuzzing_engine') == ''
221    # Add CFLAGS to tell clang to add fuzzer-related instrumentation to all the
222    # compiled code.  To build non-fuzzer binaries with --enable-fuzzing, link
223    # everything with fsanitize=fuzzer-no-link. Otherwise, the linker will be
224    # unable to bind the fuzzer-related callbacks added by instrumentation.
225    add_global_arguments('-fsanitize=fuzzer-no-link',
226                         native: false, language: ['c', 'cpp', 'objc'])
227    add_global_link_arguments('-fsanitize=fuzzer-no-link',
228                              native: false, language: ['c', 'cpp', 'objc'])
229    # For the actual fuzzer binaries, we need to link against the libfuzzer
230    # library. They need to be configurable, to support OSS-Fuzz
231    fuzz_exe_ldflags = ['-fsanitize=fuzzer']
232  else
233    # LIB_FUZZING_ENGINE was set; assume we are running on OSS-Fuzz, and
234    # the needed CFLAGS have already been provided
235    fuzz_exe_ldflags = get_option('fuzzing_engine').split()
236  endif
237endif
238
239add_global_arguments(qemu_cflags, native: false, language: ['c'])
240add_global_arguments(qemu_cxxflags, native: false, language: ['cpp'])
241add_global_arguments(qemu_objcflags, native: false, language: ['objc'])
242add_global_link_arguments(qemu_ldflags, native: false, language: ['c', 'cpp', 'objc'])
243
244if targetos == 'linux'
245  add_project_arguments('-isystem', meson.current_source_dir() / 'linux-headers',
246                        '-isystem', 'linux-headers',
247                        language: ['c', 'cpp'])
248endif
249
250add_project_arguments('-iquote', '.',
251                      '-iquote', meson.current_source_dir(),
252                      '-iquote', meson.current_source_dir() / 'include',
253                      '-iquote', meson.current_source_dir() / 'disas/libvixl',
254                      language: ['c', 'cpp', 'objc'])
255
256link_language = meson.get_external_property('link_language', 'cpp')
257if link_language == 'cpp'
258  add_languages('cpp', required: true, native: false)
259  cxx = meson.get_compiler('cpp')
260  linker = cxx
261else
262  linker = cc
263endif
264if host_machine.system() == 'darwin'
265  add_languages('objc', required: false, native: false)
266endif
267
268sparse = find_program('cgcc', required: get_option('sparse'))
269if sparse.found()
270  run_target('sparse',
271             command: [find_program('scripts/check_sparse.py'),
272                       'compile_commands.json', sparse.full_path(), '-Wbitwise',
273                       '-Wno-transparent-union', '-Wno-old-initializer',
274                       '-Wno-non-pointer-null'])
275endif
276
277###########################################
278# Target-specific checks and dependencies #
279###########################################
280
281# Fuzzing
282if get_option('fuzzing') and get_option('fuzzing_engine') == '' and \
283    not cc.links('''
284          #include <stdint.h>
285          #include <sys/types.h>
286          int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
287          int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { return 0; }
288        ''',
289        args: ['-Werror', '-fsanitize=fuzzer'])
290  error('Your compiler does not support -fsanitize=fuzzer')
291endif
292
293# Tracing backends
294if 'ftrace' in get_option('trace_backends') and targetos != 'linux'
295  error('ftrace is supported only on Linux')
296endif
297if 'syslog' in get_option('trace_backends') and not cc.compiles('''
298    #include <syslog.h>
299    int main(void) {
300        openlog("qemu", LOG_PID, LOG_DAEMON);
301        syslog(LOG_INFO, "configure");
302        return 0;
303    }''')
304  error('syslog is not supported on this system')
305endif
306
307# Miscellaneous Linux-only features
308get_option('mpath') \
309  .require(targetos == 'linux', error_message: 'Multipath is supported only on Linux')
310
311multiprocess_allowed = get_option('multiprocess') \
312  .require(targetos == 'linux', error_message: 'Multiprocess QEMU is supported only on Linux') \
313  .allowed()
314
315vfio_user_server_allowed = get_option('vfio_user_server') \
316  .require(targetos == 'linux', error_message: 'vfio-user server is supported only on Linux') \
317  .allowed()
318
319have_tpm = get_option('tpm') \
320  .require(targetos != 'windows', error_message: 'TPM emulation only available on POSIX systems') \
321  .allowed()
322
323# vhost
324have_vhost_user = get_option('vhost_user') \
325  .disable_auto_if(targetos != 'linux') \
326  .require(targetos != 'windows',
327           error_message: 'vhost-user is not available on Windows').allowed()
328have_vhost_vdpa = get_option('vhost_vdpa') \
329  .require(targetos == 'linux',
330           error_message: 'vhost-vdpa is only available on Linux').allowed()
331have_vhost_kernel = get_option('vhost_kernel') \
332  .require(targetos == 'linux',
333           error_message: 'vhost-kernel is only available on Linux').allowed()
334have_vhost_user_crypto = get_option('vhost_crypto') \
335  .require(have_vhost_user,
336           error_message: 'vhost-crypto requires vhost-user to be enabled').allowed()
337
338have_vhost = have_vhost_user or have_vhost_vdpa or have_vhost_kernel
339
340have_vhost_net_user = have_vhost_user and get_option('vhost_net').allowed()
341have_vhost_net_vdpa = have_vhost_vdpa and get_option('vhost_net').allowed()
342have_vhost_net_kernel = have_vhost_kernel and get_option('vhost_net').allowed()
343have_vhost_net = have_vhost_net_kernel or have_vhost_net_user or have_vhost_net_vdpa
344
345# Target-specific libraries and flags
346libm = cc.find_library('m', required: false)
347threads = dependency('threads')
348util = cc.find_library('util', required: false)
349winmm = []
350socket = []
351version_res = []
352coref = []
353iokit = []
354emulator_link_args = []
355nvmm =not_found
356hvf = not_found
357midl = not_found
358widl = not_found
359host_dsosuf = '.so'
360if targetos == 'windows'
361  midl = find_program('midl', required: false)
362  widl = find_program('widl', required: false)
363  socket = cc.find_library('ws2_32')
364  winmm = cc.find_library('winmm')
365
366  win = import('windows')
367  version_res = win.compile_resources('version.rc',
368                                      depend_files: files('pc-bios/qemu-nsis.ico'),
369                                      include_directories: include_directories('.'))
370  host_dsosuf = '.dll'
371elif targetos == 'darwin'
372  coref = dependency('appleframeworks', modules: 'CoreFoundation')
373  iokit = dependency('appleframeworks', modules: 'IOKit', required: false)
374  host_dsosuf = '.dylib'
375elif targetos == 'sunos'
376  socket = [cc.find_library('socket'),
377            cc.find_library('nsl'),
378            cc.find_library('resolv')]
379elif targetos == 'haiku'
380  socket = [cc.find_library('posix_error_mapper'),
381            cc.find_library('network'),
382            cc.find_library('bsd')]
383elif targetos == 'openbsd'
384  if get_option('tcg').allowed() and target_dirs.length() > 0
385    # Disable OpenBSD W^X if available
386    emulator_link_args = cc.get_supported_link_arguments('-Wl,-z,wxneeded')
387  endif
388endif
389
390# Target-specific configuration of accelerators
391accelerators = []
392if get_option('kvm').allowed() and targetos == 'linux'
393  accelerators += 'CONFIG_KVM'
394endif
395if get_option('whpx').allowed() and targetos == 'windows'
396  if get_option('whpx').enabled() and host_machine.cpu() != 'x86_64'
397    error('WHPX requires 64-bit host')
398  elif cc.has_header('WinHvPlatform.h', required: get_option('whpx')) and \
399       cc.has_header('WinHvEmulation.h', required: get_option('whpx'))
400    accelerators += 'CONFIG_WHPX'
401  endif
402endif
403if get_option('hvf').allowed()
404  hvf = dependency('appleframeworks', modules: 'Hypervisor',
405                   required: get_option('hvf'))
406  if hvf.found()
407    accelerators += 'CONFIG_HVF'
408  endif
409endif
410if get_option('hax').allowed()
411  if get_option('hax').enabled() or targetos in ['windows', 'darwin', 'netbsd']
412    accelerators += 'CONFIG_HAX'
413  endif
414endif
415if targetos == 'netbsd'
416  nvmm = cc.find_library('nvmm', required: get_option('nvmm'))
417  if nvmm.found()
418    accelerators += 'CONFIG_NVMM'
419  endif
420endif
421
422tcg_arch = host_arch
423if get_option('tcg').allowed()
424  if host_arch == 'unknown'
425    if get_option('tcg_interpreter')
426      warning('Unsupported CPU @0@, will use TCG with TCI (slow)'.format(cpu))
427    else
428      error('Unsupported CPU @0@, try --enable-tcg-interpreter'.format(cpu))
429    endif
430  elif get_option('tcg_interpreter')
431    warning('Use of the TCG interpreter is not recommended on this host')
432    warning('architecture. There is a native TCG execution backend available')
433    warning('which provides substantially better performance and reliability.')
434    warning('It is strongly recommended to remove the --enable-tcg-interpreter')
435    warning('configuration option on this architecture to use the native')
436    warning('backend.')
437  endif
438  if get_option('tcg_interpreter')
439    tcg_arch = 'tci'
440  elif host_arch == 'sparc64'
441    tcg_arch = 'sparc'
442  elif host_arch == 'x86_64'
443    tcg_arch = 'i386'
444  elif host_arch == 'ppc64'
445    tcg_arch = 'ppc'
446  endif
447  add_project_arguments('-iquote', meson.current_source_dir() / 'tcg' / tcg_arch,
448                        language: ['c', 'cpp', 'objc'])
449
450  accelerators += 'CONFIG_TCG'
451  config_host += { 'CONFIG_TCG': 'y' }
452endif
453
454if 'CONFIG_KVM' not in accelerators and get_option('kvm').enabled()
455  error('KVM not available on this platform')
456endif
457if 'CONFIG_HVF' not in accelerators and get_option('hvf').enabled()
458  error('HVF not available on this platform')
459endif
460if 'CONFIG_NVMM' not in accelerators and get_option('nvmm').enabled()
461  error('NVMM not available on this platform')
462endif
463if 'CONFIG_WHPX' not in accelerators and get_option('whpx').enabled()
464  error('WHPX not available on this platform')
465endif
466
467################
468# Dependencies #
469################
470
471# The path to glib.h is added to all compilation commands.  This was
472# grandfathered in from the QEMU Makefiles.
473add_project_arguments(config_host['GLIB_CFLAGS'].split(),
474                      native: false, language: ['c', 'cpp', 'objc'])
475glib = declare_dependency(compile_args: config_host['GLIB_CFLAGS'].split(),
476                          link_args: config_host['GLIB_LIBS'].split(),
477                          version: config_host['GLIB_VERSION'],
478                          variables: {
479                            'bindir': config_host['GLIB_BINDIR'],
480                          })
481# override glib dep with the configure results (for subprojects)
482meson.override_dependency('glib-2.0', glib)
483
484gio = not_found
485gdbus_codegen = not_found
486if not get_option('gio').auto() or have_system
487  gio = dependency('gio-2.0', required: get_option('gio'),
488                   method: 'pkg-config', kwargs: static_kwargs)
489  if gio.found() and not cc.links('''
490    #include <gio/gio.h>
491    int main(void)
492    {
493      g_dbus_proxy_new_sync(0, 0, 0, 0, 0, 0, 0, 0);
494      return 0;
495    }''', dependencies: [glib, gio])
496    if get_option('gio').enabled()
497      error('The installed libgio is broken for static linking')
498    endif
499    gio = not_found
500  endif
501  if gio.found()
502    gdbus_codegen = find_program(gio.get_variable('gdbus_codegen'),
503                                 required: get_option('gio'))
504    gio_unix = dependency('gio-unix-2.0', required: get_option('gio'),
505                          method: 'pkg-config', kwargs: static_kwargs)
506    gio = declare_dependency(dependencies: [gio, gio_unix],
507                             version: gio.version())
508  endif
509endif
510
511lttng = not_found
512if 'ust' in get_option('trace_backends')
513  lttng = dependency('lttng-ust', required: true, version: '>= 2.1',
514                     method: 'pkg-config', kwargs: static_kwargs)
515endif
516pixman = not_found
517if have_system or have_tools
518  pixman = dependency('pixman-1', required: have_system, version:'>=0.21.8',
519                      method: 'pkg-config', kwargs: static_kwargs)
520endif
521zlib = dependency('zlib', required: true, kwargs: static_kwargs)
522
523libaio = not_found
524if not get_option('linux_aio').auto() or have_block
525  libaio = cc.find_library('aio', has_headers: ['libaio.h'],
526                           required: get_option('linux_aio'),
527                           kwargs: static_kwargs)
528endif
529
530linux_io_uring_test = '''
531  #include <liburing.h>
532  #include <linux/errqueue.h>
533
534  int main(void) { return 0; }'''
535
536linux_io_uring = not_found
537if not get_option('linux_io_uring').auto() or have_block
538  linux_io_uring = dependency('liburing', version: '>=0.3',
539                              required: get_option('linux_io_uring'),
540                              method: 'pkg-config', kwargs: static_kwargs)
541  if not cc.links(linux_io_uring_test)
542    linux_io_uring = not_found
543  endif
544endif
545
546libnfs = not_found
547if not get_option('libnfs').auto() or have_block
548  libnfs = dependency('libnfs', version: '>=1.9.3',
549                      required: get_option('libnfs'),
550                      method: 'pkg-config', kwargs: static_kwargs)
551endif
552
553libattr_test = '''
554  #include <stddef.h>
555  #include <sys/types.h>
556  #ifdef CONFIG_LIBATTR
557  #include <attr/xattr.h>
558  #else
559  #include <sys/xattr.h>
560  #endif
561  int main(void) { getxattr(NULL, NULL, NULL, 0); setxattr(NULL, NULL, NULL, 0, 0); return 0; }'''
562
563libattr = not_found
564have_old_libattr = false
565if get_option('attr').allowed()
566  if cc.links(libattr_test)
567    libattr = declare_dependency()
568  else
569    libattr = cc.find_library('attr', has_headers: ['attr/xattr.h'],
570                              required: get_option('attr'),
571                              kwargs: static_kwargs)
572    if libattr.found() and not \
573      cc.links(libattr_test, dependencies: libattr, args: '-DCONFIG_LIBATTR')
574      libattr = not_found
575      if get_option('attr').enabled()
576        error('could not link libattr')
577      else
578        warning('could not link libattr, disabling')
579      endif
580    else
581      have_old_libattr = libattr.found()
582    endif
583  endif
584endif
585
586cocoa = dependency('appleframeworks', modules: 'Cocoa', required: get_option('cocoa'))
587if cocoa.found() and get_option('sdl').enabled()
588  error('Cocoa and SDL cannot be enabled at the same time')
589endif
590if cocoa.found() and get_option('gtk').enabled()
591  error('Cocoa and GTK+ cannot be enabled at the same time')
592endif
593
594vmnet = dependency('appleframeworks', modules: 'vmnet', required: get_option('vmnet'))
595if vmnet.found() and not cc.has_header_symbol('vmnet/vmnet.h',
596                                              'VMNET_BRIDGED_MODE',
597                                              dependencies: vmnet)
598  vmnet = not_found
599  if get_option('vmnet').enabled()
600    error('vmnet.framework API is outdated')
601  else
602    warning('vmnet.framework API is outdated, disabling')
603  endif
604endif
605
606seccomp = not_found
607if not get_option('seccomp').auto() or have_system or have_tools
608  seccomp = dependency('libseccomp', version: '>=2.3.0',
609                       required: get_option('seccomp'),
610                       method: 'pkg-config', kwargs: static_kwargs)
611endif
612
613libcap_ng = not_found
614if not get_option('cap_ng').auto() or have_system or have_tools
615  libcap_ng = cc.find_library('cap-ng', has_headers: ['cap-ng.h'],
616                              required: get_option('cap_ng'),
617                              kwargs: static_kwargs)
618endif
619if libcap_ng.found() and not cc.links('''
620   #include <cap-ng.h>
621   int main(void)
622   {
623     capng_capability_to_name(CAPNG_EFFECTIVE);
624     return 0;
625   }''', dependencies: libcap_ng)
626  libcap_ng = not_found
627  if get_option('cap_ng').enabled()
628    error('could not link libcap-ng')
629  else
630    warning('could not link libcap-ng, disabling')
631  endif
632endif
633
634if get_option('xkbcommon').auto() and not have_system and not have_tools
635  xkbcommon = not_found
636else
637  xkbcommon = dependency('xkbcommon', required: get_option('xkbcommon'),
638                         method: 'pkg-config', kwargs: static_kwargs)
639endif
640
641vde = not_found
642if not get_option('vde').auto() or have_system or have_tools
643  vde = cc.find_library('vdeplug', has_headers: ['libvdeplug.h'],
644                           required: get_option('vde'),
645                           kwargs: static_kwargs)
646endif
647if vde.found() and not cc.links('''
648   #include <libvdeplug.h>
649   int main(void)
650   {
651     struct vde_open_args a = {0, 0, 0};
652     char s[] = "";
653     vde_open(s, s, &a);
654     return 0;
655   }''', dependencies: vde)
656  vde = not_found
657  if get_option('cap_ng').enabled()
658    error('could not link libvdeplug')
659  else
660    warning('could not link libvdeplug, disabling')
661  endif
662endif
663
664pulse = not_found
665if not get_option('pa').auto() or (targetos == 'linux' and have_system)
666  pulse = dependency('libpulse', required: get_option('pa'),
667                     method: 'pkg-config', kwargs: static_kwargs)
668endif
669alsa = not_found
670if not get_option('alsa').auto() or (targetos == 'linux' and have_system)
671  alsa = dependency('alsa', required: get_option('alsa'),
672                    method: 'pkg-config', kwargs: static_kwargs)
673endif
674jack = not_found
675if not get_option('jack').auto() or have_system
676  jack = dependency('jack', required: get_option('jack'),
677                    method: 'pkg-config', kwargs: static_kwargs)
678endif
679
680spice_protocol = not_found
681if not get_option('spice_protocol').auto() or have_system
682  spice_protocol = dependency('spice-protocol', version: '>=0.12.3',
683                              required: get_option('spice_protocol'),
684                              method: 'pkg-config', kwargs: static_kwargs)
685endif
686spice = not_found
687if not get_option('spice').auto() or have_system
688  spice = dependency('spice-server', version: '>=0.12.5',
689                     required: get_option('spice'),
690                     method: 'pkg-config', kwargs: static_kwargs)
691endif
692spice_headers = spice.partial_dependency(compile_args: true, includes: true)
693
694rt = cc.find_library('rt', required: false)
695
696libiscsi = not_found
697if not get_option('libiscsi').auto() or have_block
698  libiscsi = dependency('libiscsi', version: '>=1.9.0',
699                         required: get_option('libiscsi'),
700                         method: 'pkg-config', kwargs: static_kwargs)
701endif
702zstd = not_found
703if not get_option('zstd').auto() or have_block
704  zstd = dependency('libzstd', version: '>=1.4.0',
705                    required: get_option('zstd'),
706                    method: 'pkg-config', kwargs: static_kwargs)
707endif
708virgl = not_found
709
710have_vhost_user_gpu = have_tools and targetos == 'linux' and pixman.found()
711if not get_option('virglrenderer').auto() or have_system or have_vhost_user_gpu
712  virgl = dependency('virglrenderer',
713                     method: 'pkg-config',
714                     required: get_option('virglrenderer'),
715                     kwargs: static_kwargs)
716endif
717curl = not_found
718if not get_option('curl').auto() or have_block
719  curl = dependency('libcurl', version: '>=7.29.0',
720                    method: 'pkg-config',
721                    required: get_option('curl'),
722                    kwargs: static_kwargs)
723endif
724libudev = not_found
725if targetos == 'linux' and (have_system or have_tools)
726  libudev = dependency('libudev',
727                       method: 'pkg-config',
728                       required: get_option('libudev'),
729                       kwargs: static_kwargs)
730endif
731
732mpathlibs = [libudev]
733mpathpersist = not_found
734mpathpersist_new_api = false
735if targetos == 'linux' and have_tools and get_option('mpath').allowed()
736  mpath_test_source_new = '''
737    #include <libudev.h>
738    #include <mpath_persist.h>
739    unsigned mpath_mx_alloc_len = 1024;
740    int logsink;
741    static struct config *multipath_conf;
742    extern struct udev *udev;
743    extern struct config *get_multipath_config(void);
744    extern void put_multipath_config(struct config *conf);
745    struct udev *udev;
746    struct config *get_multipath_config(void) { return multipath_conf; }
747    void put_multipath_config(struct config *conf) { }
748    int main(void) {
749        udev = udev_new();
750        multipath_conf = mpath_lib_init();
751        return 0;
752    }'''
753  mpath_test_source_old = '''
754      #include <libudev.h>
755      #include <mpath_persist.h>
756      unsigned mpath_mx_alloc_len = 1024;
757      int logsink;
758      int main(void) {
759          struct udev *udev = udev_new();
760          mpath_lib_init(udev);
761          return 0;
762      }'''
763  libmpathpersist = cc.find_library('mpathpersist',
764                                    required: get_option('mpath'),
765                                    kwargs: static_kwargs)
766  if libmpathpersist.found()
767    mpathlibs += libmpathpersist
768    if enable_static
769      mpathlibs += cc.find_library('devmapper',
770                                     required: get_option('mpath'),
771                                     kwargs: static_kwargs)
772    endif
773    mpathlibs += cc.find_library('multipath',
774                                 required: get_option('mpath'),
775                                 kwargs: static_kwargs)
776    foreach lib: mpathlibs
777      if not lib.found()
778        mpathlibs = []
779        break
780      endif
781    endforeach
782    if mpathlibs.length() == 0
783      msg = 'Dependencies missing for libmpathpersist'
784    elif cc.links(mpath_test_source_new, dependencies: mpathlibs)
785      mpathpersist = declare_dependency(dependencies: mpathlibs)
786      mpathpersist_new_api = true
787    elif cc.links(mpath_test_source_old, dependencies: mpathlibs)
788      mpathpersist = declare_dependency(dependencies: mpathlibs)
789    else
790      msg = 'Cannot detect libmpathpersist API'
791    endif
792    if not mpathpersist.found()
793      if get_option('mpath').enabled()
794        error(msg)
795      else
796        warning(msg + ', disabling')
797      endif
798    endif
799  endif
800endif
801
802iconv = not_found
803curses = not_found
804if have_system and get_option('curses').allowed()
805  curses_test = '''
806    #if defined(__APPLE__) || defined(__OpenBSD__)
807    #define _XOPEN_SOURCE_EXTENDED 1
808    #endif
809    #include <locale.h>
810    #include <curses.h>
811    #include <wchar.h>
812    int main(void) {
813      wchar_t wch = L'w';
814      setlocale(LC_ALL, "");
815      resize_term(0, 0);
816      addwstr(L"wide chars\n");
817      addnwstr(&wch, 1);
818      add_wch(WACS_DEGREE);
819      return 0;
820    }'''
821
822  curses_dep_list = targetos == 'windows' ? ['ncurses', 'ncursesw'] : ['ncursesw']
823  foreach curses_dep : curses_dep_list
824    if not curses.found()
825      curses = dependency(curses_dep,
826                          required: false,
827                          method: 'pkg-config',
828                          kwargs: static_kwargs)
829    endif
830  endforeach
831  msg = get_option('curses').enabled() ? 'curses library not found' : ''
832  curses_compile_args = ['-DNCURSES_WIDECHAR=1']
833  if curses.found()
834    if cc.links(curses_test, args: curses_compile_args, dependencies: [curses])
835      curses = declare_dependency(compile_args: curses_compile_args, dependencies: [curses])
836    else
837      msg = 'curses package not usable'
838      curses = not_found
839    endif
840  endif
841  if not curses.found()
842    has_curses_h = cc.has_header('curses.h', args: curses_compile_args)
843    if targetos != 'windows' and not has_curses_h
844      message('Trying with /usr/include/ncursesw')
845      curses_compile_args += ['-I/usr/include/ncursesw']
846      has_curses_h = cc.has_header('curses.h', args: curses_compile_args)
847    endif
848    if has_curses_h
849      curses_libname_list = (targetos == 'windows' ? ['pdcurses'] : ['ncursesw', 'cursesw'])
850      foreach curses_libname : curses_libname_list
851        libcurses = cc.find_library(curses_libname,
852                                    required: false,
853                                    kwargs: static_kwargs)
854        if libcurses.found()
855          if cc.links(curses_test, args: curses_compile_args, dependencies: libcurses)
856            curses = declare_dependency(compile_args: curses_compile_args,
857                                        dependencies: [libcurses])
858            break
859          else
860            msg = 'curses library not usable'
861          endif
862        endif
863      endforeach
864    endif
865  endif
866  if get_option('iconv').allowed()
867    foreach link_args : [ ['-liconv'], [] ]
868      # Programs will be linked with glib and this will bring in libiconv on FreeBSD.
869      # We need to use libiconv if available because mixing libiconv's headers with
870      # the system libc does not work.
871      # However, without adding glib to the dependencies -L/usr/local/lib will not be
872      # included in the command line and libiconv will not be found.
873      if cc.links('''
874        #include <iconv.h>
875        int main(void) {
876          iconv_t conv = iconv_open("WCHAR_T", "UCS-2");
877          return conv != (iconv_t) -1;
878        }''', args: config_host['GLIB_CFLAGS'].split() + config_host['GLIB_LIBS'].split() + link_args)
879        iconv = declare_dependency(link_args: link_args, dependencies: glib)
880        break
881      endif
882    endforeach
883  endif
884  if curses.found() and not iconv.found()
885    if get_option('iconv').enabled()
886      error('iconv not available')
887    endif
888    msg = 'iconv required for curses UI but not available'
889    curses = not_found
890  endif
891  if not curses.found() and msg != ''
892    if get_option('curses').enabled()
893      error(msg)
894    else
895      warning(msg + ', disabling')
896    endif
897  endif
898endif
899
900brlapi = not_found
901if not get_option('brlapi').auto() or have_system
902  brlapi = cc.find_library('brlapi', has_headers: ['brlapi.h'],
903                         required: get_option('brlapi'),
904                         kwargs: static_kwargs)
905  if brlapi.found() and not cc.links('''
906     #include <brlapi.h>
907     #include <stddef.h>
908     int main(void) { return brlapi__openConnection (NULL, NULL, NULL); }''', dependencies: brlapi)
909    brlapi = not_found
910    if get_option('brlapi').enabled()
911      error('could not link brlapi')
912    else
913      warning('could not link brlapi, disabling')
914    endif
915  endif
916endif
917
918sdl = not_found
919if not get_option('sdl').auto() or (have_system and not cocoa.found())
920  sdl = dependency('sdl2', required: get_option('sdl'), kwargs: static_kwargs)
921  sdl_image = not_found
922endif
923if sdl.found()
924  # work around 2.0.8 bug
925  sdl = declare_dependency(compile_args: '-Wno-undef',
926                           dependencies: sdl)
927  sdl_image = dependency('SDL2_image', required: get_option('sdl_image'),
928                         method: 'pkg-config', kwargs: static_kwargs)
929else
930  if get_option('sdl_image').enabled()
931    error('sdl-image required, but SDL was @0@'.format(
932          get_option('sdl').disabled() ? 'disabled' : 'not found'))
933  endif
934  sdl_image = not_found
935endif
936
937rbd = not_found
938if not get_option('rbd').auto() or have_block
939  librados = cc.find_library('rados', required: get_option('rbd'),
940                             kwargs: static_kwargs)
941  librbd = cc.find_library('rbd', has_headers: ['rbd/librbd.h'],
942                           required: get_option('rbd'),
943                           kwargs: static_kwargs)
944  if librados.found() and librbd.found()
945    if cc.links('''
946      #include <stdio.h>
947      #include <rbd/librbd.h>
948      int main(void) {
949        rados_t cluster;
950        rados_create(&cluster, NULL);
951        #if LIBRBD_VERSION_CODE < LIBRBD_VERSION(1, 12, 0)
952        #error
953        #endif
954        return 0;
955      }''', dependencies: [librbd, librados])
956      rbd = declare_dependency(dependencies: [librbd, librados])
957    elif get_option('rbd').enabled()
958      error('librbd >= 1.12.0 required')
959    else
960      warning('librbd >= 1.12.0 not found, disabling')
961    endif
962  endif
963endif
964
965glusterfs = not_found
966glusterfs_ftruncate_has_stat = false
967glusterfs_iocb_has_stat = false
968if not get_option('glusterfs').auto() or have_block
969  glusterfs = dependency('glusterfs-api', version: '>=3',
970                         required: get_option('glusterfs'),
971                         method: 'pkg-config', kwargs: static_kwargs)
972  if glusterfs.found()
973    glusterfs_ftruncate_has_stat = cc.links('''
974      #include <glusterfs/api/glfs.h>
975
976      int
977      main(void)
978      {
979          /* new glfs_ftruncate() passes two additional args */
980          return glfs_ftruncate(NULL, 0, NULL, NULL);
981      }
982    ''', dependencies: glusterfs)
983    glusterfs_iocb_has_stat = cc.links('''
984      #include <glusterfs/api/glfs.h>
985
986      /* new glfs_io_cbk() passes two additional glfs_stat structs */
987      static void
988      glusterfs_iocb(glfs_fd_t *fd, ssize_t ret, struct glfs_stat *prestat, struct glfs_stat *poststat, void *data)
989      {}
990
991      int
992      main(void)
993      {
994          glfs_io_cbk iocb = &glusterfs_iocb;
995          iocb(NULL, 0 , NULL, NULL, NULL);
996          return 0;
997      }
998    ''', dependencies: glusterfs)
999  endif
1000endif
1001
1002libssh = not_found
1003if not get_option('libssh').auto() or have_block
1004  libssh = dependency('libssh', version: '>=0.8.7',
1005                    method: 'pkg-config',
1006                    required: get_option('libssh'),
1007                    kwargs: static_kwargs)
1008endif
1009
1010libbzip2 = not_found
1011if not get_option('bzip2').auto() or have_block
1012  libbzip2 = cc.find_library('bz2', has_headers: ['bzlib.h'],
1013                             required: get_option('bzip2'),
1014                             kwargs: static_kwargs)
1015  if libbzip2.found() and not cc.links('''
1016     #include <bzlib.h>
1017     int main(void) { BZ2_bzlibVersion(); return 0; }''', dependencies: libbzip2)
1018    libbzip2 = not_found
1019    if get_option('bzip2').enabled()
1020      error('could not link libbzip2')
1021    else
1022      warning('could not link libbzip2, disabling')
1023    endif
1024  endif
1025endif
1026
1027liblzfse = not_found
1028if not get_option('lzfse').auto() or have_block
1029  liblzfse = cc.find_library('lzfse', has_headers: ['lzfse.h'],
1030                             required: get_option('lzfse'),
1031                             kwargs: static_kwargs)
1032endif
1033if liblzfse.found() and not cc.links('''
1034   #include <lzfse.h>
1035   int main(void) { lzfse_decode_scratch_size(); return 0; }''', dependencies: liblzfse)
1036  liblzfse = not_found
1037  if get_option('lzfse').enabled()
1038    error('could not link liblzfse')
1039  else
1040    warning('could not link liblzfse, disabling')
1041  endif
1042endif
1043
1044oss = not_found
1045if get_option('oss').allowed() and have_system
1046  if not cc.has_header('sys/soundcard.h')
1047    # not found
1048  elif targetos == 'netbsd'
1049    oss = cc.find_library('ossaudio', required: get_option('oss'),
1050                          kwargs: static_kwargs)
1051  else
1052    oss = declare_dependency()
1053  endif
1054
1055  if not oss.found()
1056    if get_option('oss').enabled()
1057      error('OSS not found')
1058    endif
1059  endif
1060endif
1061dsound = not_found
1062if not get_option('dsound').auto() or (targetos == 'windows' and have_system)
1063  if cc.has_header('dsound.h')
1064    dsound = declare_dependency(link_args: ['-lole32', '-ldxguid'])
1065  endif
1066
1067  if not dsound.found()
1068    if get_option('dsound').enabled()
1069      error('DirectSound not found')
1070    endif
1071  endif
1072endif
1073
1074coreaudio = not_found
1075if not get_option('coreaudio').auto() or (targetos == 'darwin' and have_system)
1076  coreaudio = dependency('appleframeworks', modules: 'CoreAudio',
1077                         required: get_option('coreaudio'))
1078endif
1079
1080opengl = not_found
1081if not get_option('opengl').auto() or have_system or have_vhost_user_gpu
1082  epoxy = dependency('epoxy', method: 'pkg-config',
1083                      required: get_option('opengl'), kwargs: static_kwargs)
1084  if cc.has_header('epoxy/egl.h', dependencies: epoxy)
1085    opengl = epoxy
1086  elif get_option('opengl').enabled()
1087    error('epoxy/egl.h not found')
1088  endif
1089endif
1090gbm = not_found
1091if (have_system or have_tools) and (virgl.found() or opengl.found())
1092  gbm = dependency('gbm', method: 'pkg-config', required: false,
1093                   kwargs: static_kwargs)
1094endif
1095have_vhost_user_gpu = have_vhost_user_gpu and virgl.found() and gbm.found()
1096
1097gnutls = not_found
1098gnutls_crypto = not_found
1099if get_option('gnutls').enabled() or (get_option('gnutls').auto() and have_system)
1100  # For general TLS support our min gnutls matches
1101  # that implied by our platform support matrix
1102  #
1103  # For the crypto backends, we look for a newer
1104  # gnutls:
1105  #
1106  #   Version 3.6.8  is needed to get XTS
1107  #   Version 3.6.13 is needed to get PBKDF
1108  #   Version 3.6.14 is needed to get HW accelerated XTS
1109  #
1110  # If newer enough gnutls isn't available, we can
1111  # still use a different crypto backend to satisfy
1112  # the platform support requirements
1113  gnutls_crypto = dependency('gnutls', version: '>=3.6.14',
1114                             method: 'pkg-config',
1115                             required: false,
1116                             kwargs: static_kwargs)
1117  if gnutls_crypto.found()
1118    gnutls = gnutls_crypto
1119  else
1120    # Our min version if all we need is TLS
1121    gnutls = dependency('gnutls', version: '>=3.5.18',
1122                        method: 'pkg-config',
1123                        required: get_option('gnutls'),
1124                        kwargs: static_kwargs)
1125  endif
1126endif
1127
1128# We prefer use of gnutls for crypto, unless the options
1129# explicitly asked for nettle or gcrypt.
1130#
1131# If gnutls isn't available for crypto, then we'll prefer
1132# gcrypt over nettle for performance reasons.
1133gcrypt = not_found
1134nettle = not_found
1135hogweed = not_found
1136xts = 'none'
1137
1138if get_option('nettle').enabled() and get_option('gcrypt').enabled()
1139  error('Only one of gcrypt & nettle can be enabled')
1140endif
1141
1142# Explicit nettle/gcrypt request, so ignore gnutls for crypto
1143if get_option('nettle').enabled() or get_option('gcrypt').enabled()
1144  gnutls_crypto = not_found
1145endif
1146
1147if not gnutls_crypto.found()
1148  if (not get_option('gcrypt').auto() or have_system) and not get_option('nettle').enabled()
1149    gcrypt = dependency('libgcrypt', version: '>=1.8',
1150                        method: 'config-tool',
1151                        required: get_option('gcrypt'),
1152                        kwargs: static_kwargs)
1153    # Debian has removed -lgpg-error from libgcrypt-config
1154    # as it "spreads unnecessary dependencies" which in
1155    # turn breaks static builds...
1156    if gcrypt.found() and enable_static
1157      gcrypt = declare_dependency(dependencies: [
1158        gcrypt,
1159        cc.find_library('gpg-error', required: true, kwargs: static_kwargs)])
1160    endif
1161  endif
1162  if (not get_option('nettle').auto() or have_system) and not gcrypt.found()
1163    nettle = dependency('nettle', version: '>=3.4',
1164                        method: 'pkg-config',
1165                        required: get_option('nettle'),
1166                        kwargs: static_kwargs)
1167    if nettle.found() and not cc.has_header('nettle/xts.h', dependencies: nettle)
1168      xts = 'private'
1169    endif
1170  endif
1171endif
1172
1173gmp = dependency('gmp', required: false, method: 'pkg-config', kwargs: static_kwargs)
1174if nettle.found() and gmp.found()
1175  hogweed = dependency('hogweed', version: '>=3.4',
1176                       method: 'pkg-config',
1177                       required: get_option('nettle'),
1178                       kwargs: static_kwargs)
1179endif
1180
1181
1182gtk = not_found
1183gtkx11 = not_found
1184vte = not_found
1185if not get_option('gtk').auto() or (have_system and not cocoa.found())
1186  gtk = dependency('gtk+-3.0', version: '>=3.22.0',
1187                   method: 'pkg-config',
1188                   required: get_option('gtk'),
1189                   kwargs: static_kwargs)
1190  if gtk.found()
1191    gtkx11 = dependency('gtk+-x11-3.0', version: '>=3.22.0',
1192                        method: 'pkg-config',
1193                        required: false,
1194                        kwargs: static_kwargs)
1195    gtk = declare_dependency(dependencies: [gtk, gtkx11])
1196
1197    if not get_option('vte').auto() or have_system
1198      vte = dependency('vte-2.91',
1199                       method: 'pkg-config',
1200                       required: get_option('vte'),
1201                       kwargs: static_kwargs)
1202    endif
1203  endif
1204endif
1205
1206x11 = not_found
1207if gtkx11.found()
1208  x11 = dependency('x11', method: 'pkg-config', required: gtkx11.found(),
1209                   kwargs: static_kwargs)
1210endif
1211png = not_found
1212if get_option('png').allowed() and have_system
1213   png = dependency('libpng', required: get_option('png'),
1214                    method: 'pkg-config', kwargs: static_kwargs)
1215endif
1216vnc = not_found
1217jpeg = not_found
1218sasl = not_found
1219if get_option('vnc').allowed() and have_system
1220  vnc = declare_dependency() # dummy dependency
1221  jpeg = dependency('libjpeg', required: get_option('vnc_jpeg'),
1222                    method: 'pkg-config', kwargs: static_kwargs)
1223  sasl = cc.find_library('sasl2', has_headers: ['sasl/sasl.h'],
1224                         required: get_option('vnc_sasl'),
1225                         kwargs: static_kwargs)
1226  if sasl.found()
1227    sasl = declare_dependency(dependencies: sasl,
1228                              compile_args: '-DSTRUCT_IOVEC_DEFINED')
1229  endif
1230endif
1231
1232pam = not_found
1233if not get_option('auth_pam').auto() or have_system
1234  pam = cc.find_library('pam', has_headers: ['security/pam_appl.h'],
1235                        required: get_option('auth_pam'),
1236                        kwargs: static_kwargs)
1237endif
1238if pam.found() and not cc.links('''
1239   #include <stddef.h>
1240   #include <security/pam_appl.h>
1241   int main(void) {
1242     const char *service_name = "qemu";
1243     const char *user = "frank";
1244     const struct pam_conv pam_conv = { 0 };
1245     pam_handle_t *pamh = NULL;
1246     pam_start(service_name, user, &pam_conv, &pamh);
1247     return 0;
1248   }''', dependencies: pam)
1249  pam = not_found
1250  if get_option('auth_pam').enabled()
1251    error('could not link libpam')
1252  else
1253    warning('could not link libpam, disabling')
1254  endif
1255endif
1256
1257snappy = not_found
1258if not get_option('snappy').auto() or have_system
1259  snappy = cc.find_library('snappy', has_headers: ['snappy-c.h'],
1260                           required: get_option('snappy'),
1261                           kwargs: static_kwargs)
1262endif
1263if snappy.found() and not linker.links('''
1264   #include <snappy-c.h>
1265   int main(void) { snappy_max_compressed_length(4096); return 0; }''', dependencies: snappy)
1266  snappy = not_found
1267  if get_option('snappy').enabled()
1268    error('could not link libsnappy')
1269  else
1270    warning('could not link libsnappy, disabling')
1271  endif
1272endif
1273
1274lzo = not_found
1275if not get_option('lzo').auto() or have_system
1276  lzo = cc.find_library('lzo2', has_headers: ['lzo/lzo1x.h'],
1277                        required: get_option('lzo'),
1278                        kwargs: static_kwargs)
1279endif
1280if lzo.found() and not cc.links('''
1281   #include <lzo/lzo1x.h>
1282   int main(void) { lzo_version(); return 0; }''', dependencies: lzo)
1283  lzo = not_found
1284  if get_option('lzo').enabled()
1285    error('could not link liblzo2')
1286  else
1287    warning('could not link liblzo2, disabling')
1288  endif
1289endif
1290
1291numa = not_found
1292if not get_option('numa').auto() or have_system or have_tools
1293  numa = cc.find_library('numa', has_headers: ['numa.h'],
1294                              required: get_option('numa'),
1295                              kwargs: static_kwargs)
1296endif
1297if numa.found() and not cc.links('''
1298   #include <numa.h>
1299   int main(void) { return numa_available(); }
1300   ''', dependencies: numa)
1301  numa = not_found
1302  if get_option('numa').enabled()
1303    error('could not link numa')
1304  else
1305    warning('could not link numa, disabling')
1306  endif
1307endif
1308
1309rdma = not_found
1310if not get_option('rdma').auto() or have_system
1311  libumad = cc.find_library('ibumad', required: get_option('rdma'))
1312  rdma_libs = [cc.find_library('rdmacm', has_headers: ['rdma/rdma_cma.h'],
1313                               required: get_option('rdma'),
1314                               kwargs: static_kwargs),
1315               cc.find_library('ibverbs', required: get_option('rdma'),
1316                               kwargs: static_kwargs),
1317               libumad]
1318  rdma = declare_dependency(dependencies: rdma_libs)
1319  foreach lib: rdma_libs
1320    if not lib.found()
1321      rdma = not_found
1322    endif
1323  endforeach
1324endif
1325
1326xen = not_found
1327if get_option('xen').enabled() or (get_option('xen').auto() and have_system)
1328  xencontrol = dependency('xencontrol', required: false,
1329                          method: 'pkg-config', kwargs: static_kwargs)
1330  if xencontrol.found()
1331    xen_pc = declare_dependency(version: xencontrol.version(),
1332      dependencies: [
1333        xencontrol,
1334        # disabler: true makes xen_pc.found() return false if any is not found
1335        dependency('xenstore', required: false,
1336                   method: 'pkg-config', kwargs: static_kwargs,
1337                   disabler: true),
1338        dependency('xenforeignmemory', required: false,
1339                   method: 'pkg-config', kwargs: static_kwargs,
1340                   disabler: true),
1341        dependency('xengnttab', required: false,
1342                   method: 'pkg-config', kwargs: static_kwargs,
1343                   disabler: true),
1344        dependency('xenevtchn', required: false,
1345                   method: 'pkg-config', kwargs: static_kwargs,
1346                   disabler: true),
1347        dependency('xendevicemodel', required: false,
1348                   method: 'pkg-config', kwargs: static_kwargs,
1349                   disabler: true),
1350        # optional, no "disabler: true"
1351        dependency('xentoolcore', required: false,
1352                   method: 'pkg-config', kwargs: static_kwargs)])
1353    if xen_pc.found()
1354      xen = xen_pc
1355    endif
1356  endif
1357  if not xen.found()
1358    xen_tests = [ '4.11.0', '4.10.0', '4.9.0', '4.8.0', '4.7.1', '4.6.0', '4.5.0', '4.2.0' ]
1359    xen_libs = {
1360      '4.11.0': [ 'xenstore', 'xenctrl', 'xendevicemodel', 'xenforeignmemory', 'xengnttab', 'xenevtchn', 'xentoolcore' ],
1361      '4.10.0': [ 'xenstore', 'xenctrl', 'xendevicemodel', 'xenforeignmemory', 'xengnttab', 'xenevtchn', 'xentoolcore' ],
1362      '4.9.0': [ 'xenstore', 'xenctrl', 'xendevicemodel', 'xenforeignmemory', 'xengnttab', 'xenevtchn' ],
1363      '4.8.0': [ 'xenstore', 'xenctrl', 'xenforeignmemory', 'xengnttab', 'xenevtchn' ],
1364      '4.7.1': [ 'xenstore', 'xenctrl', 'xenforeignmemory', 'xengnttab', 'xenevtchn' ],
1365      '4.6.0': [ 'xenstore', 'xenctrl' ],
1366      '4.5.0': [ 'xenstore', 'xenctrl' ],
1367      '4.2.0': [ 'xenstore', 'xenctrl' ],
1368    }
1369    xen_deps = {}
1370    foreach ver: xen_tests
1371      # cache the various library tests to avoid polluting the logs
1372      xen_test_deps = []
1373      foreach l: xen_libs[ver]
1374        if l not in xen_deps
1375          xen_deps += { l: cc.find_library(l, required: false) }
1376        endif
1377        xen_test_deps += xen_deps[l]
1378      endforeach
1379
1380      # Use -D to pick just one of the test programs in scripts/xen-detect.c
1381      xen_version = ver.split('.')
1382      xen_ctrl_version = xen_version[0] + \
1383        ('0' + xen_version[1]).substring(-2) + \
1384        ('0' + xen_version[2]).substring(-2)
1385      if cc.links(files('scripts/xen-detect.c'),
1386                  args: '-DCONFIG_XEN_CTRL_INTERFACE_VERSION=' + xen_ctrl_version,
1387                  dependencies: xen_test_deps)
1388        xen = declare_dependency(version: ver, dependencies: xen_test_deps)
1389        break
1390      endif
1391    endforeach
1392  endif
1393  if xen.found()
1394    accelerators += 'CONFIG_XEN'
1395  elif get_option('xen').enabled()
1396    error('could not compile and link Xen test program')
1397  endif
1398endif
1399have_xen_pci_passthrough = get_option('xen_pci_passthrough') \
1400  .require(xen.found(),
1401           error_message: 'Xen PCI passthrough requested but Xen not enabled') \
1402  .require(targetos == 'linux',
1403           error_message: 'Xen PCI passthrough not available on this platform') \
1404  .allowed()
1405
1406
1407cacard = not_found
1408if not get_option('smartcard').auto() or have_system
1409  cacard = dependency('libcacard', required: get_option('smartcard'),
1410                      version: '>=2.5.1', method: 'pkg-config',
1411                      kwargs: static_kwargs)
1412endif
1413u2f = not_found
1414if have_system
1415  u2f = dependency('u2f-emu', required: get_option('u2f'),
1416                   method: 'pkg-config',
1417                   kwargs: static_kwargs)
1418endif
1419canokey = not_found
1420if have_system
1421  canokey = dependency('canokey-qemu', required: get_option('canokey'),
1422                   method: 'pkg-config',
1423                   kwargs: static_kwargs)
1424endif
1425usbredir = not_found
1426if not get_option('usb_redir').auto() or have_system
1427  usbredir = dependency('libusbredirparser-0.5', required: get_option('usb_redir'),
1428                        version: '>=0.6', method: 'pkg-config',
1429                        kwargs: static_kwargs)
1430endif
1431libusb = not_found
1432if not get_option('libusb').auto() or have_system
1433  libusb = dependency('libusb-1.0', required: get_option('libusb'),
1434                      version: '>=1.0.13', method: 'pkg-config',
1435                      kwargs: static_kwargs)
1436endif
1437
1438libpmem = not_found
1439if not get_option('libpmem').auto() or have_system
1440  libpmem = dependency('libpmem', required: get_option('libpmem'),
1441                       method: 'pkg-config', kwargs: static_kwargs)
1442endif
1443libdaxctl = not_found
1444if not get_option('libdaxctl').auto() or have_system
1445  libdaxctl = dependency('libdaxctl', required: get_option('libdaxctl'),
1446                         version: '>=57', method: 'pkg-config',
1447                         kwargs: static_kwargs)
1448endif
1449tasn1 = not_found
1450if gnutls.found()
1451  tasn1 = dependency('libtasn1',
1452                     method: 'pkg-config',
1453                     kwargs: static_kwargs)
1454endif
1455keyutils = dependency('libkeyutils', required: false,
1456                      method: 'pkg-config', kwargs: static_kwargs)
1457
1458has_gettid = cc.has_function('gettid')
1459
1460# libselinux
1461selinux = dependency('libselinux',
1462                     required: get_option('selinux'),
1463                     method: 'pkg-config', kwargs: static_kwargs)
1464
1465# Malloc tests
1466
1467malloc = []
1468if get_option('malloc') == 'system'
1469  has_malloc_trim = \
1470    get_option('malloc_trim').allowed() and \
1471    cc.links('''#include <malloc.h>
1472                int main(void) { malloc_trim(0); return 0; }''')
1473else
1474  has_malloc_trim = false
1475  malloc = cc.find_library(get_option('malloc'), required: true)
1476endif
1477if not has_malloc_trim and get_option('malloc_trim').enabled()
1478  if get_option('malloc') == 'system'
1479    error('malloc_trim not available on this platform.')
1480  else
1481    error('malloc_trim not available with non-libc memory allocator')
1482  endif
1483endif
1484
1485# Check whether the glibc provides statx()
1486
1487gnu_source_prefix = '''
1488  #ifndef _GNU_SOURCE
1489  #define _GNU_SOURCE
1490  #endif
1491'''
1492statx_test = gnu_source_prefix + '''
1493  #include <sys/stat.h>
1494  int main(void) {
1495    struct statx statxbuf;
1496    statx(0, "", 0, STATX_BASIC_STATS, &statxbuf);
1497    return 0;
1498  }'''
1499
1500has_statx = cc.links(statx_test)
1501
1502# Check whether statx() provides mount ID information
1503
1504statx_mnt_id_test = gnu_source_prefix + '''
1505  #include <sys/stat.h>
1506  int main(void) {
1507    struct statx statxbuf;
1508    statx(0, "", 0, STATX_BASIC_STATS | STATX_MNT_ID, &statxbuf);
1509    return statxbuf.stx_mnt_id;
1510  }'''
1511
1512has_statx_mnt_id = cc.links(statx_mnt_id_test)
1513
1514have_vhost_user_blk_server = get_option('vhost_user_blk_server') \
1515  .require(targetos == 'linux',
1516           error_message: 'vhost_user_blk_server requires linux') \
1517  .require(have_vhost_user,
1518           error_message: 'vhost_user_blk_server requires vhost-user support') \
1519  .disable_auto_if(not have_system) \
1520  .allowed()
1521
1522if get_option('fuse').disabled() and get_option('fuse_lseek').enabled()
1523  error('Cannot enable fuse-lseek while fuse is disabled')
1524endif
1525
1526fuse = dependency('fuse3', required: get_option('fuse'),
1527                  version: '>=3.1', method: 'pkg-config',
1528                  kwargs: static_kwargs)
1529
1530fuse_lseek = not_found
1531if get_option('fuse_lseek').allowed()
1532  if fuse.version().version_compare('>=3.8')
1533    # Dummy dependency
1534    fuse_lseek = declare_dependency()
1535  elif get_option('fuse_lseek').enabled()
1536    if fuse.found()
1537      error('fuse-lseek requires libfuse >=3.8, found ' + fuse.version())
1538    else
1539      error('fuse-lseek requires libfuse, which was not found')
1540    endif
1541  endif
1542endif
1543
1544# libbpf
1545libbpf = dependency('libbpf', required: get_option('bpf'), method: 'pkg-config')
1546if libbpf.found() and not cc.links('''
1547   #include <bpf/libbpf.h>
1548   int main(void)
1549   {
1550     bpf_object__destroy_skeleton(NULL);
1551     return 0;
1552   }''', dependencies: libbpf)
1553  libbpf = not_found
1554  if get_option('bpf').enabled()
1555    error('libbpf skeleton test failed')
1556  else
1557    warning('libbpf skeleton test failed, disabling')
1558  endif
1559endif
1560
1561#################
1562# config-host.h #
1563#################
1564
1565audio_drivers_selected = []
1566if have_system
1567  audio_drivers_available = {
1568    'alsa': alsa.found(),
1569    'coreaudio': coreaudio.found(),
1570    'dsound': dsound.found(),
1571    'jack': jack.found(),
1572    'oss': oss.found(),
1573    'pa': pulse.found(),
1574    'sdl': sdl.found(),
1575  }
1576  foreach k, v: audio_drivers_available
1577    config_host_data.set('CONFIG_AUDIO_' + k.to_upper(), v)
1578  endforeach
1579
1580  # Default to native drivers first, OSS second, SDL third
1581  audio_drivers_priority = \
1582    [ 'pa', 'coreaudio', 'dsound', 'oss' ] + \
1583    (targetos == 'linux' ? [] : [ 'sdl' ])
1584  audio_drivers_default = []
1585  foreach k: audio_drivers_priority
1586    if audio_drivers_available[k]
1587      audio_drivers_default += k
1588    endif
1589  endforeach
1590
1591  foreach k: get_option('audio_drv_list')
1592    if k == 'default'
1593      audio_drivers_selected += audio_drivers_default
1594    elif not audio_drivers_available[k]
1595      error('Audio driver "@0@" not available.'.format(k))
1596    else
1597      audio_drivers_selected += k
1598    endif
1599  endforeach
1600endif
1601config_host_data.set('CONFIG_AUDIO_DRIVERS',
1602                     '"' + '", "'.join(audio_drivers_selected) + '", ')
1603
1604if get_option('cfi')
1605  cfi_flags=[]
1606  # Check for dependency on LTO
1607  if not get_option('b_lto')
1608    error('Selected Control-Flow Integrity but LTO is disabled')
1609  endif
1610  if config_host.has_key('CONFIG_MODULES')
1611    error('Selected Control-Flow Integrity is not compatible with modules')
1612  endif
1613  # Check for cfi flags. CFI requires LTO so we can't use
1614  # get_supported_arguments, but need a more complex "compiles" which allows
1615  # custom arguments
1616  if cc.compiles('int main () { return 0; }', name: '-fsanitize=cfi-icall',
1617                 args: ['-flto', '-fsanitize=cfi-icall'] )
1618    cfi_flags += '-fsanitize=cfi-icall'
1619  else
1620    error('-fsanitize=cfi-icall is not supported by the compiler')
1621  endif
1622  if cc.compiles('int main () { return 0; }',
1623                 name: '-fsanitize-cfi-icall-generalize-pointers',
1624                 args: ['-flto', '-fsanitize=cfi-icall',
1625                        '-fsanitize-cfi-icall-generalize-pointers'] )
1626    cfi_flags += '-fsanitize-cfi-icall-generalize-pointers'
1627  else
1628    error('-fsanitize-cfi-icall-generalize-pointers is not supported by the compiler')
1629  endif
1630  if get_option('cfi_debug')
1631    if cc.compiles('int main () { return 0; }',
1632                   name: '-fno-sanitize-trap=cfi-icall',
1633                   args: ['-flto', '-fsanitize=cfi-icall',
1634                          '-fno-sanitize-trap=cfi-icall'] )
1635      cfi_flags += '-fno-sanitize-trap=cfi-icall'
1636    else
1637      error('-fno-sanitize-trap=cfi-icall is not supported by the compiler')
1638    endif
1639  endif
1640  add_global_arguments(cfi_flags, native: false, language: ['c', 'cpp', 'objc'])
1641  add_global_link_arguments(cfi_flags, native: false, language: ['c', 'cpp', 'objc'])
1642endif
1643
1644have_host_block_device = (targetos != 'darwin' or
1645    cc.has_header('IOKit/storage/IOMedia.h'))
1646
1647# FIXME enable_modules shouldn't be necessary, but: https://github.com/mesonbuild/meson/issues/8333
1648dbus_display = get_option('dbus_display') \
1649  .require(gio.version().version_compare('>=2.64'),
1650           error_message: '-display dbus requires glib>=2.64') \
1651  .require(enable_modules,
1652           error_message: '-display dbus requires --enable-modules') \
1653  .require(gdbus_codegen.found(),
1654           error_message: '-display dbus requires gdbus-codegen') \
1655  .allowed()
1656
1657have_virtfs = get_option('virtfs') \
1658    .require(targetos == 'linux' or targetos == 'darwin',
1659             error_message: 'virtio-9p (virtfs) requires Linux or macOS') \
1660    .require(targetos == 'linux' or cc.has_function('pthread_fchdir_np'),
1661             error_message: 'virtio-9p (virtfs) on macOS requires the presence of pthread_fchdir_np') \
1662    .require(targetos == 'darwin' or (libattr.found() and libcap_ng.found()),
1663             error_message: 'virtio-9p (virtfs) on Linux requires libcap-ng-devel and libattr-devel') \
1664    .disable_auto_if(not have_tools and not have_system) \
1665    .allowed()
1666
1667have_virtfs_proxy_helper = targetos != 'darwin' and have_virtfs and have_tools
1668
1669if get_option('block_drv_ro_whitelist') == ''
1670  config_host_data.set('CONFIG_BDRV_RO_WHITELIST', '')
1671else
1672  config_host_data.set('CONFIG_BDRV_RO_WHITELIST',
1673        '"' + get_option('block_drv_ro_whitelist').replace(',', '", "') + '", ')
1674endif
1675if get_option('block_drv_rw_whitelist') == ''
1676  config_host_data.set('CONFIG_BDRV_RW_WHITELIST', '')
1677else
1678  config_host_data.set('CONFIG_BDRV_RW_WHITELIST',
1679        '"' + get_option('block_drv_rw_whitelist').replace(',', '", "') + '", ')
1680endif
1681
1682foreach k : get_option('trace_backends')
1683  config_host_data.set('CONFIG_TRACE_' + k.to_upper(), true)
1684endforeach
1685config_host_data.set_quoted('CONFIG_TRACE_FILE', get_option('trace_file'))
1686config_host_data.set_quoted('CONFIG_TLS_PRIORITY', get_option('tls_priority'))
1687if iasl.found()
1688  config_host_data.set_quoted('CONFIG_IASL', iasl.full_path())
1689endif
1690config_host_data.set_quoted('CONFIG_BINDIR', get_option('prefix') / get_option('bindir'))
1691config_host_data.set_quoted('CONFIG_PREFIX', get_option('prefix'))
1692config_host_data.set_quoted('CONFIG_QEMU_CONFDIR', get_option('prefix') / qemu_confdir)
1693config_host_data.set_quoted('CONFIG_QEMU_DATADIR', get_option('prefix') / qemu_datadir)
1694config_host_data.set_quoted('CONFIG_QEMU_DESKTOPDIR', get_option('prefix') / qemu_desktopdir)
1695config_host_data.set_quoted('CONFIG_QEMU_FIRMWAREPATH', get_option('prefix') / get_option('qemu_firmwarepath'))
1696config_host_data.set_quoted('CONFIG_QEMU_HELPERDIR', get_option('prefix') / get_option('libexecdir'))
1697config_host_data.set_quoted('CONFIG_QEMU_ICONDIR', get_option('prefix') / qemu_icondir)
1698config_host_data.set_quoted('CONFIG_QEMU_LOCALEDIR', get_option('prefix') / get_option('localedir'))
1699config_host_data.set_quoted('CONFIG_QEMU_LOCALSTATEDIR', get_option('prefix') / get_option('localstatedir'))
1700config_host_data.set_quoted('CONFIG_QEMU_MODDIR', get_option('prefix') / qemu_moddir)
1701config_host_data.set_quoted('CONFIG_SYSCONFDIR', get_option('prefix') / get_option('sysconfdir'))
1702
1703if config_host.has_key('CONFIG_MODULES')
1704  config_host_data.set('CONFIG_STAMP', run_command(
1705      meson.current_source_dir() / 'scripts/qemu-stamp.py',
1706      meson.project_version(), get_option('pkgversion'), '--',
1707      meson.current_source_dir() / 'configure',
1708      capture: true, check: true).stdout().strip())
1709endif
1710
1711have_slirp_smbd = get_option('slirp_smbd') \
1712  .require(targetos != 'windows', error_message: 'Host smbd not supported on this platform.') \
1713  .allowed()
1714if have_slirp_smbd
1715  smbd_path = get_option('smbd')
1716  if smbd_path == ''
1717    smbd_path = (targetos == 'solaris' ? '/usr/sfw/sbin/smbd' : '/usr/sbin/smbd')
1718  endif
1719  config_host_data.set_quoted('CONFIG_SMBD_COMMAND', smbd_path)
1720endif
1721
1722config_host_data.set('HOST_' + host_arch.to_upper(), 1)
1723
1724if get_option('module_upgrades') and not enable_modules
1725  error('Cannot enable module-upgrades as modules are not enabled')
1726endif
1727config_host_data.set('CONFIG_MODULE_UPGRADES', get_option('module_upgrades'))
1728
1729config_host_data.set('CONFIG_ATTR', libattr.found())
1730config_host_data.set('CONFIG_BDRV_WHITELIST_TOOLS', get_option('block_drv_whitelist_in_tools'))
1731config_host_data.set('CONFIG_BRLAPI', brlapi.found())
1732config_host_data.set('CONFIG_COCOA', cocoa.found())
1733config_host_data.set('CONFIG_FUZZ', get_option('fuzzing'))
1734config_host_data.set('CONFIG_GCOV', get_option('b_coverage'))
1735config_host_data.set('CONFIG_LIBUDEV', libudev.found())
1736config_host_data.set('CONFIG_LZO', lzo.found())
1737config_host_data.set('CONFIG_MPATH', mpathpersist.found())
1738config_host_data.set('CONFIG_MPATH_NEW_API', mpathpersist_new_api)
1739config_host_data.set('CONFIG_CURL', curl.found())
1740config_host_data.set('CONFIG_CURSES', curses.found())
1741config_host_data.set('CONFIG_GBM', gbm.found())
1742config_host_data.set('CONFIG_GIO', gio.found())
1743config_host_data.set('CONFIG_GLUSTERFS', glusterfs.found())
1744if glusterfs.found()
1745  config_host_data.set('CONFIG_GLUSTERFS_XLATOR_OPT', glusterfs.version().version_compare('>=4'))
1746  config_host_data.set('CONFIG_GLUSTERFS_DISCARD', glusterfs.version().version_compare('>=5'))
1747  config_host_data.set('CONFIG_GLUSTERFS_FALLOCATE', glusterfs.version().version_compare('>=6'))
1748  config_host_data.set('CONFIG_GLUSTERFS_ZEROFILL', glusterfs.version().version_compare('>=6'))
1749  config_host_data.set('CONFIG_GLUSTERFS_FTRUNCATE_HAS_STAT', glusterfs_ftruncate_has_stat)
1750  config_host_data.set('CONFIG_GLUSTERFS_IOCB_HAS_STAT', glusterfs_iocb_has_stat)
1751endif
1752config_host_data.set('CONFIG_GTK', gtk.found())
1753config_host_data.set('CONFIG_VTE', vte.found())
1754config_host_data.set('CONFIG_LIBATTR', have_old_libattr)
1755config_host_data.set('CONFIG_LIBCAP_NG', libcap_ng.found())
1756config_host_data.set('CONFIG_EBPF', libbpf.found())
1757config_host_data.set('CONFIG_LIBDAXCTL', libdaxctl.found())
1758config_host_data.set('CONFIG_LIBISCSI', libiscsi.found())
1759config_host_data.set('CONFIG_LIBNFS', libnfs.found())
1760config_host_data.set('CONFIG_LIBSSH', libssh.found())
1761config_host_data.set('CONFIG_LINUX_AIO', libaio.found())
1762config_host_data.set('CONFIG_LINUX_IO_URING', linux_io_uring.found())
1763config_host_data.set('CONFIG_LIBURING_REGISTER_RING_FD', cc.has_function('io_uring_register_ring_fd', prefix: '#include <liburing.h>', dependencies:linux_io_uring))
1764config_host_data.set('CONFIG_LIBPMEM', libpmem.found())
1765config_host_data.set('CONFIG_NUMA', numa.found())
1766config_host_data.set('CONFIG_OPENGL', opengl.found())
1767config_host_data.set('CONFIG_PROFILER', get_option('profiler'))
1768config_host_data.set('CONFIG_RBD', rbd.found())
1769config_host_data.set('CONFIG_RDMA', rdma.found())
1770config_host_data.set('CONFIG_SDL', sdl.found())
1771config_host_data.set('CONFIG_SDL_IMAGE', sdl_image.found())
1772config_host_data.set('CONFIG_SECCOMP', seccomp.found())
1773config_host_data.set('CONFIG_SNAPPY', snappy.found())
1774config_host_data.set('CONFIG_TPM', have_tpm)
1775config_host_data.set('CONFIG_USB_LIBUSB', libusb.found())
1776config_host_data.set('CONFIG_VDE', vde.found())
1777config_host_data.set('CONFIG_VHOST_NET', have_vhost_net)
1778config_host_data.set('CONFIG_VHOST_NET_USER', have_vhost_net_user)
1779config_host_data.set('CONFIG_VHOST_NET_VDPA', have_vhost_net_vdpa)
1780config_host_data.set('CONFIG_VHOST_KERNEL', have_vhost_kernel)
1781config_host_data.set('CONFIG_VHOST_USER', have_vhost_user)
1782config_host_data.set('CONFIG_VHOST_CRYPTO', have_vhost_user_crypto)
1783config_host_data.set('CONFIG_VHOST_VDPA', have_vhost_vdpa)
1784config_host_data.set('CONFIG_VMNET', vmnet.found())
1785config_host_data.set('CONFIG_VHOST_USER_BLK_SERVER', have_vhost_user_blk_server)
1786config_host_data.set('CONFIG_PNG', png.found())
1787config_host_data.set('CONFIG_VNC', vnc.found())
1788config_host_data.set('CONFIG_VNC_JPEG', jpeg.found())
1789config_host_data.set('CONFIG_VNC_SASL', sasl.found())
1790config_host_data.set('CONFIG_VIRTFS', have_virtfs)
1791config_host_data.set('CONFIG_VTE', vte.found())
1792config_host_data.set('CONFIG_XKBCOMMON', xkbcommon.found())
1793config_host_data.set('CONFIG_KEYUTILS', keyutils.found())
1794config_host_data.set('CONFIG_GETTID', has_gettid)
1795config_host_data.set('CONFIG_GNUTLS', gnutls.found())
1796config_host_data.set('CONFIG_GNUTLS_CRYPTO', gnutls_crypto.found())
1797config_host_data.set('CONFIG_TASN1', tasn1.found())
1798config_host_data.set('CONFIG_GCRYPT', gcrypt.found())
1799config_host_data.set('CONFIG_NETTLE', nettle.found())
1800config_host_data.set('CONFIG_HOGWEED', hogweed.found())
1801config_host_data.set('CONFIG_QEMU_PRIVATE_XTS', xts == 'private')
1802config_host_data.set('CONFIG_MALLOC_TRIM', has_malloc_trim)
1803config_host_data.set('CONFIG_STATX', has_statx)
1804config_host_data.set('CONFIG_STATX_MNT_ID', has_statx_mnt_id)
1805config_host_data.set('CONFIG_ZSTD', zstd.found())
1806config_host_data.set('CONFIG_FUSE', fuse.found())
1807config_host_data.set('CONFIG_FUSE_LSEEK', fuse_lseek.found())
1808config_host_data.set('CONFIG_SPICE_PROTOCOL', spice_protocol.found())
1809if spice_protocol.found()
1810config_host_data.set('CONFIG_SPICE_PROTOCOL_MAJOR', spice_protocol.version().split('.')[0])
1811config_host_data.set('CONFIG_SPICE_PROTOCOL_MINOR', spice_protocol.version().split('.')[1])
1812config_host_data.set('CONFIG_SPICE_PROTOCOL_MICRO', spice_protocol.version().split('.')[2])
1813endif
1814config_host_data.set('CONFIG_SPICE', spice.found())
1815config_host_data.set('CONFIG_X11', x11.found())
1816config_host_data.set('CONFIG_DBUS_DISPLAY', dbus_display)
1817config_host_data.set('CONFIG_CFI', get_option('cfi'))
1818config_host_data.set('CONFIG_SELINUX', selinux.found())
1819config_host_data.set('CONFIG_XEN_BACKEND', xen.found())
1820if xen.found()
1821  # protect from xen.version() having less than three components
1822  xen_version = xen.version().split('.') + ['0', '0']
1823  xen_ctrl_version = xen_version[0] + \
1824    ('0' + xen_version[1]).substring(-2) + \
1825    ('0' + xen_version[2]).substring(-2)
1826  config_host_data.set('CONFIG_XEN_CTRL_INTERFACE_VERSION', xen_ctrl_version)
1827endif
1828config_host_data.set('QEMU_VERSION', '"@0@"'.format(meson.project_version()))
1829config_host_data.set('QEMU_VERSION_MAJOR', meson.project_version().split('.')[0])
1830config_host_data.set('QEMU_VERSION_MINOR', meson.project_version().split('.')[1])
1831config_host_data.set('QEMU_VERSION_MICRO', meson.project_version().split('.')[2])
1832
1833config_host_data.set_quoted('CONFIG_HOST_DSOSUF', host_dsosuf)
1834config_host_data.set('HAVE_HOST_BLOCK_DEVICE', have_host_block_device)
1835
1836have_coroutine_pool = get_option('coroutine_pool')
1837if get_option('debug_stack_usage') and have_coroutine_pool
1838  message('Disabling coroutine pool to measure stack usage')
1839  have_coroutine_pool = false
1840endif
1841config_host_data.set10('CONFIG_COROUTINE_POOL', have_coroutine_pool)
1842config_host_data.set('CONFIG_DEBUG_MUTEX', get_option('debug_mutex'))
1843config_host_data.set('CONFIG_DEBUG_STACK_USAGE', get_option('debug_stack_usage'))
1844config_host_data.set('CONFIG_GPROF', get_option('gprof'))
1845config_host_data.set('CONFIG_LIVE_BLOCK_MIGRATION', get_option('live_block_migration').allowed())
1846config_host_data.set('CONFIG_QOM_CAST_DEBUG', get_option('qom_cast_debug'))
1847config_host_data.set('CONFIG_REPLICATION', get_option('live_block_migration').allowed())
1848
1849# has_header
1850config_host_data.set('CONFIG_EPOLL', cc.has_header('sys/epoll.h'))
1851config_host_data.set('CONFIG_LINUX_MAGIC_H', cc.has_header('linux/magic.h'))
1852config_host_data.set('CONFIG_VALGRIND_H', cc.has_header('valgrind/valgrind.h'))
1853config_host_data.set('HAVE_BTRFS_H', cc.has_header('linux/btrfs.h'))
1854config_host_data.set('HAVE_DRM_H', cc.has_header('libdrm/drm.h'))
1855config_host_data.set('HAVE_PTY_H', cc.has_header('pty.h'))
1856config_host_data.set('HAVE_SYS_DISK_H', cc.has_header('sys/disk.h'))
1857config_host_data.set('HAVE_SYS_IOCCOM_H', cc.has_header('sys/ioccom.h'))
1858config_host_data.set('HAVE_SYS_KCOV_H', cc.has_header('sys/kcov.h'))
1859
1860# has_function
1861config_host_data.set('CONFIG_ACCEPT4', cc.has_function('accept4'))
1862config_host_data.set('CONFIG_CLOCK_ADJTIME', cc.has_function('clock_adjtime'))
1863config_host_data.set('CONFIG_DUP3', cc.has_function('dup3'))
1864config_host_data.set('CONFIG_FALLOCATE', cc.has_function('fallocate'))
1865config_host_data.set('CONFIG_POSIX_FALLOCATE', cc.has_function('posix_fallocate'))
1866# Note that we need to specify prefix: here to avoid incorrectly
1867# thinking that Windows has posix_memalign()
1868config_host_data.set('CONFIG_POSIX_MEMALIGN', cc.has_function('posix_memalign', prefix: '#include <stdlib.h>'))
1869config_host_data.set('CONFIG_ALIGNED_MALLOC', cc.has_function('_aligned_malloc'))
1870config_host_data.set('CONFIG_VALLOC', cc.has_function('valloc'))
1871config_host_data.set('CONFIG_MEMALIGN', cc.has_function('memalign'))
1872config_host_data.set('CONFIG_PPOLL', cc.has_function('ppoll'))
1873config_host_data.set('CONFIG_PREADV', cc.has_function('preadv', prefix: '#include <sys/uio.h>'))
1874config_host_data.set('CONFIG_PTHREAD_FCHDIR_NP', cc.has_function('pthread_fchdir_np'))
1875config_host_data.set('CONFIG_SENDFILE', cc.has_function('sendfile'))
1876config_host_data.set('CONFIG_SETNS', cc.has_function('setns') and cc.has_function('unshare'))
1877config_host_data.set('CONFIG_SYNCFS', cc.has_function('syncfs'))
1878config_host_data.set('CONFIG_SYNC_FILE_RANGE', cc.has_function('sync_file_range'))
1879config_host_data.set('CONFIG_TIMERFD', cc.has_function('timerfd_create'))
1880config_host_data.set('HAVE_COPY_FILE_RANGE', cc.has_function('copy_file_range'))
1881config_host_data.set('HAVE_GETIFADDRS', cc.has_function('getifaddrs'))
1882config_host_data.set('HAVE_OPENPTY', cc.has_function('openpty', dependencies: util))
1883config_host_data.set('HAVE_STRCHRNUL', cc.has_function('strchrnul'))
1884config_host_data.set('HAVE_SYSTEM_FUNCTION', cc.has_function('system', prefix: '#include <stdlib.h>'))
1885if rdma.found()
1886  config_host_data.set('HAVE_IBV_ADVISE_MR',
1887                       cc.has_function('ibv_advise_mr',
1888                                       dependencies: rdma,
1889                                       prefix: '#include <infiniband/verbs.h>'))
1890endif
1891
1892# has_header_symbol
1893config_host_data.set('CONFIG_BYTESWAP_H',
1894                     cc.has_header_symbol('byteswap.h', 'bswap_32'))
1895config_host_data.set('CONFIG_EPOLL_CREATE1',
1896                     cc.has_header_symbol('sys/epoll.h', 'epoll_create1'))
1897config_host_data.set('CONFIG_FALLOCATE_PUNCH_HOLE',
1898                     cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_PUNCH_HOLE') and
1899                     cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_KEEP_SIZE'))
1900config_host_data.set('CONFIG_FALLOCATE_ZERO_RANGE',
1901                     cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_ZERO_RANGE'))
1902config_host_data.set('CONFIG_FIEMAP',
1903                     cc.has_header('linux/fiemap.h') and
1904                     cc.has_header_symbol('linux/fs.h', 'FS_IOC_FIEMAP'))
1905config_host_data.set('CONFIG_GETRANDOM',
1906                     cc.has_function('getrandom') and
1907                     cc.has_header_symbol('sys/random.h', 'GRND_NONBLOCK'))
1908config_host_data.set('CONFIG_INOTIFY',
1909                     cc.has_header_symbol('sys/inotify.h', 'inotify_init'))
1910config_host_data.set('CONFIG_INOTIFY1',
1911                     cc.has_header_symbol('sys/inotify.h', 'inotify_init1'))
1912config_host_data.set('CONFIG_MACHINE_BSWAP_H',
1913                     cc.has_header_symbol('machine/bswap.h', 'bswap32',
1914                                          prefix: '''#include <sys/endian.h>
1915                                                     #include <sys/types.h>'''))
1916config_host_data.set('CONFIG_PRCTL_PR_SET_TIMERSLACK',
1917                     cc.has_header_symbol('sys/prctl.h', 'PR_SET_TIMERSLACK'))
1918config_host_data.set('CONFIG_RTNETLINK',
1919                     cc.has_header_symbol('linux/rtnetlink.h', 'IFLA_PROTO_DOWN'))
1920config_host_data.set('CONFIG_SYSMACROS',
1921                     cc.has_header_symbol('sys/sysmacros.h', 'makedev'))
1922config_host_data.set('HAVE_OPTRESET',
1923                     cc.has_header_symbol('getopt.h', 'optreset'))
1924config_host_data.set('HAVE_IPPROTO_MPTCP',
1925                     cc.has_header_symbol('netinet/in.h', 'IPPROTO_MPTCP'))
1926
1927# has_member
1928config_host_data.set('HAVE_SIGEV_NOTIFY_THREAD_ID',
1929                     cc.has_member('struct sigevent', 'sigev_notify_thread_id',
1930                                   prefix: '#include <signal.h>'))
1931config_host_data.set('HAVE_STRUCT_STAT_ST_ATIM',
1932                     cc.has_member('struct stat', 'st_atim',
1933                                   prefix: '#include <sys/stat.h>'))
1934
1935# has_type
1936config_host_data.set('CONFIG_IOVEC',
1937                     cc.has_type('struct iovec',
1938                                 prefix: '#include <sys/uio.h>'))
1939config_host_data.set('HAVE_UTMPX',
1940                     cc.has_type('struct utmpx',
1941                                 prefix: '#include <utmpx.h>'))
1942
1943config_host_data.set('CONFIG_EVENTFD', cc.links('''
1944  #include <sys/eventfd.h>
1945  int main(void) { return eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); }'''))
1946config_host_data.set('CONFIG_FDATASYNC', cc.links(gnu_source_prefix + '''
1947  #include <unistd.h>
1948  int main(void) {
1949  #if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
1950  return fdatasync(0);
1951  #else
1952  #error Not supported
1953  #endif
1954  }'''))
1955
1956has_madvise = cc.links(gnu_source_prefix + '''
1957  #include <sys/types.h>
1958  #include <sys/mman.h>
1959  #include <stddef.h>
1960  int main(void) { return madvise(NULL, 0, MADV_DONTNEED); }''')
1961missing_madvise_proto = false
1962if has_madvise
1963  # Some platforms (illumos and Solaris before Solaris 11) provide madvise()
1964  # but forget to prototype it. In this case, has_madvise will be true (the
1965  # test program links despite a compile warning). To detect the
1966  # missing-prototype case, we try again with a definitely-bogus prototype.
1967  # This will only compile if the system headers don't provide the prototype;
1968  # otherwise the conflicting prototypes will cause a compiler error.
1969  missing_madvise_proto = cc.links(gnu_source_prefix + '''
1970    #include <sys/types.h>
1971    #include <sys/mman.h>
1972    #include <stddef.h>
1973    extern int madvise(int);
1974    int main(void) { return madvise(0); }''')
1975endif
1976config_host_data.set('CONFIG_MADVISE', has_madvise)
1977config_host_data.set('HAVE_MADVISE_WITHOUT_PROTOTYPE', missing_madvise_proto)
1978
1979config_host_data.set('CONFIG_MEMFD', cc.links(gnu_source_prefix + '''
1980  #include <sys/mman.h>
1981  int main(void) { return memfd_create("foo", MFD_ALLOW_SEALING); }'''))
1982config_host_data.set('CONFIG_OPEN_BY_HANDLE', cc.links(gnu_source_prefix + '''
1983  #include <fcntl.h>
1984  #if !defined(AT_EMPTY_PATH)
1985  # error missing definition
1986  #else
1987  int main(void) { struct file_handle fh; return open_by_handle_at(0, &fh, 0); }
1988  #endif'''))
1989config_host_data.set('CONFIG_PIPE2', cc.links(gnu_source_prefix + '''
1990  #include <unistd.h>
1991  #include <fcntl.h>
1992
1993  int main(void)
1994  {
1995      int pipefd[2];
1996      return pipe2(pipefd, O_CLOEXEC);
1997  }'''))
1998config_host_data.set('CONFIG_POSIX_MADVISE', cc.links(gnu_source_prefix + '''
1999  #include <sys/mman.h>
2000  #include <stddef.h>
2001  int main(void) { return posix_madvise(NULL, 0, POSIX_MADV_DONTNEED); }'''))
2002
2003config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_W_TID', cc.links(gnu_source_prefix + '''
2004  #include <pthread.h>
2005
2006  static void *f(void *p) { return NULL; }
2007  int main(void)
2008  {
2009    pthread_t thread;
2010    pthread_create(&thread, 0, f, 0);
2011    pthread_setname_np(thread, "QEMU");
2012    return 0;
2013  }''', dependencies: threads))
2014config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_WO_TID', cc.links(gnu_source_prefix + '''
2015  #include <pthread.h>
2016
2017  static void *f(void *p) { pthread_setname_np("QEMU"); return NULL; }
2018  int main(void)
2019  {
2020    pthread_t thread;
2021    pthread_create(&thread, 0, f, 0);
2022    return 0;
2023  }''', dependencies: threads))
2024config_host_data.set('CONFIG_PTHREAD_CONDATTR_SETCLOCK', cc.links(gnu_source_prefix + '''
2025  #include <pthread.h>
2026  #include <time.h>
2027
2028  int main(void)
2029  {
2030    pthread_condattr_t attr
2031    pthread_condattr_init(&attr);
2032    pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
2033    return 0;
2034  }''', dependencies: threads))
2035
2036config_host_data.set('CONFIG_SIGNALFD', cc.links(gnu_source_prefix + '''
2037  #include <sys/signalfd.h>
2038  #include <stddef.h>
2039  int main(void) { return signalfd(-1, NULL, SFD_CLOEXEC); }'''))
2040config_host_data.set('CONFIG_SPLICE', cc.links(gnu_source_prefix + '''
2041  #include <unistd.h>
2042  #include <fcntl.h>
2043  #include <limits.h>
2044
2045  int main(void)
2046  {
2047    int len, fd = 0;
2048    len = tee(STDIN_FILENO, STDOUT_FILENO, INT_MAX, SPLICE_F_NONBLOCK);
2049    splice(STDIN_FILENO, NULL, fd, NULL, len, SPLICE_F_MOVE);
2050    return 0;
2051  }'''))
2052
2053config_host_data.set('HAVE_MLOCKALL', cc.links(gnu_source_prefix + '''
2054  #include <sys/mman.h>
2055  int main(int argc, char *argv[]) {
2056    return mlockall(MCL_FUTURE);
2057  }'''))
2058
2059have_l2tpv3 = false
2060if get_option('l2tpv3').allowed() and have_system
2061  have_l2tpv3 = cc.has_type('struct mmsghdr',
2062    prefix: gnu_source_prefix + '''
2063      #include <sys/socket.h>
2064      #include <linux/ip.h>''')
2065endif
2066config_host_data.set('CONFIG_L2TPV3', have_l2tpv3)
2067
2068have_netmap = false
2069if get_option('netmap').allowed() and have_system
2070  have_netmap = cc.compiles('''
2071    #include <inttypes.h>
2072    #include <net/if.h>
2073    #include <net/netmap.h>
2074    #include <net/netmap_user.h>
2075    #if (NETMAP_API < 11) || (NETMAP_API > 15)
2076    #error
2077    #endif
2078    int main(void) { return 0; }''')
2079  if not have_netmap and get_option('netmap').enabled()
2080    error('Netmap headers not available')
2081  endif
2082endif
2083config_host_data.set('CONFIG_NETMAP', have_netmap)
2084
2085# Work around a system header bug with some kernel/XFS header
2086# versions where they both try to define 'struct fsxattr':
2087# xfs headers will not try to redefine structs from linux headers
2088# if this macro is set.
2089config_host_data.set('HAVE_FSXATTR', cc.links('''
2090  #include <linux/fs.h>
2091  struct fsxattr foo;
2092  int main(void) {
2093    return 0;
2094  }'''))
2095
2096# Some versions of Mac OS X incorrectly define SIZE_MAX
2097config_host_data.set('HAVE_BROKEN_SIZE_MAX', not cc.compiles('''
2098    #include <stdint.h>
2099    #include <stdio.h>
2100    int main(int argc, char *argv[]) {
2101        return printf("%zu", SIZE_MAX);
2102    }''', args: ['-Werror']))
2103
2104atomic_test = '''
2105  #include <stdint.h>
2106  int main(void)
2107  {
2108    @0@ x = 0, y = 0;
2109    y = __atomic_load_n(&x, __ATOMIC_RELAXED);
2110    __atomic_store_n(&x, y, __ATOMIC_RELAXED);
2111    __atomic_compare_exchange_n(&x, &y, x, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
2112    __atomic_exchange_n(&x, y, __ATOMIC_RELAXED);
2113    __atomic_fetch_add(&x, y, __ATOMIC_RELAXED);
2114    return 0;
2115  }'''
2116
2117# See if 64-bit atomic operations are supported.
2118# Note that without __atomic builtins, we can only
2119# assume atomic loads/stores max at pointer size.
2120config_host_data.set('CONFIG_ATOMIC64', cc.links(atomic_test.format('uint64_t')))
2121
2122has_int128 = cc.links('''
2123  __int128_t a;
2124  __uint128_t b;
2125  int main (void) {
2126    a = a + b;
2127    b = a * b;
2128    a = a * a;
2129    return 0;
2130  }''')
2131
2132config_host_data.set('CONFIG_INT128', has_int128)
2133
2134if has_int128
2135  # "do we have 128-bit atomics which are handled inline and specifically not
2136  # via libatomic". The reason we can't use libatomic is documented in the
2137  # comment starting "GCC is a house divided" in include/qemu/atomic128.h.
2138  has_atomic128 = cc.links(atomic_test.format('unsigned __int128'))
2139
2140  config_host_data.set('CONFIG_ATOMIC128', has_atomic128)
2141
2142  if not has_atomic128
2143    has_cmpxchg128 = cc.links('''
2144      int main(void)
2145      {
2146        unsigned __int128 x = 0, y = 0;
2147        __sync_val_compare_and_swap_16(&x, y, x);
2148        return 0;
2149      }
2150    ''')
2151
2152    config_host_data.set('CONFIG_CMPXCHG128', has_cmpxchg128)
2153  endif
2154endif
2155
2156config_host_data.set('CONFIG_GETAUXVAL', cc.links(gnu_source_prefix + '''
2157  #include <sys/auxv.h>
2158  int main(void) {
2159    return getauxval(AT_HWCAP) == 0;
2160  }'''))
2161
2162config_host_data.set('CONFIG_USBFS', have_linux_user and cc.compiles('''
2163  #include <linux/usbdevice_fs.h>
2164
2165  #ifndef USBDEVFS_GET_CAPABILITIES
2166  #error "USBDEVFS_GET_CAPABILITIES undefined"
2167  #endif
2168
2169  #ifndef USBDEVFS_DISCONNECT_CLAIM
2170  #error "USBDEVFS_DISCONNECT_CLAIM undefined"
2171  #endif
2172
2173  int main(void) { return 0; }'''))
2174
2175have_keyring = get_option('keyring') \
2176  .require(targetos == 'linux', error_message: 'keyring is only available on Linux') \
2177  .require(cc.compiles('''
2178    #include <errno.h>
2179    #include <asm/unistd.h>
2180    #include <linux/keyctl.h>
2181    #include <sys/syscall.h>
2182    #include <unistd.h>
2183    int main(void) {
2184        return syscall(__NR_keyctl, KEYCTL_READ, 0, NULL, NULL, 0);
2185    }'''), error_message: 'keyctl syscall not available on this system').allowed()
2186config_host_data.set('CONFIG_SECRET_KEYRING', have_keyring)
2187
2188have_cpuid_h = cc.links('''
2189  #include <cpuid.h>
2190  int main(void) {
2191    unsigned a, b, c, d;
2192    unsigned max = __get_cpuid_max(0, 0);
2193
2194    if (max >= 1) {
2195        __cpuid(1, a, b, c, d);
2196    }
2197
2198    if (max >= 7) {
2199        __cpuid_count(7, 0, a, b, c, d);
2200    }
2201
2202    return 0;
2203  }''')
2204config_host_data.set('CONFIG_CPUID_H', have_cpuid_h)
2205
2206config_host_data.set('CONFIG_AVX2_OPT', get_option('avx2') \
2207  .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable AVX2') \
2208  .require(cc.links('''
2209    #pragma GCC push_options
2210    #pragma GCC target("avx2")
2211    #include <cpuid.h>
2212    #include <immintrin.h>
2213    static int bar(void *a) {
2214      __m256i x = *(__m256i *)a;
2215      return _mm256_testz_si256(x, x);
2216    }
2217    int main(int argc, char *argv[]) { return bar(argv[0]); }
2218  '''), error_message: 'AVX2 not available').allowed())
2219
2220config_host_data.set('CONFIG_AVX512F_OPT', get_option('avx512f') \
2221  .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable AVX512F') \
2222  .require(cc.links('''
2223    #pragma GCC push_options
2224    #pragma GCC target("avx512f")
2225    #include <cpuid.h>
2226    #include <immintrin.h>
2227    static int bar(void *a) {
2228      __m512i x = *(__m512i *)a;
2229      return _mm512_test_epi64_mask(x, x);
2230    }
2231    int main(int argc, char *argv[]) { return bar(argv[0]); }
2232  '''), error_message: 'AVX512F not available').allowed())
2233
2234have_pvrdma = get_option('pvrdma') \
2235  .require(rdma.found(), error_message: 'PVRDMA requires OpenFabrics libraries') \
2236  .require(cc.compiles(gnu_source_prefix + '''
2237    #include <sys/mman.h>
2238    int main(void)
2239    {
2240      char buf = 0;
2241      void *addr = &buf;
2242      addr = mremap(addr, 0, 1, MREMAP_MAYMOVE | MREMAP_FIXED);
2243
2244      return 0;
2245    }'''), error_message: 'PVRDMA requires mremap').allowed()
2246
2247if have_pvrdma
2248  config_host_data.set('LEGACY_RDMA_REG_MR', not cc.links('''
2249    #include <infiniband/verbs.h>
2250    int main(void)
2251    {
2252      struct ibv_mr *mr;
2253      struct ibv_pd *pd = NULL;
2254      size_t length = 10;
2255      uint64_t iova = 0;
2256      int access = 0;
2257      void *addr = NULL;
2258
2259      mr = ibv_reg_mr_iova(pd, addr, length, iova, access);
2260      ibv_dereg_mr(mr);
2261      return 0;
2262    }'''))
2263endif
2264
2265if get_option('membarrier').disabled()
2266  have_membarrier = false
2267elif targetos == 'windows'
2268  have_membarrier = true
2269elif targetos == 'linux'
2270  have_membarrier = cc.compiles('''
2271    #include <linux/membarrier.h>
2272    #include <sys/syscall.h>
2273    #include <unistd.h>
2274    #include <stdlib.h>
2275    int main(void) {
2276        syscall(__NR_membarrier, MEMBARRIER_CMD_QUERY, 0);
2277        syscall(__NR_membarrier, MEMBARRIER_CMD_SHARED, 0);
2278        exit(0);
2279    }''')
2280endif
2281config_host_data.set('CONFIG_MEMBARRIER', get_option('membarrier') \
2282  .require(have_membarrier, error_message: 'membarrier system call not available') \
2283  .allowed())
2284
2285have_afalg = get_option('crypto_afalg') \
2286  .require(cc.compiles(gnu_source_prefix + '''
2287    #include <errno.h>
2288    #include <sys/types.h>
2289    #include <sys/socket.h>
2290    #include <linux/if_alg.h>
2291    int main(void) {
2292      int sock;
2293      sock = socket(AF_ALG, SOCK_SEQPACKET, 0);
2294      return sock;
2295    }
2296  '''), error_message: 'AF_ALG requested but could not be detected').allowed()
2297config_host_data.set('CONFIG_AF_ALG', have_afalg)
2298
2299config_host_data.set('CONFIG_AF_VSOCK', cc.has_header_symbol(
2300  'linux/vm_sockets.h', 'AF_VSOCK',
2301  prefix: '#include <sys/socket.h>',
2302))
2303
2304have_vss = false
2305have_vss_sdk = false # old xp/2003 SDK
2306if targetos == 'windows' and link_language == 'cpp'
2307  have_vss = cxx.compiles('''
2308    #define __MIDL_user_allocate_free_DEFINED__
2309    #include <vss.h>
2310    int main(void) { return VSS_CTX_BACKUP; }''')
2311  have_vss_sdk = cxx.has_header('vscoordint.h')
2312endif
2313config_host_data.set('HAVE_VSS_SDK', have_vss_sdk)
2314
2315foreach k, v: config_host
2316  if k.startswith('CONFIG_')
2317    config_host_data.set(k, v == 'y' ? 1 : v)
2318  endif
2319endforeach
2320
2321# Older versions of MinGW do not import _lock_file and _unlock_file properly.
2322# This was fixed for v6.0.0 with commit b48e3ac8969d.
2323if targetos == 'windows'
2324  config_host_data.set('HAVE__LOCK_FILE', cc.links('''
2325    #include <stdio.h>
2326    int main(void) {
2327      _lock_file(NULL);
2328      _unlock_file(NULL);
2329      return 0;
2330    }''', name: '_lock_file and _unlock_file'))
2331endif
2332
2333########################
2334# Target configuration #
2335########################
2336
2337minikconf = find_program('scripts/minikconf.py')
2338config_all = {}
2339config_all_devices = {}
2340config_all_disas = {}
2341config_devices_mak_list = []
2342config_devices_h = {}
2343config_target_h = {}
2344config_target_mak = {}
2345
2346disassemblers = {
2347  'alpha' : ['CONFIG_ALPHA_DIS'],
2348  'arm' : ['CONFIG_ARM_DIS'],
2349  'avr' : ['CONFIG_AVR_DIS'],
2350  'cris' : ['CONFIG_CRIS_DIS'],
2351  'hexagon' : ['CONFIG_HEXAGON_DIS'],
2352  'hppa' : ['CONFIG_HPPA_DIS'],
2353  'i386' : ['CONFIG_I386_DIS'],
2354  'x86_64' : ['CONFIG_I386_DIS'],
2355  'm68k' : ['CONFIG_M68K_DIS'],
2356  'microblaze' : ['CONFIG_MICROBLAZE_DIS'],
2357  'mips' : ['CONFIG_MIPS_DIS'],
2358  'nios2' : ['CONFIG_NIOS2_DIS'],
2359  'or1k' : ['CONFIG_OPENRISC_DIS'],
2360  'ppc' : ['CONFIG_PPC_DIS'],
2361  'riscv' : ['CONFIG_RISCV_DIS'],
2362  'rx' : ['CONFIG_RX_DIS'],
2363  's390' : ['CONFIG_S390_DIS'],
2364  'sh4' : ['CONFIG_SH4_DIS'],
2365  'sparc' : ['CONFIG_SPARC_DIS'],
2366  'xtensa' : ['CONFIG_XTENSA_DIS'],
2367  'loongarch' : ['CONFIG_LOONGARCH_DIS'],
2368}
2369if link_language == 'cpp'
2370  disassemblers += {
2371    'aarch64' : [ 'CONFIG_ARM_A64_DIS'],
2372    'arm' : [ 'CONFIG_ARM_DIS', 'CONFIG_ARM_A64_DIS'],
2373    'mips' : [ 'CONFIG_MIPS_DIS', 'CONFIG_NANOMIPS_DIS'],
2374  }
2375endif
2376
2377have_ivshmem = config_host_data.get('CONFIG_EVENTFD')
2378host_kconfig = \
2379  (get_option('fuzzing') ? ['CONFIG_FUZZ=y'] : []) + \
2380  (have_tpm ? ['CONFIG_TPM=y'] : []) + \
2381  (spice.found() ? ['CONFIG_SPICE=y'] : []) + \
2382  (have_ivshmem ? ['CONFIG_IVSHMEM=y'] : []) + \
2383  (opengl.found() ? ['CONFIG_OPENGL=y'] : []) + \
2384  (x11.found() ? ['CONFIG_X11=y'] : []) + \
2385  (have_vhost_user ? ['CONFIG_VHOST_USER=y'] : []) + \
2386  (have_vhost_vdpa ? ['CONFIG_VHOST_VDPA=y'] : []) + \
2387  (have_vhost_kernel ? ['CONFIG_VHOST_KERNEL=y'] : []) + \
2388  (have_virtfs ? ['CONFIG_VIRTFS=y'] : []) + \
2389  ('CONFIG_LINUX' in config_host ? ['CONFIG_LINUX=y'] : []) + \
2390  (have_pvrdma ? ['CONFIG_PVRDMA=y'] : []) + \
2391  (multiprocess_allowed ? ['CONFIG_MULTIPROCESS_ALLOWED=y'] : []) + \
2392  (vfio_user_server_allowed ? ['CONFIG_VFIO_USER_SERVER_ALLOWED=y'] : [])
2393
2394ignored = [ 'TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_ARCH' ]
2395
2396default_targets = 'CONFIG_DEFAULT_TARGETS' in config_host
2397actual_target_dirs = []
2398fdt_required = []
2399foreach target : target_dirs
2400  config_target = { 'TARGET_NAME': target.split('-')[0] }
2401  if target.endswith('linux-user')
2402    if targetos != 'linux'
2403      if default_targets
2404        continue
2405      endif
2406      error('Target @0@ is only available on a Linux host'.format(target))
2407    endif
2408    config_target += { 'CONFIG_LINUX_USER': 'y' }
2409  elif target.endswith('bsd-user')
2410    if 'CONFIG_BSD' not in config_host
2411      if default_targets
2412        continue
2413      endif
2414      error('Target @0@ is only available on a BSD host'.format(target))
2415    endif
2416    config_target += { 'CONFIG_BSD_USER': 'y' }
2417  elif target.endswith('softmmu')
2418    config_target += { 'CONFIG_SOFTMMU': 'y' }
2419  endif
2420  if target.endswith('-user')
2421    config_target += {
2422      'CONFIG_USER_ONLY': 'y',
2423      'CONFIG_QEMU_INTERP_PREFIX':
2424        get_option('interp_prefix').replace('%M', config_target['TARGET_NAME'])
2425    }
2426  endif
2427
2428  accel_kconfig = []
2429  foreach sym: accelerators
2430    if sym == 'CONFIG_TCG' or target in accelerator_targets.get(sym, [])
2431      config_target += { sym: 'y' }
2432      config_all += { sym: 'y' }
2433      if sym == 'CONFIG_TCG' and tcg_arch == 'tci'
2434        config_target += { 'CONFIG_TCG_INTERPRETER': 'y' }
2435      endif
2436      if target in modular_tcg
2437        config_target += { 'CONFIG_TCG_MODULAR': 'y' }
2438      else
2439        config_target += { 'CONFIG_TCG_BUILTIN': 'y' }
2440      endif
2441      accel_kconfig += [ sym + '=y' ]
2442    endif
2443  endforeach
2444  if accel_kconfig.length() == 0
2445    if default_targets
2446      continue
2447    endif
2448    error('No accelerator available for target @0@'.format(target))
2449  endif
2450
2451  actual_target_dirs += target
2452  config_target += keyval.load('configs/targets' / target + '.mak')
2453  config_target += { 'TARGET_' + config_target['TARGET_ARCH'].to_upper(): 'y' }
2454
2455  if 'TARGET_NEED_FDT' in config_target
2456    fdt_required += target
2457  endif
2458
2459  # Add default keys
2460  if 'TARGET_BASE_ARCH' not in config_target
2461    config_target += {'TARGET_BASE_ARCH': config_target['TARGET_ARCH']}
2462  endif
2463  if 'TARGET_ABI_DIR' not in config_target
2464    config_target += {'TARGET_ABI_DIR': config_target['TARGET_ARCH']}
2465  endif
2466  if 'TARGET_BIG_ENDIAN' not in config_target
2467    config_target += {'TARGET_BIG_ENDIAN': 'n'}
2468  endif
2469
2470  foreach k, v: disassemblers
2471    if host_arch.startswith(k) or config_target['TARGET_BASE_ARCH'].startswith(k)
2472      foreach sym: v
2473        config_target += { sym: 'y' }
2474        config_all_disas += { sym: 'y' }
2475      endforeach
2476    endif
2477  endforeach
2478
2479  config_target_data = configuration_data()
2480  foreach k, v: config_target
2481    if not k.startswith('TARGET_') and not k.startswith('CONFIG_')
2482      # do nothing
2483    elif ignored.contains(k)
2484      # do nothing
2485    elif k == 'TARGET_BASE_ARCH'
2486      # Note that TARGET_BASE_ARCH ends up in config-target.h but it is
2487      # not used to select files from sourcesets.
2488      config_target_data.set('TARGET_' + v.to_upper(), 1)
2489    elif k == 'TARGET_NAME' or k == 'CONFIG_QEMU_INTERP_PREFIX'
2490      config_target_data.set_quoted(k, v)
2491    elif v == 'y'
2492      config_target_data.set(k, 1)
2493    elif v == 'n'
2494      config_target_data.set(k, 0)
2495    else
2496      config_target_data.set(k, v)
2497    endif
2498  endforeach
2499  config_target_data.set('QEMU_ARCH',
2500                         'QEMU_ARCH_' + config_target['TARGET_BASE_ARCH'].to_upper())
2501  config_target_h += {target: configure_file(output: target + '-config-target.h',
2502                                               configuration: config_target_data)}
2503
2504  if target.endswith('-softmmu')
2505    config_input = meson.get_external_property(target, 'default')
2506    config_devices_mak = target + '-config-devices.mak'
2507    config_devices_mak = configure_file(
2508      input: ['configs/devices' / target / config_input + '.mak', 'Kconfig'],
2509      output: config_devices_mak,
2510      depfile: config_devices_mak + '.d',
2511      capture: true,
2512      command: [minikconf,
2513                get_option('default_devices') ? '--defconfig' : '--allnoconfig',
2514                config_devices_mak, '@DEPFILE@', '@INPUT@',
2515                host_kconfig, accel_kconfig,
2516                'CONFIG_' + config_target['TARGET_ARCH'].to_upper() + '=y'])
2517
2518    config_devices_data = configuration_data()
2519    config_devices = keyval.load(config_devices_mak)
2520    foreach k, v: config_devices
2521      config_devices_data.set(k, 1)
2522    endforeach
2523    config_devices_mak_list += config_devices_mak
2524    config_devices_h += {target: configure_file(output: target + '-config-devices.h',
2525                                                configuration: config_devices_data)}
2526    config_target += config_devices
2527    config_all_devices += config_devices
2528  endif
2529  config_target_mak += {target: config_target}
2530endforeach
2531target_dirs = actual_target_dirs
2532
2533# This configuration is used to build files that are shared by
2534# multiple binaries, and then extracted out of the "common"
2535# static_library target.
2536#
2537# We do not use all_sources()/all_dependencies(), because it would
2538# build literally all source files, including devices only used by
2539# targets that are not built for this compilation.  The CONFIG_ALL
2540# pseudo symbol replaces it.
2541
2542config_all += config_all_devices
2543config_all += config_host
2544config_all += config_all_disas
2545config_all += {
2546  'CONFIG_XEN': xen.found(),
2547  'CONFIG_SOFTMMU': have_system,
2548  'CONFIG_USER_ONLY': have_user,
2549  'CONFIG_ALL': true,
2550}
2551
2552target_configs_h = []
2553foreach target: target_dirs
2554  target_configs_h += config_target_h[target]
2555  target_configs_h += config_devices_h.get(target, [])
2556endforeach
2557genh += custom_target('config-poison.h',
2558                      input: [target_configs_h],
2559                      output: 'config-poison.h',
2560                      capture: true,
2561                      command: [find_program('scripts/make-config-poison.sh'),
2562                                target_configs_h])
2563
2564##############
2565# Submodules #
2566##############
2567
2568capstone = not_found
2569if not get_option('capstone').auto() or have_system or have_user
2570  capstone = dependency('capstone', version: '>=3.0.5',
2571                        kwargs: static_kwargs, method: 'pkg-config',
2572                        required: get_option('capstone'))
2573
2574  # Some versions of capstone have broken pkg-config file
2575  # that reports a wrong -I path, causing the #include to
2576  # fail later. If the system has such a broken version
2577  # do not use it.
2578  if capstone.found() and not cc.compiles('#include <capstone.h>',
2579                                          dependencies: [capstone])
2580    capstone = not_found
2581    if get_option('capstone').enabled()
2582      error('capstone requested, but it does not appear to work')
2583    endif
2584  endif
2585endif
2586
2587slirp = not_found
2588slirp_opt = 'disabled'
2589if have_system
2590  slirp_opt = get_option('slirp')
2591  if slirp_opt in ['enabled', 'auto', 'system']
2592    have_internal = fs.exists(meson.current_source_dir() / 'slirp/meson.build')
2593    slirp_dep_required = (slirp_opt == 'system' or
2594                          slirp_opt == 'enabled' and not have_internal)
2595    slirp = dependency('slirp', kwargs: static_kwargs,
2596                       method: 'pkg-config', version: '>=4.1.0',
2597                       required: slirp_dep_required)
2598    # slirp <4.7 is incompatible with CFI support in QEMU.  This is because
2599    # it passes function pointers within libslirp as callbacks for timers.
2600    # When using a system-wide shared libslirp, the type information for the
2601    # callback is missing and the timer call produces a false positive with CFI.
2602    # Do not use the "version" keyword argument to produce a better error.
2603    # with control-flow integrity.
2604    if get_option('cfi') and slirp.found() and slirp.version().version_compare('<4.7')
2605      if slirp_dep_required
2606        error('Control-Flow Integrity requires libslirp 4.7.')
2607      else
2608        warning('Control-Flow Integrity requires libslirp 4.7, not using system-wide libslirp.')
2609        slirp = not_found
2610      endif
2611    endif
2612    if slirp.found()
2613      slirp_opt = 'system'
2614    elif have_internal
2615      slirp_opt = 'internal'
2616    else
2617      slirp_opt = 'disabled'
2618    endif
2619  endif
2620  if slirp_opt == 'internal'
2621    slirp_deps = []
2622    if targetos == 'windows'
2623      slirp_deps = cc.find_library('iphlpapi')
2624    elif targetos == 'darwin'
2625      slirp_deps = cc.find_library('resolv')
2626    endif
2627    slirp_conf = configuration_data()
2628    slirp_conf.set('SLIRP_MAJOR_VERSION', meson.project_version().split('.')[0])
2629    slirp_conf.set('SLIRP_MINOR_VERSION', meson.project_version().split('.')[1])
2630    slirp_conf.set('SLIRP_MICRO_VERSION', meson.project_version().split('.')[2])
2631    slirp_conf.set_quoted('SLIRP_VERSION_STRING', meson.project_version())
2632    slirp_cargs = ['-DG_LOG_DOMAIN="Slirp"']
2633    slirp_files = [
2634      'slirp/src/arp_table.c',
2635      'slirp/src/bootp.c',
2636      'slirp/src/cksum.c',
2637      'slirp/src/dhcpv6.c',
2638      'slirp/src/dnssearch.c',
2639      'slirp/src/if.c',
2640      'slirp/src/ip6_icmp.c',
2641      'slirp/src/ip6_input.c',
2642      'slirp/src/ip6_output.c',
2643      'slirp/src/ip_icmp.c',
2644      'slirp/src/ip_input.c',
2645      'slirp/src/ip_output.c',
2646      'slirp/src/mbuf.c',
2647      'slirp/src/misc.c',
2648      'slirp/src/ncsi.c',
2649      'slirp/src/ndp_table.c',
2650      'slirp/src/sbuf.c',
2651      'slirp/src/slirp.c',
2652      'slirp/src/socket.c',
2653      'slirp/src/state.c',
2654      'slirp/src/stream.c',
2655      'slirp/src/tcp_input.c',
2656      'slirp/src/tcp_output.c',
2657      'slirp/src/tcp_subr.c',
2658      'slirp/src/tcp_timer.c',
2659      'slirp/src/tftp.c',
2660      'slirp/src/udp.c',
2661      'slirp/src/udp6.c',
2662      'slirp/src/util.c',
2663      'slirp/src/version.c',
2664      'slirp/src/vmstate.c',
2665    ]
2666
2667    configure_file(
2668      input : 'slirp/src/libslirp-version.h.in',
2669      output : 'libslirp-version.h',
2670      configuration: slirp_conf)
2671
2672    slirp_inc = include_directories('slirp', 'slirp/src')
2673    libslirp = static_library('slirp',
2674                              build_by_default: false,
2675                              sources: slirp_files,
2676                              c_args: slirp_cargs,
2677                              include_directories: slirp_inc)
2678    slirp = declare_dependency(link_with: libslirp,
2679                               dependencies: slirp_deps,
2680                               include_directories: slirp_inc)
2681  endif
2682endif
2683
2684libvfio_user_dep = not_found
2685if have_system and vfio_user_server_allowed
2686  have_internal = fs.exists(meson.current_source_dir() / 'subprojects/libvfio-user/meson.build')
2687
2688  if not have_internal
2689    error('libvfio-user source not found - please pull git submodule')
2690  endif
2691
2692  libvfio_user_proj = subproject('libvfio-user')
2693
2694  libvfio_user_lib = libvfio_user_proj.get_variable('libvfio_user_dep')
2695
2696  libvfio_user_dep = declare_dependency(dependencies: [libvfio_user_lib])
2697endif
2698
2699fdt = not_found
2700if have_system
2701  fdt_opt = get_option('fdt')
2702  if fdt_opt in ['enabled', 'auto', 'system']
2703    have_internal = fs.exists(meson.current_source_dir() / 'dtc/libfdt/Makefile.libfdt')
2704    fdt = cc.find_library('fdt', kwargs: static_kwargs,
2705                          required: fdt_opt == 'system' or
2706                                    fdt_opt == 'enabled' and not have_internal)
2707    if fdt.found() and cc.links('''
2708       #include <libfdt.h>
2709       #include <libfdt_env.h>
2710       int main(void) { fdt_find_max_phandle(NULL, NULL); return 0; }''',
2711         dependencies: fdt)
2712      fdt_opt = 'system'
2713    elif fdt_opt == 'system'
2714       error('system libfdt requested, but it is too old (1.5.1 or newer required)')
2715    elif have_internal
2716      fdt_opt = 'internal'
2717    else
2718      fdt_opt = 'disabled'
2719      fdt = not_found
2720    endif
2721  endif
2722  if fdt_opt == 'internal'
2723    fdt_files = files(
2724      'dtc/libfdt/fdt.c',
2725      'dtc/libfdt/fdt_ro.c',
2726      'dtc/libfdt/fdt_wip.c',
2727      'dtc/libfdt/fdt_sw.c',
2728      'dtc/libfdt/fdt_rw.c',
2729      'dtc/libfdt/fdt_strerror.c',
2730      'dtc/libfdt/fdt_empty_tree.c',
2731      'dtc/libfdt/fdt_addresses.c',
2732      'dtc/libfdt/fdt_overlay.c',
2733      'dtc/libfdt/fdt_check.c',
2734    )
2735
2736    fdt_inc = include_directories('dtc/libfdt')
2737    libfdt = static_library('fdt',
2738                            build_by_default: false,
2739                            sources: fdt_files,
2740                            include_directories: fdt_inc)
2741    fdt = declare_dependency(link_with: libfdt,
2742                             include_directories: fdt_inc)
2743  endif
2744else
2745  fdt_opt = 'disabled'
2746endif
2747if not fdt.found() and fdt_required.length() > 0
2748  error('fdt not available but required by targets ' + ', '.join(fdt_required))
2749endif
2750
2751config_host_data.set('CONFIG_CAPSTONE', capstone.found())
2752config_host_data.set('CONFIG_FDT', fdt.found())
2753config_host_data.set('CONFIG_SLIRP', slirp.found())
2754
2755#####################
2756# Generated sources #
2757#####################
2758
2759genh += configure_file(output: 'config-host.h', configuration: config_host_data)
2760
2761hxtool = find_program('scripts/hxtool')
2762shaderinclude = find_program('scripts/shaderinclude.pl')
2763qapi_gen = find_program('scripts/qapi-gen.py')
2764qapi_gen_depends = [ meson.current_source_dir() / 'scripts/qapi/__init__.py',
2765                     meson.current_source_dir() / 'scripts/qapi/commands.py',
2766                     meson.current_source_dir() / 'scripts/qapi/common.py',
2767                     meson.current_source_dir() / 'scripts/qapi/error.py',
2768                     meson.current_source_dir() / 'scripts/qapi/events.py',
2769                     meson.current_source_dir() / 'scripts/qapi/expr.py',
2770                     meson.current_source_dir() / 'scripts/qapi/gen.py',
2771                     meson.current_source_dir() / 'scripts/qapi/introspect.py',
2772                     meson.current_source_dir() / 'scripts/qapi/parser.py',
2773                     meson.current_source_dir() / 'scripts/qapi/schema.py',
2774                     meson.current_source_dir() / 'scripts/qapi/source.py',
2775                     meson.current_source_dir() / 'scripts/qapi/types.py',
2776                     meson.current_source_dir() / 'scripts/qapi/visit.py',
2777                     meson.current_source_dir() / 'scripts/qapi/common.py',
2778                     meson.current_source_dir() / 'scripts/qapi-gen.py'
2779]
2780
2781tracetool = [
2782  python, files('scripts/tracetool.py'),
2783   '--backend=' + ','.join(get_option('trace_backends'))
2784]
2785tracetool_depends = files(
2786  'scripts/tracetool/backend/log.py',
2787  'scripts/tracetool/backend/__init__.py',
2788  'scripts/tracetool/backend/dtrace.py',
2789  'scripts/tracetool/backend/ftrace.py',
2790  'scripts/tracetool/backend/simple.py',
2791  'scripts/tracetool/backend/syslog.py',
2792  'scripts/tracetool/backend/ust.py',
2793  'scripts/tracetool/format/ust_events_c.py',
2794  'scripts/tracetool/format/ust_events_h.py',
2795  'scripts/tracetool/format/__init__.py',
2796  'scripts/tracetool/format/d.py',
2797  'scripts/tracetool/format/simpletrace_stap.py',
2798  'scripts/tracetool/format/c.py',
2799  'scripts/tracetool/format/h.py',
2800  'scripts/tracetool/format/log_stap.py',
2801  'scripts/tracetool/format/stap.py',
2802  'scripts/tracetool/__init__.py',
2803  'scripts/tracetool/transform.py',
2804  'scripts/tracetool/vcpu.py'
2805)
2806
2807qemu_version_cmd = [find_program('scripts/qemu-version.sh'),
2808                    meson.current_source_dir(),
2809                    get_option('pkgversion'), meson.project_version()]
2810qemu_version = custom_target('qemu-version.h',
2811                             output: 'qemu-version.h',
2812                             command: qemu_version_cmd,
2813                             capture: true,
2814                             build_by_default: true,
2815                             build_always_stale: true)
2816genh += qemu_version
2817
2818hxdep = []
2819hx_headers = [
2820  ['qemu-options.hx', 'qemu-options.def'],
2821  ['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
2822]
2823if have_system
2824  hx_headers += [
2825    ['hmp-commands.hx', 'hmp-commands.h'],
2826    ['hmp-commands-info.hx', 'hmp-commands-info.h'],
2827  ]
2828endif
2829foreach d : hx_headers
2830  hxdep += custom_target(d[1],
2831                input: files(d[0]),
2832                output: d[1],
2833                capture: true,
2834                build_by_default: true, # to be removed when added to a target
2835                command: [hxtool, '-h', '@INPUT0@'])
2836endforeach
2837genh += hxdep
2838
2839###################
2840# Collect sources #
2841###################
2842
2843authz_ss = ss.source_set()
2844blockdev_ss = ss.source_set()
2845block_ss = ss.source_set()
2846chardev_ss = ss.source_set()
2847common_ss = ss.source_set()
2848crypto_ss = ss.source_set()
2849hwcore_ss = ss.source_set()
2850io_ss = ss.source_set()
2851qmp_ss = ss.source_set()
2852qom_ss = ss.source_set()
2853softmmu_ss = ss.source_set()
2854specific_fuzz_ss = ss.source_set()
2855specific_ss = ss.source_set()
2856stub_ss = ss.source_set()
2857trace_ss = ss.source_set()
2858user_ss = ss.source_set()
2859util_ss = ss.source_set()
2860
2861# accel modules
2862qtest_module_ss = ss.source_set()
2863tcg_module_ss = ss.source_set()
2864
2865modules = {}
2866target_modules = {}
2867hw_arch = {}
2868target_arch = {}
2869target_softmmu_arch = {}
2870target_user_arch = {}
2871
2872###############
2873# Trace files #
2874###############
2875
2876# TODO: add each directory to the subdirs from its own meson.build, once
2877# we have those
2878trace_events_subdirs = [
2879  'crypto',
2880  'qapi',
2881  'qom',
2882  'monitor',
2883  'util',
2884]
2885if have_linux_user
2886  trace_events_subdirs += [ 'linux-user' ]
2887endif
2888if have_bsd_user
2889  trace_events_subdirs += [ 'bsd-user' ]
2890endif
2891if have_block
2892  trace_events_subdirs += [
2893    'authz',
2894    'block',
2895    'io',
2896    'nbd',
2897    'scsi',
2898  ]
2899endif
2900if have_system
2901  trace_events_subdirs += [
2902    'accel/kvm',
2903    'audio',
2904    'backends',
2905    'backends/tpm',
2906    'chardev',
2907    'ebpf',
2908    'hw/9pfs',
2909    'hw/acpi',
2910    'hw/adc',
2911    'hw/alpha',
2912    'hw/arm',
2913    'hw/audio',
2914    'hw/block',
2915    'hw/block/dataplane',
2916    'hw/char',
2917    'hw/display',
2918    'hw/dma',
2919    'hw/hyperv',
2920    'hw/i2c',
2921    'hw/i386',
2922    'hw/i386/xen',
2923    'hw/ide',
2924    'hw/input',
2925    'hw/intc',
2926    'hw/isa',
2927    'hw/mem',
2928    'hw/mips',
2929    'hw/misc',
2930    'hw/misc/macio',
2931    'hw/net',
2932    'hw/net/can',
2933    'hw/nubus',
2934    'hw/nvme',
2935    'hw/nvram',
2936    'hw/pci',
2937    'hw/pci-host',
2938    'hw/ppc',
2939    'hw/rdma',
2940    'hw/rdma/vmw',
2941    'hw/rtc',
2942    'hw/s390x',
2943    'hw/scsi',
2944    'hw/sd',
2945    'hw/sh4',
2946    'hw/sparc',
2947    'hw/sparc64',
2948    'hw/ssi',
2949    'hw/timer',
2950    'hw/tpm',
2951    'hw/usb',
2952    'hw/vfio',
2953    'hw/virtio',
2954    'hw/watchdog',
2955    'hw/xen',
2956    'hw/gpio',
2957    'migration',
2958    'net',
2959    'softmmu',
2960    'ui',
2961    'hw/remote',
2962  ]
2963endif
2964if have_system or have_user
2965  trace_events_subdirs += [
2966    'accel/tcg',
2967    'hw/core',
2968    'target/arm',
2969    'target/arm/hvf',
2970    'target/hppa',
2971    'target/i386',
2972    'target/i386/kvm',
2973    'target/mips/tcg',
2974    'target/nios2',
2975    'target/ppc',
2976    'target/riscv',
2977    'target/s390x',
2978    'target/s390x/kvm',
2979    'target/sparc',
2980  ]
2981endif
2982
2983vhost_user = not_found
2984if targetos == 'linux' and have_vhost_user
2985  libvhost_user = subproject('libvhost-user')
2986  vhost_user = libvhost_user.get_variable('vhost_user_dep')
2987endif
2988
2989# NOTE: the trace/ subdirectory needs the qapi_trace_events variable
2990# that is filled in by qapi/.
2991subdir('qapi')
2992subdir('qobject')
2993subdir('stubs')
2994subdir('trace')
2995subdir('util')
2996subdir('qom')
2997subdir('authz')
2998subdir('crypto')
2999subdir('ui')
3000subdir('hw')
3001
3002
3003if enable_modules
3004  libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
3005  modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
3006endif
3007
3008qom_ss = qom_ss.apply(config_host, strict: false)
3009libqom = static_library('qom', qom_ss.sources() + genh,
3010                        dependencies: [qom_ss.dependencies()],
3011                        name_suffix: 'fa')
3012qom = declare_dependency(link_whole: libqom)
3013
3014event_loop_base = files('event-loop-base.c')
3015event_loop_base = static_library('event-loop-base', sources: event_loop_base + genh,
3016                                 build_by_default: true)
3017event_loop_base = declare_dependency(link_whole: event_loop_base,
3018                                     dependencies: [qom])
3019
3020stub_ss = stub_ss.apply(config_all, strict: false)
3021
3022util_ss.add_all(trace_ss)
3023util_ss = util_ss.apply(config_all, strict: false)
3024libqemuutil = static_library('qemuutil',
3025                             sources: util_ss.sources() + stub_ss.sources() + genh,
3026                             dependencies: [util_ss.dependencies(), libm, threads, glib, socket, malloc, pixman])
3027qemuutil = declare_dependency(link_with: libqemuutil,
3028                              sources: genh + version_res,
3029                              dependencies: [event_loop_base])
3030
3031if have_system or have_user
3032  decodetree = generator(find_program('scripts/decodetree.py'),
3033                         output: 'decode-@BASENAME@.c.inc',
3034                         arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
3035  subdir('libdecnumber')
3036  subdir('target')
3037endif
3038
3039subdir('audio')
3040subdir('io')
3041subdir('chardev')
3042subdir('fsdev')
3043subdir('dump')
3044
3045if have_block
3046  block_ss.add(files(
3047    'block.c',
3048    'blockjob.c',
3049    'job.c',
3050    'qemu-io-cmds.c',
3051  ))
3052  if config_host_data.get('CONFIG_REPLICATION')
3053    block_ss.add(files('replication.c'))
3054  endif
3055
3056  subdir('nbd')
3057  subdir('scsi')
3058  subdir('block')
3059
3060  blockdev_ss.add(files(
3061    'blockdev.c',
3062    'blockdev-nbd.c',
3063    'iothread.c',
3064    'job-qmp.c',
3065  ), gnutls)
3066
3067  # os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
3068  # os-win32.c does not
3069  blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c'))
3070  softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')])
3071endif
3072
3073common_ss.add(files('cpus-common.c'))
3074
3075subdir('softmmu')
3076
3077common_ss.add(capstone)
3078specific_ss.add(files('cpu.c', 'disas.c', 'gdbstub.c'), capstone)
3079
3080# Work around a gcc bug/misfeature wherein constant propagation looks
3081# through an alias:
3082#   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99696
3083# to guess that a const variable is always zero.  Without lto, this is
3084# impossible, as the alias is restricted to page-vary-common.c.  Indeed,
3085# without lto, not even the alias is required -- we simply use different
3086# declarations in different compilation units.
3087pagevary = files('page-vary-common.c')
3088if get_option('b_lto')
3089  pagevary_flags = ['-fno-lto']
3090  if get_option('cfi')
3091    pagevary_flags += '-fno-sanitize=cfi-icall'
3092  endif
3093  pagevary = static_library('page-vary-common', sources: pagevary + genh,
3094                            c_args: pagevary_flags)
3095  pagevary = declare_dependency(link_with: pagevary)
3096endif
3097common_ss.add(pagevary)
3098specific_ss.add(files('page-vary.c'))
3099
3100subdir('backends')
3101subdir('disas')
3102subdir('migration')
3103subdir('monitor')
3104subdir('net')
3105subdir('replay')
3106subdir('semihosting')
3107subdir('tcg')
3108subdir('fpu')
3109subdir('accel')
3110subdir('plugins')
3111subdir('ebpf')
3112
3113common_user_inc = []
3114
3115subdir('common-user')
3116subdir('bsd-user')
3117subdir('linux-user')
3118
3119# needed for fuzzing binaries
3120subdir('tests/qtest/libqos')
3121subdir('tests/qtest/fuzz')
3122
3123# accel modules
3124tcg_real_module_ss = ss.source_set()
3125tcg_real_module_ss.add_all(when: 'CONFIG_TCG_MODULAR', if_true: tcg_module_ss)
3126specific_ss.add_all(when: 'CONFIG_TCG_BUILTIN', if_true: tcg_module_ss)
3127target_modules += { 'accel' : { 'qtest': qtest_module_ss,
3128                                'tcg': tcg_real_module_ss }}
3129
3130########################
3131# Library dependencies #
3132########################
3133
3134modinfo_collect = find_program('scripts/modinfo-collect.py')
3135modinfo_generate = find_program('scripts/modinfo-generate.py')
3136modinfo_files = []
3137
3138block_mods = []
3139softmmu_mods = []
3140foreach d, list : modules
3141  foreach m, module_ss : list
3142    if enable_modules and targetos != 'windows'
3143      module_ss = module_ss.apply(config_all, strict: false)
3144      sl = static_library(d + '-' + m, [genh, module_ss.sources()],
3145                          dependencies: [modulecommon, module_ss.dependencies()], pic: true)
3146      if d == 'block'
3147        block_mods += sl
3148      else
3149        softmmu_mods += sl
3150      endif
3151      if module_ss.sources() != []
3152        # FIXME: Should use sl.extract_all_objects(recursive: true) as
3153        # input. Sources can be used multiple times but objects are
3154        # unique when it comes to lookup in compile_commands.json.
3155        # Depnds on a mesion version with
3156        # https://github.com/mesonbuild/meson/pull/8900
3157        modinfo_files += custom_target(d + '-' + m + '.modinfo',
3158                                       output: d + '-' + m + '.modinfo',
3159                                       input: module_ss.sources() + genh,
3160                                       capture: true,
3161                                       command: [modinfo_collect, module_ss.sources()])
3162      endif
3163    else
3164      if d == 'block'
3165        block_ss.add_all(module_ss)
3166      else
3167        softmmu_ss.add_all(module_ss)
3168      endif
3169    endif
3170  endforeach
3171endforeach
3172
3173foreach d, list : target_modules
3174  foreach m, module_ss : list
3175    if enable_modules and targetos != 'windows'
3176      foreach target : target_dirs
3177        if target.endswith('-softmmu')
3178          config_target = config_target_mak[target]
3179          config_target += config_host
3180          target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
3181          c_args = ['-DNEED_CPU_H',
3182                    '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
3183                    '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
3184          target_module_ss = module_ss.apply(config_target, strict: false)
3185          if target_module_ss.sources() != []
3186            module_name = d + '-' + m + '-' + config_target['TARGET_NAME']
3187            sl = static_library(module_name,
3188                                [genh, target_module_ss.sources()],
3189                                dependencies: [modulecommon, target_module_ss.dependencies()],
3190                                include_directories: target_inc,
3191                                c_args: c_args,
3192                                pic: true)
3193            softmmu_mods += sl
3194            # FIXME: Should use sl.extract_all_objects(recursive: true) too.
3195            modinfo_files += custom_target(module_name + '.modinfo',
3196                                           output: module_name + '.modinfo',
3197                                           input: target_module_ss.sources() + genh,
3198                                           capture: true,
3199                                           command: [modinfo_collect, '--target', target, target_module_ss.sources()])
3200          endif
3201        endif
3202      endforeach
3203    else
3204      specific_ss.add_all(module_ss)
3205    endif
3206  endforeach
3207endforeach
3208
3209if enable_modules
3210  foreach target : target_dirs
3211    if target.endswith('-softmmu')
3212      config_target = config_target_mak[target]
3213      config_devices_mak = target + '-config-devices.mak'
3214      modinfo_src = custom_target('modinfo-' + target + '.c',
3215                                  output: 'modinfo-' + target + '.c',
3216                                  input: modinfo_files,
3217                                  command: [modinfo_generate, '--devices', config_devices_mak, '@INPUT@'],
3218                                  capture: true)
3219
3220      modinfo_lib = static_library('modinfo-' + target + '.c', modinfo_src)
3221      modinfo_dep = declare_dependency(link_with: modinfo_lib)
3222
3223      arch = config_target['TARGET_NAME'] == 'sparc64' ? 'sparc64' : config_target['TARGET_BASE_ARCH']
3224      hw_arch[arch].add(modinfo_dep)
3225    endif
3226  endforeach
3227endif
3228
3229nm = find_program('nm')
3230undefsym = find_program('scripts/undefsym.py')
3231block_syms = custom_target('block.syms', output: 'block.syms',
3232                             input: [libqemuutil, block_mods],
3233                             capture: true,
3234                             command: [undefsym, nm, '@INPUT@'])
3235qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
3236                             input: [libqemuutil, softmmu_mods],
3237                             capture: true,
3238                             command: [undefsym, nm, '@INPUT@'])
3239
3240authz_ss = authz_ss.apply(config_host, strict: false)
3241libauthz = static_library('authz', authz_ss.sources() + genh,
3242                          dependencies: [authz_ss.dependencies()],
3243                          name_suffix: 'fa',
3244                          build_by_default: false)
3245
3246authz = declare_dependency(link_whole: libauthz,
3247                           dependencies: qom)
3248
3249crypto_ss = crypto_ss.apply(config_host, strict: false)
3250libcrypto = static_library('crypto', crypto_ss.sources() + genh,
3251                           dependencies: [crypto_ss.dependencies()],
3252                           name_suffix: 'fa',
3253                           build_by_default: false)
3254
3255crypto = declare_dependency(link_whole: libcrypto,
3256                            dependencies: [authz, qom])
3257
3258io_ss = io_ss.apply(config_host, strict: false)
3259libio = static_library('io', io_ss.sources() + genh,
3260                       dependencies: [io_ss.dependencies()],
3261                       link_with: libqemuutil,
3262                       name_suffix: 'fa',
3263                       build_by_default: false)
3264
3265io = declare_dependency(link_whole: libio, dependencies: [crypto, qom])
3266
3267libmigration = static_library('migration', sources: migration_files + genh,
3268                              name_suffix: 'fa',
3269                              build_by_default: false)
3270migration = declare_dependency(link_with: libmigration,
3271                               dependencies: [zlib, qom, io])
3272softmmu_ss.add(migration)
3273
3274block_ss = block_ss.apply(config_host, strict: false)
3275libblock = static_library('block', block_ss.sources() + genh,
3276                          dependencies: block_ss.dependencies(),
3277                          link_depends: block_syms,
3278                          name_suffix: 'fa',
3279                          build_by_default: false)
3280
3281block = declare_dependency(link_whole: [libblock],
3282                           link_args: '@block.syms',
3283                           dependencies: [crypto, io])
3284
3285blockdev_ss = blockdev_ss.apply(config_host, strict: false)
3286libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
3287                             dependencies: blockdev_ss.dependencies(),
3288                             name_suffix: 'fa',
3289                             build_by_default: false)
3290
3291blockdev = declare_dependency(link_whole: [libblockdev],
3292                              dependencies: [block, event_loop_base])
3293
3294qmp_ss = qmp_ss.apply(config_host, strict: false)
3295libqmp = static_library('qmp', qmp_ss.sources() + genh,
3296                        dependencies: qmp_ss.dependencies(),
3297                        name_suffix: 'fa',
3298                        build_by_default: false)
3299
3300qmp = declare_dependency(link_whole: [libqmp])
3301
3302libchardev = static_library('chardev', chardev_ss.sources() + genh,
3303                            name_suffix: 'fa',
3304                            dependencies: chardev_ss.dependencies(),
3305                            build_by_default: false)
3306
3307chardev = declare_dependency(link_whole: libchardev)
3308
3309hwcore_ss = hwcore_ss.apply(config_host, strict: false)
3310libhwcore = static_library('hwcore', sources: hwcore_ss.sources() + genh,
3311                           name_suffix: 'fa',
3312                           build_by_default: false)
3313hwcore = declare_dependency(link_whole: libhwcore)
3314common_ss.add(hwcore)
3315
3316###########
3317# Targets #
3318###########
3319
3320emulator_modules = []
3321foreach m : block_mods + softmmu_mods
3322  emulator_modules += shared_module(m.name(),
3323                build_by_default: true,
3324                name_prefix: '',
3325                link_whole: m,
3326                install: true,
3327                install_dir: qemu_moddir)
3328endforeach
3329if emulator_modules.length() > 0
3330  alias_target('modules', emulator_modules)
3331endif
3332
3333softmmu_ss.add(authz, blockdev, chardev, crypto, io, qmp)
3334common_ss.add(qom, qemuutil)
3335
3336common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss])
3337common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
3338
3339common_all = common_ss.apply(config_all, strict: false)
3340common_all = static_library('common',
3341                            build_by_default: false,
3342                            sources: common_all.sources() + genh,
3343                            include_directories: common_user_inc,
3344                            implicit_include_directories: false,
3345                            dependencies: common_all.dependencies(),
3346                            name_suffix: 'fa')
3347
3348feature_to_c = find_program('scripts/feature_to_c.sh')
3349
3350if targetos == 'darwin'
3351  entitlement = find_program('scripts/entitlement.sh')
3352endif
3353
3354emulators = {}
3355foreach target : target_dirs
3356  config_target = config_target_mak[target]
3357  target_name = config_target['TARGET_NAME']
3358  target_base_arch = config_target['TARGET_BASE_ARCH']
3359  arch_srcs = [config_target_h[target]]
3360  arch_deps = []
3361  c_args = ['-DNEED_CPU_H',
3362            '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
3363            '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
3364  link_args = emulator_link_args
3365
3366  config_target += config_host
3367  target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
3368  if targetos == 'linux'
3369    target_inc += include_directories('linux-headers', is_system: true)
3370  endif
3371  if target.endswith('-softmmu')
3372    qemu_target_name = 'qemu-system-' + target_name
3373    target_type='system'
3374    t = target_softmmu_arch[target_base_arch].apply(config_target, strict: false)
3375    arch_srcs += t.sources()
3376    arch_deps += t.dependencies()
3377
3378    hw_dir = target_name == 'sparc64' ? 'sparc64' : target_base_arch
3379    hw = hw_arch[hw_dir].apply(config_target, strict: false)
3380    arch_srcs += hw.sources()
3381    arch_deps += hw.dependencies()
3382
3383    arch_srcs += config_devices_h[target]
3384    link_args += ['@block.syms', '@qemu.syms']
3385  else
3386    abi = config_target['TARGET_ABI_DIR']
3387    target_type='user'
3388    target_inc += common_user_inc
3389    qemu_target_name = 'qemu-' + target_name
3390    if target_base_arch in target_user_arch
3391      t = target_user_arch[target_base_arch].apply(config_target, strict: false)
3392      arch_srcs += t.sources()
3393      arch_deps += t.dependencies()
3394    endif
3395    if 'CONFIG_LINUX_USER' in config_target
3396      base_dir = 'linux-user'
3397    endif
3398    if 'CONFIG_BSD_USER' in config_target
3399      base_dir = 'bsd-user'
3400      target_inc += include_directories('bsd-user/' / targetos)
3401      target_inc += include_directories('bsd-user/host/' / host_arch)
3402      dir = base_dir / abi
3403      arch_srcs += files(dir / 'signal.c', dir / 'target_arch_cpu.c')
3404    endif
3405    target_inc += include_directories(
3406      base_dir,
3407      base_dir / abi,
3408    )
3409    if 'CONFIG_LINUX_USER' in config_target
3410      dir = base_dir / abi
3411      arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
3412      if config_target.has_key('TARGET_SYSTBL_ABI')
3413        arch_srcs += \
3414          syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
3415                                             extra_args : config_target['TARGET_SYSTBL_ABI'])
3416      endif
3417    endif
3418  endif
3419
3420  if 'TARGET_XML_FILES' in config_target
3421    gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
3422                                output: target + '-gdbstub-xml.c',
3423                                input: files(config_target['TARGET_XML_FILES'].split()),
3424                                command: [feature_to_c, '@INPUT@'],
3425                                capture: true)
3426    arch_srcs += gdbstub_xml
3427  endif
3428
3429  t = target_arch[target_base_arch].apply(config_target, strict: false)
3430  arch_srcs += t.sources()
3431  arch_deps += t.dependencies()
3432
3433  target_common = common_ss.apply(config_target, strict: false)
3434  objects = common_all.extract_objects(target_common.sources())
3435  deps = target_common.dependencies()
3436
3437  target_specific = specific_ss.apply(config_target, strict: false)
3438  arch_srcs += target_specific.sources()
3439  arch_deps += target_specific.dependencies()
3440
3441  lib = static_library('qemu-' + target,
3442                 sources: arch_srcs + genh,
3443                 dependencies: arch_deps,
3444                 objects: objects,
3445                 include_directories: target_inc,
3446                 c_args: c_args,
3447                 build_by_default: false,
3448                 name_suffix: 'fa')
3449
3450  if target.endswith('-softmmu')
3451    execs = [{
3452      'name': 'qemu-system-' + target_name,
3453      'win_subsystem': 'console',
3454      'sources': files('softmmu/main.c'),
3455      'dependencies': []
3456    }]
3457    if targetos == 'windows' and (sdl.found() or gtk.found())
3458      execs += [{
3459        'name': 'qemu-system-' + target_name + 'w',
3460        'win_subsystem': 'windows',
3461        'sources': files('softmmu/main.c'),
3462        'dependencies': []
3463      }]
3464    endif
3465    if get_option('fuzzing')
3466      specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
3467      execs += [{
3468        'name': 'qemu-fuzz-' + target_name,
3469        'win_subsystem': 'console',
3470        'sources': specific_fuzz.sources(),
3471        'dependencies': specific_fuzz.dependencies(),
3472      }]
3473    endif
3474  else
3475    execs = [{
3476      'name': 'qemu-' + target_name,
3477      'win_subsystem': 'console',
3478      'sources': [],
3479      'dependencies': []
3480    }]
3481  endif
3482  foreach exe: execs
3483    exe_name = exe['name']
3484    if targetos == 'darwin'
3485      exe_name += '-unsigned'
3486    endif
3487
3488    emulator = executable(exe_name, exe['sources'],
3489               install: true,
3490               c_args: c_args,
3491               dependencies: arch_deps + deps + exe['dependencies'],
3492               objects: lib.extract_all_objects(recursive: true),
3493               link_language: link_language,
3494               link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
3495               link_args: link_args,
3496               win_subsystem: exe['win_subsystem'])
3497
3498    if targetos == 'darwin'
3499      icon = 'pc-bios/qemu.rsrc'
3500      build_input = [emulator, files(icon)]
3501      install_input = [
3502        get_option('bindir') / exe_name,
3503        meson.current_source_dir() / icon
3504      ]
3505      if 'CONFIG_HVF' in config_target
3506        entitlements = 'accel/hvf/entitlements.plist'
3507        build_input += files(entitlements)
3508        install_input += meson.current_source_dir() / entitlements
3509      endif
3510
3511      emulators += {exe['name'] : custom_target(exe['name'],
3512                   input: build_input,
3513                   output: exe['name'],
3514                   command: [entitlement, '@OUTPUT@', '@INPUT@'])
3515      }
3516
3517      meson.add_install_script(entitlement, '--install',
3518                               get_option('bindir') / exe['name'],
3519                               install_input)
3520    else
3521      emulators += {exe['name']: emulator}
3522    endif
3523
3524    if stap.found()
3525      foreach stp: [
3526        {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
3527        {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
3528        {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
3529        {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
3530      ]
3531        custom_target(exe['name'] + stp['ext'],
3532                      input: trace_events_all,
3533                      output: exe['name'] + stp['ext'],
3534                      install: stp['install'],
3535                      install_dir: get_option('datadir') / 'systemtap/tapset',
3536                      command: [
3537                        tracetool, '--group=all', '--format=' + stp['fmt'],
3538                        '--binary=' + stp['bin'],
3539                        '--target-name=' + target_name,
3540                        '--target-type=' + target_type,
3541                        '--probe-prefix=qemu.' + target_type + '.' + target_name,
3542                        '@INPUT@', '@OUTPUT@'
3543                      ],
3544                      depend_files: tracetool_depends)
3545      endforeach
3546    endif
3547  endforeach
3548endforeach
3549
3550# Other build targets
3551
3552if 'CONFIG_PLUGIN' in config_host
3553  install_headers('include/qemu/qemu-plugin.h')
3554endif
3555
3556subdir('qga')
3557
3558# Don't build qemu-keymap if xkbcommon is not explicitly enabled
3559# when we don't build tools or system
3560if xkbcommon.found()
3561  # used for the update-keymaps target, so include rules even if !have_tools
3562  qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
3563                           dependencies: [qemuutil, xkbcommon], install: have_tools)
3564endif
3565
3566if have_tools
3567  qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
3568             dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
3569  qemu_io = executable('qemu-io', files('qemu-io.c'),
3570             dependencies: [block, qemuutil], install: true)
3571  qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
3572               dependencies: [blockdev, qemuutil, gnutls, selinux],
3573               install: true)
3574
3575  subdir('storage-daemon')
3576  subdir('contrib/rdmacm-mux')
3577  subdir('contrib/elf2dmp')
3578
3579  executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
3580             dependencies: qemuutil,
3581             install: true)
3582
3583  if have_vhost_user
3584    subdir('contrib/vhost-user-blk')
3585    subdir('contrib/vhost-user-gpu')
3586    subdir('contrib/vhost-user-input')
3587    subdir('contrib/vhost-user-scsi')
3588  endif
3589
3590  if targetos == 'linux'
3591    executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
3592               dependencies: [qemuutil, libcap_ng],
3593               install: true,
3594               install_dir: get_option('libexecdir'))
3595
3596    executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
3597               dependencies: [authz, crypto, io, qom, qemuutil,
3598                              libcap_ng, mpathpersist],
3599               install: true)
3600  endif
3601
3602  if have_ivshmem
3603    subdir('contrib/ivshmem-client')
3604    subdir('contrib/ivshmem-server')
3605  endif
3606endif
3607
3608subdir('scripts')
3609subdir('tools')
3610subdir('pc-bios')
3611subdir('docs')
3612subdir('tests')
3613if gtk.found()
3614  subdir('po')
3615endif
3616
3617if host_machine.system() == 'windows'
3618  nsis_cmd = [
3619    find_program('scripts/nsis.py'),
3620    '@OUTPUT@',
3621    get_option('prefix'),
3622    meson.current_source_dir(),
3623    host_machine.cpu(),
3624    '--',
3625    '-DDISPLAYVERSION=' + meson.project_version(),
3626  ]
3627  if build_docs
3628    nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
3629  endif
3630  if gtk.found()
3631    nsis_cmd += '-DCONFIG_GTK=y'
3632  endif
3633
3634  nsis = custom_target('nsis',
3635                       output: 'qemu-setup-' + meson.project_version() + '.exe',
3636                       input: files('qemu.nsi'),
3637                       build_always_stale: true,
3638                       command: nsis_cmd + ['@INPUT@'])
3639  alias_target('installer', nsis)
3640endif
3641
3642#########################
3643# Configuration summary #
3644#########################
3645
3646# Directories
3647summary_info = {}
3648summary_info += {'Install prefix':    get_option('prefix')}
3649summary_info += {'BIOS directory':    qemu_datadir}
3650summary_info += {'firmware path':     get_option('prefix') / get_option('qemu_firmwarepath')}
3651summary_info += {'binary directory':  get_option('prefix') / get_option('bindir')}
3652summary_info += {'library directory': get_option('prefix') / get_option('libdir')}
3653summary_info += {'module directory':  qemu_moddir}
3654summary_info += {'libexec directory': get_option('prefix') / get_option('libexecdir')}
3655summary_info += {'include directory': get_option('prefix') / get_option('includedir')}
3656summary_info += {'config directory':  get_option('prefix') / get_option('sysconfdir')}
3657if targetos != 'windows'
3658  summary_info += {'local state directory': get_option('prefix') / get_option('localstatedir')}
3659  summary_info += {'Manual directory':      get_option('prefix') / get_option('mandir')}
3660else
3661  summary_info += {'local state directory': 'queried at runtime'}
3662endif
3663summary_info += {'Doc directory':     get_option('prefix') / get_option('docdir')}
3664summary_info += {'Build directory':   meson.current_build_dir()}
3665summary_info += {'Source path':       meson.current_source_dir()}
3666summary_info += {'GIT submodules':    config_host['GIT_SUBMODULES']}
3667summary(summary_info, bool_yn: true, section: 'Directories')
3668
3669# Host binaries
3670summary_info = {}
3671summary_info += {'git':               config_host['GIT']}
3672summary_info += {'make':              config_host['MAKE']}
3673summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
3674summary_info += {'sphinx-build':      sphinx_build}
3675if config_host.has_key('HAVE_GDB_BIN')
3676  summary_info += {'gdb':             config_host['HAVE_GDB_BIN']}
3677endif
3678summary_info += {'iasl':              iasl}
3679summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
3680if targetos == 'windows' and have_ga
3681  summary_info += {'wixl':            wixl}
3682endif
3683if slirp_opt != 'disabled' and have_system
3684  summary_info += {'smbd':            have_slirp_smbd ? smbd_path : false}
3685endif
3686summary(summary_info, bool_yn: true, section: 'Host binaries')
3687
3688# Configurable features
3689summary_info = {}
3690summary_info += {'Documentation':     build_docs}
3691summary_info += {'system-mode emulation': have_system}
3692summary_info += {'user-mode emulation': have_user}
3693summary_info += {'block layer':       have_block}
3694summary_info += {'Install blobs':     get_option('install_blobs')}
3695summary_info += {'module support':    config_host.has_key('CONFIG_MODULES')}
3696if config_host.has_key('CONFIG_MODULES')
3697  summary_info += {'alternative module path': get_option('module_upgrades')}
3698endif
3699summary_info += {'fuzzing support':   get_option('fuzzing')}
3700if have_system
3701  summary_info += {'Audio drivers':     ' '.join(audio_drivers_selected)}
3702endif
3703summary_info += {'Trace backends':    ','.join(get_option('trace_backends'))}
3704if 'simple' in get_option('trace_backends')
3705  summary_info += {'Trace output file': get_option('trace_file') + '-<pid>'}
3706endif
3707summary_info += {'D-Bus display':     dbus_display}
3708summary_info += {'QOM debugging':     get_option('qom_cast_debug')}
3709summary_info += {'vhost-kernel support': have_vhost_kernel}
3710summary_info += {'vhost-net support': have_vhost_net}
3711summary_info += {'vhost-user support': have_vhost_user}
3712summary_info += {'vhost-user-crypto support': have_vhost_user_crypto}
3713summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
3714summary_info += {'vhost-vdpa support': have_vhost_vdpa}
3715summary_info += {'build guest agent': have_ga}
3716summary(summary_info, bool_yn: true, section: 'Configurable features')
3717
3718# Compilation information
3719summary_info = {}
3720summary_info += {'host CPU':          cpu}
3721summary_info += {'host endianness':   build_machine.endian()}
3722summary_info += {'C compiler':        ' '.join(meson.get_compiler('c').cmd_array())}
3723summary_info += {'Host C compiler':   ' '.join(meson.get_compiler('c', native: true).cmd_array())}
3724if link_language == 'cpp'
3725  summary_info += {'C++ compiler':    ' '.join(meson.get_compiler('cpp').cmd_array())}
3726else
3727  summary_info += {'C++ compiler':      false}
3728endif
3729if targetos == 'darwin'
3730  summary_info += {'Objective-C compiler': ' '.join(meson.get_compiler('objc').cmd_array())}
3731endif
3732summary_info += {'CFLAGS':            ' '.join(get_option('c_args')
3733                                               + ['-O' + get_option('optimization')]
3734                                               + (get_option('debug') ? ['-g'] : []))}
3735if link_language == 'cpp'
3736  summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args')
3737                                               + ['-O' + get_option('optimization')]
3738                                               + (get_option('debug') ? ['-g'] : []))}
3739endif
3740if targetos == 'darwin'
3741  summary_info += {'OBJCFLAGS':       ' '.join(get_option('objc_args')
3742                                               + ['-O' + get_option('optimization')]
3743                                               + (get_option('debug') ? ['-g'] : []))}
3744endif
3745link_args = get_option(link_language + '_link_args')
3746if link_args.length() > 0
3747  summary_info += {'LDFLAGS':         ' '.join(link_args)}
3748endif
3749summary_info += {'QEMU_CFLAGS':       ' '.join(qemu_cflags)}
3750summary_info += {'QEMU_CXXFLAGS':     ' '.join(qemu_cxxflags)}
3751summary_info += {'QEMU_OBJCFLAGS':    ' '.join(qemu_objcflags)}
3752summary_info += {'QEMU_LDFLAGS':      ' '.join(qemu_ldflags)}
3753summary_info += {'profiler':          get_option('profiler')}
3754summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
3755summary_info += {'PIE':               get_option('b_pie')}
3756summary_info += {'static build':      config_host.has_key('CONFIG_STATIC')}
3757summary_info += {'malloc trim support': has_malloc_trim}
3758summary_info += {'membarrier':        have_membarrier}
3759summary_info += {'debug stack usage': get_option('debug_stack_usage')}
3760summary_info += {'mutex debugging':   get_option('debug_mutex')}
3761summary_info += {'memory allocator':  get_option('malloc')}
3762summary_info += {'avx2 optimization': config_host_data.get('CONFIG_AVX2_OPT')}
3763summary_info += {'avx512f optimization': config_host_data.get('CONFIG_AVX512F_OPT')}
3764summary_info += {'gprof enabled':     get_option('gprof')}
3765summary_info += {'gcov':              get_option('b_coverage')}
3766summary_info += {'thread sanitizer':  config_host.has_key('CONFIG_TSAN')}
3767summary_info += {'CFI support':       get_option('cfi')}
3768if get_option('cfi')
3769  summary_info += {'CFI debug support': get_option('cfi_debug')}
3770endif
3771summary_info += {'strip binaries':    get_option('strip')}
3772summary_info += {'sparse':            sparse}
3773summary_info += {'mingw32 support':   targetos == 'windows'}
3774summary(summary_info, bool_yn: true, section: 'Compilation')
3775
3776# snarf the cross-compilation information for tests
3777summary_info = {}
3778have_cross = false
3779foreach target: target_dirs
3780  tcg_mak = meson.current_build_dir() / 'tests/tcg' / 'config-' + target + '.mak'
3781  if fs.exists(tcg_mak)
3782    config_cross_tcg = keyval.load(tcg_mak)
3783    if 'CC' in config_cross_tcg
3784      summary_info += {config_cross_tcg['TARGET_NAME']: config_cross_tcg['CC']}
3785      have_cross = true
3786    endif
3787  endif
3788endforeach
3789if have_cross
3790  summary(summary_info, bool_yn: true, section: 'Cross compilers')
3791endif
3792
3793# Targets and accelerators
3794summary_info = {}
3795if have_system
3796  summary_info += {'KVM support':       config_all.has_key('CONFIG_KVM')}
3797  summary_info += {'HAX support':       config_all.has_key('CONFIG_HAX')}
3798  summary_info += {'HVF support':       config_all.has_key('CONFIG_HVF')}
3799  summary_info += {'WHPX support':      config_all.has_key('CONFIG_WHPX')}
3800  summary_info += {'NVMM support':      config_all.has_key('CONFIG_NVMM')}
3801  summary_info += {'Xen support':       xen.found()}
3802  if xen.found()
3803    summary_info += {'xen ctrl version':  xen.version()}
3804  endif
3805endif
3806summary_info += {'TCG support':       config_all.has_key('CONFIG_TCG')}
3807if config_all.has_key('CONFIG_TCG')
3808  if get_option('tcg_interpreter')
3809    summary_info += {'TCG backend':   'TCI (TCG with bytecode interpreter, slow)'}
3810  else
3811    summary_info += {'TCG backend':   'native (@0@)'.format(cpu)}
3812  endif
3813  summary_info += {'TCG plugins': config_host.has_key('CONFIG_PLUGIN')}
3814  summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')}
3815endif
3816summary_info += {'target list':       ' '.join(target_dirs)}
3817if have_system
3818  summary_info += {'default devices':   get_option('default_devices')}
3819  summary_info += {'out of process emulation': multiprocess_allowed}
3820  summary_info += {'vfio-user server': vfio_user_server_allowed}
3821endif
3822summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
3823
3824# Block layer
3825summary_info = {}
3826summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']}
3827summary_info += {'coroutine pool':    have_coroutine_pool}
3828if have_block
3829  summary_info += {'Block whitelist (rw)': get_option('block_drv_rw_whitelist')}
3830  summary_info += {'Block whitelist (ro)': get_option('block_drv_ro_whitelist')}
3831  summary_info += {'Use block whitelist in tools': get_option('block_drv_whitelist_in_tools')}
3832  summary_info += {'VirtFS support':    have_virtfs}
3833  summary_info += {'build virtiofs daemon': have_virtiofsd}
3834  summary_info += {'Live block migration': config_host_data.get('CONFIG_LIVE_BLOCK_MIGRATION')}
3835  summary_info += {'replication support': config_host_data.get('CONFIG_REPLICATION')}
3836  summary_info += {'bochs support':     get_option('bochs').allowed()}
3837  summary_info += {'cloop support':     get_option('cloop').allowed()}
3838  summary_info += {'dmg support':       get_option('dmg').allowed()}
3839  summary_info += {'qcow v1 support':   get_option('qcow1').allowed()}
3840  summary_info += {'vdi support':       get_option('vdi').allowed()}
3841  summary_info += {'vvfat support':     get_option('vvfat').allowed()}
3842  summary_info += {'qed support':       get_option('qed').allowed()}
3843  summary_info += {'parallels support': get_option('parallels').allowed()}
3844  summary_info += {'FUSE exports':      fuse}
3845endif
3846summary(summary_info, bool_yn: true, section: 'Block layer support')
3847
3848# Crypto
3849summary_info = {}
3850summary_info += {'TLS priority':      get_option('tls_priority')}
3851summary_info += {'GNUTLS support':    gnutls}
3852if gnutls.found()
3853  summary_info += {'  GNUTLS crypto':   gnutls_crypto.found()}
3854endif
3855summary_info += {'libgcrypt':         gcrypt}
3856summary_info += {'nettle':            nettle}
3857if nettle.found()
3858   summary_info += {'  XTS':             xts != 'private'}
3859endif
3860summary_info += {'AF_ALG support':    have_afalg}
3861summary_info += {'rng-none':          get_option('rng_none')}
3862summary_info += {'Linux keyring':     have_keyring}
3863summary(summary_info, bool_yn: true, section: 'Crypto')
3864
3865# Libraries
3866summary_info = {}
3867if targetos == 'darwin'
3868  summary_info += {'Cocoa support':           cocoa}
3869  summary_info += {'vmnet.framework support': vmnet}
3870endif
3871summary_info += {'SDL support':       sdl}
3872summary_info += {'SDL image support': sdl_image}
3873summary_info += {'GTK support':       gtk}
3874summary_info += {'pixman':            pixman}
3875summary_info += {'VTE support':       vte}
3876summary_info += {'slirp support':     slirp_opt == 'internal' ? slirp_opt : slirp}
3877summary_info += {'libtasn1':          tasn1}
3878summary_info += {'PAM':               pam}
3879summary_info += {'iconv support':     iconv}
3880summary_info += {'curses support':    curses}
3881summary_info += {'virgl support':     virgl}
3882summary_info += {'curl support':      curl}
3883summary_info += {'Multipath support': mpathpersist}
3884summary_info += {'PNG support':       png}
3885summary_info += {'VNC support':       vnc}
3886if vnc.found()
3887  summary_info += {'VNC SASL support':  sasl}
3888  summary_info += {'VNC JPEG support':  jpeg}
3889endif
3890if targetos not in ['darwin', 'haiku', 'windows']
3891  summary_info += {'OSS support':     oss}
3892elif targetos == 'darwin'
3893  summary_info += {'CoreAudio support': coreaudio}
3894elif targetos == 'windows'
3895  summary_info += {'DirectSound support': dsound}
3896endif
3897if targetos == 'linux'
3898  summary_info += {'ALSA support':    alsa}
3899  summary_info += {'PulseAudio support': pulse}
3900endif
3901summary_info += {'JACK support':      jack}
3902summary_info += {'brlapi support':    brlapi}
3903summary_info += {'vde support':       vde}
3904summary_info += {'netmap support':    have_netmap}
3905summary_info += {'l2tpv3 support':    have_l2tpv3}
3906summary_info += {'Linux AIO support': libaio}
3907summary_info += {'Linux io_uring support': linux_io_uring}
3908summary_info += {'ATTR/XATTR support': libattr}
3909summary_info += {'RDMA support':      rdma}
3910summary_info += {'PVRDMA support':    have_pvrdma}
3911summary_info += {'fdt support':       fdt_opt == 'disabled' ? false : fdt_opt}
3912summary_info += {'libcap-ng support': libcap_ng}
3913summary_info += {'bpf support':       libbpf}
3914summary_info += {'spice protocol support': spice_protocol}
3915if spice_protocol.found()
3916  summary_info += {'  spice server support': spice}
3917endif
3918summary_info += {'rbd support':       rbd}
3919summary_info += {'smartcard support': cacard}
3920summary_info += {'U2F support':       u2f}
3921summary_info += {'libusb':            libusb}
3922summary_info += {'usb net redir':     usbredir}
3923summary_info += {'OpenGL support (epoxy)': opengl}
3924summary_info += {'GBM':               gbm}
3925summary_info += {'libiscsi support':  libiscsi}
3926summary_info += {'libnfs support':    libnfs}
3927if targetos == 'windows'
3928  if have_ga
3929    summary_info += {'QGA VSS support':   have_qga_vss}
3930  endif
3931endif
3932summary_info += {'seccomp support':   seccomp}
3933summary_info += {'GlusterFS support': glusterfs}
3934summary_info += {'TPM support':       have_tpm}
3935summary_info += {'libssh support':    libssh}
3936summary_info += {'lzo support':       lzo}
3937summary_info += {'snappy support':    snappy}
3938summary_info += {'bzip2 support':     libbzip2}
3939summary_info += {'lzfse support':     liblzfse}
3940summary_info += {'zstd support':      zstd}
3941summary_info += {'NUMA host support': numa}
3942summary_info += {'capstone':          capstone}
3943summary_info += {'libpmem support':   libpmem}
3944summary_info += {'libdaxctl support': libdaxctl}
3945summary_info += {'libudev':           libudev}
3946# Dummy dependency, keep .found()
3947summary_info += {'FUSE lseek':        fuse_lseek.found()}
3948summary_info += {'selinux':           selinux}
3949summary(summary_info, bool_yn: true, section: 'Dependencies')
3950
3951if not supported_cpus.contains(cpu)
3952  message()
3953  warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!')
3954  message()
3955  message('CPU host architecture ' + cpu + ' support is not currently maintained.')
3956  message('The QEMU project intends to remove support for this host CPU in')
3957  message('a future release if nobody volunteers to maintain it and to')
3958  message('provide a build host for our continuous integration setup.')
3959  message('configure has succeeded and you can continue to build, but')
3960  message('if you care about QEMU on this platform you should contact')
3961  message('us upstream at qemu-devel@nongnu.org.')
3962endif
3963
3964if not supported_oses.contains(targetos)
3965  message()
3966  warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!')
3967  message()
3968  message('Host OS ' + targetos + 'support is not currently maintained.')
3969  message('The QEMU project intends to remove support for this host OS in')
3970  message('a future release if nobody volunteers to maintain it and to')
3971  message('provide a build host for our continuous integration setup.')
3972  message('configure has succeeded and you can continue to build, but')
3973  message('if you care about QEMU on this platform you should contact')
3974  message('us upstream at qemu-devel@nongnu.org.')
3975endif
3976