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