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