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