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