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