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