xref: /qemu/meson.build (revision 0f900bae)
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]
2867if have_linux_user
2868  trace_events_subdirs += [ 'linux-user' ]
2869endif
2870if have_bsd_user
2871  trace_events_subdirs += [ 'bsd-user' ]
2872endif
2873if have_block
2874  trace_events_subdirs += [
2875    'authz',
2876    'block',
2877    'io',
2878    'nbd',
2879    'scsi',
2880  ]
2881endif
2882if have_system
2883  trace_events_subdirs += [
2884    'accel/kvm',
2885    'audio',
2886    'backends',
2887    'backends/tpm',
2888    'chardev',
2889    'ebpf',
2890    'hw/9pfs',
2891    'hw/acpi',
2892    'hw/adc',
2893    'hw/alpha',
2894    'hw/arm',
2895    'hw/audio',
2896    'hw/block',
2897    'hw/block/dataplane',
2898    'hw/char',
2899    'hw/display',
2900    'hw/dma',
2901    'hw/hyperv',
2902    'hw/i2c',
2903    'hw/i386',
2904    'hw/i386/xen',
2905    'hw/ide',
2906    'hw/input',
2907    'hw/intc',
2908    'hw/isa',
2909    'hw/mem',
2910    'hw/mips',
2911    'hw/misc',
2912    'hw/misc/macio',
2913    'hw/net',
2914    'hw/net/can',
2915    'hw/nubus',
2916    'hw/nvme',
2917    'hw/nvram',
2918    'hw/pci',
2919    'hw/pci-host',
2920    'hw/ppc',
2921    'hw/rdma',
2922    'hw/rdma/vmw',
2923    'hw/rtc',
2924    'hw/s390x',
2925    'hw/scsi',
2926    'hw/sd',
2927    'hw/sh4',
2928    'hw/sparc',
2929    'hw/sparc64',
2930    'hw/ssi',
2931    'hw/timer',
2932    'hw/tpm',
2933    'hw/usb',
2934    'hw/vfio',
2935    'hw/virtio',
2936    'hw/watchdog',
2937    'hw/xen',
2938    'hw/gpio',
2939    'migration',
2940    'net',
2941    'softmmu',
2942    'ui',
2943    'hw/remote',
2944  ]
2945endif
2946if have_system or have_user
2947  trace_events_subdirs += [
2948    'accel/tcg',
2949    'hw/core',
2950    'target/arm',
2951    'target/arm/hvf',
2952    'target/hppa',
2953    'target/i386',
2954    'target/i386/kvm',
2955    'target/mips/tcg',
2956    'target/nios2',
2957    'target/ppc',
2958    'target/riscv',
2959    'target/s390x',
2960    'target/s390x/kvm',
2961    'target/sparc',
2962  ]
2963endif
2964
2965vhost_user = not_found
2966if targetos == 'linux' and have_vhost_user
2967  libvhost_user = subproject('libvhost-user')
2968  vhost_user = libvhost_user.get_variable('vhost_user_dep')
2969endif
2970
2971libvduse = not_found
2972if have_libvduse
2973  libvduse_proj = subproject('libvduse')
2974  libvduse = libvduse_proj.get_variable('libvduse_dep')
2975endif
2976
2977# NOTE: the trace/ subdirectory needs the qapi_trace_events variable
2978# that is filled in by qapi/.
2979subdir('qapi')
2980subdir('qobject')
2981subdir('stubs')
2982subdir('trace')
2983subdir('util')
2984subdir('qom')
2985subdir('authz')
2986subdir('crypto')
2987subdir('ui')
2988subdir('hw')
2989
2990
2991if enable_modules
2992  libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
2993  modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
2994endif
2995
2996qom_ss = qom_ss.apply(config_host, strict: false)
2997libqom = static_library('qom', qom_ss.sources() + genh,
2998                        dependencies: [qom_ss.dependencies()],
2999                        name_suffix: 'fa')
3000qom = declare_dependency(link_whole: libqom)
3001
3002event_loop_base = files('event-loop-base.c')
3003event_loop_base = static_library('event-loop-base', sources: event_loop_base + genh,
3004                                 build_by_default: true)
3005event_loop_base = declare_dependency(link_whole: event_loop_base,
3006                                     dependencies: [qom])
3007
3008stub_ss = stub_ss.apply(config_all, strict: false)
3009
3010util_ss.add_all(trace_ss)
3011util_ss = util_ss.apply(config_all, strict: false)
3012libqemuutil = static_library('qemuutil',
3013                             sources: util_ss.sources() + stub_ss.sources() + genh,
3014                             dependencies: [util_ss.dependencies(), libm, threads, glib, socket, malloc, pixman])
3015qemuutil = declare_dependency(link_with: libqemuutil,
3016                              sources: genh + version_res,
3017                              dependencies: [event_loop_base])
3018
3019if have_system or have_user
3020  decodetree = generator(find_program('scripts/decodetree.py'),
3021                         output: 'decode-@BASENAME@.c.inc',
3022                         arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
3023  subdir('libdecnumber')
3024  subdir('target')
3025endif
3026
3027subdir('audio')
3028subdir('io')
3029subdir('chardev')
3030subdir('fsdev')
3031subdir('dump')
3032
3033if have_block
3034  block_ss.add(files(
3035    'block.c',
3036    'blockjob.c',
3037    'job.c',
3038    'qemu-io-cmds.c',
3039  ))
3040  if config_host_data.get('CONFIG_REPLICATION')
3041    block_ss.add(files('replication.c'))
3042  endif
3043
3044  subdir('nbd')
3045  subdir('scsi')
3046  subdir('block')
3047
3048  blockdev_ss.add(files(
3049    'blockdev.c',
3050    'blockdev-nbd.c',
3051    'iothread.c',
3052    'job-qmp.c',
3053  ), gnutls)
3054
3055  # os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
3056  # os-win32.c does not
3057  blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c'))
3058  softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')])
3059endif
3060
3061common_ss.add(files('cpus-common.c'))
3062
3063subdir('softmmu')
3064
3065common_ss.add(capstone)
3066specific_ss.add(files('cpu.c', 'disas.c', 'gdbstub.c'), capstone)
3067
3068# Work around a gcc bug/misfeature wherein constant propagation looks
3069# through an alias:
3070#   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99696
3071# to guess that a const variable is always zero.  Without lto, this is
3072# impossible, as the alias is restricted to page-vary-common.c.  Indeed,
3073# without lto, not even the alias is required -- we simply use different
3074# declarations in different compilation units.
3075pagevary = files('page-vary-common.c')
3076if get_option('b_lto')
3077  pagevary_flags = ['-fno-lto']
3078  if get_option('cfi')
3079    pagevary_flags += '-fno-sanitize=cfi-icall'
3080  endif
3081  pagevary = static_library('page-vary-common', sources: pagevary + genh,
3082                            c_args: pagevary_flags)
3083  pagevary = declare_dependency(link_with: pagevary)
3084endif
3085common_ss.add(pagevary)
3086specific_ss.add(files('page-vary.c'))
3087
3088subdir('backends')
3089subdir('disas')
3090subdir('migration')
3091subdir('monitor')
3092subdir('net')
3093subdir('replay')
3094subdir('semihosting')
3095subdir('tcg')
3096subdir('fpu')
3097subdir('accel')
3098subdir('plugins')
3099subdir('ebpf')
3100
3101common_user_inc = []
3102
3103subdir('common-user')
3104subdir('bsd-user')
3105subdir('linux-user')
3106
3107# needed for fuzzing binaries
3108subdir('tests/qtest/libqos')
3109subdir('tests/qtest/fuzz')
3110
3111# accel modules
3112tcg_real_module_ss = ss.source_set()
3113tcg_real_module_ss.add_all(when: 'CONFIG_TCG_MODULAR', if_true: tcg_module_ss)
3114specific_ss.add_all(when: 'CONFIG_TCG_BUILTIN', if_true: tcg_module_ss)
3115target_modules += { 'accel' : { 'qtest': qtest_module_ss,
3116                                'tcg': tcg_real_module_ss }}
3117
3118########################
3119# Library dependencies #
3120########################
3121
3122modinfo_collect = find_program('scripts/modinfo-collect.py')
3123modinfo_generate = find_program('scripts/modinfo-generate.py')
3124modinfo_files = []
3125
3126block_mods = []
3127softmmu_mods = []
3128foreach d, list : modules
3129  foreach m, module_ss : list
3130    if enable_modules and targetos != 'windows'
3131      module_ss = module_ss.apply(config_all, strict: false)
3132      sl = static_library(d + '-' + m, [genh, module_ss.sources()],
3133                          dependencies: [modulecommon, module_ss.dependencies()], pic: true)
3134      if d == 'block'
3135        block_mods += sl
3136      else
3137        softmmu_mods += sl
3138      endif
3139      if module_ss.sources() != []
3140        # FIXME: Should use sl.extract_all_objects(recursive: true) as
3141        # input. Sources can be used multiple times but objects are
3142        # unique when it comes to lookup in compile_commands.json.
3143        # Depnds on a mesion version with
3144        # https://github.com/mesonbuild/meson/pull/8900
3145        modinfo_files += custom_target(d + '-' + m + '.modinfo',
3146                                       output: d + '-' + m + '.modinfo',
3147                                       input: module_ss.sources() + genh,
3148                                       capture: true,
3149                                       command: [modinfo_collect, module_ss.sources()])
3150      endif
3151    else
3152      if d == 'block'
3153        block_ss.add_all(module_ss)
3154      else
3155        softmmu_ss.add_all(module_ss)
3156      endif
3157    endif
3158  endforeach
3159endforeach
3160
3161foreach d, list : target_modules
3162  foreach m, module_ss : list
3163    if enable_modules and targetos != 'windows'
3164      foreach target : target_dirs
3165        if target.endswith('-softmmu')
3166          config_target = config_target_mak[target]
3167          config_target += config_host
3168          target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
3169          c_args = ['-DNEED_CPU_H',
3170                    '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
3171                    '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
3172          target_module_ss = module_ss.apply(config_target, strict: false)
3173          if target_module_ss.sources() != []
3174            module_name = d + '-' + m + '-' + config_target['TARGET_NAME']
3175            sl = static_library(module_name,
3176                                [genh, target_module_ss.sources()],
3177                                dependencies: [modulecommon, target_module_ss.dependencies()],
3178                                include_directories: target_inc,
3179                                c_args: c_args,
3180                                pic: true)
3181            softmmu_mods += sl
3182            # FIXME: Should use sl.extract_all_objects(recursive: true) too.
3183            modinfo_files += custom_target(module_name + '.modinfo',
3184                                           output: module_name + '.modinfo',
3185                                           input: target_module_ss.sources() + genh,
3186                                           capture: true,
3187                                           command: [modinfo_collect, '--target', target, target_module_ss.sources()])
3188          endif
3189        endif
3190      endforeach
3191    else
3192      specific_ss.add_all(module_ss)
3193    endif
3194  endforeach
3195endforeach
3196
3197if enable_modules
3198  foreach target : target_dirs
3199    if target.endswith('-softmmu')
3200      config_target = config_target_mak[target]
3201      config_devices_mak = target + '-config-devices.mak'
3202      modinfo_src = custom_target('modinfo-' + target + '.c',
3203                                  output: 'modinfo-' + target + '.c',
3204                                  input: modinfo_files,
3205                                  command: [modinfo_generate, '--devices', config_devices_mak, '@INPUT@'],
3206                                  capture: true)
3207
3208      modinfo_lib = static_library('modinfo-' + target + '.c', modinfo_src)
3209      modinfo_dep = declare_dependency(link_with: modinfo_lib)
3210
3211      arch = config_target['TARGET_NAME'] == 'sparc64' ? 'sparc64' : config_target['TARGET_BASE_ARCH']
3212      hw_arch[arch].add(modinfo_dep)
3213    endif
3214  endforeach
3215endif
3216
3217nm = find_program('nm')
3218undefsym = find_program('scripts/undefsym.py')
3219block_syms = custom_target('block.syms', output: 'block.syms',
3220                             input: [libqemuutil, block_mods],
3221                             capture: true,
3222                             command: [undefsym, nm, '@INPUT@'])
3223qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
3224                             input: [libqemuutil, softmmu_mods],
3225                             capture: true,
3226                             command: [undefsym, nm, '@INPUT@'])
3227
3228authz_ss = authz_ss.apply(config_host, strict: false)
3229libauthz = static_library('authz', authz_ss.sources() + genh,
3230                          dependencies: [authz_ss.dependencies()],
3231                          name_suffix: 'fa',
3232                          build_by_default: false)
3233
3234authz = declare_dependency(link_whole: libauthz,
3235                           dependencies: qom)
3236
3237crypto_ss = crypto_ss.apply(config_host, strict: false)
3238libcrypto = static_library('crypto', crypto_ss.sources() + genh,
3239                           dependencies: [crypto_ss.dependencies()],
3240                           name_suffix: 'fa',
3241                           build_by_default: false)
3242
3243crypto = declare_dependency(link_whole: libcrypto,
3244                            dependencies: [authz, qom])
3245
3246io_ss = io_ss.apply(config_host, strict: false)
3247libio = static_library('io', io_ss.sources() + genh,
3248                       dependencies: [io_ss.dependencies()],
3249                       link_with: libqemuutil,
3250                       name_suffix: 'fa',
3251                       build_by_default: false)
3252
3253io = declare_dependency(link_whole: libio, dependencies: [crypto, qom])
3254
3255libmigration = static_library('migration', sources: migration_files + genh,
3256                              name_suffix: 'fa',
3257                              build_by_default: false)
3258migration = declare_dependency(link_with: libmigration,
3259                               dependencies: [zlib, qom, io])
3260softmmu_ss.add(migration)
3261
3262block_ss = block_ss.apply(config_host, strict: false)
3263libblock = static_library('block', block_ss.sources() + genh,
3264                          dependencies: block_ss.dependencies(),
3265                          link_depends: block_syms,
3266                          name_suffix: 'fa',
3267                          build_by_default: false)
3268
3269block = declare_dependency(link_whole: [libblock],
3270                           link_args: '@block.syms',
3271                           dependencies: [crypto, io])
3272
3273blockdev_ss = blockdev_ss.apply(config_host, strict: false)
3274libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
3275                             dependencies: blockdev_ss.dependencies(),
3276                             name_suffix: 'fa',
3277                             build_by_default: false)
3278
3279blockdev = declare_dependency(link_whole: [libblockdev],
3280                              dependencies: [block, event_loop_base])
3281
3282qmp_ss = qmp_ss.apply(config_host, strict: false)
3283libqmp = static_library('qmp', qmp_ss.sources() + genh,
3284                        dependencies: qmp_ss.dependencies(),
3285                        name_suffix: 'fa',
3286                        build_by_default: false)
3287
3288qmp = declare_dependency(link_whole: [libqmp])
3289
3290libchardev = static_library('chardev', chardev_ss.sources() + genh,
3291                            name_suffix: 'fa',
3292                            dependencies: chardev_ss.dependencies(),
3293                            build_by_default: false)
3294
3295chardev = declare_dependency(link_whole: libchardev)
3296
3297hwcore_ss = hwcore_ss.apply(config_host, strict: false)
3298libhwcore = static_library('hwcore', sources: hwcore_ss.sources() + genh,
3299                           name_suffix: 'fa',
3300                           build_by_default: false)
3301hwcore = declare_dependency(link_whole: libhwcore)
3302common_ss.add(hwcore)
3303
3304###########
3305# Targets #
3306###########
3307
3308emulator_modules = []
3309foreach m : block_mods + softmmu_mods
3310  emulator_modules += shared_module(m.name(),
3311                build_by_default: true,
3312                name_prefix: '',
3313                link_whole: m,
3314                install: true,
3315                install_dir: qemu_moddir)
3316endforeach
3317if emulator_modules.length() > 0
3318  alias_target('modules', emulator_modules)
3319endif
3320
3321softmmu_ss.add(authz, blockdev, chardev, crypto, io, qmp)
3322common_ss.add(qom, qemuutil)
3323
3324common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss])
3325common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
3326
3327common_all = common_ss.apply(config_all, strict: false)
3328common_all = static_library('common',
3329                            build_by_default: false,
3330                            sources: common_all.sources() + genh,
3331                            include_directories: common_user_inc,
3332                            implicit_include_directories: false,
3333                            dependencies: common_all.dependencies(),
3334                            name_suffix: 'fa')
3335
3336feature_to_c = find_program('scripts/feature_to_c.sh')
3337
3338if targetos == 'darwin'
3339  entitlement = find_program('scripts/entitlement.sh')
3340endif
3341
3342emulators = {}
3343foreach target : target_dirs
3344  config_target = config_target_mak[target]
3345  target_name = config_target['TARGET_NAME']
3346  target_base_arch = config_target['TARGET_BASE_ARCH']
3347  arch_srcs = [config_target_h[target]]
3348  arch_deps = []
3349  c_args = ['-DNEED_CPU_H',
3350            '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
3351            '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
3352  link_args = emulator_link_args
3353
3354  config_target += config_host
3355  target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
3356  if targetos == 'linux'
3357    target_inc += include_directories('linux-headers', is_system: true)
3358  endif
3359  if target.endswith('-softmmu')
3360    target_type='system'
3361    t = target_softmmu_arch[target_base_arch].apply(config_target, strict: false)
3362    arch_srcs += t.sources()
3363    arch_deps += t.dependencies()
3364
3365    hw_dir = target_name == 'sparc64' ? 'sparc64' : target_base_arch
3366    hw = hw_arch[hw_dir].apply(config_target, strict: false)
3367    arch_srcs += hw.sources()
3368    arch_deps += hw.dependencies()
3369
3370    arch_srcs += config_devices_h[target]
3371    link_args += ['@block.syms', '@qemu.syms']
3372  else
3373    abi = config_target['TARGET_ABI_DIR']
3374    target_type='user'
3375    target_inc += common_user_inc
3376    if target_base_arch in target_user_arch
3377      t = target_user_arch[target_base_arch].apply(config_target, strict: false)
3378      arch_srcs += t.sources()
3379      arch_deps += t.dependencies()
3380    endif
3381    if 'CONFIG_LINUX_USER' in config_target
3382      base_dir = 'linux-user'
3383    endif
3384    if 'CONFIG_BSD_USER' in config_target
3385      base_dir = 'bsd-user'
3386      target_inc += include_directories('bsd-user/' / targetos)
3387      target_inc += include_directories('bsd-user/host/' / host_arch)
3388      dir = base_dir / abi
3389      arch_srcs += files(dir / 'signal.c', dir / 'target_arch_cpu.c')
3390    endif
3391    target_inc += include_directories(
3392      base_dir,
3393      base_dir / abi,
3394    )
3395    if 'CONFIG_LINUX_USER' in config_target
3396      dir = base_dir / abi
3397      arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
3398      if config_target.has_key('TARGET_SYSTBL_ABI')
3399        arch_srcs += \
3400          syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
3401                                             extra_args : config_target['TARGET_SYSTBL_ABI'])
3402      endif
3403    endif
3404  endif
3405
3406  if 'TARGET_XML_FILES' in config_target
3407    gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
3408                                output: target + '-gdbstub-xml.c',
3409                                input: files(config_target['TARGET_XML_FILES'].split()),
3410                                command: [feature_to_c, '@INPUT@'],
3411                                capture: true)
3412    arch_srcs += gdbstub_xml
3413  endif
3414
3415  t = target_arch[target_base_arch].apply(config_target, strict: false)
3416  arch_srcs += t.sources()
3417  arch_deps += t.dependencies()
3418
3419  target_common = common_ss.apply(config_target, strict: false)
3420  objects = common_all.extract_objects(target_common.sources())
3421  deps = target_common.dependencies()
3422
3423  target_specific = specific_ss.apply(config_target, strict: false)
3424  arch_srcs += target_specific.sources()
3425  arch_deps += target_specific.dependencies()
3426
3427  lib = static_library('qemu-' + target,
3428                 sources: arch_srcs + genh,
3429                 dependencies: arch_deps,
3430                 objects: objects,
3431                 include_directories: target_inc,
3432                 c_args: c_args,
3433                 build_by_default: false,
3434                 name_suffix: 'fa')
3435
3436  if target.endswith('-softmmu')
3437    execs = [{
3438      'name': 'qemu-system-' + target_name,
3439      'win_subsystem': 'console',
3440      'sources': files('softmmu/main.c'),
3441      'dependencies': []
3442    }]
3443    if targetos == 'windows' and (sdl.found() or gtk.found())
3444      execs += [{
3445        'name': 'qemu-system-' + target_name + 'w',
3446        'win_subsystem': 'windows',
3447        'sources': files('softmmu/main.c'),
3448        'dependencies': []
3449      }]
3450    endif
3451    if get_option('fuzzing')
3452      specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
3453      execs += [{
3454        'name': 'qemu-fuzz-' + target_name,
3455        'win_subsystem': 'console',
3456        'sources': specific_fuzz.sources(),
3457        'dependencies': specific_fuzz.dependencies(),
3458      }]
3459    endif
3460  else
3461    execs = [{
3462      'name': 'qemu-' + target_name,
3463      'win_subsystem': 'console',
3464      'sources': [],
3465      'dependencies': []
3466    }]
3467  endif
3468  foreach exe: execs
3469    exe_name = exe['name']
3470    if targetos == 'darwin'
3471      exe_name += '-unsigned'
3472    endif
3473
3474    emulator = executable(exe_name, exe['sources'],
3475               install: true,
3476               c_args: c_args,
3477               dependencies: arch_deps + deps + exe['dependencies'],
3478               objects: lib.extract_all_objects(recursive: true),
3479               link_language: link_language,
3480               link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
3481               link_args: link_args,
3482               win_subsystem: exe['win_subsystem'])
3483
3484    if targetos == 'darwin'
3485      icon = 'pc-bios/qemu.rsrc'
3486      build_input = [emulator, files(icon)]
3487      install_input = [
3488        get_option('bindir') / exe_name,
3489        meson.current_source_dir() / icon
3490      ]
3491      if 'CONFIG_HVF' in config_target
3492        entitlements = 'accel/hvf/entitlements.plist'
3493        build_input += files(entitlements)
3494        install_input += meson.current_source_dir() / entitlements
3495      endif
3496
3497      emulators += {exe['name'] : custom_target(exe['name'],
3498                   input: build_input,
3499                   output: exe['name'],
3500                   command: [entitlement, '@OUTPUT@', '@INPUT@'])
3501      }
3502
3503      meson.add_install_script(entitlement, '--install',
3504                               get_option('bindir') / exe['name'],
3505                               install_input)
3506    else
3507      emulators += {exe['name']: emulator}
3508    endif
3509
3510    if stap.found()
3511      foreach stp: [
3512        {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
3513        {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
3514        {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
3515        {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
3516      ]
3517        custom_target(exe['name'] + stp['ext'],
3518                      input: trace_events_all,
3519                      output: exe['name'] + stp['ext'],
3520                      install: stp['install'],
3521                      install_dir: get_option('datadir') / 'systemtap/tapset',
3522                      command: [
3523                        tracetool, '--group=all', '--format=' + stp['fmt'],
3524                        '--binary=' + stp['bin'],
3525                        '--target-name=' + target_name,
3526                        '--target-type=' + target_type,
3527                        '--probe-prefix=qemu.' + target_type + '.' + target_name,
3528                        '@INPUT@', '@OUTPUT@'
3529                      ],
3530                      depend_files: tracetool_depends)
3531      endforeach
3532    endif
3533  endforeach
3534endforeach
3535
3536# Other build targets
3537
3538if 'CONFIG_PLUGIN' in config_host
3539  install_headers('include/qemu/qemu-plugin.h')
3540endif
3541
3542subdir('qga')
3543
3544# Don't build qemu-keymap if xkbcommon is not explicitly enabled
3545# when we don't build tools or system
3546if xkbcommon.found()
3547  # used for the update-keymaps target, so include rules even if !have_tools
3548  qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
3549                           dependencies: [qemuutil, xkbcommon], install: have_tools)
3550endif
3551
3552if have_tools
3553  qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
3554             dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
3555  qemu_io = executable('qemu-io', files('qemu-io.c'),
3556             dependencies: [block, qemuutil], install: true)
3557  qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
3558               dependencies: [blockdev, qemuutil, gnutls, selinux],
3559               install: true)
3560
3561  subdir('storage-daemon')
3562  subdir('contrib/rdmacm-mux')
3563  subdir('contrib/elf2dmp')
3564
3565  executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
3566             dependencies: qemuutil,
3567             install: true)
3568
3569  if have_vhost_user
3570    subdir('contrib/vhost-user-blk')
3571    subdir('contrib/vhost-user-gpu')
3572    subdir('contrib/vhost-user-input')
3573    subdir('contrib/vhost-user-scsi')
3574  endif
3575
3576  if targetos == 'linux'
3577    executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
3578               dependencies: [qemuutil, libcap_ng],
3579               install: true,
3580               install_dir: get_option('libexecdir'))
3581
3582    executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
3583               dependencies: [authz, crypto, io, qom, qemuutil,
3584                              libcap_ng, mpathpersist],
3585               install: true)
3586  endif
3587
3588  if have_ivshmem
3589    subdir('contrib/ivshmem-client')
3590    subdir('contrib/ivshmem-server')
3591  endif
3592endif
3593
3594subdir('scripts')
3595subdir('tools')
3596subdir('pc-bios')
3597subdir('docs')
3598subdir('tests')
3599if gtk.found()
3600  subdir('po')
3601endif
3602
3603if host_machine.system() == 'windows'
3604  nsis_cmd = [
3605    find_program('scripts/nsis.py'),
3606    '@OUTPUT@',
3607    get_option('prefix'),
3608    meson.current_source_dir(),
3609    host_machine.cpu(),
3610    '--',
3611    '-DDISPLAYVERSION=' + meson.project_version(),
3612  ]
3613  if build_docs
3614    nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
3615  endif
3616  if gtk.found()
3617    nsis_cmd += '-DCONFIG_GTK=y'
3618  endif
3619
3620  nsis = custom_target('nsis',
3621                       output: 'qemu-setup-' + meson.project_version() + '.exe',
3622                       input: files('qemu.nsi'),
3623                       build_always_stale: true,
3624                       command: nsis_cmd + ['@INPUT@'])
3625  alias_target('installer', nsis)
3626endif
3627
3628#########################
3629# Configuration summary #
3630#########################
3631
3632# Directories
3633summary_info = {}
3634summary_info += {'Install prefix':    get_option('prefix')}
3635summary_info += {'BIOS directory':    qemu_datadir}
3636pathsep = targetos == 'windows' ? ';' : ':'
3637summary_info += {'firmware path':     pathsep.join(get_option('qemu_firmwarepath'))}
3638summary_info += {'binary directory':  get_option('prefix') / get_option('bindir')}
3639summary_info += {'library directory': get_option('prefix') / get_option('libdir')}
3640summary_info += {'module directory':  qemu_moddir}
3641summary_info += {'libexec directory': get_option('prefix') / get_option('libexecdir')}
3642summary_info += {'include directory': get_option('prefix') / get_option('includedir')}
3643summary_info += {'config directory':  get_option('prefix') / get_option('sysconfdir')}
3644if targetos != 'windows'
3645  summary_info += {'local state directory': get_option('prefix') / get_option('localstatedir')}
3646  summary_info += {'Manual directory':      get_option('prefix') / get_option('mandir')}
3647else
3648  summary_info += {'local state directory': 'queried at runtime'}
3649endif
3650summary_info += {'Doc directory':     get_option('prefix') / get_option('docdir')}
3651summary_info += {'Build directory':   meson.current_build_dir()}
3652summary_info += {'Source path':       meson.current_source_dir()}
3653summary_info += {'GIT submodules':    config_host['GIT_SUBMODULES']}
3654summary(summary_info, bool_yn: true, section: 'Directories')
3655
3656# Host binaries
3657summary_info = {}
3658summary_info += {'git':               config_host['GIT']}
3659summary_info += {'make':              config_host['MAKE']}
3660summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
3661summary_info += {'sphinx-build':      sphinx_build}
3662if config_host.has_key('HAVE_GDB_BIN')
3663  summary_info += {'gdb':             config_host['HAVE_GDB_BIN']}
3664endif
3665summary_info += {'iasl':              iasl}
3666summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
3667if targetos == 'windows' and have_ga
3668  summary_info += {'wixl':            wixl}
3669endif
3670if slirp.found() and have_system
3671  summary_info += {'smbd':            have_slirp_smbd ? smbd_path : false}
3672endif
3673summary(summary_info, bool_yn: true, section: 'Host binaries')
3674
3675# Configurable features
3676summary_info = {}
3677summary_info += {'Documentation':     build_docs}
3678summary_info += {'system-mode emulation': have_system}
3679summary_info += {'user-mode emulation': have_user}
3680summary_info += {'block layer':       have_block}
3681summary_info += {'Install blobs':     get_option('install_blobs')}
3682summary_info += {'module support':    config_host.has_key('CONFIG_MODULES')}
3683if config_host.has_key('CONFIG_MODULES')
3684  summary_info += {'alternative module path': get_option('module_upgrades')}
3685endif
3686summary_info += {'fuzzing support':   get_option('fuzzing')}
3687if have_system
3688  summary_info += {'Audio drivers':     ' '.join(audio_drivers_selected)}
3689endif
3690summary_info += {'Trace backends':    ','.join(get_option('trace_backends'))}
3691if 'simple' in get_option('trace_backends')
3692  summary_info += {'Trace output file': get_option('trace_file') + '-<pid>'}
3693endif
3694summary_info += {'D-Bus display':     dbus_display}
3695summary_info += {'QOM debugging':     get_option('qom_cast_debug')}
3696summary_info += {'vhost-kernel support': have_vhost_kernel}
3697summary_info += {'vhost-net support': have_vhost_net}
3698summary_info += {'vhost-user support': have_vhost_user}
3699summary_info += {'vhost-user-crypto support': have_vhost_user_crypto}
3700summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
3701summary_info += {'vhost-vdpa support': have_vhost_vdpa}
3702summary_info += {'build guest agent': have_ga}
3703summary(summary_info, bool_yn: true, section: 'Configurable features')
3704
3705# Compilation information
3706summary_info = {}
3707summary_info += {'host CPU':          cpu}
3708summary_info += {'host endianness':   build_machine.endian()}
3709summary_info += {'C compiler':        ' '.join(meson.get_compiler('c').cmd_array())}
3710summary_info += {'Host C compiler':   ' '.join(meson.get_compiler('c', native: true).cmd_array())}
3711if link_language == 'cpp'
3712  summary_info += {'C++ compiler':    ' '.join(meson.get_compiler('cpp').cmd_array())}
3713else
3714  summary_info += {'C++ compiler':      false}
3715endif
3716if targetos == 'darwin'
3717  summary_info += {'Objective-C compiler': ' '.join(meson.get_compiler('objc').cmd_array())}
3718endif
3719summary_info += {'CFLAGS':            ' '.join(get_option('c_args')
3720                                               + ['-O' + get_option('optimization')]
3721                                               + (get_option('debug') ? ['-g'] : []))}
3722if link_language == 'cpp'
3723  summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args')
3724                                               + ['-O' + get_option('optimization')]
3725                                               + (get_option('debug') ? ['-g'] : []))}
3726endif
3727if targetos == 'darwin'
3728  summary_info += {'OBJCFLAGS':       ' '.join(get_option('objc_args')
3729                                               + ['-O' + get_option('optimization')]
3730                                               + (get_option('debug') ? ['-g'] : []))}
3731endif
3732link_args = get_option(link_language + '_link_args')
3733if link_args.length() > 0
3734  summary_info += {'LDFLAGS':         ' '.join(link_args)}
3735endif
3736summary_info += {'QEMU_CFLAGS':       ' '.join(qemu_cflags)}
3737summary_info += {'QEMU_CXXFLAGS':     ' '.join(qemu_cxxflags)}
3738summary_info += {'QEMU_OBJCFLAGS':    ' '.join(qemu_objcflags)}
3739summary_info += {'QEMU_LDFLAGS':      ' '.join(qemu_ldflags)}
3740summary_info += {'profiler':          get_option('profiler')}
3741summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
3742summary_info += {'PIE':               get_option('b_pie')}
3743summary_info += {'static build':      config_host.has_key('CONFIG_STATIC')}
3744summary_info += {'malloc trim support': has_malloc_trim}
3745summary_info += {'membarrier':        have_membarrier}
3746summary_info += {'debug stack usage': get_option('debug_stack_usage')}
3747summary_info += {'mutex debugging':   get_option('debug_mutex')}
3748summary_info += {'memory allocator':  get_option('malloc')}
3749summary_info += {'avx2 optimization': config_host_data.get('CONFIG_AVX2_OPT')}
3750summary_info += {'avx512f optimization': config_host_data.get('CONFIG_AVX512F_OPT')}
3751summary_info += {'gprof enabled':     get_option('gprof')}
3752summary_info += {'gcov':              get_option('b_coverage')}
3753summary_info += {'thread sanitizer':  config_host.has_key('CONFIG_TSAN')}
3754summary_info += {'CFI support':       get_option('cfi')}
3755if get_option('cfi')
3756  summary_info += {'CFI debug support': get_option('cfi_debug')}
3757endif
3758summary_info += {'strip binaries':    get_option('strip')}
3759summary_info += {'sparse':            sparse}
3760summary_info += {'mingw32 support':   targetos == 'windows'}
3761summary(summary_info, bool_yn: true, section: 'Compilation')
3762
3763# snarf the cross-compilation information for tests
3764summary_info = {}
3765have_cross = false
3766foreach target: target_dirs
3767  tcg_mak = meson.current_build_dir() / 'tests/tcg' / 'config-' + target + '.mak'
3768  if fs.exists(tcg_mak)
3769    config_cross_tcg = keyval.load(tcg_mak)
3770    if 'CC' in config_cross_tcg
3771      summary_info += {config_cross_tcg['TARGET_NAME']: config_cross_tcg['CC']}
3772      have_cross = true
3773    endif
3774  endif
3775endforeach
3776if have_cross
3777  summary(summary_info, bool_yn: true, section: 'Cross compilers')
3778endif
3779
3780# Targets and accelerators
3781summary_info = {}
3782if have_system
3783  summary_info += {'KVM support':       config_all.has_key('CONFIG_KVM')}
3784  summary_info += {'HAX support':       config_all.has_key('CONFIG_HAX')}
3785  summary_info += {'HVF support':       config_all.has_key('CONFIG_HVF')}
3786  summary_info += {'WHPX support':      config_all.has_key('CONFIG_WHPX')}
3787  summary_info += {'NVMM support':      config_all.has_key('CONFIG_NVMM')}
3788  summary_info += {'Xen support':       xen.found()}
3789  if xen.found()
3790    summary_info += {'xen ctrl version':  xen.version()}
3791  endif
3792endif
3793summary_info += {'TCG support':       config_all.has_key('CONFIG_TCG')}
3794if config_all.has_key('CONFIG_TCG')
3795  if get_option('tcg_interpreter')
3796    summary_info += {'TCG backend':   'TCI (TCG with bytecode interpreter, slow)'}
3797  else
3798    summary_info += {'TCG backend':   'native (@0@)'.format(cpu)}
3799  endif
3800  summary_info += {'TCG plugins': config_host.has_key('CONFIG_PLUGIN')}
3801  summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')}
3802endif
3803summary_info += {'target list':       ' '.join(target_dirs)}
3804if have_system
3805  summary_info += {'default devices':   get_option('default_devices')}
3806  summary_info += {'out of process emulation': multiprocess_allowed}
3807  summary_info += {'vfio-user server': vfio_user_server_allowed}
3808endif
3809summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
3810
3811# Block layer
3812summary_info = {}
3813summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']}
3814summary_info += {'coroutine pool':    have_coroutine_pool}
3815if have_block
3816  summary_info += {'Block whitelist (rw)': get_option('block_drv_rw_whitelist')}
3817  summary_info += {'Block whitelist (ro)': get_option('block_drv_ro_whitelist')}
3818  summary_info += {'Use block whitelist in tools': get_option('block_drv_whitelist_in_tools')}
3819  summary_info += {'VirtFS support':    have_virtfs}
3820  summary_info += {'build virtiofs daemon': have_virtiofsd}
3821  summary_info += {'Live block migration': config_host_data.get('CONFIG_LIVE_BLOCK_MIGRATION')}
3822  summary_info += {'replication support': config_host_data.get('CONFIG_REPLICATION')}
3823  summary_info += {'bochs support':     get_option('bochs').allowed()}
3824  summary_info += {'cloop support':     get_option('cloop').allowed()}
3825  summary_info += {'dmg support':       get_option('dmg').allowed()}
3826  summary_info += {'qcow v1 support':   get_option('qcow1').allowed()}
3827  summary_info += {'vdi support':       get_option('vdi').allowed()}
3828  summary_info += {'vvfat support':     get_option('vvfat').allowed()}
3829  summary_info += {'qed support':       get_option('qed').allowed()}
3830  summary_info += {'parallels support': get_option('parallels').allowed()}
3831  summary_info += {'FUSE exports':      fuse}
3832  summary_info += {'VDUSE block exports': have_vduse_blk_export}
3833endif
3834summary(summary_info, bool_yn: true, section: 'Block layer support')
3835
3836# Crypto
3837summary_info = {}
3838summary_info += {'TLS priority':      get_option('tls_priority')}
3839summary_info += {'GNUTLS support':    gnutls}
3840if gnutls.found()
3841  summary_info += {'  GNUTLS crypto':   gnutls_crypto.found()}
3842endif
3843summary_info += {'libgcrypt':         gcrypt}
3844summary_info += {'nettle':            nettle}
3845if nettle.found()
3846   summary_info += {'  XTS':             xts != 'private'}
3847endif
3848summary_info += {'AF_ALG support':    have_afalg}
3849summary_info += {'rng-none':          get_option('rng_none')}
3850summary_info += {'Linux keyring':     have_keyring}
3851summary(summary_info, bool_yn: true, section: 'Crypto')
3852
3853# Libraries
3854summary_info = {}
3855if targetos == 'darwin'
3856  summary_info += {'Cocoa support':           cocoa}
3857  summary_info += {'vmnet.framework support': vmnet}
3858endif
3859summary_info += {'SDL support':       sdl}
3860summary_info += {'SDL image support': sdl_image}
3861summary_info += {'GTK support':       gtk}
3862summary_info += {'pixman':            pixman}
3863summary_info += {'VTE support':       vte}
3864summary_info += {'slirp support':     slirp}
3865summary_info += {'libtasn1':          tasn1}
3866summary_info += {'PAM':               pam}
3867summary_info += {'iconv support':     iconv}
3868summary_info += {'curses support':    curses}
3869summary_info += {'virgl support':     virgl}
3870summary_info += {'curl support':      curl}
3871summary_info += {'Multipath support': mpathpersist}
3872summary_info += {'PNG support':       png}
3873summary_info += {'VNC support':       vnc}
3874if vnc.found()
3875  summary_info += {'VNC SASL support':  sasl}
3876  summary_info += {'VNC JPEG support':  jpeg}
3877endif
3878if targetos not in ['darwin', 'haiku', 'windows']
3879  summary_info += {'OSS support':     oss}
3880  summary_info += {'sndio support':   sndio}
3881elif targetos == 'darwin'
3882  summary_info += {'CoreAudio support': coreaudio}
3883elif targetos == 'windows'
3884  summary_info += {'DirectSound support': dsound}
3885endif
3886if targetos == 'linux'
3887  summary_info += {'ALSA support':    alsa}
3888  summary_info += {'PulseAudio support': pulse}
3889endif
3890summary_info += {'JACK support':      jack}
3891summary_info += {'brlapi support':    brlapi}
3892summary_info += {'vde support':       vde}
3893summary_info += {'netmap support':    have_netmap}
3894summary_info += {'l2tpv3 support':    have_l2tpv3}
3895summary_info += {'Linux AIO support': libaio}
3896summary_info += {'Linux io_uring support': linux_io_uring}
3897summary_info += {'ATTR/XATTR support': libattr}
3898summary_info += {'RDMA support':      rdma}
3899summary_info += {'PVRDMA support':    have_pvrdma}
3900summary_info += {'fdt support':       fdt_opt == 'disabled' ? false : fdt_opt}
3901summary_info += {'libcap-ng support': libcap_ng}
3902summary_info += {'bpf support':       libbpf}
3903summary_info += {'spice protocol support': spice_protocol}
3904if spice_protocol.found()
3905  summary_info += {'  spice server support': spice}
3906endif
3907summary_info += {'rbd support':       rbd}
3908summary_info += {'smartcard support': cacard}
3909summary_info += {'U2F support':       u2f}
3910summary_info += {'libusb':            libusb}
3911summary_info += {'usb net redir':     usbredir}
3912summary_info += {'OpenGL support (epoxy)': opengl}
3913summary_info += {'GBM':               gbm}
3914summary_info += {'libiscsi support':  libiscsi}
3915summary_info += {'libnfs support':    libnfs}
3916if targetos == 'windows'
3917  if have_ga
3918    summary_info += {'QGA VSS support':   have_qga_vss}
3919  endif
3920endif
3921summary_info += {'seccomp support':   seccomp}
3922summary_info += {'GlusterFS support': glusterfs}
3923summary_info += {'TPM support':       have_tpm}
3924summary_info += {'libssh support':    libssh}
3925summary_info += {'lzo support':       lzo}
3926summary_info += {'snappy support':    snappy}
3927summary_info += {'bzip2 support':     libbzip2}
3928summary_info += {'lzfse support':     liblzfse}
3929summary_info += {'zstd support':      zstd}
3930summary_info += {'NUMA host support': numa}
3931summary_info += {'capstone':          capstone}
3932summary_info += {'libpmem support':   libpmem}
3933summary_info += {'libdaxctl support': libdaxctl}
3934summary_info += {'libudev':           libudev}
3935# Dummy dependency, keep .found()
3936summary_info += {'FUSE lseek':        fuse_lseek.found()}
3937summary_info += {'selinux':           selinux}
3938summary(summary_info, bool_yn: true, section: 'Dependencies')
3939
3940if not supported_cpus.contains(cpu)
3941  message()
3942  warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!')
3943  message()
3944  message('CPU host architecture ' + cpu + ' support is not currently maintained.')
3945  message('The QEMU project intends to remove support for this host CPU in')
3946  message('a future release if nobody volunteers to maintain it and to')
3947  message('provide a build host for our continuous integration setup.')
3948  message('configure has succeeded and you can continue to build, but')
3949  message('if you care about QEMU on this platform you should contact')
3950  message('us upstream at qemu-devel@nongnu.org.')
3951endif
3952
3953if not supported_oses.contains(targetos)
3954  message()
3955  warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!')
3956  message()
3957  message('Host OS ' + targetos + 'support is not currently maintained.')
3958  message('The QEMU project intends to remove support for this host OS in')
3959  message('a future release if nobody volunteers to maintain it and to')
3960  message('provide a build host for our continuous integration setup.')
3961  message('configure has succeeded and you can continue to build, but')
3962  message('if you care about QEMU on this platform you should contact')
3963  message('us upstream at qemu-devel@nongnu.org.')
3964endif
3965