xref: /qemu/meson.build (revision ca61e750)
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
1411usbredir = not_found
1412if not get_option('usb_redir').auto() or have_system
1413  usbredir = dependency('libusbredirparser-0.5', required: get_option('usb_redir'),
1414                        version: '>=0.6', method: 'pkg-config',
1415                        kwargs: static_kwargs)
1416endif
1417libusb = not_found
1418if not get_option('libusb').auto() or have_system
1419  libusb = dependency('libusb-1.0', required: get_option('libusb'),
1420                      version: '>=1.0.13', method: 'pkg-config',
1421                      kwargs: static_kwargs)
1422endif
1423
1424libpmem = not_found
1425if not get_option('libpmem').auto() or have_system
1426  libpmem = dependency('libpmem', required: get_option('libpmem'),
1427                       method: 'pkg-config', kwargs: static_kwargs)
1428endif
1429libdaxctl = not_found
1430if not get_option('libdaxctl').auto() or have_system
1431  libdaxctl = dependency('libdaxctl', required: get_option('libdaxctl'),
1432                         version: '>=57', method: 'pkg-config',
1433                         kwargs: static_kwargs)
1434endif
1435tasn1 = not_found
1436if gnutls.found()
1437  tasn1 = dependency('libtasn1',
1438                     method: 'pkg-config',
1439                     kwargs: static_kwargs)
1440endif
1441keyutils = dependency('libkeyutils', required: false,
1442                      method: 'pkg-config', kwargs: static_kwargs)
1443
1444has_gettid = cc.has_function('gettid')
1445
1446# libselinux
1447selinux = dependency('libselinux',
1448                     required: get_option('selinux'),
1449                     method: 'pkg-config', kwargs: static_kwargs)
1450
1451# Malloc tests
1452
1453malloc = []
1454if get_option('malloc') == 'system'
1455  has_malloc_trim = \
1456    get_option('malloc_trim').allowed() and \
1457    cc.links('''#include <malloc.h>
1458                int main(void) { malloc_trim(0); return 0; }''')
1459else
1460  has_malloc_trim = false
1461  malloc = cc.find_library(get_option('malloc'), required: true)
1462endif
1463if not has_malloc_trim and get_option('malloc_trim').enabled()
1464  if get_option('malloc') == 'system'
1465    error('malloc_trim not available on this platform.')
1466  else
1467    error('malloc_trim not available with non-libc memory allocator')
1468  endif
1469endif
1470
1471# Check whether the glibc provides statx()
1472
1473gnu_source_prefix = '''
1474  #ifndef _GNU_SOURCE
1475  #define _GNU_SOURCE
1476  #endif
1477'''
1478statx_test = gnu_source_prefix + '''
1479  #include <sys/stat.h>
1480  int main(void) {
1481    struct statx statxbuf;
1482    statx(0, "", 0, STATX_BASIC_STATS, &statxbuf);
1483    return 0;
1484  }'''
1485
1486has_statx = cc.links(statx_test)
1487
1488# Check whether statx() provides mount ID information
1489
1490statx_mnt_id_test = gnu_source_prefix + '''
1491  #include <sys/stat.h>
1492  int main(void) {
1493    struct statx statxbuf;
1494    statx(0, "", 0, STATX_BASIC_STATS | STATX_MNT_ID, &statxbuf);
1495    return statxbuf.stx_mnt_id;
1496  }'''
1497
1498has_statx_mnt_id = cc.links(statx_mnt_id_test)
1499
1500have_vhost_user_blk_server = get_option('vhost_user_blk_server') \
1501  .require(targetos == 'linux',
1502           error_message: 'vhost_user_blk_server requires linux') \
1503  .require(have_vhost_user,
1504           error_message: 'vhost_user_blk_server requires vhost-user support') \
1505  .disable_auto_if(not have_system) \
1506  .allowed()
1507
1508if get_option('fuse').disabled() and get_option('fuse_lseek').enabled()
1509  error('Cannot enable fuse-lseek while fuse is disabled')
1510endif
1511
1512fuse = dependency('fuse3', required: get_option('fuse'),
1513                  version: '>=3.1', method: 'pkg-config',
1514                  kwargs: static_kwargs)
1515
1516fuse_lseek = not_found
1517if get_option('fuse_lseek').allowed()
1518  if fuse.version().version_compare('>=3.8')
1519    # Dummy dependency
1520    fuse_lseek = declare_dependency()
1521  elif get_option('fuse_lseek').enabled()
1522    if fuse.found()
1523      error('fuse-lseek requires libfuse >=3.8, found ' + fuse.version())
1524    else
1525      error('fuse-lseek requires libfuse, which was not found')
1526    endif
1527  endif
1528endif
1529
1530# libbpf
1531libbpf = dependency('libbpf', required: get_option('bpf'), method: 'pkg-config')
1532if libbpf.found() and not cc.links('''
1533   #include <bpf/libbpf.h>
1534   int main(void)
1535   {
1536     bpf_object__destroy_skeleton(NULL);
1537     return 0;
1538   }''', dependencies: libbpf)
1539  libbpf = not_found
1540  if get_option('bpf').enabled()
1541    error('libbpf skeleton test failed')
1542  else
1543    warning('libbpf skeleton test failed, disabling')
1544  endif
1545endif
1546
1547#################
1548# config-host.h #
1549#################
1550
1551audio_drivers_selected = []
1552if have_system
1553  audio_drivers_available = {
1554    'alsa': alsa.found(),
1555    'coreaudio': coreaudio.found(),
1556    'dsound': dsound.found(),
1557    'jack': jack.found(),
1558    'oss': oss.found(),
1559    'pa': pulse.found(),
1560    'sdl': sdl.found(),
1561  }
1562  foreach k, v: audio_drivers_available
1563    config_host_data.set('CONFIG_AUDIO_' + k.to_upper(), v)
1564  endforeach
1565
1566  # Default to native drivers first, OSS second, SDL third
1567  audio_drivers_priority = \
1568    [ 'pa', 'coreaudio', 'dsound', 'oss' ] + \
1569    (targetos == 'linux' ? [] : [ 'sdl' ])
1570  audio_drivers_default = []
1571  foreach k: audio_drivers_priority
1572    if audio_drivers_available[k]
1573      audio_drivers_default += k
1574    endif
1575  endforeach
1576
1577  foreach k: get_option('audio_drv_list')
1578    if k == 'default'
1579      audio_drivers_selected += audio_drivers_default
1580    elif not audio_drivers_available[k]
1581      error('Audio driver "@0@" not available.'.format(k))
1582    else
1583      audio_drivers_selected += k
1584    endif
1585  endforeach
1586endif
1587config_host_data.set('CONFIG_AUDIO_DRIVERS',
1588                     '"' + '", "'.join(audio_drivers_selected) + '", ')
1589
1590if get_option('cfi')
1591  cfi_flags=[]
1592  # Check for dependency on LTO
1593  if not get_option('b_lto')
1594    error('Selected Control-Flow Integrity but LTO is disabled')
1595  endif
1596  if config_host.has_key('CONFIG_MODULES')
1597    error('Selected Control-Flow Integrity is not compatible with modules')
1598  endif
1599  # Check for cfi flags. CFI requires LTO so we can't use
1600  # get_supported_arguments, but need a more complex "compiles" which allows
1601  # custom arguments
1602  if cc.compiles('int main () { return 0; }', name: '-fsanitize=cfi-icall',
1603                 args: ['-flto', '-fsanitize=cfi-icall'] )
1604    cfi_flags += '-fsanitize=cfi-icall'
1605  else
1606    error('-fsanitize=cfi-icall is not supported by the compiler')
1607  endif
1608  if cc.compiles('int main () { return 0; }',
1609                 name: '-fsanitize-cfi-icall-generalize-pointers',
1610                 args: ['-flto', '-fsanitize=cfi-icall',
1611                        '-fsanitize-cfi-icall-generalize-pointers'] )
1612    cfi_flags += '-fsanitize-cfi-icall-generalize-pointers'
1613  else
1614    error('-fsanitize-cfi-icall-generalize-pointers is not supported by the compiler')
1615  endif
1616  if get_option('cfi_debug')
1617    if cc.compiles('int main () { return 0; }',
1618                   name: '-fno-sanitize-trap=cfi-icall',
1619                   args: ['-flto', '-fsanitize=cfi-icall',
1620                          '-fno-sanitize-trap=cfi-icall'] )
1621      cfi_flags += '-fno-sanitize-trap=cfi-icall'
1622    else
1623      error('-fno-sanitize-trap=cfi-icall is not supported by the compiler')
1624    endif
1625  endif
1626  add_global_arguments(cfi_flags, native: false, language: ['c', 'cpp', 'objc'])
1627  add_global_link_arguments(cfi_flags, native: false, language: ['c', 'cpp', 'objc'])
1628endif
1629
1630have_host_block_device = (targetos != 'darwin' or
1631    cc.has_header('IOKit/storage/IOMedia.h'))
1632
1633# FIXME enable_modules shouldn't be necessary, but: https://github.com/mesonbuild/meson/issues/8333
1634dbus_display = get_option('dbus_display') \
1635  .require(gio.version().version_compare('>=2.64'),
1636           error_message: '-display dbus requires glib>=2.64') \
1637  .require(enable_modules,
1638           error_message: '-display dbus requires --enable-modules') \
1639  .require(gdbus_codegen.found(),
1640           error_message: '-display dbus requires gdbus-codegen') \
1641  .allowed()
1642
1643have_virtfs = get_option('virtfs') \
1644    .require(targetos == 'linux' or targetos == 'darwin',
1645             error_message: 'virtio-9p (virtfs) requires Linux or macOS') \
1646    .require(targetos == 'linux' or cc.has_function('pthread_fchdir_np'),
1647             error_message: 'virtio-9p (virtfs) on macOS requires the presence of pthread_fchdir_np') \
1648    .require(targetos == 'darwin' or (libattr.found() and libcap_ng.found()),
1649             error_message: 'virtio-9p (virtfs) on Linux requires libcap-ng-devel and libattr-devel') \
1650    .disable_auto_if(not have_tools and not have_system) \
1651    .allowed()
1652
1653have_virtfs_proxy_helper = targetos != 'darwin' and have_virtfs and have_tools
1654
1655if get_option('block_drv_ro_whitelist') == ''
1656  config_host_data.set('CONFIG_BDRV_RO_WHITELIST', '')
1657else
1658  config_host_data.set('CONFIG_BDRV_RO_WHITELIST',
1659        '"' + get_option('block_drv_ro_whitelist').replace(',', '", "') + '", ')
1660endif
1661if get_option('block_drv_rw_whitelist') == ''
1662  config_host_data.set('CONFIG_BDRV_RW_WHITELIST', '')
1663else
1664  config_host_data.set('CONFIG_BDRV_RW_WHITELIST',
1665        '"' + get_option('block_drv_rw_whitelist').replace(',', '", "') + '", ')
1666endif
1667
1668foreach k : get_option('trace_backends')
1669  config_host_data.set('CONFIG_TRACE_' + k.to_upper(), true)
1670endforeach
1671config_host_data.set_quoted('CONFIG_TRACE_FILE', get_option('trace_file'))
1672config_host_data.set_quoted('CONFIG_TLS_PRIORITY', get_option('tls_priority'))
1673if iasl.found()
1674  config_host_data.set_quoted('CONFIG_IASL', iasl.full_path())
1675endif
1676config_host_data.set_quoted('CONFIG_BINDIR', get_option('prefix') / get_option('bindir'))
1677config_host_data.set_quoted('CONFIG_PREFIX', get_option('prefix'))
1678config_host_data.set_quoted('CONFIG_QEMU_CONFDIR', get_option('prefix') / qemu_confdir)
1679config_host_data.set_quoted('CONFIG_QEMU_DATADIR', get_option('prefix') / qemu_datadir)
1680config_host_data.set_quoted('CONFIG_QEMU_DESKTOPDIR', get_option('prefix') / qemu_desktopdir)
1681config_host_data.set_quoted('CONFIG_QEMU_FIRMWAREPATH', get_option('prefix') / get_option('qemu_firmwarepath'))
1682config_host_data.set_quoted('CONFIG_QEMU_HELPERDIR', get_option('prefix') / get_option('libexecdir'))
1683config_host_data.set_quoted('CONFIG_QEMU_ICONDIR', get_option('prefix') / qemu_icondir)
1684config_host_data.set_quoted('CONFIG_QEMU_LOCALEDIR', get_option('prefix') / get_option('localedir'))
1685config_host_data.set_quoted('CONFIG_QEMU_LOCALSTATEDIR', get_option('prefix') / get_option('localstatedir'))
1686config_host_data.set_quoted('CONFIG_QEMU_MODDIR', get_option('prefix') / qemu_moddir)
1687config_host_data.set_quoted('CONFIG_SYSCONFDIR', get_option('prefix') / get_option('sysconfdir'))
1688
1689if config_host.has_key('CONFIG_MODULES')
1690  config_host_data.set('CONFIG_STAMP', run_command(
1691      meson.current_source_dir() / 'scripts/qemu-stamp.py',
1692      meson.project_version(), get_option('pkgversion'), '--',
1693      meson.current_source_dir() / 'configure',
1694      capture: true, check: true).stdout().strip())
1695endif
1696
1697have_slirp_smbd = get_option('slirp_smbd') \
1698  .require(targetos != 'windows', error_message: 'Host smbd not supported on this platform.') \
1699  .allowed()
1700if have_slirp_smbd
1701  smbd_path = get_option('smbd')
1702  if smbd_path == ''
1703    smbd_path = (targetos == 'solaris' ? '/usr/sfw/sbin/smbd' : '/usr/sbin/smbd')
1704  endif
1705  config_host_data.set_quoted('CONFIG_SMBD_COMMAND', smbd_path)
1706endif
1707
1708config_host_data.set('HOST_' + host_arch.to_upper(), 1)
1709
1710if get_option('module_upgrades') and not enable_modules
1711  error('Cannot enable module-upgrades as modules are not enabled')
1712endif
1713config_host_data.set('CONFIG_MODULE_UPGRADES', get_option('module_upgrades'))
1714
1715config_host_data.set('CONFIG_ATTR', libattr.found())
1716config_host_data.set('CONFIG_BDRV_WHITELIST_TOOLS', get_option('block_drv_whitelist_in_tools'))
1717config_host_data.set('CONFIG_BRLAPI', brlapi.found())
1718config_host_data.set('CONFIG_COCOA', cocoa.found())
1719config_host_data.set('CONFIG_FUZZ', get_option('fuzzing'))
1720config_host_data.set('CONFIG_GCOV', get_option('b_coverage'))
1721config_host_data.set('CONFIG_LIBUDEV', libudev.found())
1722config_host_data.set('CONFIG_LZO', lzo.found())
1723config_host_data.set('CONFIG_MPATH', mpathpersist.found())
1724config_host_data.set('CONFIG_MPATH_NEW_API', mpathpersist_new_api)
1725config_host_data.set('CONFIG_CURL', curl.found())
1726config_host_data.set('CONFIG_CURSES', curses.found())
1727config_host_data.set('CONFIG_GBM', gbm.found())
1728config_host_data.set('CONFIG_GIO', gio.found())
1729config_host_data.set('CONFIG_GLUSTERFS', glusterfs.found())
1730if glusterfs.found()
1731  config_host_data.set('CONFIG_GLUSTERFS_XLATOR_OPT', glusterfs.version().version_compare('>=4'))
1732  config_host_data.set('CONFIG_GLUSTERFS_DISCARD', glusterfs.version().version_compare('>=5'))
1733  config_host_data.set('CONFIG_GLUSTERFS_FALLOCATE', glusterfs.version().version_compare('>=6'))
1734  config_host_data.set('CONFIG_GLUSTERFS_ZEROFILL', glusterfs.version().version_compare('>=6'))
1735  config_host_data.set('CONFIG_GLUSTERFS_FTRUNCATE_HAS_STAT', glusterfs_ftruncate_has_stat)
1736  config_host_data.set('CONFIG_GLUSTERFS_IOCB_HAS_STAT', glusterfs_iocb_has_stat)
1737endif
1738config_host_data.set('CONFIG_GTK', gtk.found())
1739config_host_data.set('CONFIG_VTE', vte.found())
1740config_host_data.set('CONFIG_LIBATTR', have_old_libattr)
1741config_host_data.set('CONFIG_LIBCAP_NG', libcap_ng.found())
1742config_host_data.set('CONFIG_EBPF', libbpf.found())
1743config_host_data.set('CONFIG_LIBDAXCTL', libdaxctl.found())
1744config_host_data.set('CONFIG_LIBISCSI', libiscsi.found())
1745config_host_data.set('CONFIG_LIBNFS', libnfs.found())
1746config_host_data.set('CONFIG_LIBSSH', libssh.found())
1747config_host_data.set('CONFIG_LINUX_AIO', libaio.found())
1748config_host_data.set('CONFIG_LINUX_IO_URING', linux_io_uring.found())
1749config_host_data.set('CONFIG_LIBPMEM', libpmem.found())
1750config_host_data.set('CONFIG_NUMA', numa.found())
1751config_host_data.set('CONFIG_OPENGL', opengl.found())
1752config_host_data.set('CONFIG_PROFILER', get_option('profiler'))
1753config_host_data.set('CONFIG_RBD', rbd.found())
1754config_host_data.set('CONFIG_RDMA', rdma.found())
1755config_host_data.set('CONFIG_SDL', sdl.found())
1756config_host_data.set('CONFIG_SDL_IMAGE', sdl_image.found())
1757config_host_data.set('CONFIG_SECCOMP', seccomp.found())
1758config_host_data.set('CONFIG_SNAPPY', snappy.found())
1759config_host_data.set('CONFIG_TPM', have_tpm)
1760config_host_data.set('CONFIG_USB_LIBUSB', libusb.found())
1761config_host_data.set('CONFIG_VDE', vde.found())
1762config_host_data.set('CONFIG_VHOST_NET', have_vhost_net)
1763config_host_data.set('CONFIG_VHOST_NET_USER', have_vhost_net_user)
1764config_host_data.set('CONFIG_VHOST_NET_VDPA', have_vhost_net_vdpa)
1765config_host_data.set('CONFIG_VHOST_KERNEL', have_vhost_kernel)
1766config_host_data.set('CONFIG_VHOST_USER', have_vhost_user)
1767config_host_data.set('CONFIG_VHOST_CRYPTO', have_vhost_user_crypto)
1768config_host_data.set('CONFIG_VHOST_VDPA', have_vhost_vdpa)
1769config_host_data.set('CONFIG_VMNET', vmnet.found())
1770config_host_data.set('CONFIG_VHOST_USER_BLK_SERVER', have_vhost_user_blk_server)
1771config_host_data.set('CONFIG_PNG', png.found())
1772config_host_data.set('CONFIG_VNC', vnc.found())
1773config_host_data.set('CONFIG_VNC_JPEG', jpeg.found())
1774config_host_data.set('CONFIG_VNC_SASL', sasl.found())
1775config_host_data.set('CONFIG_VIRTFS', have_virtfs)
1776config_host_data.set('CONFIG_VTE', vte.found())
1777config_host_data.set('CONFIG_XKBCOMMON', xkbcommon.found())
1778config_host_data.set('CONFIG_KEYUTILS', keyutils.found())
1779config_host_data.set('CONFIG_GETTID', has_gettid)
1780config_host_data.set('CONFIG_GNUTLS', gnutls.found())
1781config_host_data.set('CONFIG_GNUTLS_CRYPTO', gnutls_crypto.found())
1782config_host_data.set('CONFIG_TASN1', tasn1.found())
1783config_host_data.set('CONFIG_GCRYPT', gcrypt.found())
1784config_host_data.set('CONFIG_NETTLE', nettle.found())
1785config_host_data.set('CONFIG_HOGWEED', hogweed.found())
1786config_host_data.set('CONFIG_QEMU_PRIVATE_XTS', xts == 'private')
1787config_host_data.set('CONFIG_MALLOC_TRIM', has_malloc_trim)
1788config_host_data.set('CONFIG_STATX', has_statx)
1789config_host_data.set('CONFIG_STATX_MNT_ID', has_statx_mnt_id)
1790config_host_data.set('CONFIG_ZSTD', zstd.found())
1791config_host_data.set('CONFIG_FUSE', fuse.found())
1792config_host_data.set('CONFIG_FUSE_LSEEK', fuse_lseek.found())
1793config_host_data.set('CONFIG_SPICE_PROTOCOL', spice_protocol.found())
1794if spice_protocol.found()
1795config_host_data.set('CONFIG_SPICE_PROTOCOL_MAJOR', spice_protocol.version().split('.')[0])
1796config_host_data.set('CONFIG_SPICE_PROTOCOL_MINOR', spice_protocol.version().split('.')[1])
1797config_host_data.set('CONFIG_SPICE_PROTOCOL_MICRO', spice_protocol.version().split('.')[2])
1798endif
1799config_host_data.set('CONFIG_SPICE', spice.found())
1800config_host_data.set('CONFIG_X11', x11.found())
1801config_host_data.set('CONFIG_DBUS_DISPLAY', dbus_display)
1802config_host_data.set('CONFIG_CFI', get_option('cfi'))
1803config_host_data.set('CONFIG_SELINUX', selinux.found())
1804config_host_data.set('CONFIG_XEN_BACKEND', xen.found())
1805if xen.found()
1806  # protect from xen.version() having less than three components
1807  xen_version = xen.version().split('.') + ['0', '0']
1808  xen_ctrl_version = xen_version[0] + \
1809    ('0' + xen_version[1]).substring(-2) + \
1810    ('0' + xen_version[2]).substring(-2)
1811  config_host_data.set('CONFIG_XEN_CTRL_INTERFACE_VERSION', xen_ctrl_version)
1812endif
1813config_host_data.set('QEMU_VERSION', '"@0@"'.format(meson.project_version()))
1814config_host_data.set('QEMU_VERSION_MAJOR', meson.project_version().split('.')[0])
1815config_host_data.set('QEMU_VERSION_MINOR', meson.project_version().split('.')[1])
1816config_host_data.set('QEMU_VERSION_MICRO', meson.project_version().split('.')[2])
1817
1818config_host_data.set_quoted('CONFIG_HOST_DSOSUF', host_dsosuf)
1819config_host_data.set('HAVE_HOST_BLOCK_DEVICE', have_host_block_device)
1820
1821have_coroutine_pool = get_option('coroutine_pool')
1822if get_option('debug_stack_usage') and have_coroutine_pool
1823  message('Disabling coroutine pool to measure stack usage')
1824  have_coroutine_pool = false
1825endif
1826config_host_data.set10('CONFIG_COROUTINE_POOL', have_coroutine_pool)
1827config_host_data.set('CONFIG_DEBUG_MUTEX', get_option('debug_mutex'))
1828config_host_data.set('CONFIG_DEBUG_STACK_USAGE', get_option('debug_stack_usage'))
1829config_host_data.set('CONFIG_GPROF', get_option('gprof'))
1830config_host_data.set('CONFIG_LIVE_BLOCK_MIGRATION', get_option('live_block_migration').allowed())
1831config_host_data.set('CONFIG_QOM_CAST_DEBUG', get_option('qom_cast_debug'))
1832config_host_data.set('CONFIG_REPLICATION', get_option('live_block_migration').allowed())
1833
1834# has_header
1835config_host_data.set('CONFIG_EPOLL', cc.has_header('sys/epoll.h'))
1836config_host_data.set('CONFIG_LINUX_MAGIC_H', cc.has_header('linux/magic.h'))
1837config_host_data.set('CONFIG_VALGRIND_H', cc.has_header('valgrind/valgrind.h'))
1838config_host_data.set('HAVE_BTRFS_H', cc.has_header('linux/btrfs.h'))
1839config_host_data.set('HAVE_DRM_H', cc.has_header('libdrm/drm.h'))
1840config_host_data.set('HAVE_PTY_H', cc.has_header('pty.h'))
1841config_host_data.set('HAVE_SYS_DISK_H', cc.has_header('sys/disk.h'))
1842config_host_data.set('HAVE_SYS_IOCCOM_H', cc.has_header('sys/ioccom.h'))
1843config_host_data.set('HAVE_SYS_KCOV_H', cc.has_header('sys/kcov.h'))
1844
1845# has_function
1846config_host_data.set('CONFIG_ACCEPT4', cc.has_function('accept4'))
1847config_host_data.set('CONFIG_CLOCK_ADJTIME', cc.has_function('clock_adjtime'))
1848config_host_data.set('CONFIG_DUP3', cc.has_function('dup3'))
1849config_host_data.set('CONFIG_FALLOCATE', cc.has_function('fallocate'))
1850config_host_data.set('CONFIG_POSIX_FALLOCATE', cc.has_function('posix_fallocate'))
1851# Note that we need to specify prefix: here to avoid incorrectly
1852# thinking that Windows has posix_memalign()
1853config_host_data.set('CONFIG_POSIX_MEMALIGN', cc.has_function('posix_memalign', prefix: '#include <stdlib.h>'))
1854config_host_data.set('CONFIG_ALIGNED_MALLOC', cc.has_function('_aligned_malloc'))
1855config_host_data.set('CONFIG_VALLOC', cc.has_function('valloc'))
1856config_host_data.set('CONFIG_MEMALIGN', cc.has_function('memalign'))
1857config_host_data.set('CONFIG_PPOLL', cc.has_function('ppoll'))
1858config_host_data.set('CONFIG_PREADV', cc.has_function('preadv', prefix: '#include <sys/uio.h>'))
1859config_host_data.set('CONFIG_PTHREAD_FCHDIR_NP', cc.has_function('pthread_fchdir_np'))
1860config_host_data.set('CONFIG_SENDFILE', cc.has_function('sendfile'))
1861config_host_data.set('CONFIG_SETNS', cc.has_function('setns') and cc.has_function('unshare'))
1862config_host_data.set('CONFIG_SYNCFS', cc.has_function('syncfs'))
1863config_host_data.set('CONFIG_SYNC_FILE_RANGE', cc.has_function('sync_file_range'))
1864config_host_data.set('CONFIG_TIMERFD', cc.has_function('timerfd_create'))
1865config_host_data.set('HAVE_COPY_FILE_RANGE', cc.has_function('copy_file_range'))
1866config_host_data.set('HAVE_GETIFADDRS', cc.has_function('getifaddrs'))
1867config_host_data.set('HAVE_OPENPTY', cc.has_function('openpty', dependencies: util))
1868config_host_data.set('HAVE_STRCHRNUL', cc.has_function('strchrnul'))
1869config_host_data.set('HAVE_SYSTEM_FUNCTION', cc.has_function('system', prefix: '#include <stdlib.h>'))
1870if rdma.found()
1871  config_host_data.set('HAVE_IBV_ADVISE_MR',
1872                       cc.has_function('ibv_advise_mr',
1873                                       dependencies: rdma,
1874                                       prefix: '#include <infiniband/verbs.h>'))
1875endif
1876
1877# has_header_symbol
1878config_host_data.set('CONFIG_BYTESWAP_H',
1879                     cc.has_header_symbol('byteswap.h', 'bswap_32'))
1880config_host_data.set('CONFIG_EPOLL_CREATE1',
1881                     cc.has_header_symbol('sys/epoll.h', 'epoll_create1'))
1882config_host_data.set('CONFIG_FALLOCATE_PUNCH_HOLE',
1883                     cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_PUNCH_HOLE') and
1884                     cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_KEEP_SIZE'))
1885config_host_data.set('CONFIG_FALLOCATE_ZERO_RANGE',
1886                     cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_ZERO_RANGE'))
1887config_host_data.set('CONFIG_FIEMAP',
1888                     cc.has_header('linux/fiemap.h') and
1889                     cc.has_header_symbol('linux/fs.h', 'FS_IOC_FIEMAP'))
1890config_host_data.set('CONFIG_GETRANDOM',
1891                     cc.has_function('getrandom') and
1892                     cc.has_header_symbol('sys/random.h', 'GRND_NONBLOCK'))
1893config_host_data.set('CONFIG_INOTIFY',
1894                     cc.has_header_symbol('sys/inotify.h', 'inotify_init'))
1895config_host_data.set('CONFIG_INOTIFY1',
1896                     cc.has_header_symbol('sys/inotify.h', 'inotify_init1'))
1897config_host_data.set('CONFIG_MACHINE_BSWAP_H',
1898                     cc.has_header_symbol('machine/bswap.h', 'bswap32',
1899                                          prefix: '''#include <sys/endian.h>
1900                                                     #include <sys/types.h>'''))
1901config_host_data.set('CONFIG_PRCTL_PR_SET_TIMERSLACK',
1902                     cc.has_header_symbol('sys/prctl.h', 'PR_SET_TIMERSLACK'))
1903config_host_data.set('CONFIG_RTNETLINK',
1904                     cc.has_header_symbol('linux/rtnetlink.h', 'IFLA_PROTO_DOWN'))
1905config_host_data.set('CONFIG_SYSMACROS',
1906                     cc.has_header_symbol('sys/sysmacros.h', 'makedev'))
1907config_host_data.set('HAVE_OPTRESET',
1908                     cc.has_header_symbol('getopt.h', 'optreset'))
1909config_host_data.set('HAVE_IPPROTO_MPTCP',
1910                     cc.has_header_symbol('netinet/in.h', 'IPPROTO_MPTCP'))
1911
1912# has_member
1913config_host_data.set('HAVE_SIGEV_NOTIFY_THREAD_ID',
1914                     cc.has_member('struct sigevent', 'sigev_notify_thread_id',
1915                                   prefix: '#include <signal.h>'))
1916config_host_data.set('HAVE_STRUCT_STAT_ST_ATIM',
1917                     cc.has_member('struct stat', 'st_atim',
1918                                   prefix: '#include <sys/stat.h>'))
1919
1920# has_type
1921config_host_data.set('CONFIG_IOVEC',
1922                     cc.has_type('struct iovec',
1923                                 prefix: '#include <sys/uio.h>'))
1924config_host_data.set('HAVE_UTMPX',
1925                     cc.has_type('struct utmpx',
1926                                 prefix: '#include <utmpx.h>'))
1927
1928config_host_data.set('CONFIG_EVENTFD', cc.links('''
1929  #include <sys/eventfd.h>
1930  int main(void) { return eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); }'''))
1931config_host_data.set('CONFIG_FDATASYNC', cc.links(gnu_source_prefix + '''
1932  #include <unistd.h>
1933  int main(void) {
1934  #if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
1935  return fdatasync(0);
1936  #else
1937  #error Not supported
1938  #endif
1939  }'''))
1940
1941has_madvise = cc.links(gnu_source_prefix + '''
1942  #include <sys/types.h>
1943  #include <sys/mman.h>
1944  #include <stddef.h>
1945  int main(void) { return madvise(NULL, 0, MADV_DONTNEED); }''')
1946missing_madvise_proto = false
1947if has_madvise
1948  # Some platforms (illumos and Solaris before Solaris 11) provide madvise()
1949  # but forget to prototype it. In this case, has_madvise will be true (the
1950  # test program links despite a compile warning). To detect the
1951  # missing-prototype case, we try again with a definitely-bogus prototype.
1952  # This will only compile if the system headers don't provide the prototype;
1953  # otherwise the conflicting prototypes will cause a compiler error.
1954  missing_madvise_proto = cc.links(gnu_source_prefix + '''
1955    #include <sys/types.h>
1956    #include <sys/mman.h>
1957    #include <stddef.h>
1958    extern int madvise(int);
1959    int main(void) { return madvise(0); }''')
1960endif
1961config_host_data.set('CONFIG_MADVISE', has_madvise)
1962config_host_data.set('HAVE_MADVISE_WITHOUT_PROTOTYPE', missing_madvise_proto)
1963
1964config_host_data.set('CONFIG_MEMFD', cc.links(gnu_source_prefix + '''
1965  #include <sys/mman.h>
1966  int main(void) { return memfd_create("foo", MFD_ALLOW_SEALING); }'''))
1967config_host_data.set('CONFIG_OPEN_BY_HANDLE', cc.links(gnu_source_prefix + '''
1968  #include <fcntl.h>
1969  #if !defined(AT_EMPTY_PATH)
1970  # error missing definition
1971  #else
1972  int main(void) { struct file_handle fh; return open_by_handle_at(0, &fh, 0); }
1973  #endif'''))
1974config_host_data.set('CONFIG_PIPE2', cc.links(gnu_source_prefix + '''
1975  #include <unistd.h>
1976  #include <fcntl.h>
1977
1978  int main(void)
1979  {
1980      int pipefd[2];
1981      return pipe2(pipefd, O_CLOEXEC);
1982  }'''))
1983config_host_data.set('CONFIG_POSIX_MADVISE', cc.links(gnu_source_prefix + '''
1984  #include <sys/mman.h>
1985  #include <stddef.h>
1986  int main(void) { return posix_madvise(NULL, 0, POSIX_MADV_DONTNEED); }'''))
1987
1988config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_W_TID', cc.links(gnu_source_prefix + '''
1989  #include <pthread.h>
1990
1991  static void *f(void *p) { return NULL; }
1992  int main(void)
1993  {
1994    pthread_t thread;
1995    pthread_create(&thread, 0, f, 0);
1996    pthread_setname_np(thread, "QEMU");
1997    return 0;
1998  }''', dependencies: threads))
1999config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_WO_TID', cc.links(gnu_source_prefix + '''
2000  #include <pthread.h>
2001
2002  static void *f(void *p) { pthread_setname_np("QEMU"); return NULL; }
2003  int main(void)
2004  {
2005    pthread_t thread;
2006    pthread_create(&thread, 0, f, 0);
2007    return 0;
2008  }''', dependencies: threads))
2009config_host_data.set('CONFIG_PTHREAD_CONDATTR_SETCLOCK', cc.links(gnu_source_prefix + '''
2010  #include <pthread.h>
2011  #include <time.h>
2012
2013  int main(void)
2014  {
2015    pthread_condattr_t attr
2016    pthread_condattr_init(&attr);
2017    pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
2018    return 0;
2019  }''', dependencies: threads))
2020
2021config_host_data.set('CONFIG_SIGNALFD', cc.links(gnu_source_prefix + '''
2022  #include <sys/signalfd.h>
2023  #include <stddef.h>
2024  int main(void) { return signalfd(-1, NULL, SFD_CLOEXEC); }'''))
2025config_host_data.set('CONFIG_SPLICE', cc.links(gnu_source_prefix + '''
2026  #include <unistd.h>
2027  #include <fcntl.h>
2028  #include <limits.h>
2029
2030  int main(void)
2031  {
2032    int len, fd = 0;
2033    len = tee(STDIN_FILENO, STDOUT_FILENO, INT_MAX, SPLICE_F_NONBLOCK);
2034    splice(STDIN_FILENO, NULL, fd, NULL, len, SPLICE_F_MOVE);
2035    return 0;
2036  }'''))
2037
2038config_host_data.set('HAVE_MLOCKALL', cc.links(gnu_source_prefix + '''
2039  #include <sys/mman.h>
2040  int main(int argc, char *argv[]) {
2041    return mlockall(MCL_FUTURE);
2042  }'''))
2043
2044have_l2tpv3 = false
2045if get_option('l2tpv3').allowed() and have_system
2046  have_l2tpv3 = cc.has_type('struct mmsghdr',
2047    prefix: gnu_source_prefix + '''
2048      #include <sys/socket.h>
2049      #include <linux/ip.h>''')
2050endif
2051config_host_data.set('CONFIG_L2TPV3', have_l2tpv3)
2052
2053have_netmap = false
2054if get_option('netmap').allowed() and have_system
2055  have_netmap = cc.compiles('''
2056    #include <inttypes.h>
2057    #include <net/if.h>
2058    #include <net/netmap.h>
2059    #include <net/netmap_user.h>
2060    #if (NETMAP_API < 11) || (NETMAP_API > 15)
2061    #error
2062    #endif
2063    int main(void) { return 0; }''')
2064  if not have_netmap and get_option('netmap').enabled()
2065    error('Netmap headers not available')
2066  endif
2067endif
2068config_host_data.set('CONFIG_NETMAP', have_netmap)
2069
2070# Work around a system header bug with some kernel/XFS header
2071# versions where they both try to define 'struct fsxattr':
2072# xfs headers will not try to redefine structs from linux headers
2073# if this macro is set.
2074config_host_data.set('HAVE_FSXATTR', cc.links('''
2075  #include <linux/fs.h>
2076  struct fsxattr foo;
2077  int main(void) {
2078    return 0;
2079  }'''))
2080
2081# Some versions of Mac OS X incorrectly define SIZE_MAX
2082config_host_data.set('HAVE_BROKEN_SIZE_MAX', not cc.compiles('''
2083    #include <stdint.h>
2084    #include <stdio.h>
2085    int main(int argc, char *argv[]) {
2086        return printf("%zu", SIZE_MAX);
2087    }''', args: ['-Werror']))
2088
2089atomic_test = '''
2090  #include <stdint.h>
2091  int main(void)
2092  {
2093    @0@ x = 0, y = 0;
2094    y = __atomic_load_n(&x, __ATOMIC_RELAXED);
2095    __atomic_store_n(&x, y, __ATOMIC_RELAXED);
2096    __atomic_compare_exchange_n(&x, &y, x, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
2097    __atomic_exchange_n(&x, y, __ATOMIC_RELAXED);
2098    __atomic_fetch_add(&x, y, __ATOMIC_RELAXED);
2099    return 0;
2100  }'''
2101
2102# See if 64-bit atomic operations are supported.
2103# Note that without __atomic builtins, we can only
2104# assume atomic loads/stores max at pointer size.
2105config_host_data.set('CONFIG_ATOMIC64', cc.links(atomic_test.format('uint64_t')))
2106
2107has_int128 = cc.links('''
2108  __int128_t a;
2109  __uint128_t b;
2110  int main (void) {
2111    a = a + b;
2112    b = a * b;
2113    a = a * a;
2114    return 0;
2115  }''')
2116
2117config_host_data.set('CONFIG_INT128', has_int128)
2118
2119if has_int128
2120  # "do we have 128-bit atomics which are handled inline and specifically not
2121  # via libatomic". The reason we can't use libatomic is documented in the
2122  # comment starting "GCC is a house divided" in include/qemu/atomic128.h.
2123  has_atomic128 = cc.links(atomic_test.format('unsigned __int128'))
2124
2125  config_host_data.set('CONFIG_ATOMIC128', has_atomic128)
2126
2127  if not has_atomic128
2128    has_cmpxchg128 = cc.links('''
2129      int main(void)
2130      {
2131        unsigned __int128 x = 0, y = 0;
2132        __sync_val_compare_and_swap_16(&x, y, x);
2133        return 0;
2134      }
2135    ''')
2136
2137    config_host_data.set('CONFIG_CMPXCHG128', has_cmpxchg128)
2138  endif
2139endif
2140
2141config_host_data.set('CONFIG_GETAUXVAL', cc.links(gnu_source_prefix + '''
2142  #include <sys/auxv.h>
2143  int main(void) {
2144    return getauxval(AT_HWCAP) == 0;
2145  }'''))
2146
2147config_host_data.set('CONFIG_USBFS', have_linux_user and cc.compiles('''
2148  #include <linux/usbdevice_fs.h>
2149
2150  #ifndef USBDEVFS_GET_CAPABILITIES
2151  #error "USBDEVFS_GET_CAPABILITIES undefined"
2152  #endif
2153
2154  #ifndef USBDEVFS_DISCONNECT_CLAIM
2155  #error "USBDEVFS_DISCONNECT_CLAIM undefined"
2156  #endif
2157
2158  int main(void) { return 0; }'''))
2159
2160have_keyring = get_option('keyring') \
2161  .require(targetos == 'linux', error_message: 'keyring is only available on Linux') \
2162  .require(cc.compiles('''
2163    #include <errno.h>
2164    #include <asm/unistd.h>
2165    #include <linux/keyctl.h>
2166    #include <sys/syscall.h>
2167    #include <unistd.h>
2168    int main(void) {
2169        return syscall(__NR_keyctl, KEYCTL_READ, 0, NULL, NULL, 0);
2170    }'''), error_message: 'keyctl syscall not available on this system').allowed()
2171config_host_data.set('CONFIG_SECRET_KEYRING', have_keyring)
2172
2173have_cpuid_h = cc.links('''
2174  #include <cpuid.h>
2175  int main(void) {
2176    unsigned a, b, c, d;
2177    unsigned max = __get_cpuid_max(0, 0);
2178
2179    if (max >= 1) {
2180        __cpuid(1, a, b, c, d);
2181    }
2182
2183    if (max >= 7) {
2184        __cpuid_count(7, 0, a, b, c, d);
2185    }
2186
2187    return 0;
2188  }''')
2189config_host_data.set('CONFIG_CPUID_H', have_cpuid_h)
2190
2191config_host_data.set('CONFIG_AVX2_OPT', get_option('avx2') \
2192  .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable AVX2') \
2193  .require(cc.links('''
2194    #pragma GCC push_options
2195    #pragma GCC target("avx2")
2196    #include <cpuid.h>
2197    #include <immintrin.h>
2198    static int bar(void *a) {
2199      __m256i x = *(__m256i *)a;
2200      return _mm256_testz_si256(x, x);
2201    }
2202    int main(int argc, char *argv[]) { return bar(argv[0]); }
2203  '''), error_message: 'AVX2 not available').allowed())
2204
2205config_host_data.set('CONFIG_AVX512F_OPT', get_option('avx512f') \
2206  .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable AVX512F') \
2207  .require(cc.links('''
2208    #pragma GCC push_options
2209    #pragma GCC target("avx512f")
2210    #include <cpuid.h>
2211    #include <immintrin.h>
2212    static int bar(void *a) {
2213      __m512i x = *(__m512i *)a;
2214      return _mm512_test_epi64_mask(x, x);
2215    }
2216    int main(int argc, char *argv[]) { return bar(argv[0]); }
2217  '''), error_message: 'AVX512F not available').allowed())
2218
2219have_pvrdma = get_option('pvrdma') \
2220  .require(rdma.found(), error_message: 'PVRDMA requires OpenFabrics libraries') \
2221  .require(cc.compiles(gnu_source_prefix + '''
2222    #include <sys/mman.h>
2223    int main(void)
2224    {
2225      char buf = 0;
2226      void *addr = &buf;
2227      addr = mremap(addr, 0, 1, MREMAP_MAYMOVE | MREMAP_FIXED);
2228
2229      return 0;
2230    }'''), error_message: 'PVRDMA requires mremap').allowed()
2231
2232if have_pvrdma
2233  config_host_data.set('LEGACY_RDMA_REG_MR', not cc.links('''
2234    #include <infiniband/verbs.h>
2235    int main(void)
2236    {
2237      struct ibv_mr *mr;
2238      struct ibv_pd *pd = NULL;
2239      size_t length = 10;
2240      uint64_t iova = 0;
2241      int access = 0;
2242      void *addr = NULL;
2243
2244      mr = ibv_reg_mr_iova(pd, addr, length, iova, access);
2245      ibv_dereg_mr(mr);
2246      return 0;
2247    }'''))
2248endif
2249
2250if get_option('membarrier').disabled()
2251  have_membarrier = false
2252elif targetos == 'windows'
2253  have_membarrier = true
2254elif targetos == 'linux'
2255  have_membarrier = cc.compiles('''
2256    #include <linux/membarrier.h>
2257    #include <sys/syscall.h>
2258    #include <unistd.h>
2259    #include <stdlib.h>
2260    int main(void) {
2261        syscall(__NR_membarrier, MEMBARRIER_CMD_QUERY, 0);
2262        syscall(__NR_membarrier, MEMBARRIER_CMD_SHARED, 0);
2263        exit(0);
2264    }''')
2265endif
2266config_host_data.set('CONFIG_MEMBARRIER', get_option('membarrier') \
2267  .require(have_membarrier, error_message: 'membarrier system call not available') \
2268  .allowed())
2269
2270have_afalg = get_option('crypto_afalg') \
2271  .require(cc.compiles(gnu_source_prefix + '''
2272    #include <errno.h>
2273    #include <sys/types.h>
2274    #include <sys/socket.h>
2275    #include <linux/if_alg.h>
2276    int main(void) {
2277      int sock;
2278      sock = socket(AF_ALG, SOCK_SEQPACKET, 0);
2279      return sock;
2280    }
2281  '''), error_message: 'AF_ALG requested but could not be detected').allowed()
2282config_host_data.set('CONFIG_AF_ALG', have_afalg)
2283
2284config_host_data.set('CONFIG_AF_VSOCK', cc.has_header_symbol(
2285  'linux/vm_sockets.h', 'AF_VSOCK',
2286  prefix: '#include <sys/socket.h>',
2287))
2288
2289have_vss = false
2290have_vss_sdk = false # old xp/2003 SDK
2291if targetos == 'windows' and link_language == 'cpp'
2292  have_vss = cxx.compiles('''
2293    #define __MIDL_user_allocate_free_DEFINED__
2294    #include <vss.h>
2295    int main(void) { return VSS_CTX_BACKUP; }''')
2296  have_vss_sdk = cxx.has_header('vscoordint.h')
2297endif
2298config_host_data.set('HAVE_VSS_SDK', have_vss_sdk)
2299
2300foreach k, v: config_host
2301  if k.startswith('CONFIG_')
2302    config_host_data.set(k, v == 'y' ? 1 : v)
2303  endif
2304endforeach
2305
2306# Older versions of MinGW do not import _lock_file and _unlock_file properly.
2307# This was fixed for v6.0.0 with commit b48e3ac8969d.
2308if targetos == 'windows'
2309  config_host_data.set('HAVE__LOCK_FILE', cc.links('''
2310    #include <stdio.h>
2311    int main(void) {
2312      _lock_file(NULL);
2313      _unlock_file(NULL);
2314      return 0;
2315    }''', name: '_lock_file and _unlock_file'))
2316endif
2317
2318########################
2319# Target configuration #
2320########################
2321
2322minikconf = find_program('scripts/minikconf.py')
2323config_all = {}
2324config_all_devices = {}
2325config_all_disas = {}
2326config_devices_mak_list = []
2327config_devices_h = {}
2328config_target_h = {}
2329config_target_mak = {}
2330
2331disassemblers = {
2332  'alpha' : ['CONFIG_ALPHA_DIS'],
2333  'arm' : ['CONFIG_ARM_DIS'],
2334  'avr' : ['CONFIG_AVR_DIS'],
2335  'cris' : ['CONFIG_CRIS_DIS'],
2336  'hexagon' : ['CONFIG_HEXAGON_DIS'],
2337  'hppa' : ['CONFIG_HPPA_DIS'],
2338  'i386' : ['CONFIG_I386_DIS'],
2339  'x86_64' : ['CONFIG_I386_DIS'],
2340  'm68k' : ['CONFIG_M68K_DIS'],
2341  'microblaze' : ['CONFIG_MICROBLAZE_DIS'],
2342  'mips' : ['CONFIG_MIPS_DIS'],
2343  'nios2' : ['CONFIG_NIOS2_DIS'],
2344  'or1k' : ['CONFIG_OPENRISC_DIS'],
2345  'ppc' : ['CONFIG_PPC_DIS'],
2346  'riscv' : ['CONFIG_RISCV_DIS'],
2347  'rx' : ['CONFIG_RX_DIS'],
2348  's390' : ['CONFIG_S390_DIS'],
2349  'sh4' : ['CONFIG_SH4_DIS'],
2350  'sparc' : ['CONFIG_SPARC_DIS'],
2351  'xtensa' : ['CONFIG_XTENSA_DIS'],
2352  'loongarch' : ['CONFIG_LOONGARCH_DIS'],
2353}
2354if link_language == 'cpp'
2355  disassemblers += {
2356    'aarch64' : [ 'CONFIG_ARM_A64_DIS'],
2357    'arm' : [ 'CONFIG_ARM_DIS', 'CONFIG_ARM_A64_DIS'],
2358    'mips' : [ 'CONFIG_MIPS_DIS', 'CONFIG_NANOMIPS_DIS'],
2359  }
2360endif
2361
2362have_ivshmem = config_host_data.get('CONFIG_EVENTFD')
2363host_kconfig = \
2364  (get_option('fuzzing') ? ['CONFIG_FUZZ=y'] : []) + \
2365  (have_tpm ? ['CONFIG_TPM=y'] : []) + \
2366  (spice.found() ? ['CONFIG_SPICE=y'] : []) + \
2367  (have_ivshmem ? ['CONFIG_IVSHMEM=y'] : []) + \
2368  (opengl.found() ? ['CONFIG_OPENGL=y'] : []) + \
2369  (x11.found() ? ['CONFIG_X11=y'] : []) + \
2370  (have_vhost_user ? ['CONFIG_VHOST_USER=y'] : []) + \
2371  (have_vhost_vdpa ? ['CONFIG_VHOST_VDPA=y'] : []) + \
2372  (have_vhost_kernel ? ['CONFIG_VHOST_KERNEL=y'] : []) + \
2373  (have_virtfs ? ['CONFIG_VIRTFS=y'] : []) + \
2374  ('CONFIG_LINUX' in config_host ? ['CONFIG_LINUX=y'] : []) + \
2375  (have_pvrdma ? ['CONFIG_PVRDMA=y'] : []) + \
2376  (multiprocess_allowed ? ['CONFIG_MULTIPROCESS_ALLOWED=y'] : [])
2377
2378ignored = [ 'TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_ARCH' ]
2379
2380default_targets = 'CONFIG_DEFAULT_TARGETS' in config_host
2381actual_target_dirs = []
2382fdt_required = []
2383foreach target : target_dirs
2384  config_target = { 'TARGET_NAME': target.split('-')[0] }
2385  if target.endswith('linux-user')
2386    if targetos != 'linux'
2387      if default_targets
2388        continue
2389      endif
2390      error('Target @0@ is only available on a Linux host'.format(target))
2391    endif
2392    config_target += { 'CONFIG_LINUX_USER': 'y' }
2393  elif target.endswith('bsd-user')
2394    if 'CONFIG_BSD' not in config_host
2395      if default_targets
2396        continue
2397      endif
2398      error('Target @0@ is only available on a BSD host'.format(target))
2399    endif
2400    config_target += { 'CONFIG_BSD_USER': 'y' }
2401  elif target.endswith('softmmu')
2402    config_target += { 'CONFIG_SOFTMMU': 'y' }
2403  endif
2404  if target.endswith('-user')
2405    config_target += {
2406      'CONFIG_USER_ONLY': 'y',
2407      'CONFIG_QEMU_INTERP_PREFIX':
2408        get_option('interp_prefix').replace('%M', config_target['TARGET_NAME'])
2409    }
2410  endif
2411
2412  accel_kconfig = []
2413  foreach sym: accelerators
2414    if sym == 'CONFIG_TCG' or target in accelerator_targets.get(sym, [])
2415      config_target += { sym: 'y' }
2416      config_all += { sym: 'y' }
2417      if sym == 'CONFIG_TCG' and tcg_arch == 'tci'
2418        config_target += { 'CONFIG_TCG_INTERPRETER': 'y' }
2419      endif
2420      if target in modular_tcg
2421        config_target += { 'CONFIG_TCG_MODULAR': 'y' }
2422      else
2423        config_target += { 'CONFIG_TCG_BUILTIN': 'y' }
2424      endif
2425      accel_kconfig += [ sym + '=y' ]
2426    endif
2427  endforeach
2428  if accel_kconfig.length() == 0
2429    if default_targets
2430      continue
2431    endif
2432    error('No accelerator available for target @0@'.format(target))
2433  endif
2434
2435  actual_target_dirs += target
2436  config_target += keyval.load('configs/targets' / target + '.mak')
2437  config_target += { 'TARGET_' + config_target['TARGET_ARCH'].to_upper(): 'y' }
2438
2439  if 'TARGET_NEED_FDT' in config_target
2440    fdt_required += target
2441  endif
2442
2443  # Add default keys
2444  if 'TARGET_BASE_ARCH' not in config_target
2445    config_target += {'TARGET_BASE_ARCH': config_target['TARGET_ARCH']}
2446  endif
2447  if 'TARGET_ABI_DIR' not in config_target
2448    config_target += {'TARGET_ABI_DIR': config_target['TARGET_ARCH']}
2449  endif
2450  if 'TARGET_BIG_ENDIAN' not in config_target
2451    config_target += {'TARGET_BIG_ENDIAN': 'n'}
2452  endif
2453
2454  foreach k, v: disassemblers
2455    if host_arch.startswith(k) or config_target['TARGET_BASE_ARCH'].startswith(k)
2456      foreach sym: v
2457        config_target += { sym: 'y' }
2458        config_all_disas += { sym: 'y' }
2459      endforeach
2460    endif
2461  endforeach
2462
2463  config_target_data = configuration_data()
2464  foreach k, v: config_target
2465    if not k.startswith('TARGET_') and not k.startswith('CONFIG_')
2466      # do nothing
2467    elif ignored.contains(k)
2468      # do nothing
2469    elif k == 'TARGET_BASE_ARCH'
2470      # Note that TARGET_BASE_ARCH ends up in config-target.h but it is
2471      # not used to select files from sourcesets.
2472      config_target_data.set('TARGET_' + v.to_upper(), 1)
2473    elif k == 'TARGET_NAME' or k == 'CONFIG_QEMU_INTERP_PREFIX'
2474      config_target_data.set_quoted(k, v)
2475    elif v == 'y'
2476      config_target_data.set(k, 1)
2477    elif v == 'n'
2478      config_target_data.set(k, 0)
2479    else
2480      config_target_data.set(k, v)
2481    endif
2482  endforeach
2483  config_target_data.set('QEMU_ARCH',
2484                         'QEMU_ARCH_' + config_target['TARGET_BASE_ARCH'].to_upper())
2485  config_target_h += {target: configure_file(output: target + '-config-target.h',
2486                                               configuration: config_target_data)}
2487
2488  if target.endswith('-softmmu')
2489    config_input = meson.get_external_property(target, 'default')
2490    config_devices_mak = target + '-config-devices.mak'
2491    config_devices_mak = configure_file(
2492      input: ['configs/devices' / target / config_input + '.mak', 'Kconfig'],
2493      output: config_devices_mak,
2494      depfile: config_devices_mak + '.d',
2495      capture: true,
2496      command: [minikconf,
2497                get_option('default_devices') ? '--defconfig' : '--allnoconfig',
2498                config_devices_mak, '@DEPFILE@', '@INPUT@',
2499                host_kconfig, accel_kconfig,
2500                'CONFIG_' + config_target['TARGET_ARCH'].to_upper() + '=y'])
2501
2502    config_devices_data = configuration_data()
2503    config_devices = keyval.load(config_devices_mak)
2504    foreach k, v: config_devices
2505      config_devices_data.set(k, 1)
2506    endforeach
2507    config_devices_mak_list += config_devices_mak
2508    config_devices_h += {target: configure_file(output: target + '-config-devices.h',
2509                                                configuration: config_devices_data)}
2510    config_target += config_devices
2511    config_all_devices += config_devices
2512  endif
2513  config_target_mak += {target: config_target}
2514endforeach
2515target_dirs = actual_target_dirs
2516
2517# This configuration is used to build files that are shared by
2518# multiple binaries, and then extracted out of the "common"
2519# static_library target.
2520#
2521# We do not use all_sources()/all_dependencies(), because it would
2522# build literally all source files, including devices only used by
2523# targets that are not built for this compilation.  The CONFIG_ALL
2524# pseudo symbol replaces it.
2525
2526config_all += config_all_devices
2527config_all += config_host
2528config_all += config_all_disas
2529config_all += {
2530  'CONFIG_XEN': xen.found(),
2531  'CONFIG_SOFTMMU': have_system,
2532  'CONFIG_USER_ONLY': have_user,
2533  'CONFIG_ALL': true,
2534}
2535
2536target_configs_h = []
2537foreach target: target_dirs
2538  target_configs_h += config_target_h[target]
2539  target_configs_h += config_devices_h.get(target, [])
2540endforeach
2541genh += custom_target('config-poison.h',
2542                      input: [target_configs_h],
2543                      output: 'config-poison.h',
2544                      capture: true,
2545                      command: [find_program('scripts/make-config-poison.sh'),
2546                                target_configs_h])
2547
2548##############
2549# Submodules #
2550##############
2551
2552capstone = not_found
2553if not get_option('capstone').auto() or have_system or have_user
2554  capstone = dependency('capstone', version: '>=3.0.5',
2555                        kwargs: static_kwargs, method: 'pkg-config',
2556                        required: get_option('capstone'))
2557
2558  # Some versions of capstone have broken pkg-config file
2559  # that reports a wrong -I path, causing the #include to
2560  # fail later. If the system has such a broken version
2561  # do not use it.
2562  if capstone.found() and not cc.compiles('#include <capstone.h>',
2563                                          dependencies: [capstone])
2564    capstone = not_found
2565    if get_option('capstone').enabled()
2566      error('capstone requested, but it does not appear to work')
2567    endif
2568  endif
2569endif
2570
2571slirp = not_found
2572slirp_opt = 'disabled'
2573if have_system
2574  slirp_opt = get_option('slirp')
2575  if slirp_opt in ['enabled', 'auto', 'system']
2576    have_internal = fs.exists(meson.current_source_dir() / 'slirp/meson.build')
2577    slirp_dep_required = (slirp_opt == 'system' or
2578                          slirp_opt == 'enabled' and not have_internal)
2579    slirp = dependency('slirp', kwargs: static_kwargs,
2580                       method: 'pkg-config', version: '>=4.1.0',
2581                       required: slirp_dep_required)
2582    # slirp <4.7 is incompatible with CFI support in QEMU.  This is because
2583    # it passes function pointers within libslirp as callbacks for timers.
2584    # When using a system-wide shared libslirp, the type information for the
2585    # callback is missing and the timer call produces a false positive with CFI.
2586    # Do not use the "version" keyword argument to produce a better error.
2587    # with control-flow integrity.
2588    if get_option('cfi') and slirp.found() and slirp.version().version_compare('<4.7')
2589      if slirp_dep_required
2590        error('Control-Flow Integrity requires libslirp 4.7.')
2591      else
2592        warning('Control-Flow Integrity requires libslirp 4.7, not using system-wide libslirp.')
2593        slirp = not_found
2594      endif
2595    endif
2596    if slirp.found()
2597      slirp_opt = 'system'
2598    elif have_internal
2599      slirp_opt = 'internal'
2600    else
2601      slirp_opt = 'disabled'
2602    endif
2603  endif
2604  if slirp_opt == 'internal'
2605    slirp_deps = []
2606    if targetos == 'windows'
2607      slirp_deps = cc.find_library('iphlpapi')
2608    elif targetos == 'darwin'
2609      slirp_deps = cc.find_library('resolv')
2610    endif
2611    slirp_conf = configuration_data()
2612    slirp_conf.set('SLIRP_MAJOR_VERSION', meson.project_version().split('.')[0])
2613    slirp_conf.set('SLIRP_MINOR_VERSION', meson.project_version().split('.')[1])
2614    slirp_conf.set('SLIRP_MICRO_VERSION', meson.project_version().split('.')[2])
2615    slirp_conf.set_quoted('SLIRP_VERSION_STRING', meson.project_version())
2616    slirp_cargs = ['-DG_LOG_DOMAIN="Slirp"']
2617    slirp_files = [
2618      'slirp/src/arp_table.c',
2619      'slirp/src/bootp.c',
2620      'slirp/src/cksum.c',
2621      'slirp/src/dhcpv6.c',
2622      'slirp/src/dnssearch.c',
2623      'slirp/src/if.c',
2624      'slirp/src/ip6_icmp.c',
2625      'slirp/src/ip6_input.c',
2626      'slirp/src/ip6_output.c',
2627      'slirp/src/ip_icmp.c',
2628      'slirp/src/ip_input.c',
2629      'slirp/src/ip_output.c',
2630      'slirp/src/mbuf.c',
2631      'slirp/src/misc.c',
2632      'slirp/src/ncsi.c',
2633      'slirp/src/ndp_table.c',
2634      'slirp/src/sbuf.c',
2635      'slirp/src/slirp.c',
2636      'slirp/src/socket.c',
2637      'slirp/src/state.c',
2638      'slirp/src/stream.c',
2639      'slirp/src/tcp_input.c',
2640      'slirp/src/tcp_output.c',
2641      'slirp/src/tcp_subr.c',
2642      'slirp/src/tcp_timer.c',
2643      'slirp/src/tftp.c',
2644      'slirp/src/udp.c',
2645      'slirp/src/udp6.c',
2646      'slirp/src/util.c',
2647      'slirp/src/version.c',
2648      'slirp/src/vmstate.c',
2649    ]
2650
2651    configure_file(
2652      input : 'slirp/src/libslirp-version.h.in',
2653      output : 'libslirp-version.h',
2654      configuration: slirp_conf)
2655
2656    slirp_inc = include_directories('slirp', 'slirp/src')
2657    libslirp = static_library('slirp',
2658                              build_by_default: false,
2659                              sources: slirp_files,
2660                              c_args: slirp_cargs,
2661                              include_directories: slirp_inc)
2662    slirp = declare_dependency(link_with: libslirp,
2663                               dependencies: slirp_deps,
2664                               include_directories: slirp_inc)
2665  endif
2666endif
2667
2668fdt = not_found
2669if have_system
2670  fdt_opt = get_option('fdt')
2671  if fdt_opt in ['enabled', 'auto', 'system']
2672    have_internal = fs.exists(meson.current_source_dir() / 'dtc/libfdt/Makefile.libfdt')
2673    fdt = cc.find_library('fdt', kwargs: static_kwargs,
2674                          required: fdt_opt == 'system' or
2675                                    fdt_opt == 'enabled' and not have_internal)
2676    if fdt.found() and cc.links('''
2677       #include <libfdt.h>
2678       #include <libfdt_env.h>
2679       int main(void) { fdt_find_max_phandle(NULL, NULL); return 0; }''',
2680         dependencies: fdt)
2681      fdt_opt = 'system'
2682    elif fdt_opt == 'system'
2683       error('system libfdt requested, but it is too old (1.5.1 or newer required)')
2684    elif have_internal
2685      fdt_opt = 'internal'
2686    else
2687      fdt_opt = 'disabled'
2688      fdt = not_found
2689    endif
2690  endif
2691  if fdt_opt == 'internal'
2692    fdt_files = files(
2693      'dtc/libfdt/fdt.c',
2694      'dtc/libfdt/fdt_ro.c',
2695      'dtc/libfdt/fdt_wip.c',
2696      'dtc/libfdt/fdt_sw.c',
2697      'dtc/libfdt/fdt_rw.c',
2698      'dtc/libfdt/fdt_strerror.c',
2699      'dtc/libfdt/fdt_empty_tree.c',
2700      'dtc/libfdt/fdt_addresses.c',
2701      'dtc/libfdt/fdt_overlay.c',
2702      'dtc/libfdt/fdt_check.c',
2703    )
2704
2705    fdt_inc = include_directories('dtc/libfdt')
2706    libfdt = static_library('fdt',
2707                            build_by_default: false,
2708                            sources: fdt_files,
2709                            include_directories: fdt_inc)
2710    fdt = declare_dependency(link_with: libfdt,
2711                             include_directories: fdt_inc)
2712  endif
2713else
2714  fdt_opt = 'disabled'
2715endif
2716if not fdt.found() and fdt_required.length() > 0
2717  error('fdt not available but required by targets ' + ', '.join(fdt_required))
2718endif
2719
2720config_host_data.set('CONFIG_CAPSTONE', capstone.found())
2721config_host_data.set('CONFIG_FDT', fdt.found())
2722config_host_data.set('CONFIG_SLIRP', slirp.found())
2723
2724#####################
2725# Generated sources #
2726#####################
2727
2728genh += configure_file(output: 'config-host.h', configuration: config_host_data)
2729
2730hxtool = find_program('scripts/hxtool')
2731shaderinclude = find_program('scripts/shaderinclude.pl')
2732qapi_gen = find_program('scripts/qapi-gen.py')
2733qapi_gen_depends = [ meson.current_source_dir() / 'scripts/qapi/__init__.py',
2734                     meson.current_source_dir() / 'scripts/qapi/commands.py',
2735                     meson.current_source_dir() / 'scripts/qapi/common.py',
2736                     meson.current_source_dir() / 'scripts/qapi/error.py',
2737                     meson.current_source_dir() / 'scripts/qapi/events.py',
2738                     meson.current_source_dir() / 'scripts/qapi/expr.py',
2739                     meson.current_source_dir() / 'scripts/qapi/gen.py',
2740                     meson.current_source_dir() / 'scripts/qapi/introspect.py',
2741                     meson.current_source_dir() / 'scripts/qapi/parser.py',
2742                     meson.current_source_dir() / 'scripts/qapi/schema.py',
2743                     meson.current_source_dir() / 'scripts/qapi/source.py',
2744                     meson.current_source_dir() / 'scripts/qapi/types.py',
2745                     meson.current_source_dir() / 'scripts/qapi/visit.py',
2746                     meson.current_source_dir() / 'scripts/qapi/common.py',
2747                     meson.current_source_dir() / 'scripts/qapi-gen.py'
2748]
2749
2750tracetool = [
2751  python, files('scripts/tracetool.py'),
2752   '--backend=' + ','.join(get_option('trace_backends'))
2753]
2754tracetool_depends = files(
2755  'scripts/tracetool/backend/log.py',
2756  'scripts/tracetool/backend/__init__.py',
2757  'scripts/tracetool/backend/dtrace.py',
2758  'scripts/tracetool/backend/ftrace.py',
2759  'scripts/tracetool/backend/simple.py',
2760  'scripts/tracetool/backend/syslog.py',
2761  'scripts/tracetool/backend/ust.py',
2762  'scripts/tracetool/format/ust_events_c.py',
2763  'scripts/tracetool/format/ust_events_h.py',
2764  'scripts/tracetool/format/__init__.py',
2765  'scripts/tracetool/format/d.py',
2766  'scripts/tracetool/format/simpletrace_stap.py',
2767  'scripts/tracetool/format/c.py',
2768  'scripts/tracetool/format/h.py',
2769  'scripts/tracetool/format/log_stap.py',
2770  'scripts/tracetool/format/stap.py',
2771  'scripts/tracetool/__init__.py',
2772  'scripts/tracetool/transform.py',
2773  'scripts/tracetool/vcpu.py'
2774)
2775
2776qemu_version_cmd = [find_program('scripts/qemu-version.sh'),
2777                    meson.current_source_dir(),
2778                    get_option('pkgversion'), meson.project_version()]
2779qemu_version = custom_target('qemu-version.h',
2780                             output: 'qemu-version.h',
2781                             command: qemu_version_cmd,
2782                             capture: true,
2783                             build_by_default: true,
2784                             build_always_stale: true)
2785genh += qemu_version
2786
2787hxdep = []
2788hx_headers = [
2789  ['qemu-options.hx', 'qemu-options.def'],
2790  ['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
2791]
2792if have_system
2793  hx_headers += [
2794    ['hmp-commands.hx', 'hmp-commands.h'],
2795    ['hmp-commands-info.hx', 'hmp-commands-info.h'],
2796  ]
2797endif
2798foreach d : hx_headers
2799  hxdep += custom_target(d[1],
2800                input: files(d[0]),
2801                output: d[1],
2802                capture: true,
2803                build_by_default: true, # to be removed when added to a target
2804                command: [hxtool, '-h', '@INPUT0@'])
2805endforeach
2806genh += hxdep
2807
2808###################
2809# Collect sources #
2810###################
2811
2812authz_ss = ss.source_set()
2813blockdev_ss = ss.source_set()
2814block_ss = ss.source_set()
2815chardev_ss = ss.source_set()
2816common_ss = ss.source_set()
2817crypto_ss = ss.source_set()
2818hwcore_ss = ss.source_set()
2819io_ss = ss.source_set()
2820qmp_ss = ss.source_set()
2821qom_ss = ss.source_set()
2822softmmu_ss = ss.source_set()
2823specific_fuzz_ss = ss.source_set()
2824specific_ss = ss.source_set()
2825stub_ss = ss.source_set()
2826trace_ss = ss.source_set()
2827user_ss = ss.source_set()
2828util_ss = ss.source_set()
2829
2830# accel modules
2831qtest_module_ss = ss.source_set()
2832tcg_module_ss = ss.source_set()
2833
2834modules = {}
2835target_modules = {}
2836hw_arch = {}
2837target_arch = {}
2838target_softmmu_arch = {}
2839target_user_arch = {}
2840
2841###############
2842# Trace files #
2843###############
2844
2845# TODO: add each directory to the subdirs from its own meson.build, once
2846# we have those
2847trace_events_subdirs = [
2848  'crypto',
2849  'qapi',
2850  'qom',
2851  'monitor',
2852  'util',
2853]
2854if have_linux_user
2855  trace_events_subdirs += [ 'linux-user' ]
2856endif
2857if have_bsd_user
2858  trace_events_subdirs += [ 'bsd-user' ]
2859endif
2860if have_block
2861  trace_events_subdirs += [
2862    'authz',
2863    'block',
2864    'io',
2865    'nbd',
2866    'scsi',
2867  ]
2868endif
2869if have_system
2870  trace_events_subdirs += [
2871    'accel/kvm',
2872    'audio',
2873    'backends',
2874    'backends/tpm',
2875    'chardev',
2876    'ebpf',
2877    'hw/9pfs',
2878    'hw/acpi',
2879    'hw/adc',
2880    'hw/alpha',
2881    'hw/arm',
2882    'hw/audio',
2883    'hw/block',
2884    'hw/block/dataplane',
2885    'hw/char',
2886    'hw/display',
2887    'hw/dma',
2888    'hw/hyperv',
2889    'hw/i2c',
2890    'hw/i386',
2891    'hw/i386/xen',
2892    'hw/ide',
2893    'hw/input',
2894    'hw/intc',
2895    'hw/isa',
2896    'hw/mem',
2897    'hw/mips',
2898    'hw/misc',
2899    'hw/misc/macio',
2900    'hw/net',
2901    'hw/net/can',
2902    'hw/nubus',
2903    'hw/nvme',
2904    'hw/nvram',
2905    'hw/pci',
2906    'hw/pci-host',
2907    'hw/ppc',
2908    'hw/rdma',
2909    'hw/rdma/vmw',
2910    'hw/rtc',
2911    'hw/s390x',
2912    'hw/scsi',
2913    'hw/sd',
2914    'hw/sh4',
2915    'hw/sparc',
2916    'hw/sparc64',
2917    'hw/ssi',
2918    'hw/timer',
2919    'hw/tpm',
2920    'hw/usb',
2921    'hw/vfio',
2922    'hw/virtio',
2923    'hw/watchdog',
2924    'hw/xen',
2925    'hw/gpio',
2926    'migration',
2927    'net',
2928    'softmmu',
2929    'ui',
2930    'hw/remote',
2931  ]
2932endif
2933if have_system or have_user
2934  trace_events_subdirs += [
2935    'accel/tcg',
2936    'hw/core',
2937    'target/arm',
2938    'target/arm/hvf',
2939    'target/hppa',
2940    'target/i386',
2941    'target/i386/kvm',
2942    'target/mips/tcg',
2943    'target/nios2',
2944    'target/ppc',
2945    'target/riscv',
2946    'target/s390x',
2947    'target/s390x/kvm',
2948    'target/sparc',
2949  ]
2950endif
2951
2952vhost_user = not_found
2953if targetos == 'linux' and have_vhost_user
2954  libvhost_user = subproject('libvhost-user')
2955  vhost_user = libvhost_user.get_variable('vhost_user_dep')
2956endif
2957
2958# NOTE: the trace/ subdirectory needs the qapi_trace_events variable
2959# that is filled in by qapi/.
2960subdir('qapi')
2961subdir('qobject')
2962subdir('stubs')
2963subdir('trace')
2964subdir('util')
2965subdir('qom')
2966subdir('authz')
2967subdir('crypto')
2968subdir('ui')
2969subdir('hw')
2970
2971
2972if enable_modules
2973  libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
2974  modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
2975endif
2976
2977qom_ss = qom_ss.apply(config_host, strict: false)
2978libqom = static_library('qom', qom_ss.sources() + genh,
2979                        dependencies: [qom_ss.dependencies()],
2980                        name_suffix: 'fa')
2981qom = declare_dependency(link_whole: libqom)
2982
2983event_loop_base = files('event-loop-base.c')
2984event_loop_base = static_library('event-loop-base', sources: event_loop_base + genh,
2985                                 build_by_default: true)
2986event_loop_base = declare_dependency(link_whole: event_loop_base,
2987                                     dependencies: [qom])
2988
2989stub_ss = stub_ss.apply(config_all, strict: false)
2990
2991util_ss.add_all(trace_ss)
2992util_ss = util_ss.apply(config_all, strict: false)
2993libqemuutil = static_library('qemuutil',
2994                             sources: util_ss.sources() + stub_ss.sources() + genh,
2995                             dependencies: [util_ss.dependencies(), libm, threads, glib, socket, malloc, pixman])
2996qemuutil = declare_dependency(link_with: libqemuutil,
2997                              sources: genh + version_res,
2998                              dependencies: [event_loop_base])
2999
3000if have_system or have_user
3001  decodetree = generator(find_program('scripts/decodetree.py'),
3002                         output: 'decode-@BASENAME@.c.inc',
3003                         arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
3004  subdir('libdecnumber')
3005  subdir('target')
3006endif
3007
3008subdir('audio')
3009subdir('io')
3010subdir('chardev')
3011subdir('fsdev')
3012subdir('dump')
3013
3014if have_block
3015  block_ss.add(files(
3016    'block.c',
3017    'blockjob.c',
3018    'job.c',
3019    'qemu-io-cmds.c',
3020  ))
3021  if config_host_data.get('CONFIG_REPLICATION')
3022    block_ss.add(files('replication.c'))
3023  endif
3024
3025  subdir('nbd')
3026  subdir('scsi')
3027  subdir('block')
3028
3029  blockdev_ss.add(files(
3030    'blockdev.c',
3031    'blockdev-nbd.c',
3032    'iothread.c',
3033    'job-qmp.c',
3034  ), gnutls)
3035
3036  # os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
3037  # os-win32.c does not
3038  blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c'))
3039  softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')])
3040endif
3041
3042common_ss.add(files('cpus-common.c'))
3043
3044subdir('softmmu')
3045
3046common_ss.add(capstone)
3047specific_ss.add(files('cpu.c', 'disas.c', 'gdbstub.c'), capstone)
3048
3049# Work around a gcc bug/misfeature wherein constant propagation looks
3050# through an alias:
3051#   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99696
3052# to guess that a const variable is always zero.  Without lto, this is
3053# impossible, as the alias is restricted to page-vary-common.c.  Indeed,
3054# without lto, not even the alias is required -- we simply use different
3055# declarations in different compilation units.
3056pagevary = files('page-vary-common.c')
3057if get_option('b_lto')
3058  pagevary_flags = ['-fno-lto']
3059  if get_option('cfi')
3060    pagevary_flags += '-fno-sanitize=cfi-icall'
3061  endif
3062  pagevary = static_library('page-vary-common', sources: pagevary + genh,
3063                            c_args: pagevary_flags)
3064  pagevary = declare_dependency(link_with: pagevary)
3065endif
3066common_ss.add(pagevary)
3067specific_ss.add(files('page-vary.c'))
3068
3069subdir('backends')
3070subdir('disas')
3071subdir('migration')
3072subdir('monitor')
3073subdir('net')
3074subdir('replay')
3075subdir('semihosting')
3076subdir('tcg')
3077subdir('fpu')
3078subdir('accel')
3079subdir('plugins')
3080subdir('ebpf')
3081
3082common_user_inc = []
3083
3084subdir('common-user')
3085subdir('bsd-user')
3086subdir('linux-user')
3087
3088# needed for fuzzing binaries
3089subdir('tests/qtest/libqos')
3090subdir('tests/qtest/fuzz')
3091
3092# accel modules
3093tcg_real_module_ss = ss.source_set()
3094tcg_real_module_ss.add_all(when: 'CONFIG_TCG_MODULAR', if_true: tcg_module_ss)
3095specific_ss.add_all(when: 'CONFIG_TCG_BUILTIN', if_true: tcg_module_ss)
3096target_modules += { 'accel' : { 'qtest': qtest_module_ss,
3097                                'tcg': tcg_real_module_ss }}
3098
3099########################
3100# Library dependencies #
3101########################
3102
3103modinfo_collect = find_program('scripts/modinfo-collect.py')
3104modinfo_generate = find_program('scripts/modinfo-generate.py')
3105modinfo_files = []
3106
3107block_mods = []
3108softmmu_mods = []
3109foreach d, list : modules
3110  foreach m, module_ss : list
3111    if enable_modules and targetos != 'windows'
3112      module_ss = module_ss.apply(config_all, strict: false)
3113      sl = static_library(d + '-' + m, [genh, module_ss.sources()],
3114                          dependencies: [modulecommon, module_ss.dependencies()], pic: true)
3115      if d == 'block'
3116        block_mods += sl
3117      else
3118        softmmu_mods += sl
3119      endif
3120      if module_ss.sources() != []
3121        # FIXME: Should use sl.extract_all_objects(recursive: true) as
3122        # input. Sources can be used multiple times but objects are
3123        # unique when it comes to lookup in compile_commands.json.
3124        # Depnds on a mesion version with
3125        # https://github.com/mesonbuild/meson/pull/8900
3126        modinfo_files += custom_target(d + '-' + m + '.modinfo',
3127                                       output: d + '-' + m + '.modinfo',
3128                                       input: module_ss.sources() + genh,
3129                                       capture: true,
3130                                       command: [modinfo_collect, module_ss.sources()])
3131      endif
3132    else
3133      if d == 'block'
3134        block_ss.add_all(module_ss)
3135      else
3136        softmmu_ss.add_all(module_ss)
3137      endif
3138    endif
3139  endforeach
3140endforeach
3141
3142foreach d, list : target_modules
3143  foreach m, module_ss : list
3144    if enable_modules and targetos != 'windows'
3145      foreach target : target_dirs
3146        if target.endswith('-softmmu')
3147          config_target = config_target_mak[target]
3148          config_target += config_host
3149          target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
3150          c_args = ['-DNEED_CPU_H',
3151                    '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
3152                    '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
3153          target_module_ss = module_ss.apply(config_target, strict: false)
3154          if target_module_ss.sources() != []
3155            module_name = d + '-' + m + '-' + config_target['TARGET_NAME']
3156            sl = static_library(module_name,
3157                                [genh, target_module_ss.sources()],
3158                                dependencies: [modulecommon, target_module_ss.dependencies()],
3159                                include_directories: target_inc,
3160                                c_args: c_args,
3161                                pic: true)
3162            softmmu_mods += sl
3163            # FIXME: Should use sl.extract_all_objects(recursive: true) too.
3164            modinfo_files += custom_target(module_name + '.modinfo',
3165                                           output: module_name + '.modinfo',
3166                                           input: target_module_ss.sources() + genh,
3167                                           capture: true,
3168                                           command: [modinfo_collect, '--target', target, target_module_ss.sources()])
3169          endif
3170        endif
3171      endforeach
3172    else
3173      specific_ss.add_all(module_ss)
3174    endif
3175  endforeach
3176endforeach
3177
3178if enable_modules
3179  foreach target : target_dirs
3180    if target.endswith('-softmmu')
3181      config_target = config_target_mak[target]
3182      config_devices_mak = target + '-config-devices.mak'
3183      modinfo_src = custom_target('modinfo-' + target + '.c',
3184                                  output: 'modinfo-' + target + '.c',
3185                                  input: modinfo_files,
3186                                  command: [modinfo_generate, '--devices', config_devices_mak, '@INPUT@'],
3187                                  capture: true)
3188
3189      modinfo_lib = static_library('modinfo-' + target + '.c', modinfo_src)
3190      modinfo_dep = declare_dependency(link_with: modinfo_lib)
3191
3192      arch = config_target['TARGET_NAME'] == 'sparc64' ? 'sparc64' : config_target['TARGET_BASE_ARCH']
3193      hw_arch[arch].add(modinfo_dep)
3194    endif
3195  endforeach
3196endif
3197
3198nm = find_program('nm')
3199undefsym = find_program('scripts/undefsym.py')
3200block_syms = custom_target('block.syms', output: 'block.syms',
3201                             input: [libqemuutil, block_mods],
3202                             capture: true,
3203                             command: [undefsym, nm, '@INPUT@'])
3204qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
3205                             input: [libqemuutil, softmmu_mods],
3206                             capture: true,
3207                             command: [undefsym, nm, '@INPUT@'])
3208
3209authz_ss = authz_ss.apply(config_host, strict: false)
3210libauthz = static_library('authz', authz_ss.sources() + genh,
3211                          dependencies: [authz_ss.dependencies()],
3212                          name_suffix: 'fa',
3213                          build_by_default: false)
3214
3215authz = declare_dependency(link_whole: libauthz,
3216                           dependencies: qom)
3217
3218crypto_ss = crypto_ss.apply(config_host, strict: false)
3219libcrypto = static_library('crypto', crypto_ss.sources() + genh,
3220                           dependencies: [crypto_ss.dependencies()],
3221                           name_suffix: 'fa',
3222                           build_by_default: false)
3223
3224crypto = declare_dependency(link_whole: libcrypto,
3225                            dependencies: [authz, qom])
3226
3227io_ss = io_ss.apply(config_host, strict: false)
3228libio = static_library('io', io_ss.sources() + genh,
3229                       dependencies: [io_ss.dependencies()],
3230                       link_with: libqemuutil,
3231                       name_suffix: 'fa',
3232                       build_by_default: false)
3233
3234io = declare_dependency(link_whole: libio, dependencies: [crypto, qom])
3235
3236libmigration = static_library('migration', sources: migration_files + genh,
3237                              name_suffix: 'fa',
3238                              build_by_default: false)
3239migration = declare_dependency(link_with: libmigration,
3240                               dependencies: [zlib, qom, io])
3241softmmu_ss.add(migration)
3242
3243block_ss = block_ss.apply(config_host, strict: false)
3244libblock = static_library('block', block_ss.sources() + genh,
3245                          dependencies: block_ss.dependencies(),
3246                          link_depends: block_syms,
3247                          name_suffix: 'fa',
3248                          build_by_default: false)
3249
3250block = declare_dependency(link_whole: [libblock],
3251                           link_args: '@block.syms',
3252                           dependencies: [crypto, io])
3253
3254blockdev_ss = blockdev_ss.apply(config_host, strict: false)
3255libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
3256                             dependencies: blockdev_ss.dependencies(),
3257                             name_suffix: 'fa',
3258                             build_by_default: false)
3259
3260blockdev = declare_dependency(link_whole: [libblockdev],
3261                              dependencies: [block, event_loop_base])
3262
3263qmp_ss = qmp_ss.apply(config_host, strict: false)
3264libqmp = static_library('qmp', qmp_ss.sources() + genh,
3265                        dependencies: qmp_ss.dependencies(),
3266                        name_suffix: 'fa',
3267                        build_by_default: false)
3268
3269qmp = declare_dependency(link_whole: [libqmp])
3270
3271libchardev = static_library('chardev', chardev_ss.sources() + genh,
3272                            name_suffix: 'fa',
3273                            dependencies: chardev_ss.dependencies(),
3274                            build_by_default: false)
3275
3276chardev = declare_dependency(link_whole: libchardev)
3277
3278hwcore_ss = hwcore_ss.apply(config_host, strict: false)
3279libhwcore = static_library('hwcore', sources: hwcore_ss.sources() + genh,
3280                           name_suffix: 'fa',
3281                           build_by_default: false)
3282hwcore = declare_dependency(link_whole: libhwcore)
3283common_ss.add(hwcore)
3284
3285###########
3286# Targets #
3287###########
3288
3289emulator_modules = []
3290foreach m : block_mods + softmmu_mods
3291  emulator_modules += shared_module(m.name(),
3292                build_by_default: true,
3293                name_prefix: '',
3294                link_whole: m,
3295                install: true,
3296                install_dir: qemu_moddir)
3297endforeach
3298if emulator_modules.length() > 0
3299  alias_target('modules', emulator_modules)
3300endif
3301
3302softmmu_ss.add(authz, blockdev, chardev, crypto, io, qmp)
3303common_ss.add(qom, qemuutil)
3304
3305common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss])
3306common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
3307
3308common_all = common_ss.apply(config_all, strict: false)
3309common_all = static_library('common',
3310                            build_by_default: false,
3311                            sources: common_all.sources() + genh,
3312                            include_directories: common_user_inc,
3313                            implicit_include_directories: false,
3314                            dependencies: common_all.dependencies(),
3315                            name_suffix: 'fa')
3316
3317feature_to_c = find_program('scripts/feature_to_c.sh')
3318
3319if targetos == 'darwin'
3320  entitlement = find_program('scripts/entitlement.sh')
3321endif
3322
3323emulators = {}
3324foreach target : target_dirs
3325  config_target = config_target_mak[target]
3326  target_name = config_target['TARGET_NAME']
3327  target_base_arch = config_target['TARGET_BASE_ARCH']
3328  arch_srcs = [config_target_h[target]]
3329  arch_deps = []
3330  c_args = ['-DNEED_CPU_H',
3331            '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
3332            '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
3333  link_args = emulator_link_args
3334
3335  config_target += config_host
3336  target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
3337  if targetos == 'linux'
3338    target_inc += include_directories('linux-headers', is_system: true)
3339  endif
3340  if target.endswith('-softmmu')
3341    qemu_target_name = 'qemu-system-' + target_name
3342    target_type='system'
3343    t = target_softmmu_arch[target_base_arch].apply(config_target, strict: false)
3344    arch_srcs += t.sources()
3345    arch_deps += t.dependencies()
3346
3347    hw_dir = target_name == 'sparc64' ? 'sparc64' : target_base_arch
3348    hw = hw_arch[hw_dir].apply(config_target, strict: false)
3349    arch_srcs += hw.sources()
3350    arch_deps += hw.dependencies()
3351
3352    arch_srcs += config_devices_h[target]
3353    link_args += ['@block.syms', '@qemu.syms']
3354  else
3355    abi = config_target['TARGET_ABI_DIR']
3356    target_type='user'
3357    target_inc += common_user_inc
3358    qemu_target_name = 'qemu-' + target_name
3359    if target_base_arch in target_user_arch
3360      t = target_user_arch[target_base_arch].apply(config_target, strict: false)
3361      arch_srcs += t.sources()
3362      arch_deps += t.dependencies()
3363    endif
3364    if 'CONFIG_LINUX_USER' in config_target
3365      base_dir = 'linux-user'
3366    endif
3367    if 'CONFIG_BSD_USER' in config_target
3368      base_dir = 'bsd-user'
3369      target_inc += include_directories('bsd-user/' / targetos)
3370      target_inc += include_directories('bsd-user/host/' / host_arch)
3371      dir = base_dir / abi
3372      arch_srcs += files(dir / 'signal.c', dir / 'target_arch_cpu.c')
3373    endif
3374    target_inc += include_directories(
3375      base_dir,
3376      base_dir / abi,
3377    )
3378    if 'CONFIG_LINUX_USER' in config_target
3379      dir = base_dir / abi
3380      arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
3381      if config_target.has_key('TARGET_SYSTBL_ABI')
3382        arch_srcs += \
3383          syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
3384                                             extra_args : config_target['TARGET_SYSTBL_ABI'])
3385      endif
3386    endif
3387  endif
3388
3389  if 'TARGET_XML_FILES' in config_target
3390    gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
3391                                output: target + '-gdbstub-xml.c',
3392                                input: files(config_target['TARGET_XML_FILES'].split()),
3393                                command: [feature_to_c, '@INPUT@'],
3394                                capture: true)
3395    arch_srcs += gdbstub_xml
3396  endif
3397
3398  t = target_arch[target_base_arch].apply(config_target, strict: false)
3399  arch_srcs += t.sources()
3400  arch_deps += t.dependencies()
3401
3402  target_common = common_ss.apply(config_target, strict: false)
3403  objects = common_all.extract_objects(target_common.sources())
3404  deps = target_common.dependencies()
3405
3406  target_specific = specific_ss.apply(config_target, strict: false)
3407  arch_srcs += target_specific.sources()
3408  arch_deps += target_specific.dependencies()
3409
3410  lib = static_library('qemu-' + target,
3411                 sources: arch_srcs + genh,
3412                 dependencies: arch_deps,
3413                 objects: objects,
3414                 include_directories: target_inc,
3415                 c_args: c_args,
3416                 build_by_default: false,
3417                 name_suffix: 'fa')
3418
3419  if target.endswith('-softmmu')
3420    execs = [{
3421      'name': 'qemu-system-' + target_name,
3422      'win_subsystem': 'console',
3423      'sources': files('softmmu/main.c'),
3424      'dependencies': []
3425    }]
3426    if targetos == 'windows' and (sdl.found() or gtk.found())
3427      execs += [{
3428        'name': 'qemu-system-' + target_name + 'w',
3429        'win_subsystem': 'windows',
3430        'sources': files('softmmu/main.c'),
3431        'dependencies': []
3432      }]
3433    endif
3434    if get_option('fuzzing')
3435      specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
3436      execs += [{
3437        'name': 'qemu-fuzz-' + target_name,
3438        'win_subsystem': 'console',
3439        'sources': specific_fuzz.sources(),
3440        'dependencies': specific_fuzz.dependencies(),
3441      }]
3442    endif
3443  else
3444    execs = [{
3445      'name': 'qemu-' + target_name,
3446      'win_subsystem': 'console',
3447      'sources': [],
3448      'dependencies': []
3449    }]
3450  endif
3451  foreach exe: execs
3452    exe_name = exe['name']
3453    if targetos == 'darwin'
3454      exe_name += '-unsigned'
3455    endif
3456
3457    emulator = executable(exe_name, exe['sources'],
3458               install: true,
3459               c_args: c_args,
3460               dependencies: arch_deps + deps + exe['dependencies'],
3461               objects: lib.extract_all_objects(recursive: true),
3462               link_language: link_language,
3463               link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
3464               link_args: link_args,
3465               win_subsystem: exe['win_subsystem'])
3466
3467    if targetos == 'darwin'
3468      icon = 'pc-bios/qemu.rsrc'
3469      build_input = [emulator, files(icon)]
3470      install_input = [
3471        get_option('bindir') / exe_name,
3472        meson.current_source_dir() / icon
3473      ]
3474      if 'CONFIG_HVF' in config_target
3475        entitlements = 'accel/hvf/entitlements.plist'
3476        build_input += files(entitlements)
3477        install_input += meson.current_source_dir() / entitlements
3478      endif
3479
3480      emulators += {exe['name'] : custom_target(exe['name'],
3481                   input: build_input,
3482                   output: exe['name'],
3483                   command: [entitlement, '@OUTPUT@', '@INPUT@'])
3484      }
3485
3486      meson.add_install_script(entitlement, '--install',
3487                               get_option('bindir') / exe['name'],
3488                               install_input)
3489    else
3490      emulators += {exe['name']: emulator}
3491    endif
3492
3493    if stap.found()
3494      foreach stp: [
3495        {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
3496        {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
3497        {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
3498        {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
3499      ]
3500        custom_target(exe['name'] + stp['ext'],
3501                      input: trace_events_all,
3502                      output: exe['name'] + stp['ext'],
3503                      install: stp['install'],
3504                      install_dir: get_option('datadir') / 'systemtap/tapset',
3505                      command: [
3506                        tracetool, '--group=all', '--format=' + stp['fmt'],
3507                        '--binary=' + stp['bin'],
3508                        '--target-name=' + target_name,
3509                        '--target-type=' + target_type,
3510                        '--probe-prefix=qemu.' + target_type + '.' + target_name,
3511                        '@INPUT@', '@OUTPUT@'
3512                      ],
3513                      depend_files: tracetool_depends)
3514      endforeach
3515    endif
3516  endforeach
3517endforeach
3518
3519# Other build targets
3520
3521if 'CONFIG_PLUGIN' in config_host
3522  install_headers('include/qemu/qemu-plugin.h')
3523endif
3524
3525subdir('qga')
3526
3527# Don't build qemu-keymap if xkbcommon is not explicitly enabled
3528# when we don't build tools or system
3529if xkbcommon.found()
3530  # used for the update-keymaps target, so include rules even if !have_tools
3531  qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
3532                           dependencies: [qemuutil, xkbcommon], install: have_tools)
3533endif
3534
3535if have_tools
3536  qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
3537             dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
3538  qemu_io = executable('qemu-io', files('qemu-io.c'),
3539             dependencies: [block, qemuutil], install: true)
3540  qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
3541               dependencies: [blockdev, qemuutil, gnutls, selinux],
3542               install: true)
3543
3544  subdir('storage-daemon')
3545  subdir('contrib/rdmacm-mux')
3546  subdir('contrib/elf2dmp')
3547
3548  executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
3549             dependencies: qemuutil,
3550             install: true)
3551
3552  if have_vhost_user
3553    subdir('contrib/vhost-user-blk')
3554    subdir('contrib/vhost-user-gpu')
3555    subdir('contrib/vhost-user-input')
3556    subdir('contrib/vhost-user-scsi')
3557  endif
3558
3559  if targetos == 'linux'
3560    executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
3561               dependencies: [qemuutil, libcap_ng],
3562               install: true,
3563               install_dir: get_option('libexecdir'))
3564
3565    executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
3566               dependencies: [authz, crypto, io, qom, qemuutil,
3567                              libcap_ng, mpathpersist],
3568               install: true)
3569  endif
3570
3571  if have_ivshmem
3572    subdir('contrib/ivshmem-client')
3573    subdir('contrib/ivshmem-server')
3574  endif
3575endif
3576
3577subdir('scripts')
3578subdir('tools')
3579subdir('pc-bios')
3580subdir('docs')
3581subdir('tests')
3582if gtk.found()
3583  subdir('po')
3584endif
3585
3586if host_machine.system() == 'windows'
3587  nsis_cmd = [
3588    find_program('scripts/nsis.py'),
3589    '@OUTPUT@',
3590    get_option('prefix'),
3591    meson.current_source_dir(),
3592    host_machine.cpu(),
3593    '--',
3594    '-DDISPLAYVERSION=' + meson.project_version(),
3595  ]
3596  if build_docs
3597    nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
3598  endif
3599  if gtk.found()
3600    nsis_cmd += '-DCONFIG_GTK=y'
3601  endif
3602
3603  nsis = custom_target('nsis',
3604                       output: 'qemu-setup-' + meson.project_version() + '.exe',
3605                       input: files('qemu.nsi'),
3606                       build_always_stale: true,
3607                       command: nsis_cmd + ['@INPUT@'])
3608  alias_target('installer', nsis)
3609endif
3610
3611#########################
3612# Configuration summary #
3613#########################
3614
3615# Directories
3616summary_info = {}
3617summary_info += {'Install prefix':    get_option('prefix')}
3618summary_info += {'BIOS directory':    qemu_datadir}
3619summary_info += {'firmware path':     get_option('prefix') / get_option('qemu_firmwarepath')}
3620summary_info += {'binary directory':  get_option('prefix') / get_option('bindir')}
3621summary_info += {'library directory': get_option('prefix') / get_option('libdir')}
3622summary_info += {'module directory':  qemu_moddir}
3623summary_info += {'libexec directory': get_option('prefix') / get_option('libexecdir')}
3624summary_info += {'include directory': get_option('prefix') / get_option('includedir')}
3625summary_info += {'config directory':  get_option('prefix') / get_option('sysconfdir')}
3626if targetos != 'windows'
3627  summary_info += {'local state directory': get_option('prefix') / get_option('localstatedir')}
3628  summary_info += {'Manual directory':      get_option('prefix') / get_option('mandir')}
3629else
3630  summary_info += {'local state directory': 'queried at runtime'}
3631endif
3632summary_info += {'Doc directory':     get_option('prefix') / get_option('docdir')}
3633summary_info += {'Build directory':   meson.current_build_dir()}
3634summary_info += {'Source path':       meson.current_source_dir()}
3635summary_info += {'GIT submodules':    config_host['GIT_SUBMODULES']}
3636summary(summary_info, bool_yn: true, section: 'Directories')
3637
3638# Host binaries
3639summary_info = {}
3640summary_info += {'git':               config_host['GIT']}
3641summary_info += {'make':              config_host['MAKE']}
3642summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
3643summary_info += {'sphinx-build':      sphinx_build}
3644if config_host.has_key('HAVE_GDB_BIN')
3645  summary_info += {'gdb':             config_host['HAVE_GDB_BIN']}
3646endif
3647summary_info += {'iasl':              iasl}
3648summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
3649if targetos == 'windows' and have_ga
3650  summary_info += {'wixl':            wixl}
3651endif
3652if slirp_opt != 'disabled' and have_system
3653  summary_info += {'smbd':            have_slirp_smbd ? smbd_path : false}
3654endif
3655summary(summary_info, bool_yn: true, section: 'Host binaries')
3656
3657# Configurable features
3658summary_info = {}
3659summary_info += {'Documentation':     build_docs}
3660summary_info += {'system-mode emulation': have_system}
3661summary_info += {'user-mode emulation': have_user}
3662summary_info += {'block layer':       have_block}
3663summary_info += {'Install blobs':     get_option('install_blobs')}
3664summary_info += {'module support':    config_host.has_key('CONFIG_MODULES')}
3665if config_host.has_key('CONFIG_MODULES')
3666  summary_info += {'alternative module path': get_option('module_upgrades')}
3667endif
3668summary_info += {'fuzzing support':   get_option('fuzzing')}
3669if have_system
3670  summary_info += {'Audio drivers':     ' '.join(audio_drivers_selected)}
3671endif
3672summary_info += {'Trace backends':    ','.join(get_option('trace_backends'))}
3673if 'simple' in get_option('trace_backends')
3674  summary_info += {'Trace output file': get_option('trace_file') + '-<pid>'}
3675endif
3676summary_info += {'D-Bus display':     dbus_display}
3677summary_info += {'QOM debugging':     get_option('qom_cast_debug')}
3678summary_info += {'vhost-kernel support': have_vhost_kernel}
3679summary_info += {'vhost-net support': have_vhost_net}
3680summary_info += {'vhost-user support': have_vhost_user}
3681summary_info += {'vhost-user-crypto support': have_vhost_user_crypto}
3682summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
3683summary_info += {'vhost-vdpa support': have_vhost_vdpa}
3684summary_info += {'build guest agent': have_ga}
3685summary(summary_info, bool_yn: true, section: 'Configurable features')
3686
3687# Compilation information
3688summary_info = {}
3689summary_info += {'host CPU':          cpu}
3690summary_info += {'host endianness':   build_machine.endian()}
3691summary_info += {'C compiler':        ' '.join(meson.get_compiler('c').cmd_array())}
3692summary_info += {'Host C compiler':   ' '.join(meson.get_compiler('c', native: true).cmd_array())}
3693if link_language == 'cpp'
3694  summary_info += {'C++ compiler':    ' '.join(meson.get_compiler('cpp').cmd_array())}
3695else
3696  summary_info += {'C++ compiler':      false}
3697endif
3698if targetos == 'darwin'
3699  summary_info += {'Objective-C compiler': ' '.join(meson.get_compiler('objc').cmd_array())}
3700endif
3701summary_info += {'CFLAGS':            ' '.join(get_option('c_args')
3702                                               + ['-O' + get_option('optimization')]
3703                                               + (get_option('debug') ? ['-g'] : []))}
3704if link_language == 'cpp'
3705  summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args')
3706                                               + ['-O' + get_option('optimization')]
3707                                               + (get_option('debug') ? ['-g'] : []))}
3708endif
3709if targetos == 'darwin'
3710  summary_info += {'OBJCFLAGS':       ' '.join(get_option('objc_args')
3711                                               + ['-O' + get_option('optimization')]
3712                                               + (get_option('debug') ? ['-g'] : []))}
3713endif
3714link_args = get_option(link_language + '_link_args')
3715if link_args.length() > 0
3716  summary_info += {'LDFLAGS':         ' '.join(link_args)}
3717endif
3718summary_info += {'QEMU_CFLAGS':       ' '.join(qemu_cflags)}
3719summary_info += {'QEMU_CXXFLAGS':     ' '.join(qemu_cxxflags)}
3720summary_info += {'QEMU_OBJCFLAGS':    ' '.join(qemu_objcflags)}
3721summary_info += {'QEMU_LDFLAGS':      ' '.join(qemu_ldflags)}
3722summary_info += {'profiler':          get_option('profiler')}
3723summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
3724summary_info += {'PIE':               get_option('b_pie')}
3725summary_info += {'static build':      config_host.has_key('CONFIG_STATIC')}
3726summary_info += {'malloc trim support': has_malloc_trim}
3727summary_info += {'membarrier':        have_membarrier}
3728summary_info += {'debug stack usage': get_option('debug_stack_usage')}
3729summary_info += {'mutex debugging':   get_option('debug_mutex')}
3730summary_info += {'memory allocator':  get_option('malloc')}
3731summary_info += {'avx2 optimization': config_host_data.get('CONFIG_AVX2_OPT')}
3732summary_info += {'avx512f optimization': config_host_data.get('CONFIG_AVX512F_OPT')}
3733summary_info += {'gprof enabled':     get_option('gprof')}
3734summary_info += {'gcov':              get_option('b_coverage')}
3735summary_info += {'thread sanitizer':  config_host.has_key('CONFIG_TSAN')}
3736summary_info += {'CFI support':       get_option('cfi')}
3737if get_option('cfi')
3738  summary_info += {'CFI debug support': get_option('cfi_debug')}
3739endif
3740summary_info += {'strip binaries':    get_option('strip')}
3741summary_info += {'sparse':            sparse}
3742summary_info += {'mingw32 support':   targetos == 'windows'}
3743
3744# snarf the cross-compilation information for tests
3745foreach target: target_dirs
3746  tcg_mak = meson.current_build_dir() / 'tests/tcg' / 'config-' + target + '.mak'
3747  if fs.exists(tcg_mak)
3748    config_cross_tcg = keyval.load(tcg_mak)
3749    target = config_cross_tcg['TARGET_NAME']
3750    compiler = ''
3751    if 'CC' in config_cross_tcg
3752      summary_info += {target + ' tests': config_cross_tcg['CC']}
3753    endif
3754   endif
3755endforeach
3756
3757summary(summary_info, bool_yn: true, section: 'Compilation')
3758
3759# Targets and accelerators
3760summary_info = {}
3761if have_system
3762  summary_info += {'KVM support':       config_all.has_key('CONFIG_KVM')}
3763  summary_info += {'HAX support':       config_all.has_key('CONFIG_HAX')}
3764  summary_info += {'HVF support':       config_all.has_key('CONFIG_HVF')}
3765  summary_info += {'WHPX support':      config_all.has_key('CONFIG_WHPX')}
3766  summary_info += {'NVMM support':      config_all.has_key('CONFIG_NVMM')}
3767  summary_info += {'Xen support':       xen.found()}
3768  if xen.found()
3769    summary_info += {'xen ctrl version':  xen.version()}
3770  endif
3771endif
3772summary_info += {'TCG support':       config_all.has_key('CONFIG_TCG')}
3773if config_all.has_key('CONFIG_TCG')
3774  if get_option('tcg_interpreter')
3775    summary_info += {'TCG backend':   'TCI (TCG with bytecode interpreter, slow)'}
3776  else
3777    summary_info += {'TCG backend':   'native (@0@)'.format(cpu)}
3778  endif
3779  summary_info += {'TCG plugins': config_host.has_key('CONFIG_PLUGIN')}
3780  summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')}
3781endif
3782summary_info += {'target list':       ' '.join(target_dirs)}
3783if have_system
3784  summary_info += {'default devices':   get_option('default_devices')}
3785  summary_info += {'out of process emulation': multiprocess_allowed}
3786endif
3787summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
3788
3789# Block layer
3790summary_info = {}
3791summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']}
3792summary_info += {'coroutine pool':    have_coroutine_pool}
3793if have_block
3794  summary_info += {'Block whitelist (rw)': get_option('block_drv_rw_whitelist')}
3795  summary_info += {'Block whitelist (ro)': get_option('block_drv_ro_whitelist')}
3796  summary_info += {'Use block whitelist in tools': get_option('block_drv_whitelist_in_tools')}
3797  summary_info += {'VirtFS support':    have_virtfs}
3798  summary_info += {'build virtiofs daemon': have_virtiofsd}
3799  summary_info += {'Live block migration': config_host_data.get('CONFIG_LIVE_BLOCK_MIGRATION')}
3800  summary_info += {'replication support': config_host_data.get('CONFIG_REPLICATION')}
3801  summary_info += {'bochs support':     get_option('bochs').allowed()}
3802  summary_info += {'cloop support':     get_option('cloop').allowed()}
3803  summary_info += {'dmg support':       get_option('dmg').allowed()}
3804  summary_info += {'qcow v1 support':   get_option('qcow1').allowed()}
3805  summary_info += {'vdi support':       get_option('vdi').allowed()}
3806  summary_info += {'vvfat support':     get_option('vvfat').allowed()}
3807  summary_info += {'qed support':       get_option('qed').allowed()}
3808  summary_info += {'parallels support': get_option('parallels').allowed()}
3809  summary_info += {'FUSE exports':      fuse}
3810endif
3811summary(summary_info, bool_yn: true, section: 'Block layer support')
3812
3813# Crypto
3814summary_info = {}
3815summary_info += {'TLS priority':      get_option('tls_priority')}
3816summary_info += {'GNUTLS support':    gnutls}
3817if gnutls.found()
3818  summary_info += {'  GNUTLS crypto':   gnutls_crypto.found()}
3819endif
3820summary_info += {'libgcrypt':         gcrypt}
3821summary_info += {'nettle':            nettle}
3822if nettle.found()
3823   summary_info += {'  XTS':             xts != 'private'}
3824endif
3825summary_info += {'AF_ALG support':    have_afalg}
3826summary_info += {'rng-none':          get_option('rng_none')}
3827summary_info += {'Linux keyring':     have_keyring}
3828summary(summary_info, bool_yn: true, section: 'Crypto')
3829
3830# Libraries
3831summary_info = {}
3832if targetos == 'darwin'
3833  summary_info += {'Cocoa support':           cocoa}
3834  summary_info += {'vmnet.framework support': vmnet}
3835endif
3836summary_info += {'SDL support':       sdl}
3837summary_info += {'SDL image support': sdl_image}
3838summary_info += {'GTK support':       gtk}
3839summary_info += {'pixman':            pixman}
3840summary_info += {'VTE support':       vte}
3841summary_info += {'slirp support':     slirp_opt == 'internal' ? slirp_opt : slirp}
3842summary_info += {'libtasn1':          tasn1}
3843summary_info += {'PAM':               pam}
3844summary_info += {'iconv support':     iconv}
3845summary_info += {'curses support':    curses}
3846summary_info += {'virgl support':     virgl}
3847summary_info += {'curl support':      curl}
3848summary_info += {'Multipath support': mpathpersist}
3849summary_info += {'PNG support':       png}
3850summary_info += {'VNC support':       vnc}
3851if vnc.found()
3852  summary_info += {'VNC SASL support':  sasl}
3853  summary_info += {'VNC JPEG support':  jpeg}
3854endif
3855if targetos not in ['darwin', 'haiku', 'windows']
3856  summary_info += {'OSS support':     oss}
3857elif targetos == 'darwin'
3858  summary_info += {'CoreAudio support': coreaudio}
3859elif targetos == 'windows'
3860  summary_info += {'DirectSound support': dsound}
3861endif
3862if targetos == 'linux'
3863  summary_info += {'ALSA support':    alsa}
3864  summary_info += {'PulseAudio support': pulse}
3865endif
3866summary_info += {'JACK support':      jack}
3867summary_info += {'brlapi support':    brlapi}
3868summary_info += {'vde support':       vde}
3869summary_info += {'netmap support':    have_netmap}
3870summary_info += {'l2tpv3 support':    have_l2tpv3}
3871summary_info += {'Linux AIO support': libaio}
3872summary_info += {'Linux io_uring support': linux_io_uring}
3873summary_info += {'ATTR/XATTR support': libattr}
3874summary_info += {'RDMA support':      rdma}
3875summary_info += {'PVRDMA support':    have_pvrdma}
3876summary_info += {'fdt support':       fdt_opt == 'disabled' ? false : fdt_opt}
3877summary_info += {'libcap-ng support': libcap_ng}
3878summary_info += {'bpf support':       libbpf}
3879summary_info += {'spice protocol support': spice_protocol}
3880if spice_protocol.found()
3881  summary_info += {'  spice server support': spice}
3882endif
3883summary_info += {'rbd support':       rbd}
3884summary_info += {'smartcard support': cacard}
3885summary_info += {'U2F support':       u2f}
3886summary_info += {'libusb':            libusb}
3887summary_info += {'usb net redir':     usbredir}
3888summary_info += {'OpenGL support (epoxy)': opengl}
3889summary_info += {'GBM':               gbm}
3890summary_info += {'libiscsi support':  libiscsi}
3891summary_info += {'libnfs support':    libnfs}
3892if targetos == 'windows'
3893  if have_ga
3894    summary_info += {'QGA VSS support':   have_qga_vss}
3895  endif
3896endif
3897summary_info += {'seccomp support':   seccomp}
3898summary_info += {'GlusterFS support': glusterfs}
3899summary_info += {'TPM support':       have_tpm}
3900summary_info += {'libssh support':    libssh}
3901summary_info += {'lzo support':       lzo}
3902summary_info += {'snappy support':    snappy}
3903summary_info += {'bzip2 support':     libbzip2}
3904summary_info += {'lzfse support':     liblzfse}
3905summary_info += {'zstd support':      zstd}
3906summary_info += {'NUMA host support': numa}
3907summary_info += {'capstone':          capstone}
3908summary_info += {'libpmem support':   libpmem}
3909summary_info += {'libdaxctl support': libdaxctl}
3910summary_info += {'libudev':           libudev}
3911# Dummy dependency, keep .found()
3912summary_info += {'FUSE lseek':        fuse_lseek.found()}
3913summary_info += {'selinux':           selinux}
3914summary(summary_info, bool_yn: true, section: 'Dependencies')
3915
3916if not supported_cpus.contains(cpu)
3917  message()
3918  warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!')
3919  message()
3920  message('CPU host architecture ' + cpu + ' support is not currently maintained.')
3921  message('The QEMU project intends to remove support for this host CPU in')
3922  message('a future release if nobody volunteers to maintain it and to')
3923  message('provide a build host for our continuous integration setup.')
3924  message('configure has succeeded and you can continue to build, but')
3925  message('if you care about QEMU on this platform you should contact')
3926  message('us upstream at qemu-devel@nongnu.org.')
3927endif
3928
3929if not supported_oses.contains(targetos)
3930  message()
3931  warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!')
3932  message()
3933  message('Host OS ' + targetos + 'support is not currently maintained.')
3934  message('The QEMU project intends to remove support for this host OS in')
3935  message('a future release if nobody volunteers to maintain it and to')
3936  message('provide a build host for our continuous integration setup.')
3937  message('configure has succeeded and you can continue to build, but')
3938  message('if you care about QEMU on this platform you should contact')
3939  message('us upstream at qemu-devel@nongnu.org.')
3940endif
3941