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