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