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