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