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