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