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