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