xref: /openbmc/qemu/meson.build (revision ad6f932f)
1project('qemu', ['c'], meson_version: '>=0.55.0',
2        default_options: ['warning_level=1', 'c_std=gnu99', 'cpp_std=gnu++11', 'b_colorout=auto'] +
3                         (meson.version().version_compare('>=0.56.0') ? [ 'b_staticpic=false' ] : []),
4        version: run_command('head', meson.source_root() / 'VERSION').stdout().strip())
5
6not_found = dependency('', required: false)
7if meson.version().version_compare('>=0.56.0')
8  keyval = import('keyval')
9else
10  keyval = import('unstable-keyval')
11endif
12ss = import('sourceset')
13fs = import('fs')
14
15sh = find_program('sh')
16cc = meson.get_compiler('c')
17config_host = keyval.load(meson.current_build_dir() / 'config-host.mak')
18enable_modules = 'CONFIG_MODULES' in config_host
19enable_static = 'CONFIG_STATIC' in config_host
20
21# Temporary directory used for files created while
22# configure runs. Since it is in the build directory
23# we can safely blow away any previous version of it
24# (and we need not jump through hoops to try to delete
25# it when configure exits.)
26tmpdir = meson.current_build_dir() / 'meson-private/temp'
27
28if get_option('qemu_suffix').startswith('/')
29  error('qemu_suffix cannot start with a /')
30endif
31
32qemu_confdir = get_option('sysconfdir') / get_option('qemu_suffix')
33qemu_datadir = get_option('datadir') / get_option('qemu_suffix')
34qemu_docdir = get_option('docdir') / get_option('qemu_suffix')
35qemu_moddir = get_option('libdir') / get_option('qemu_suffix')
36
37qemu_desktopdir = get_option('datadir') / 'applications'
38qemu_icondir = get_option('datadir') / 'icons'
39
40config_host_data = configuration_data()
41genh = []
42
43target_dirs = config_host['TARGET_DIRS'].split()
44have_user = false
45have_system = false
46foreach target : target_dirs
47  have_user = have_user or target.endswith('-user')
48  have_system = have_system or target.endswith('-softmmu')
49endforeach
50have_tools = 'CONFIG_TOOLS' in config_host
51have_block = have_system or have_tools
52
53python = import('python').find_installation()
54
55supported_oses = ['windows', 'freebsd', 'netbsd', 'openbsd', 'darwin', 'sunos', 'linux']
56supported_cpus = ['ppc', 'ppc64', 's390x', 'riscv32', 'riscv64', 'x86', 'x86_64',
57  'arm', 'aarch64', 'mips', 'mips64', 'sparc', 'sparc64']
58
59cpu = host_machine.cpu_family()
60targetos = host_machine.system()
61
62if cpu in ['x86', 'x86_64']
63  kvm_targets = ['i386-softmmu', 'x86_64-softmmu']
64elif cpu == 'aarch64'
65  kvm_targets = ['aarch64-softmmu']
66elif cpu == 's390x'
67  kvm_targets = ['s390x-softmmu']
68elif cpu in ['ppc', 'ppc64']
69  kvm_targets = ['ppc-softmmu', 'ppc64-softmmu']
70elif cpu in ['mips', 'mips64']
71  kvm_targets = ['mips-softmmu', 'mipsel-softmmu', 'mips64-softmmu', 'mips64el-softmmu']
72else
73  kvm_targets = []
74endif
75
76accelerator_targets = { 'CONFIG_KVM': kvm_targets }
77if cpu in ['x86', 'x86_64', 'arm', 'aarch64']
78  # i368 emulator provides xenpv machine type for multiple architectures
79  accelerator_targets += {
80    'CONFIG_XEN': ['i386-softmmu', 'x86_64-softmmu'],
81  }
82endif
83if cpu in ['x86', 'x86_64']
84  accelerator_targets += {
85    'CONFIG_HAX': ['i386-softmmu', 'x86_64-softmmu'],
86    'CONFIG_HVF': ['x86_64-softmmu'],
87    'CONFIG_WHPX': ['i386-softmmu', 'x86_64-softmmu'],
88  }
89endif
90
91##################
92# Compiler flags #
93##################
94
95# Specify linker-script with add_project_link_arguments so that it is not placed
96# within a linker --start-group/--end-group pair
97if 'CONFIG_FUZZ' in config_host
98   add_project_link_arguments(['-Wl,-T,',
99                               (meson.current_source_dir() / 'tests/qtest/fuzz/fork_fuzz.ld')],
100                              native: false, language: ['c', 'cpp', 'objc'])
101endif
102
103add_project_arguments(config_host['QEMU_CFLAGS'].split(),
104                      native: false, language: ['c', 'objc'])
105add_project_arguments(config_host['QEMU_CXXFLAGS'].split(),
106                      native: false, language: 'cpp')
107add_project_link_arguments(config_host['QEMU_LDFLAGS'].split(),
108                           native: false, language: ['c', 'cpp', 'objc'])
109
110if targetos == 'linux'
111  add_project_arguments('-isystem', meson.current_source_dir() / 'linux-headers',
112                        '-isystem', 'linux-headers',
113                        language: ['c', 'cpp'])
114endif
115
116if 'CONFIG_TCG_INTERPRETER' in config_host
117  tcg_arch = 'tci'
118elif config_host['ARCH'] == 'sparc64'
119  tcg_arch = 'sparc'
120elif config_host['ARCH'] == 's390x'
121  tcg_arch = 's390'
122elif config_host['ARCH'] in ['x86_64', 'x32']
123  tcg_arch = 'i386'
124elif config_host['ARCH'] == 'ppc64'
125  tcg_arch = 'ppc'
126elif config_host['ARCH'] in ['riscv32', 'riscv64']
127  tcg_arch = 'riscv'
128else
129  tcg_arch = config_host['ARCH']
130endif
131add_project_arguments('-iquote', meson.current_source_dir() / 'tcg' / tcg_arch,
132                      '-iquote', '.',
133                      '-iquote', meson.current_source_dir(),
134                      '-iquote', meson.current_source_dir() / 'accel/tcg',
135                      '-iquote', meson.current_source_dir() / 'include',
136                      '-iquote', meson.current_source_dir() / 'disas/libvixl',
137                      language: ['c', 'cpp', 'objc'])
138
139link_language = meson.get_external_property('link_language', 'cpp')
140if link_language == 'cpp'
141  add_languages('cpp', required: true, native: false)
142endif
143if host_machine.system() == 'darwin'
144  add_languages('objc', required: false, native: false)
145endif
146
147sparse = find_program('cgcc', required: get_option('sparse'))
148if sparse.found()
149  run_target('sparse',
150             command: [find_program('scripts/check_sparse.py'),
151                       'compile_commands.json', sparse.full_path(), '-Wbitwise',
152                       '-Wno-transparent-union', '-Wno-old-initializer',
153                       '-Wno-non-pointer-null'])
154endif
155
156###########################################
157# Target-specific checks and dependencies #
158###########################################
159
160if targetos != 'linux' and get_option('mpath').enabled()
161  error('Multipath is supported only on Linux')
162endif
163
164m = cc.find_library('m', required: false)
165util = cc.find_library('util', required: false)
166winmm = []
167socket = []
168version_res = []
169coref = []
170iokit = []
171emulator_link_args = []
172cocoa = not_found
173hvf = not_found
174if targetos == 'windows'
175  socket = cc.find_library('ws2_32')
176  winmm = cc.find_library('winmm')
177
178  win = import('windows')
179  version_res = win.compile_resources('version.rc',
180                                      depend_files: files('pc-bios/qemu-nsis.ico'),
181                                      include_directories: include_directories('.'))
182elif targetos == 'darwin'
183  coref = dependency('appleframeworks', modules: 'CoreFoundation')
184  iokit = dependency('appleframeworks', modules: 'IOKit')
185  cocoa = dependency('appleframeworks', modules: 'Cocoa', required: get_option('cocoa'))
186elif targetos == 'sunos'
187  socket = [cc.find_library('socket'),
188            cc.find_library('nsl'),
189            cc.find_library('resolv')]
190elif targetos == 'haiku'
191  socket = [cc.find_library('posix_error_mapper'),
192            cc.find_library('network'),
193            cc.find_library('bsd')]
194elif targetos == 'openbsd'
195  if not get_option('tcg').disabled() and target_dirs.length() > 0
196    # Disable OpenBSD W^X if available
197    emulator_link_args = cc.get_supported_link_arguments('-Wl,-z,wxneeded')
198  endif
199endif
200
201accelerators = []
202if not get_option('kvm').disabled() and targetos == 'linux'
203  accelerators += 'CONFIG_KVM'
204endif
205if not get_option('xen').disabled() and 'CONFIG_XEN_BACKEND' in config_host
206  accelerators += 'CONFIG_XEN'
207  have_xen_pci_passthrough = not get_option('xen_pci_passthrough').disabled() and targetos == 'linux'
208else
209  have_xen_pci_passthrough = false
210endif
211if not get_option('whpx').disabled() and targetos == 'windows'
212  if get_option('whpx').enabled() and host_machine.cpu() != 'x86_64'
213    error('WHPX requires 64-bit host')
214  elif cc.has_header('WinHvPlatform.h', required: get_option('whpx')) and \
215       cc.has_header('WinHvEmulation.h', required: get_option('whpx'))
216    accelerators += 'CONFIG_WHPX'
217  endif
218endif
219if not get_option('hvf').disabled()
220  hvf = dependency('appleframeworks', modules: 'Hypervisor',
221                   required: get_option('hvf'))
222  if hvf.found()
223    accelerators += 'CONFIG_HVF'
224  endif
225endif
226if not get_option('hax').disabled()
227  if get_option('hax').enabled() or targetos in ['windows', 'darwin', 'netbsd']
228    accelerators += 'CONFIG_HAX'
229  endif
230endif
231if not get_option('tcg').disabled()
232  if cpu not in supported_cpus
233    if 'CONFIG_TCG_INTERPRETER' in config_host
234      warning('Unsupported CPU @0@, will use TCG with TCI (experimental)'.format(cpu))
235    else
236      error('Unsupported CPU @0@, try --enable-tcg-interpreter'.format(cpu))
237    endif
238  endif
239  accelerators += 'CONFIG_TCG'
240  config_host += { 'CONFIG_TCG': 'y' }
241endif
242
243if 'CONFIG_KVM' not in accelerators and get_option('kvm').enabled()
244  error('KVM not available on this platform')
245endif
246if 'CONFIG_HVF' not in accelerators and get_option('hvf').enabled()
247  error('HVF not available on this platform')
248endif
249if 'CONFIG_WHPX' not in accelerators and get_option('whpx').enabled()
250  error('WHPX not available on this platform')
251endif
252if not have_xen_pci_passthrough and get_option('xen_pci_passthrough').enabled()
253  if 'CONFIG_XEN' in accelerators
254    error('Xen PCI passthrough not available on this platform')
255  else
256    error('Xen PCI passthrough requested but Xen not enabled')
257  endif
258endif
259if not cocoa.found() and get_option('cocoa').enabled()
260  error('Cocoa not available on this platform')
261endif
262
263################
264# Dependencies #
265################
266
267# The path to glib.h is added to all compilation commands.  This was
268# grandfathered in from the QEMU Makefiles.
269add_project_arguments(config_host['GLIB_CFLAGS'].split(),
270                      native: false, language: ['c', 'cpp', 'objc'])
271glib = declare_dependency(link_args: config_host['GLIB_LIBS'].split())
272gio = not_found
273if 'CONFIG_GIO' in config_host
274  gio = declare_dependency(compile_args: config_host['GIO_CFLAGS'].split(),
275                           link_args: config_host['GIO_LIBS'].split())
276endif
277lttng = not_found
278if 'CONFIG_TRACE_UST' in config_host
279  lttng = declare_dependency(link_args: config_host['LTTNG_UST_LIBS'].split())
280endif
281urcubp = not_found
282if 'CONFIG_TRACE_UST' in config_host
283  urcubp = declare_dependency(link_args: config_host['URCU_BP_LIBS'].split())
284endif
285gcrypt = not_found
286if 'CONFIG_GCRYPT' in config_host
287  gcrypt = declare_dependency(compile_args: config_host['GCRYPT_CFLAGS'].split(),
288                              link_args: config_host['GCRYPT_LIBS'].split())
289endif
290nettle = not_found
291if 'CONFIG_NETTLE' in config_host
292  nettle = declare_dependency(compile_args: config_host['NETTLE_CFLAGS'].split(),
293                              link_args: config_host['NETTLE_LIBS'].split())
294endif
295gnutls = not_found
296if 'CONFIG_GNUTLS' in config_host
297  gnutls = declare_dependency(compile_args: config_host['GNUTLS_CFLAGS'].split(),
298                              link_args: config_host['GNUTLS_LIBS'].split())
299endif
300pixman = not_found
301if have_system or have_tools
302  pixman = dependency('pixman-1', required: have_system, version:'>=0.21.8',
303                      method: 'pkg-config', static: enable_static)
304endif
305pam = not_found
306if 'CONFIG_AUTH_PAM' in config_host
307  pam = cc.find_library('pam')
308endif
309libaio = cc.find_library('aio', required: false)
310zlib = dependency('zlib', required: true, static: enable_static)
311linux_io_uring = not_found
312if 'CONFIG_LINUX_IO_URING' in config_host
313  linux_io_uring = declare_dependency(compile_args: config_host['LINUX_IO_URING_CFLAGS'].split(),
314                                      link_args: config_host['LINUX_IO_URING_LIBS'].split())
315endif
316libxml2 = not_found
317if 'CONFIG_LIBXML2' in config_host
318  libxml2 = declare_dependency(compile_args: config_host['LIBXML2_CFLAGS'].split(),
319                               link_args: config_host['LIBXML2_LIBS'].split())
320endif
321libnfs = not_found
322if 'CONFIG_LIBNFS' in config_host
323  libnfs = declare_dependency(link_args: config_host['LIBNFS_LIBS'].split())
324endif
325libattr = not_found
326if 'CONFIG_ATTR' in config_host
327  libattr = declare_dependency(link_args: config_host['LIBATTR_LIBS'].split())
328endif
329seccomp = not_found
330if 'CONFIG_SECCOMP' in config_host
331  seccomp = declare_dependency(compile_args: config_host['SECCOMP_CFLAGS'].split(),
332                               link_args: config_host['SECCOMP_LIBS'].split())
333endif
334libcap_ng = not_found
335if 'CONFIG_LIBCAP_NG' in config_host
336  libcap_ng = declare_dependency(link_args: config_host['LIBCAP_NG_LIBS'].split())
337endif
338if get_option('xkbcommon').auto() and not have_system and not have_tools
339  xkbcommon = not_found
340else
341  xkbcommon = dependency('xkbcommon', required: get_option('xkbcommon'),
342                         method: 'pkg-config', static: enable_static)
343endif
344vde = not_found
345if config_host.has_key('CONFIG_VDE')
346  vde = declare_dependency(link_args: config_host['VDE_LIBS'].split())
347endif
348pulse = not_found
349if 'CONFIG_LIBPULSE' in config_host
350  pulse = declare_dependency(compile_args: config_host['PULSE_CFLAGS'].split(),
351                             link_args: config_host['PULSE_LIBS'].split())
352endif
353alsa = not_found
354if 'CONFIG_ALSA' in config_host
355  alsa = declare_dependency(compile_args: config_host['ALSA_CFLAGS'].split(),
356                            link_args: config_host['ALSA_LIBS'].split())
357endif
358jack = not_found
359if 'CONFIG_LIBJACK' in config_host
360  jack = declare_dependency(link_args: config_host['JACK_LIBS'].split())
361endif
362spice = not_found
363spice_headers = not_found
364if 'CONFIG_SPICE' in config_host
365  spice = declare_dependency(compile_args: config_host['SPICE_CFLAGS'].split(),
366                             link_args: config_host['SPICE_LIBS'].split())
367  spice_headers = declare_dependency(compile_args: config_host['SPICE_CFLAGS'].split())
368endif
369rt = cc.find_library('rt', required: false)
370libdl = not_found
371if 'CONFIG_PLUGIN' in config_host
372  libdl = cc.find_library('dl', required: true)
373endif
374libiscsi = not_found
375if 'CONFIG_LIBISCSI' in config_host
376  libiscsi = declare_dependency(compile_args: config_host['LIBISCSI_CFLAGS'].split(),
377                                link_args: config_host['LIBISCSI_LIBS'].split())
378endif
379zstd = not_found
380if 'CONFIG_ZSTD' in config_host
381  zstd = declare_dependency(compile_args: config_host['ZSTD_CFLAGS'].split(),
382                            link_args: config_host['ZSTD_LIBS'].split())
383endif
384gbm = not_found
385if 'CONFIG_GBM' in config_host
386  gbm = declare_dependency(compile_args: config_host['GBM_CFLAGS'].split(),
387                           link_args: config_host['GBM_LIBS'].split())
388endif
389virgl = not_found
390if 'CONFIG_VIRGL' in config_host
391  virgl = declare_dependency(compile_args: config_host['VIRGL_CFLAGS'].split(),
392                             link_args: config_host['VIRGL_LIBS'].split())
393endif
394curl = not_found
395if 'CONFIG_CURL' in config_host
396  curl = declare_dependency(compile_args: config_host['CURL_CFLAGS'].split(),
397                            link_args: config_host['CURL_LIBS'].split())
398endif
399libudev = not_found
400if targetos == 'linux' and (have_system or have_tools)
401  libudev = dependency('libudev',
402                       required: get_option('libudev'),
403                       static: enable_static)
404endif
405
406mpathlibs = [libudev]
407mpathpersist = not_found
408mpathpersist_new_api = false
409if targetos == 'linux' and have_tools and not get_option('mpath').disabled()
410  mpath_test_source_new = '''
411    #include <libudev.h>
412    #include <mpath_persist.h>
413    unsigned mpath_mx_alloc_len = 1024;
414    int logsink;
415    static struct config *multipath_conf;
416    extern struct udev *udev;
417    extern struct config *get_multipath_config(void);
418    extern void put_multipath_config(struct config *conf);
419    struct udev *udev;
420    struct config *get_multipath_config(void) { return multipath_conf; }
421    void put_multipath_config(struct config *conf) { }
422    int main(void) {
423        udev = udev_new();
424        multipath_conf = mpath_lib_init();
425        return 0;
426    }'''
427  mpath_test_source_old = '''
428      #include <libudev.h>
429      #include <mpath_persist.h>
430      unsigned mpath_mx_alloc_len = 1024;
431      int logsink;
432      int main(void) {
433          struct udev *udev = udev_new();
434          mpath_lib_init(udev);
435          return 0;
436      }'''
437  libmpathpersist = cc.find_library('mpathpersist',
438                                    required: get_option('mpath'),
439                                    static: enable_static)
440  if libmpathpersist.found()
441    mpathlibs += libmpathpersist
442    if enable_static
443      mpathlibs += cc.find_library('devmapper',
444                                     required: get_option('mpath'),
445                                     static: enable_static)
446    endif
447    mpathlibs += cc.find_library('multipath',
448                                 required: get_option('mpath'),
449                                 static: enable_static)
450    foreach lib: mpathlibs
451      if not lib.found()
452        mpathlibs = []
453        break
454      endif
455    endforeach
456    if mpathlibs.length() == 0
457      msg = 'Dependencies missing for libmpathpersist'
458    elif cc.links(mpath_test_source_new, dependencies: mpathlibs)
459      mpathpersist = declare_dependency(dependencies: mpathlibs)
460      mpathpersist_new_api = true
461    elif cc.links(mpath_test_source_old, dependencies: mpathlibs)
462      mpathpersist = declare_dependency(dependencies: mpathlibs)
463    else
464      msg = 'Cannot detect libmpathpersist API'
465    endif
466    if not mpathpersist.found()
467      if get_option('mpath').enabled()
468        error(msg)
469      else
470        warning(msg + ', disabling')
471      endif
472    endif
473  endif
474endif
475
476iconv = not_found
477curses = not_found
478if have_system and not get_option('curses').disabled()
479  curses_test = '''
480    #include <locale.h>
481    #include <curses.h>
482    #include <wchar.h>
483    int main(void) {
484      wchar_t wch = L'w';
485      setlocale(LC_ALL, "");
486      resize_term(0, 0);
487      addwstr(L"wide chars\n");
488      addnwstr(&wch, 1);
489      add_wch(WACS_DEGREE);
490      return 0;
491    }'''
492
493  curses_dep_list = targetos == 'windows' ? ['ncurses', 'ncursesw'] : ['ncursesw']
494  foreach curses_dep : curses_dep_list
495    if not curses.found()
496      curses = dependency(curses_dep,
497                          required: false,
498                          method: 'pkg-config',
499                          static: enable_static)
500    endif
501  endforeach
502  msg = get_option('curses').enabled() ? 'curses library not found' : ''
503  if curses.found()
504    if cc.links(curses_test, dependencies: [curses])
505      curses = declare_dependency(compile_args: '-DNCURSES_WIDECHAR', dependencies: [curses])
506    else
507      msg = 'curses package not usable'
508      curses = not_found
509    endif
510  endif
511  if not curses.found()
512    curses_compile_args = ['-DNCURSES_WIDECHAR']
513    has_curses_h = cc.has_header('curses.h', args: curses_compile_args)
514    if targetos != 'windows' and not has_curses_h
515      message('Trying with /usr/include/ncursesw')
516      curses_compile_args += ['-I/usr/include/ncursesw']
517      has_curses_h = cc.has_header('curses.h', args: curses_compile_args)
518    endif
519    if has_curses_h
520      curses_libname_list = (targetos == 'windows' ? ['pdcurses'] : ['ncursesw', 'cursesw'])
521      foreach curses_libname : curses_libname_list
522        libcurses = cc.find_library(curses_libname,
523                                    required: false,
524                                    static: enable_static)
525        if libcurses.found()
526          if cc.links(curses_test, args: curses_compile_args, dependencies: libcurses)
527            curses = declare_dependency(compile_args: curses_compile_args,
528                                        dependencies: [libcurses])
529            break
530          else
531            msg = 'curses library not usable'
532          endif
533        endif
534      endforeach
535    endif
536  endif
537  if not get_option('iconv').disabled()
538    foreach link_args : [ ['-liconv'], [] ]
539      # Programs will be linked with glib and this will bring in libiconv on FreeBSD.
540      # We need to use libiconv if available because mixing libiconv's headers with
541      # the system libc does not work.
542      # However, without adding glib to the dependencies -L/usr/local/lib will not be
543      # included in the command line and libiconv will not be found.
544      if cc.links('''
545        #include <iconv.h>
546        int main(void) {
547          iconv_t conv = iconv_open("WCHAR_T", "UCS-2");
548          return conv != (iconv_t) -1;
549        }''', args: config_host['GLIB_CFLAGS'].split() + config_host['GLIB_LIBS'].split() + link_args)
550        iconv = declare_dependency(link_args: link_args, dependencies: glib)
551        break
552      endif
553    endforeach
554  endif
555  if curses.found() and not iconv.found()
556    if get_option('iconv').enabled()
557      error('iconv not available')
558    endif
559    msg = 'iconv required for curses UI but not available'
560    curses = not_found
561  endif
562  if not curses.found() and msg != ''
563    if get_option('curses').enabled()
564      error(msg)
565    else
566      warning(msg + ', disabling')
567    endif
568  endif
569endif
570
571brlapi = not_found
572if 'CONFIG_BRLAPI' in config_host
573  brlapi = declare_dependency(link_args: config_host['BRLAPI_LIBS'].split())
574endif
575
576sdl = not_found
577if have_system
578  sdl = dependency('sdl2', required: get_option('sdl'), static: enable_static)
579  sdl_image = not_found
580endif
581if sdl.found()
582  # work around 2.0.8 bug
583  sdl = declare_dependency(compile_args: '-Wno-undef',
584                           dependencies: sdl)
585  sdl_image = dependency('SDL2_image', required: get_option('sdl_image'),
586                         method: 'pkg-config', static: enable_static)
587else
588  if get_option('sdl_image').enabled()
589    error('sdl-image required, but SDL was @0@'.format(
590          get_option('sdl').disabled() ? 'disabled' : 'not found'))
591  endif
592  sdl_image = not_found
593endif
594
595rbd = not_found
596if 'CONFIG_RBD' in config_host
597  rbd = declare_dependency(link_args: config_host['RBD_LIBS'].split())
598endif
599glusterfs = not_found
600if 'CONFIG_GLUSTERFS' in config_host
601  glusterfs = declare_dependency(compile_args: config_host['GLUSTERFS_CFLAGS'].split(),
602                                 link_args: config_host['GLUSTERFS_LIBS'].split())
603endif
604libssh = not_found
605if 'CONFIG_LIBSSH' in config_host
606  libssh = declare_dependency(compile_args: config_host['LIBSSH_CFLAGS'].split(),
607                              link_args: config_host['LIBSSH_LIBS'].split())
608endif
609libbzip2 = not_found
610if 'CONFIG_BZIP2' in config_host
611  libbzip2 = declare_dependency(link_args: config_host['BZIP2_LIBS'].split())
612endif
613liblzfse = not_found
614if 'CONFIG_LZFSE' in config_host
615  liblzfse = declare_dependency(link_args: config_host['LZFSE_LIBS'].split())
616endif
617oss = not_found
618if 'CONFIG_AUDIO_OSS' in config_host
619  oss = declare_dependency(link_args: config_host['OSS_LIBS'].split())
620endif
621dsound = not_found
622if 'CONFIG_AUDIO_DSOUND' in config_host
623  dsound = declare_dependency(link_args: config_host['DSOUND_LIBS'].split())
624endif
625coreaudio = not_found
626if 'CONFIG_AUDIO_COREAUDIO' in config_host
627  coreaudio = declare_dependency(link_args: config_host['COREAUDIO_LIBS'].split())
628endif
629opengl = not_found
630if 'CONFIG_OPENGL' in config_host
631  opengl = declare_dependency(compile_args: config_host['OPENGL_CFLAGS'].split(),
632                              link_args: config_host['OPENGL_LIBS'].split())
633endif
634gtk = not_found
635if 'CONFIG_GTK' in config_host
636  gtk = declare_dependency(compile_args: config_host['GTK_CFLAGS'].split(),
637                              link_args: config_host['GTK_LIBS'].split())
638endif
639vte = not_found
640if 'CONFIG_VTE' in config_host
641  vte = declare_dependency(compile_args: config_host['VTE_CFLAGS'].split(),
642                           link_args: config_host['VTE_LIBS'].split())
643endif
644x11 = not_found
645if 'CONFIG_X11' in config_host
646  x11 = declare_dependency(compile_args: config_host['X11_CFLAGS'].split(),
647                           link_args: config_host['X11_LIBS'].split())
648endif
649vnc = not_found
650png = not_found
651jpeg = not_found
652sasl = not_found
653if get_option('vnc').enabled()
654  vnc = declare_dependency() # dummy dependency
655  png = dependency('libpng', required: get_option('vnc_png'),
656                   method: 'pkg-config', static: enable_static)
657  jpeg = cc.find_library('jpeg', has_headers: ['jpeglib.h'],
658                         required: get_option('vnc_jpeg'),
659                         static: enable_static)
660  sasl = cc.find_library('sasl2', has_headers: ['sasl/sasl.h'],
661                         required: get_option('vnc_sasl'),
662                         static: enable_static)
663  if sasl.found()
664    sasl = declare_dependency(dependencies: sasl,
665                              compile_args: '-DSTRUCT_IOVEC_DEFINED')
666  endif
667endif
668snappy = not_found
669if 'CONFIG_SNAPPY' in config_host
670  snappy = declare_dependency(link_args: config_host['SNAPPY_LIBS'].split())
671endif
672lzo = not_found
673if 'CONFIG_LZO' in config_host
674  lzo = declare_dependency(link_args: config_host['LZO_LIBS'].split())
675endif
676rdma = not_found
677if 'CONFIG_RDMA' in config_host
678  rdma = declare_dependency(link_args: config_host['RDMA_LIBS'].split())
679endif
680numa = not_found
681if 'CONFIG_NUMA' in config_host
682  numa = declare_dependency(link_args: config_host['NUMA_LIBS'].split())
683endif
684xen = not_found
685if 'CONFIG_XEN_BACKEND' in config_host
686  xen = declare_dependency(compile_args: config_host['XEN_CFLAGS'].split(),
687                           link_args: config_host['XEN_LIBS'].split())
688endif
689cacard = not_found
690if 'CONFIG_SMARTCARD' in config_host
691  cacard = declare_dependency(compile_args: config_host['SMARTCARD_CFLAGS'].split(),
692                              link_args: config_host['SMARTCARD_LIBS'].split())
693endif
694u2f = not_found
695if have_system
696  u2f = dependency('u2f-emu', required: get_option('u2f'),
697                   method: 'pkg-config',
698                   static: enable_static)
699endif
700usbredir = not_found
701if 'CONFIG_USB_REDIR' in config_host
702  usbredir = declare_dependency(compile_args: config_host['USB_REDIR_CFLAGS'].split(),
703                                link_args: config_host['USB_REDIR_LIBS'].split())
704endif
705libusb = not_found
706if 'CONFIG_USB_LIBUSB' in config_host
707  libusb = declare_dependency(compile_args: config_host['LIBUSB_CFLAGS'].split(),
708                              link_args: config_host['LIBUSB_LIBS'].split())
709endif
710libpmem = not_found
711if 'CONFIG_LIBPMEM' in config_host
712  libpmem = declare_dependency(compile_args: config_host['LIBPMEM_CFLAGS'].split(),
713                               link_args: config_host['LIBPMEM_LIBS'].split())
714endif
715libdaxctl = not_found
716if 'CONFIG_LIBDAXCTL' in config_host
717  libdaxctl = declare_dependency(link_args: config_host['LIBDAXCTL_LIBS'].split())
718endif
719tasn1 = not_found
720if 'CONFIG_TASN1' in config_host
721  tasn1 = declare_dependency(compile_args: config_host['TASN1_CFLAGS'].split(),
722                             link_args: config_host['TASN1_LIBS'].split())
723endif
724keyutils = dependency('libkeyutils', required: false,
725                      method: 'pkg-config', static: enable_static)
726
727has_gettid = cc.has_function('gettid')
728
729# Malloc tests
730
731malloc = []
732if get_option('malloc') == 'system'
733  has_malloc_trim = \
734    not get_option('malloc_trim').disabled() and \
735    cc.links('''#include <malloc.h>
736                int main(void) { malloc_trim(0); return 0; }''')
737else
738  has_malloc_trim = false
739  malloc = cc.find_library(get_option('malloc'), required: true)
740endif
741if not has_malloc_trim and get_option('malloc_trim').enabled()
742  if get_option('malloc') == 'system'
743    error('malloc_trim not available on this platform.')
744  else
745    error('malloc_trim not available with non-libc memory allocator')
746  endif
747endif
748
749# Check whether the glibc provides statx()
750
751statx_test = '''
752  #ifndef _GNU_SOURCE
753  #define _GNU_SOURCE
754  #endif
755  #include <sys/stat.h>
756  int main(void) {
757    struct statx statxbuf;
758    statx(0, "", 0, STATX_BASIC_STATS, &statxbuf);
759    return 0;
760  }'''
761
762has_statx = cc.links(statx_test)
763
764have_vhost_user_blk_server = (targetos == 'linux' and
765    'CONFIG_VHOST_USER' in config_host)
766
767if get_option('vhost_user_blk_server').enabled()
768    if targetos != 'linux'
769        error('vhost_user_blk_server requires linux')
770    elif 'CONFIG_VHOST_USER' not in config_host
771        error('vhost_user_blk_server requires vhost-user support')
772    endif
773elif get_option('vhost_user_blk_server').disabled() or not have_system
774    have_vhost_user_blk_server = false
775endif
776
777#################
778# config-host.h #
779#################
780
781config_host_data.set_quoted('CONFIG_BINDIR', get_option('prefix') / get_option('bindir'))
782config_host_data.set_quoted('CONFIG_PREFIX', get_option('prefix'))
783config_host_data.set_quoted('CONFIG_QEMU_CONFDIR', get_option('prefix') / qemu_confdir)
784config_host_data.set_quoted('CONFIG_QEMU_DATADIR', get_option('prefix') / qemu_datadir)
785config_host_data.set_quoted('CONFIG_QEMU_DESKTOPDIR', get_option('prefix') / qemu_desktopdir)
786config_host_data.set_quoted('CONFIG_QEMU_FIRMWAREPATH', get_option('qemu_firmwarepath'))
787config_host_data.set_quoted('CONFIG_QEMU_HELPERDIR', get_option('prefix') / get_option('libexecdir'))
788config_host_data.set_quoted('CONFIG_QEMU_ICONDIR', get_option('prefix') / qemu_icondir)
789config_host_data.set_quoted('CONFIG_QEMU_LOCALEDIR', get_option('prefix') / get_option('localedir'))
790config_host_data.set_quoted('CONFIG_QEMU_LOCALSTATEDIR', get_option('prefix') / get_option('localstatedir'))
791config_host_data.set_quoted('CONFIG_QEMU_MODDIR', get_option('prefix') / qemu_moddir)
792config_host_data.set_quoted('CONFIG_SYSCONFDIR', get_option('prefix') / get_option('sysconfdir'))
793
794config_host_data.set('CONFIG_COCOA', cocoa.found())
795config_host_data.set('CONFIG_LIBUDEV', libudev.found())
796config_host_data.set('CONFIG_MPATH', mpathpersist.found())
797config_host_data.set('CONFIG_MPATH_NEW_API', mpathpersist_new_api)
798config_host_data.set('CONFIG_CURSES', curses.found())
799config_host_data.set('CONFIG_SDL', sdl.found())
800config_host_data.set('CONFIG_SDL_IMAGE', sdl_image.found())
801config_host_data.set('CONFIG_VHOST_USER_BLK_SERVER', have_vhost_user_blk_server)
802config_host_data.set('CONFIG_VNC', vnc.found())
803config_host_data.set('CONFIG_VNC_JPEG', jpeg.found())
804config_host_data.set('CONFIG_VNC_PNG', png.found())
805config_host_data.set('CONFIG_VNC_SASL', sasl.found())
806config_host_data.set('CONFIG_XKBCOMMON', xkbcommon.found())
807config_host_data.set('CONFIG_KEYUTILS', keyutils.found())
808config_host_data.set('CONFIG_GETTID', has_gettid)
809config_host_data.set('CONFIG_MALLOC_TRIM', has_malloc_trim)
810config_host_data.set('CONFIG_STATX', has_statx)
811config_host_data.set('QEMU_VERSION', '"@0@"'.format(meson.project_version()))
812config_host_data.set('QEMU_VERSION_MAJOR', meson.project_version().split('.')[0])
813config_host_data.set('QEMU_VERSION_MINOR', meson.project_version().split('.')[1])
814config_host_data.set('QEMU_VERSION_MICRO', meson.project_version().split('.')[2])
815
816config_host_data.set('HAVE_SYS_IOCCOM_H', cc.has_header('sys/ioccom.h'))
817
818ignored = ['CONFIG_QEMU_INTERP_PREFIX'] # actually per-target
819arrays = ['CONFIG_AUDIO_DRIVERS', 'CONFIG_BDRV_RW_WHITELIST', 'CONFIG_BDRV_RO_WHITELIST']
820strings = ['HOST_DSOSUF', 'CONFIG_IASL']
821foreach k, v: config_host
822  if ignored.contains(k)
823    # do nothing
824  elif arrays.contains(k)
825    if v != ''
826      v = '"' + '", "'.join(v.split()) + '", '
827    endif
828    config_host_data.set(k, v)
829  elif k == 'ARCH'
830    config_host_data.set('HOST_' + v.to_upper(), 1)
831  elif strings.contains(k)
832    if not k.startswith('CONFIG_')
833      k = 'CONFIG_' + k.to_upper()
834    endif
835    config_host_data.set_quoted(k, v)
836  elif k.startswith('CONFIG_') or k.startswith('HAVE_') or k.startswith('HOST_')
837    config_host_data.set(k, v == 'y' ? 1 : v)
838  endif
839endforeach
840
841########################
842# Target configuration #
843########################
844
845minikconf = find_program('scripts/minikconf.py')
846config_all = {}
847config_all_devices = {}
848config_all_disas = {}
849config_devices_mak_list = []
850config_devices_h = {}
851config_target_h = {}
852config_target_mak = {}
853
854disassemblers = {
855  'alpha' : ['CONFIG_ALPHA_DIS'],
856  'arm' : ['CONFIG_ARM_DIS'],
857  'avr' : ['CONFIG_AVR_DIS'],
858  'cris' : ['CONFIG_CRIS_DIS'],
859  'hppa' : ['CONFIG_HPPA_DIS'],
860  'i386' : ['CONFIG_I386_DIS'],
861  'x86_64' : ['CONFIG_I386_DIS'],
862  'x32' : ['CONFIG_I386_DIS'],
863  'lm32' : ['CONFIG_LM32_DIS'],
864  'm68k' : ['CONFIG_M68K_DIS'],
865  'microblaze' : ['CONFIG_MICROBLAZE_DIS'],
866  'mips' : ['CONFIG_MIPS_DIS'],
867  'moxie' : ['CONFIG_MOXIE_DIS'],
868  'nios2' : ['CONFIG_NIOS2_DIS'],
869  'or1k' : ['CONFIG_OPENRISC_DIS'],
870  'ppc' : ['CONFIG_PPC_DIS'],
871  'riscv' : ['CONFIG_RISCV_DIS'],
872  'rx' : ['CONFIG_RX_DIS'],
873  's390' : ['CONFIG_S390_DIS'],
874  'sh4' : ['CONFIG_SH4_DIS'],
875  'sparc' : ['CONFIG_SPARC_DIS'],
876  'xtensa' : ['CONFIG_XTENSA_DIS'],
877}
878if link_language == 'cpp'
879  disassemblers += {
880    'aarch64' : [ 'CONFIG_ARM_A64_DIS'],
881    'arm' : [ 'CONFIG_ARM_DIS', 'CONFIG_ARM_A64_DIS'],
882    'mips' : [ 'CONFIG_MIPS_DIS', 'CONFIG_NANOMIPS_DIS'],
883  }
884endif
885
886kconfig_external_symbols = [
887  'CONFIG_KVM',
888  'CONFIG_XEN',
889  'CONFIG_TPM',
890  'CONFIG_SPICE',
891  'CONFIG_IVSHMEM',
892  'CONFIG_OPENGL',
893  'CONFIG_X11',
894  'CONFIG_VHOST_USER',
895  'CONFIG_VHOST_VDPA',
896  'CONFIG_VHOST_KERNEL',
897  'CONFIG_VIRTFS',
898  'CONFIG_LINUX',
899  'CONFIG_PVRDMA',
900]
901ignored = [ 'TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_ARCH' ]
902
903default_targets = 'CONFIG_DEFAULT_TARGETS' in config_host
904actual_target_dirs = []
905fdt_required = []
906foreach target : target_dirs
907  config_target = { 'TARGET_NAME': target.split('-')[0] }
908  if target.endswith('linux-user')
909    if targetos != 'linux'
910      if default_targets
911        continue
912      endif
913      error('Target @0@ is only available on a Linux host'.format(target))
914    endif
915    config_target += { 'CONFIG_LINUX_USER': 'y' }
916  elif target.endswith('bsd-user')
917    if 'CONFIG_BSD' not in config_host
918      if default_targets
919        continue
920      endif
921      error('Target @0@ is only available on a BSD host'.format(target))
922    endif
923    config_target += { 'CONFIG_BSD_USER': 'y' }
924  elif target.endswith('softmmu')
925    config_target += { 'CONFIG_SOFTMMU': 'y' }
926  endif
927  if target.endswith('-user')
928    config_target += {
929      'CONFIG_USER_ONLY': 'y',
930      'CONFIG_QEMU_INTERP_PREFIX':
931        config_host['CONFIG_QEMU_INTERP_PREFIX'].format(config_target['TARGET_NAME'])
932    }
933  endif
934
935  have_accel = false
936  foreach sym: accelerators
937    if sym == 'CONFIG_TCG' or target in accelerator_targets.get(sym, [])
938      config_target += { sym: 'y' }
939      config_all += { sym: 'y' }
940      if sym == 'CONFIG_XEN' and have_xen_pci_passthrough
941        config_target += { 'CONFIG_XEN_PCI_PASSTHROUGH': 'y' }
942      endif
943      have_accel = true
944    endif
945  endforeach
946  if not have_accel
947    if default_targets
948      continue
949    endif
950    error('No accelerator available for target @0@'.format(target))
951  endif
952
953  actual_target_dirs += target
954  config_target += keyval.load('default-configs/targets' / target + '.mak')
955  config_target += { 'TARGET_' + config_target['TARGET_ARCH'].to_upper(): 'y' }
956
957  if 'TARGET_NEED_FDT' in config_target
958    fdt_required += target
959  endif
960
961  # Add default keys
962  if 'TARGET_BASE_ARCH' not in config_target
963    config_target += {'TARGET_BASE_ARCH': config_target['TARGET_ARCH']}
964  endif
965  if 'TARGET_ABI_DIR' not in config_target
966    config_target += {'TARGET_ABI_DIR': config_target['TARGET_ARCH']}
967  endif
968
969  foreach k, v: disassemblers
970    if config_host['ARCH'].startswith(k) or config_target['TARGET_BASE_ARCH'].startswith(k)
971      foreach sym: v
972        config_target += { sym: 'y' }
973        config_all_disas += { sym: 'y' }
974      endforeach
975    endif
976  endforeach
977
978  config_target_data = configuration_data()
979  foreach k, v: config_target
980    if not k.startswith('TARGET_') and not k.startswith('CONFIG_')
981      # do nothing
982    elif ignored.contains(k)
983      # do nothing
984    elif k == 'TARGET_BASE_ARCH'
985      # Note that TARGET_BASE_ARCH ends up in config-target.h but it is
986      # not used to select files from sourcesets.
987      config_target_data.set('TARGET_' + v.to_upper(), 1)
988    elif k == 'TARGET_NAME' or k == 'CONFIG_QEMU_INTERP_PREFIX'
989      config_target_data.set_quoted(k, v)
990    elif v == 'y'
991      config_target_data.set(k, 1)
992    else
993      config_target_data.set(k, v)
994    endif
995  endforeach
996  config_target_h += {target: configure_file(output: target + '-config-target.h',
997                                               configuration: config_target_data)}
998
999  if target.endswith('-softmmu')
1000    base_kconfig = []
1001    foreach sym : kconfig_external_symbols
1002      if sym in config_target or sym in config_host
1003        base_kconfig += '@0@=y'.format(sym)
1004      endif
1005    endforeach
1006
1007    config_devices_mak = target + '-config-devices.mak'
1008    config_devices_mak = configure_file(
1009      input: ['default-configs/devices' / target + '.mak', 'Kconfig'],
1010      output: config_devices_mak,
1011      depfile: config_devices_mak + '.d',
1012      capture: true,
1013      command: [minikconf, config_host['CONFIG_MINIKCONF_MODE'],
1014                config_devices_mak, '@DEPFILE@', '@INPUT@',
1015                base_kconfig])
1016
1017    config_devices_data = configuration_data()
1018    config_devices = keyval.load(config_devices_mak)
1019    foreach k, v: config_devices
1020      config_devices_data.set(k, 1)
1021    endforeach
1022    config_devices_mak_list += config_devices_mak
1023    config_devices_h += {target: configure_file(output: target + '-config-devices.h',
1024                                                configuration: config_devices_data)}
1025    config_target += config_devices
1026    config_all_devices += config_devices
1027  endif
1028  config_target_mak += {target: config_target}
1029endforeach
1030target_dirs = actual_target_dirs
1031
1032# This configuration is used to build files that are shared by
1033# multiple binaries, and then extracted out of the "common"
1034# static_library target.
1035#
1036# We do not use all_sources()/all_dependencies(), because it would
1037# build literally all source files, including devices only used by
1038# targets that are not built for this compilation.  The CONFIG_ALL
1039# pseudo symbol replaces it.
1040
1041config_all += config_all_devices
1042config_all += config_host
1043config_all += config_all_disas
1044config_all += {
1045  'CONFIG_XEN': config_host.has_key('CONFIG_XEN_BACKEND'),
1046  'CONFIG_SOFTMMU': have_system,
1047  'CONFIG_USER_ONLY': have_user,
1048  'CONFIG_ALL': true,
1049}
1050
1051##############
1052# Submodules #
1053##############
1054
1055capstone = not_found
1056capstone_opt = get_option('capstone')
1057if capstone_opt in ['enabled', 'auto', 'system']
1058  have_internal = fs.exists(meson.current_source_dir() / 'capstone/Makefile')
1059  capstone = dependency('capstone', version: '>=4.0',
1060                        static: enable_static, method: 'pkg-config',
1061                        required: capstone_opt == 'system' or
1062                                  capstone_opt == 'enabled' and not have_internal)
1063  if capstone.found()
1064    capstone_opt = 'system'
1065  elif have_internal
1066    capstone_opt = 'internal'
1067  else
1068    capstone_opt = 'disabled'
1069  endif
1070endif
1071if capstone_opt == 'internal'
1072  capstone_data = configuration_data()
1073  capstone_data.set('CAPSTONE_USE_SYS_DYN_MEM', '1')
1074
1075  capstone_files = files(
1076    'capstone/cs.c',
1077    'capstone/MCInst.c',
1078    'capstone/MCInstrDesc.c',
1079    'capstone/MCRegisterInfo.c',
1080    'capstone/SStream.c',
1081    'capstone/utils.c'
1082  )
1083
1084  if 'CONFIG_ARM_DIS' in config_all_disas
1085    capstone_data.set('CAPSTONE_HAS_ARM', '1')
1086    capstone_files += files(
1087      'capstone/arch/ARM/ARMDisassembler.c',
1088      'capstone/arch/ARM/ARMInstPrinter.c',
1089      'capstone/arch/ARM/ARMMapping.c',
1090      'capstone/arch/ARM/ARMModule.c'
1091    )
1092  endif
1093
1094  # FIXME: This config entry currently depends on a c++ compiler.
1095  # Which is needed for building libvixl, but not for capstone.
1096  if 'CONFIG_ARM_A64_DIS' in config_all_disas
1097    capstone_data.set('CAPSTONE_HAS_ARM64', '1')
1098    capstone_files += files(
1099      'capstone/arch/AArch64/AArch64BaseInfo.c',
1100      'capstone/arch/AArch64/AArch64Disassembler.c',
1101      'capstone/arch/AArch64/AArch64InstPrinter.c',
1102      'capstone/arch/AArch64/AArch64Mapping.c',
1103      'capstone/arch/AArch64/AArch64Module.c'
1104    )
1105  endif
1106
1107  if 'CONFIG_PPC_DIS' in config_all_disas
1108    capstone_data.set('CAPSTONE_HAS_POWERPC', '1')
1109    capstone_files += files(
1110      'capstone/arch/PowerPC/PPCDisassembler.c',
1111      'capstone/arch/PowerPC/PPCInstPrinter.c',
1112      'capstone/arch/PowerPC/PPCMapping.c',
1113      'capstone/arch/PowerPC/PPCModule.c'
1114    )
1115  endif
1116
1117  if 'CONFIG_S390_DIS' in config_all_disas
1118    capstone_data.set('CAPSTONE_HAS_SYSZ', '1')
1119    capstone_files += files(
1120      'capstone/arch/SystemZ/SystemZDisassembler.c',
1121      'capstone/arch/SystemZ/SystemZInstPrinter.c',
1122      'capstone/arch/SystemZ/SystemZMapping.c',
1123      'capstone/arch/SystemZ/SystemZModule.c',
1124      'capstone/arch/SystemZ/SystemZMCTargetDesc.c'
1125    )
1126  endif
1127
1128  if 'CONFIG_I386_DIS' in config_all_disas
1129    capstone_data.set('CAPSTONE_HAS_X86', 1)
1130    capstone_files += files(
1131      'capstone/arch/X86/X86Disassembler.c',
1132      'capstone/arch/X86/X86DisassemblerDecoder.c',
1133      'capstone/arch/X86/X86ATTInstPrinter.c',
1134      'capstone/arch/X86/X86IntelInstPrinter.c',
1135      'capstone/arch/X86/X86InstPrinterCommon.c',
1136      'capstone/arch/X86/X86Mapping.c',
1137      'capstone/arch/X86/X86Module.c'
1138    )
1139  endif
1140
1141  configure_file(output: 'capstone-defs.h', configuration: capstone_data)
1142
1143  capstone_cargs = [
1144    # FIXME: There does not seem to be a way to completely replace the c_args
1145    # that come from add_project_arguments() -- we can only add to them.
1146    # So: disable all warnings with a big hammer.
1147    '-Wno-error', '-w',
1148
1149    # Include all configuration defines via a header file, which will wind up
1150    # as a dependency on the object file, and thus changes here will result
1151    # in a rebuild.
1152    '-include', 'capstone-defs.h'
1153  ]
1154
1155  libcapstone = static_library('capstone',
1156                               sources: capstone_files,
1157                               c_args: capstone_cargs,
1158                               include_directories: 'capstone/include')
1159  capstone = declare_dependency(link_with: libcapstone,
1160                                include_directories: 'capstone/include/capstone')
1161endif
1162
1163slirp = not_found
1164slirp_opt = 'disabled'
1165if have_system
1166  slirp_opt = get_option('slirp')
1167  if slirp_opt in ['enabled', 'auto', 'system']
1168    have_internal = fs.exists(meson.current_source_dir() / 'slirp/meson.build')
1169    slirp = dependency('slirp', static: enable_static,
1170                       method: 'pkg-config',
1171                       required: slirp_opt == 'system' or
1172                                 slirp_opt == 'enabled' and not have_internal)
1173    if slirp.found()
1174      slirp_opt = 'system'
1175    elif have_internal
1176      slirp_opt = 'internal'
1177    else
1178      slirp_opt = 'disabled'
1179    endif
1180  endif
1181  if slirp_opt == 'internal'
1182    slirp_deps = []
1183    if targetos == 'windows'
1184      slirp_deps = cc.find_library('iphlpapi')
1185    endif
1186    slirp_conf = configuration_data()
1187    slirp_conf.set('SLIRP_MAJOR_VERSION', meson.project_version().split('.')[0])
1188    slirp_conf.set('SLIRP_MINOR_VERSION', meson.project_version().split('.')[1])
1189    slirp_conf.set('SLIRP_MICRO_VERSION', meson.project_version().split('.')[2])
1190    slirp_conf.set_quoted('SLIRP_VERSION_STRING', meson.project_version())
1191    slirp_cargs = ['-DG_LOG_DOMAIN="Slirp"']
1192    slirp_files = [
1193      'slirp/src/arp_table.c',
1194      'slirp/src/bootp.c',
1195      'slirp/src/cksum.c',
1196      'slirp/src/dhcpv6.c',
1197      'slirp/src/dnssearch.c',
1198      'slirp/src/if.c',
1199      'slirp/src/ip6_icmp.c',
1200      'slirp/src/ip6_input.c',
1201      'slirp/src/ip6_output.c',
1202      'slirp/src/ip_icmp.c',
1203      'slirp/src/ip_input.c',
1204      'slirp/src/ip_output.c',
1205      'slirp/src/mbuf.c',
1206      'slirp/src/misc.c',
1207      'slirp/src/ncsi.c',
1208      'slirp/src/ndp_table.c',
1209      'slirp/src/sbuf.c',
1210      'slirp/src/slirp.c',
1211      'slirp/src/socket.c',
1212      'slirp/src/state.c',
1213      'slirp/src/stream.c',
1214      'slirp/src/tcp_input.c',
1215      'slirp/src/tcp_output.c',
1216      'slirp/src/tcp_subr.c',
1217      'slirp/src/tcp_timer.c',
1218      'slirp/src/tftp.c',
1219      'slirp/src/udp.c',
1220      'slirp/src/udp6.c',
1221      'slirp/src/util.c',
1222      'slirp/src/version.c',
1223      'slirp/src/vmstate.c',
1224    ]
1225
1226    configure_file(
1227      input : 'slirp/src/libslirp-version.h.in',
1228      output : 'libslirp-version.h',
1229      configuration: slirp_conf)
1230
1231    slirp_inc = include_directories('slirp', 'slirp/src')
1232    libslirp = static_library('slirp',
1233                              sources: slirp_files,
1234                              c_args: slirp_cargs,
1235                              include_directories: slirp_inc)
1236    slirp = declare_dependency(link_with: libslirp,
1237                               dependencies: slirp_deps,
1238                               include_directories: slirp_inc)
1239  endif
1240endif
1241
1242fdt = not_found
1243fdt_opt = get_option('fdt')
1244if have_system
1245  if fdt_opt in ['enabled', 'auto', 'system']
1246    have_internal = fs.exists(meson.current_source_dir() / 'dtc/libfdt/Makefile.libfdt')
1247    fdt = cc.find_library('fdt', static: enable_static,
1248                          required: fdt_opt == 'system' or
1249                                    fdt_opt == 'enabled' and not have_internal)
1250    if fdt.found() and cc.links('''
1251       #include <libfdt.h>
1252       #include <libfdt_env.h>
1253       int main(void) { fdt_check_full(NULL, 0); return 0; }''',
1254         dependencies: fdt)
1255      fdt_opt = 'system'
1256    elif have_internal
1257      fdt_opt = 'internal'
1258    else
1259      fdt_opt = 'disabled'
1260    endif
1261  endif
1262  if fdt_opt == 'internal'
1263    fdt_files = files(
1264      'dtc/libfdt/fdt.c',
1265      'dtc/libfdt/fdt_ro.c',
1266      'dtc/libfdt/fdt_wip.c',
1267      'dtc/libfdt/fdt_sw.c',
1268      'dtc/libfdt/fdt_rw.c',
1269      'dtc/libfdt/fdt_strerror.c',
1270      'dtc/libfdt/fdt_empty_tree.c',
1271      'dtc/libfdt/fdt_addresses.c',
1272      'dtc/libfdt/fdt_overlay.c',
1273      'dtc/libfdt/fdt_check.c',
1274    )
1275
1276    fdt_inc = include_directories('dtc/libfdt')
1277    libfdt = static_library('fdt',
1278                            sources: fdt_files,
1279                            include_directories: fdt_inc)
1280    fdt = declare_dependency(link_with: libfdt,
1281                             include_directories: fdt_inc)
1282  endif
1283endif
1284if not fdt.found() and fdt_required.length() > 0
1285  error('fdt not available but required by targets ' + ', '.join(fdt_required))
1286endif
1287
1288config_host_data.set('CONFIG_CAPSTONE', capstone.found())
1289config_host_data.set('CONFIG_FDT', fdt.found())
1290config_host_data.set('CONFIG_SLIRP', slirp.found())
1291
1292#####################
1293# Generated sources #
1294#####################
1295
1296genh += configure_file(output: 'config-host.h', configuration: config_host_data)
1297
1298hxtool = find_program('scripts/hxtool')
1299shaderinclude = find_program('scripts/shaderinclude.pl')
1300qapi_gen = find_program('scripts/qapi-gen.py')
1301qapi_gen_depends = [ meson.source_root() / 'scripts/qapi/__init__.py',
1302                     meson.source_root() / 'scripts/qapi/commands.py',
1303                     meson.source_root() / 'scripts/qapi/common.py',
1304                     meson.source_root() / 'scripts/qapi/error.py',
1305                     meson.source_root() / 'scripts/qapi/events.py',
1306                     meson.source_root() / 'scripts/qapi/expr.py',
1307                     meson.source_root() / 'scripts/qapi/gen.py',
1308                     meson.source_root() / 'scripts/qapi/introspect.py',
1309                     meson.source_root() / 'scripts/qapi/parser.py',
1310                     meson.source_root() / 'scripts/qapi/schema.py',
1311                     meson.source_root() / 'scripts/qapi/source.py',
1312                     meson.source_root() / 'scripts/qapi/types.py',
1313                     meson.source_root() / 'scripts/qapi/visit.py',
1314                     meson.source_root() / 'scripts/qapi/common.py',
1315                     meson.source_root() / 'scripts/qapi-gen.py'
1316]
1317
1318tracetool = [
1319  python, files('scripts/tracetool.py'),
1320   '--backend=' + config_host['TRACE_BACKENDS']
1321]
1322
1323qemu_version_cmd = [find_program('scripts/qemu-version.sh'),
1324                    meson.current_source_dir(),
1325                    config_host['PKGVERSION'], meson.project_version()]
1326qemu_version = custom_target('qemu-version.h',
1327                             output: 'qemu-version.h',
1328                             command: qemu_version_cmd,
1329                             capture: true,
1330                             build_by_default: true,
1331                             build_always_stale: true)
1332genh += qemu_version
1333
1334hxdep = []
1335hx_headers = [
1336  ['qemu-options.hx', 'qemu-options.def'],
1337  ['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
1338]
1339if have_system
1340  hx_headers += [
1341    ['hmp-commands.hx', 'hmp-commands.h'],
1342    ['hmp-commands-info.hx', 'hmp-commands-info.h'],
1343  ]
1344endif
1345foreach d : hx_headers
1346  hxdep += custom_target(d[1],
1347                input: files(d[0]),
1348                output: d[1],
1349                capture: true,
1350                build_by_default: true, # to be removed when added to a target
1351                command: [hxtool, '-h', '@INPUT0@'])
1352endforeach
1353genh += hxdep
1354
1355###################
1356# Collect sources #
1357###################
1358
1359authz_ss = ss.source_set()
1360blockdev_ss = ss.source_set()
1361block_ss = ss.source_set()
1362bsd_user_ss = ss.source_set()
1363chardev_ss = ss.source_set()
1364common_ss = ss.source_set()
1365crypto_ss = ss.source_set()
1366io_ss = ss.source_set()
1367linux_user_ss = ss.source_set()
1368qmp_ss = ss.source_set()
1369qom_ss = ss.source_set()
1370softmmu_ss = ss.source_set()
1371specific_fuzz_ss = ss.source_set()
1372specific_ss = ss.source_set()
1373stub_ss = ss.source_set()
1374trace_ss = ss.source_set()
1375user_ss = ss.source_set()
1376util_ss = ss.source_set()
1377
1378modules = {}
1379hw_arch = {}
1380target_arch = {}
1381target_softmmu_arch = {}
1382
1383###############
1384# Trace files #
1385###############
1386
1387# TODO: add each directory to the subdirs from its own meson.build, once
1388# we have those
1389trace_events_subdirs = [
1390  'accel/kvm',
1391  'accel/tcg',
1392  'crypto',
1393  'monitor',
1394]
1395if have_user
1396  trace_events_subdirs += [ 'linux-user' ]
1397endif
1398if have_block
1399  trace_events_subdirs += [
1400    'authz',
1401    'block',
1402    'io',
1403    'nbd',
1404    'scsi',
1405  ]
1406endif
1407if have_system
1408  trace_events_subdirs += [
1409    'audio',
1410    'backends',
1411    'backends/tpm',
1412    'chardev',
1413    'hw/9pfs',
1414    'hw/acpi',
1415    'hw/alpha',
1416    'hw/arm',
1417    'hw/audio',
1418    'hw/block',
1419    'hw/block/dataplane',
1420    'hw/char',
1421    'hw/display',
1422    'hw/dma',
1423    'hw/hppa',
1424    'hw/hyperv',
1425    'hw/i2c',
1426    'hw/i386',
1427    'hw/i386/xen',
1428    'hw/ide',
1429    'hw/input',
1430    'hw/intc',
1431    'hw/isa',
1432    'hw/mem',
1433    'hw/mips',
1434    'hw/misc',
1435    'hw/misc/macio',
1436    'hw/net',
1437    'hw/nvram',
1438    'hw/pci',
1439    'hw/pci-host',
1440    'hw/ppc',
1441    'hw/rdma',
1442    'hw/rdma/vmw',
1443    'hw/rtc',
1444    'hw/s390x',
1445    'hw/scsi',
1446    'hw/sd',
1447    'hw/sparc',
1448    'hw/sparc64',
1449    'hw/ssi',
1450    'hw/timer',
1451    'hw/tpm',
1452    'hw/usb',
1453    'hw/vfio',
1454    'hw/virtio',
1455    'hw/watchdog',
1456    'hw/xen',
1457    'hw/gpio',
1458    'migration',
1459    'net',
1460    'softmmu',
1461    'ui',
1462  ]
1463endif
1464trace_events_subdirs += [
1465  'hw/core',
1466  'qapi',
1467  'qom',
1468  'target/arm',
1469  'target/hppa',
1470  'target/i386',
1471  'target/mips',
1472  'target/ppc',
1473  'target/riscv',
1474  'target/s390x',
1475  'target/sparc',
1476  'util',
1477]
1478
1479subdir('contrib/libvhost-user')
1480subdir('qapi')
1481subdir('qobject')
1482subdir('stubs')
1483subdir('trace')
1484subdir('util')
1485subdir('qom')
1486subdir('authz')
1487subdir('crypto')
1488subdir('ui')
1489
1490
1491if enable_modules
1492  libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
1493  modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
1494endif
1495
1496stub_ss = stub_ss.apply(config_all, strict: false)
1497
1498util_ss.add_all(trace_ss)
1499util_ss = util_ss.apply(config_all, strict: false)
1500libqemuutil = static_library('qemuutil',
1501                             sources: util_ss.sources() + stub_ss.sources() + genh,
1502                             dependencies: [util_ss.dependencies(), m, glib, socket, malloc])
1503qemuutil = declare_dependency(link_with: libqemuutil,
1504                              sources: genh + version_res)
1505
1506decodetree = generator(find_program('scripts/decodetree.py'),
1507                       output: 'decode-@BASENAME@.c.inc',
1508                       arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
1509
1510subdir('audio')
1511subdir('io')
1512subdir('chardev')
1513subdir('fsdev')
1514subdir('libdecnumber')
1515subdir('target')
1516subdir('dump')
1517
1518block_ss.add(files(
1519  'block.c',
1520  'blockjob.c',
1521  'job.c',
1522  'qemu-io-cmds.c',
1523))
1524block_ss.add(when: 'CONFIG_REPLICATION', if_true: files('replication.c'))
1525
1526subdir('nbd')
1527subdir('scsi')
1528subdir('block')
1529
1530blockdev_ss.add(files(
1531  'blockdev.c',
1532  'blockdev-nbd.c',
1533  'iothread.c',
1534  'job-qmp.c',
1535))
1536
1537# os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
1538# os-win32.c does not
1539blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c'))
1540softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')])
1541
1542common_ss.add(files('cpus-common.c'))
1543
1544subdir('softmmu')
1545
1546common_ss.add(capstone)
1547specific_ss.add(files('cpu.c', 'disas.c', 'gdbstub.c'), capstone)
1548specific_ss.add(files('exec-vary.c'))
1549specific_ss.add(when: 'CONFIG_TCG', if_true: files(
1550  'fpu/softfloat.c',
1551  'tcg/optimize.c',
1552  'tcg/tcg-common.c',
1553  'tcg/tcg-op-gvec.c',
1554  'tcg/tcg-op-vec.c',
1555  'tcg/tcg-op.c',
1556  'tcg/tcg.c',
1557))
1558specific_ss.add(when: 'CONFIG_TCG_INTERPRETER', if_true: files('disas/tci.c', 'tcg/tci.c'))
1559
1560subdir('backends')
1561subdir('disas')
1562subdir('migration')
1563subdir('monitor')
1564subdir('net')
1565subdir('replay')
1566subdir('hw')
1567subdir('accel')
1568subdir('plugins')
1569subdir('bsd-user')
1570subdir('linux-user')
1571
1572bsd_user_ss.add(files('gdbstub.c'))
1573specific_ss.add_all(when: 'CONFIG_BSD_USER', if_true: bsd_user_ss)
1574
1575linux_user_ss.add(files('gdbstub.c', 'thunk.c'))
1576specific_ss.add_all(when: 'CONFIG_LINUX_USER', if_true: linux_user_ss)
1577
1578# needed for fuzzing binaries
1579subdir('tests/qtest/libqos')
1580subdir('tests/qtest/fuzz')
1581
1582########################
1583# Library dependencies #
1584########################
1585
1586block_mods = []
1587softmmu_mods = []
1588foreach d, list : modules
1589  foreach m, module_ss : list
1590    if enable_modules and targetos != 'windows'
1591      module_ss = module_ss.apply(config_all, strict: false)
1592      sl = static_library(d + '-' + m, [genh, module_ss.sources()],
1593                          dependencies: [modulecommon, module_ss.dependencies()], pic: true)
1594      if d == 'block'
1595        block_mods += sl
1596      else
1597        softmmu_mods += sl
1598      endif
1599    else
1600      if d == 'block'
1601        block_ss.add_all(module_ss)
1602      else
1603        softmmu_ss.add_all(module_ss)
1604      endif
1605    endif
1606  endforeach
1607endforeach
1608
1609nm = find_program('nm')
1610undefsym = find_program('scripts/undefsym.py')
1611block_syms = custom_target('block.syms', output: 'block.syms',
1612                             input: [libqemuutil, block_mods],
1613                             capture: true,
1614                             command: [undefsym, nm, '@INPUT@'])
1615qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
1616                             input: [libqemuutil, softmmu_mods],
1617                             capture: true,
1618                             command: [undefsym, nm, '@INPUT@'])
1619
1620qom_ss = qom_ss.apply(config_host, strict: false)
1621libqom = static_library('qom', qom_ss.sources() + genh,
1622                        dependencies: [qom_ss.dependencies()],
1623                        name_suffix: 'fa')
1624
1625qom = declare_dependency(link_whole: libqom)
1626
1627authz_ss = authz_ss.apply(config_host, strict: false)
1628libauthz = static_library('authz', authz_ss.sources() + genh,
1629                          dependencies: [authz_ss.dependencies()],
1630                          name_suffix: 'fa',
1631                          build_by_default: false)
1632
1633authz = declare_dependency(link_whole: libauthz,
1634                           dependencies: qom)
1635
1636crypto_ss = crypto_ss.apply(config_host, strict: false)
1637libcrypto = static_library('crypto', crypto_ss.sources() + genh,
1638                           dependencies: [crypto_ss.dependencies()],
1639                           name_suffix: 'fa',
1640                           build_by_default: false)
1641
1642crypto = declare_dependency(link_whole: libcrypto,
1643                            dependencies: [authz, qom])
1644
1645io_ss = io_ss.apply(config_host, strict: false)
1646libio = static_library('io', io_ss.sources() + genh,
1647                       dependencies: [io_ss.dependencies()],
1648                       link_with: libqemuutil,
1649                       name_suffix: 'fa',
1650                       build_by_default: false)
1651
1652io = declare_dependency(link_whole: libio, dependencies: [crypto, qom])
1653
1654libmigration = static_library('migration', sources: migration_files + genh,
1655                              name_suffix: 'fa',
1656                              build_by_default: false)
1657migration = declare_dependency(link_with: libmigration,
1658                               dependencies: [zlib, qom, io])
1659softmmu_ss.add(migration)
1660
1661block_ss = block_ss.apply(config_host, strict: false)
1662libblock = static_library('block', block_ss.sources() + genh,
1663                          dependencies: block_ss.dependencies(),
1664                          link_depends: block_syms,
1665                          name_suffix: 'fa',
1666                          build_by_default: false)
1667
1668block = declare_dependency(link_whole: [libblock],
1669                           link_args: '@block.syms',
1670                           dependencies: [crypto, io])
1671
1672blockdev_ss = blockdev_ss.apply(config_host, strict: false)
1673libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
1674                             dependencies: blockdev_ss.dependencies(),
1675                             name_suffix: 'fa',
1676                             build_by_default: false)
1677
1678blockdev = declare_dependency(link_whole: [libblockdev],
1679                              dependencies: [block])
1680
1681qmp_ss = qmp_ss.apply(config_host, strict: false)
1682libqmp = static_library('qmp', qmp_ss.sources() + genh,
1683                        dependencies: qmp_ss.dependencies(),
1684                        name_suffix: 'fa',
1685                        build_by_default: false)
1686
1687qmp = declare_dependency(link_whole: [libqmp])
1688
1689libchardev = static_library('chardev', chardev_ss.sources() + genh,
1690                            name_suffix: 'fa',
1691                            build_by_default: false)
1692
1693chardev = declare_dependency(link_whole: libchardev)
1694
1695libhwcore = static_library('hwcore', sources: hwcore_files + genh,
1696                           name_suffix: 'fa',
1697                           build_by_default: false)
1698hwcore = declare_dependency(link_whole: libhwcore)
1699common_ss.add(hwcore)
1700
1701###########
1702# Targets #
1703###########
1704
1705foreach m : block_mods + softmmu_mods
1706  shared_module(m.name(),
1707                name_prefix: '',
1708                link_whole: m,
1709                install: true,
1710                install_dir: qemu_moddir)
1711endforeach
1712
1713softmmu_ss.add(authz, blockdev, chardev, crypto, io, qmp)
1714common_ss.add(qom, qemuutil)
1715
1716common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss])
1717common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
1718
1719common_all = common_ss.apply(config_all, strict: false)
1720common_all = static_library('common',
1721                            build_by_default: false,
1722                            sources: common_all.sources() + genh,
1723                            dependencies: common_all.dependencies(),
1724                            name_suffix: 'fa')
1725
1726feature_to_c = find_program('scripts/feature_to_c.sh')
1727
1728emulators = {}
1729foreach target : target_dirs
1730  config_target = config_target_mak[target]
1731  target_name = config_target['TARGET_NAME']
1732  arch = config_target['TARGET_BASE_ARCH']
1733  arch_srcs = [config_target_h[target]]
1734  arch_deps = []
1735  c_args = ['-DNEED_CPU_H',
1736            '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
1737            '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
1738  link_args = emulator_link_args
1739
1740  config_target += config_host
1741  target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
1742  if targetos == 'linux'
1743    target_inc += include_directories('linux-headers', is_system: true)
1744  endif
1745  if target.endswith('-softmmu')
1746    qemu_target_name = 'qemu-system-' + target_name
1747    target_type='system'
1748    t = target_softmmu_arch[arch].apply(config_target, strict: false)
1749    arch_srcs += t.sources()
1750    arch_deps += t.dependencies()
1751
1752    hw_dir = target_name == 'sparc64' ? 'sparc64' : arch
1753    hw = hw_arch[hw_dir].apply(config_target, strict: false)
1754    arch_srcs += hw.sources()
1755    arch_deps += hw.dependencies()
1756
1757    arch_srcs += config_devices_h[target]
1758    link_args += ['@block.syms', '@qemu.syms']
1759  else
1760    abi = config_target['TARGET_ABI_DIR']
1761    target_type='user'
1762    qemu_target_name = 'qemu-' + target_name
1763    if 'CONFIG_LINUX_USER' in config_target
1764      base_dir = 'linux-user'
1765      target_inc += include_directories('linux-user/host/' / config_host['ARCH'])
1766    else
1767      base_dir = 'bsd-user'
1768    endif
1769    target_inc += include_directories(
1770      base_dir,
1771      base_dir / abi,
1772    )
1773    if 'CONFIG_LINUX_USER' in config_target
1774      dir = base_dir / abi
1775      arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
1776      if config_target.has_key('TARGET_SYSTBL_ABI')
1777        arch_srcs += \
1778          syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
1779                                             extra_args : config_target['TARGET_SYSTBL_ABI'])
1780      endif
1781    endif
1782  endif
1783
1784  if 'TARGET_XML_FILES' in config_target
1785    gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
1786                                output: target + '-gdbstub-xml.c',
1787                                input: files(config_target['TARGET_XML_FILES'].split()),
1788                                command: [feature_to_c, '@INPUT@'],
1789                                capture: true)
1790    arch_srcs += gdbstub_xml
1791  endif
1792
1793  t = target_arch[arch].apply(config_target, strict: false)
1794  arch_srcs += t.sources()
1795  arch_deps += t.dependencies()
1796
1797  target_common = common_ss.apply(config_target, strict: false)
1798  objects = common_all.extract_objects(target_common.sources())
1799  deps = target_common.dependencies()
1800
1801  target_specific = specific_ss.apply(config_target, strict: false)
1802  arch_srcs += target_specific.sources()
1803  arch_deps += target_specific.dependencies()
1804
1805  lib = static_library('qemu-' + target,
1806                 sources: arch_srcs + genh,
1807                 dependencies: arch_deps,
1808                 objects: objects,
1809                 include_directories: target_inc,
1810                 c_args: c_args,
1811                 build_by_default: false,
1812                 name_suffix: 'fa')
1813
1814  if target.endswith('-softmmu')
1815    execs = [{
1816      'name': 'qemu-system-' + target_name,
1817      'gui': false,
1818      'sources': files('softmmu/main.c'),
1819      'dependencies': []
1820    }]
1821    if targetos == 'windows' and (sdl.found() or gtk.found())
1822      execs += [{
1823        'name': 'qemu-system-' + target_name + 'w',
1824        'gui': true,
1825        'sources': files('softmmu/main.c'),
1826        'dependencies': []
1827      }]
1828    endif
1829    if config_host.has_key('CONFIG_FUZZ')
1830      specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
1831      execs += [{
1832        'name': 'qemu-fuzz-' + target_name,
1833        'gui': false,
1834        'sources': specific_fuzz.sources(),
1835        'dependencies': specific_fuzz.dependencies(),
1836      }]
1837    endif
1838  else
1839    execs = [{
1840      'name': 'qemu-' + target_name,
1841      'gui': false,
1842      'sources': [],
1843      'dependencies': []
1844    }]
1845  endif
1846  foreach exe: execs
1847    emulators += {exe['name']:
1848         executable(exe['name'], exe['sources'],
1849               install: true,
1850               c_args: c_args,
1851               dependencies: arch_deps + deps + exe['dependencies'],
1852               objects: lib.extract_all_objects(recursive: true),
1853               link_language: link_language,
1854               link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
1855               link_args: link_args,
1856               gui_app: exe['gui'])
1857    }
1858
1859    if 'CONFIG_TRACE_SYSTEMTAP' in config_host
1860      foreach stp: [
1861        {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
1862        {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
1863        {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
1864        {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
1865      ]
1866        custom_target(exe['name'] + stp['ext'],
1867                      input: trace_events_all,
1868                      output: exe['name'] + stp['ext'],
1869                      capture: true,
1870                      install: stp['install'],
1871                      install_dir: get_option('datadir') / 'systemtap/tapset',
1872                      command: [
1873                        tracetool, '--group=all', '--format=' + stp['fmt'],
1874                        '--binary=' + stp['bin'],
1875                        '--target-name=' + target_name,
1876                        '--target-type=' + target_type,
1877                        '--probe-prefix=qemu.' + target_type + '.' + target_name,
1878                        '@INPUT@',
1879                      ])
1880      endforeach
1881    endif
1882  endforeach
1883endforeach
1884
1885# Other build targets
1886
1887if 'CONFIG_PLUGIN' in config_host
1888  install_headers('include/qemu/qemu-plugin.h')
1889endif
1890
1891if 'CONFIG_GUEST_AGENT' in config_host
1892  subdir('qga')
1893endif
1894
1895# Don't build qemu-keymap if xkbcommon is not explicitly enabled
1896# when we don't build tools or system
1897if xkbcommon.found()
1898  # used for the update-keymaps target, so include rules even if !have_tools
1899  qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
1900                           dependencies: [qemuutil, xkbcommon], install: have_tools)
1901endif
1902
1903if have_tools
1904  qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
1905             dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
1906  qemu_io = executable('qemu-io', files('qemu-io.c'),
1907             dependencies: [block, qemuutil], install: true)
1908  qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
1909               dependencies: [blockdev, qemuutil], install: true)
1910
1911  subdir('storage-daemon')
1912  subdir('contrib/rdmacm-mux')
1913  subdir('contrib/elf2dmp')
1914
1915  executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
1916             dependencies: qemuutil,
1917             install: true)
1918
1919  if 'CONFIG_VHOST_USER' in config_host
1920    subdir('contrib/vhost-user-blk')
1921    subdir('contrib/vhost-user-gpu')
1922    subdir('contrib/vhost-user-input')
1923    subdir('contrib/vhost-user-scsi')
1924  endif
1925
1926  if targetos == 'linux'
1927    executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
1928               dependencies: [qemuutil, libcap_ng],
1929               install: true,
1930               install_dir: get_option('libexecdir'))
1931
1932    executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
1933               dependencies: [authz, crypto, io, qom, qemuutil,
1934                              libcap_ng, mpathpersist],
1935               install: true)
1936  endif
1937
1938  if 'CONFIG_IVSHMEM' in config_host
1939    subdir('contrib/ivshmem-client')
1940    subdir('contrib/ivshmem-server')
1941  endif
1942endif
1943
1944subdir('scripts')
1945subdir('tools')
1946subdir('pc-bios')
1947subdir('docs')
1948subdir('tests')
1949if 'CONFIG_GTK' in config_host
1950  subdir('po')
1951endif
1952
1953if host_machine.system() == 'windows'
1954  nsis_cmd = [
1955    find_program('scripts/nsis.py'),
1956    '@OUTPUT@',
1957    get_option('prefix'),
1958    meson.current_source_dir(),
1959    host_machine.cpu_family(),
1960    '--',
1961    '-DDISPLAYVERSION=' + meson.project_version(),
1962  ]
1963  if build_docs
1964    nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
1965  endif
1966  if 'CONFIG_GTK' in config_host
1967    nsis_cmd += '-DCONFIG_GTK=y'
1968  endif
1969
1970  nsis = custom_target('nsis',
1971                       output: 'qemu-setup-' + meson.project_version() + '.exe',
1972                       input: files('qemu.nsi'),
1973                       build_always_stale: true,
1974                       command: nsis_cmd + ['@INPUT@'])
1975  alias_target('installer', nsis)
1976endif
1977
1978#########################
1979# Configuration summary #
1980#########################
1981
1982summary_info = {}
1983summary_info += {'Install prefix':    get_option('prefix')}
1984summary_info += {'BIOS directory':    qemu_datadir}
1985summary_info += {'firmware path':     get_option('qemu_firmwarepath')}
1986summary_info += {'binary directory':  get_option('bindir')}
1987summary_info += {'library directory': get_option('libdir')}
1988summary_info += {'module directory':  qemu_moddir}
1989summary_info += {'libexec directory': get_option('libexecdir')}
1990summary_info += {'include directory': get_option('includedir')}
1991summary_info += {'config directory':  get_option('sysconfdir')}
1992if targetos != 'windows'
1993  summary_info += {'local state directory': get_option('localstatedir')}
1994  summary_info += {'Manual directory':      get_option('mandir')}
1995else
1996  summary_info += {'local state directory': 'queried at runtime'}
1997endif
1998summary_info += {'Doc directory':     get_option('docdir')}
1999summary_info += {'Build directory':   meson.current_build_dir()}
2000summary_info += {'Source path':       meson.current_source_dir()}
2001summary_info += {'GIT binary':        config_host['GIT']}
2002summary_info += {'GIT submodules':    config_host['GIT_SUBMODULES']}
2003summary_info += {'C compiler':        meson.get_compiler('c').cmd_array()[0]}
2004summary_info += {'Host C compiler':   meson.get_compiler('c', native: true).cmd_array()[0]}
2005if link_language == 'cpp'
2006  summary_info += {'C++ compiler':      meson.get_compiler('cpp').cmd_array()[0]}
2007else
2008  summary_info += {'C++ compiler':      false}
2009endif
2010if targetos == 'darwin'
2011  summary_info += {'Objective-C compiler': meson.get_compiler('objc').cmd_array()[0]}
2012endif
2013summary_info += {'ARFLAGS':           config_host['ARFLAGS']}
2014summary_info += {'CFLAGS':            ' '.join(get_option('c_args')
2015                                               + ['-O' + get_option('optimization')]
2016                                               + (get_option('debug') ? ['-g'] : []))}
2017if link_language == 'cpp'
2018  summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args')
2019                                               + ['-O' + get_option('optimization')]
2020                                               + (get_option('debug') ? ['-g'] : []))}
2021endif
2022link_args = get_option(link_language + '_link_args')
2023if link_args.length() > 0
2024  summary_info += {'LDFLAGS':         ' '.join(link_args)}
2025endif
2026summary_info += {'QEMU_CFLAGS':       config_host['QEMU_CFLAGS']}
2027summary_info += {'QEMU_LDFLAGS':      config_host['QEMU_LDFLAGS']}
2028summary_info += {'make':              config_host['MAKE']}
2029summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
2030summary_info += {'sphinx-build':      sphinx_build.found()}
2031summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
2032# TODO: add back version
2033summary_info += {'slirp support':     slirp_opt == 'disabled' ? false : slirp_opt}
2034if slirp_opt != 'disabled'
2035  summary_info += {'smbd':            config_host['CONFIG_SMBD_COMMAND']}
2036endif
2037summary_info += {'module support':    config_host.has_key('CONFIG_MODULES')}
2038if config_host.has_key('CONFIG_MODULES')
2039  summary_info += {'alternative module path': config_host.has_key('CONFIG_MODULE_UPGRADES')}
2040endif
2041summary_info += {'host CPU':          cpu}
2042summary_info += {'host endianness':   build_machine.endian()}
2043summary_info += {'target list':       ' '.join(target_dirs)}
2044summary_info += {'gprof enabled':     config_host.has_key('CONFIG_GPROF')}
2045summary_info += {'sparse enabled':    sparse.found()}
2046summary_info += {'strip binaries':    get_option('strip')}
2047summary_info += {'profiler':          config_host.has_key('CONFIG_PROFILER')}
2048summary_info += {'static build':      config_host.has_key('CONFIG_STATIC')}
2049if targetos == 'darwin'
2050  summary_info += {'Cocoa support': config_host.has_key('CONFIG_COCOA')}
2051endif
2052# TODO: add back version
2053summary_info += {'SDL support':       sdl.found()}
2054summary_info += {'SDL image support': sdl_image.found()}
2055# TODO: add back version
2056summary_info += {'GTK support':       config_host.has_key('CONFIG_GTK')}
2057summary_info += {'GTK GL support':    config_host.has_key('CONFIG_GTK_GL')}
2058summary_info += {'pixman':            pixman.found()}
2059# TODO: add back version
2060summary_info += {'VTE support':       config_host.has_key('CONFIG_VTE')}
2061summary_info += {'TLS priority':      config_host['CONFIG_TLS_PRIORITY']}
2062summary_info += {'GNUTLS support':    config_host.has_key('CONFIG_GNUTLS')}
2063# TODO: add back version
2064summary_info += {'libgcrypt':         config_host.has_key('CONFIG_GCRYPT')}
2065if config_host.has_key('CONFIG_GCRYPT')
2066   summary_info += {'  hmac':            config_host.has_key('CONFIG_GCRYPT_HMAC')}
2067   summary_info += {'  XTS':             not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')}
2068endif
2069# TODO: add back version
2070summary_info += {'nettle':            config_host.has_key('CONFIG_NETTLE')}
2071if config_host.has_key('CONFIG_NETTLE')
2072   summary_info += {'  XTS':             not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')}
2073endif
2074summary_info += {'libtasn1':          config_host.has_key('CONFIG_TASN1')}
2075summary_info += {'PAM':               config_host.has_key('CONFIG_AUTH_PAM')}
2076summary_info += {'iconv support':     iconv.found()}
2077summary_info += {'curses support':    curses.found()}
2078# TODO: add back version
2079summary_info += {'virgl support':     config_host.has_key('CONFIG_VIRGL')}
2080summary_info += {'curl support':      config_host.has_key('CONFIG_CURL')}
2081summary_info += {'mingw32 support':   targetos == 'windows'}
2082summary_info += {'Audio drivers':     config_host['CONFIG_AUDIO_DRIVERS']}
2083summary_info += {'Block whitelist (rw)': config_host['CONFIG_BDRV_RW_WHITELIST']}
2084summary_info += {'Block whitelist (ro)': config_host['CONFIG_BDRV_RO_WHITELIST']}
2085summary_info += {'VirtFS support':    config_host.has_key('CONFIG_VIRTFS')}
2086summary_info += {'build virtiofs daemon': have_virtiofsd}
2087summary_info += {'Multipath support': mpathpersist.found()}
2088summary_info += {'VNC support':       vnc.found()}
2089if vnc.found()
2090  summary_info += {'VNC SASL support':  sasl.found()}
2091  summary_info += {'VNC JPEG support':  jpeg.found()}
2092  summary_info += {'VNC PNG support':   png.found()}
2093endif
2094summary_info += {'xen support':       config_host.has_key('CONFIG_XEN_BACKEND')}
2095if config_host.has_key('CONFIG_XEN_BACKEND')
2096  summary_info += {'xen ctrl version':  config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']}
2097endif
2098summary_info += {'brlapi support':    config_host.has_key('CONFIG_BRLAPI')}
2099summary_info += {'Documentation':     build_docs}
2100summary_info += {'PIE':               get_option('b_pie')}
2101summary_info += {'vde support':       config_host.has_key('CONFIG_VDE')}
2102summary_info += {'netmap support':    config_host.has_key('CONFIG_NETMAP')}
2103summary_info += {'Linux AIO support': config_host.has_key('CONFIG_LINUX_AIO')}
2104summary_info += {'Linux io_uring support': config_host.has_key('CONFIG_LINUX_IO_URING')}
2105summary_info += {'ATTR/XATTR support': config_host.has_key('CONFIG_ATTR')}
2106summary_info += {'Install blobs':     get_option('install_blobs')}
2107summary_info += {'KVM support':       config_all.has_key('CONFIG_KVM')}
2108summary_info += {'HAX support':       config_all.has_key('CONFIG_HAX')}
2109summary_info += {'HVF support':       config_all.has_key('CONFIG_HVF')}
2110summary_info += {'WHPX support':      config_all.has_key('CONFIG_WHPX')}
2111summary_info += {'TCG support':       config_all.has_key('CONFIG_TCG')}
2112if config_all.has_key('CONFIG_TCG')
2113  summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')}
2114  summary_info += {'TCG interpreter':   config_host.has_key('CONFIG_TCG_INTERPRETER')}
2115endif
2116summary_info += {'malloc trim support': has_malloc_trim}
2117summary_info += {'RDMA support':      config_host.has_key('CONFIG_RDMA')}
2118summary_info += {'PVRDMA support':    config_host.has_key('CONFIG_PVRDMA')}
2119summary_info += {'fdt support':       fdt_opt == 'disabled' ? false : fdt_opt}
2120summary_info += {'membarrier':        config_host.has_key('CONFIG_MEMBARRIER')}
2121summary_info += {'preadv support':    config_host.has_key('CONFIG_PREADV')}
2122summary_info += {'fdatasync':         config_host.has_key('CONFIG_FDATASYNC')}
2123summary_info += {'madvise':           config_host.has_key('CONFIG_MADVISE')}
2124summary_info += {'posix_madvise':     config_host.has_key('CONFIG_POSIX_MADVISE')}
2125summary_info += {'posix_memalign':    config_host.has_key('CONFIG_POSIX_MEMALIGN')}
2126summary_info += {'libcap-ng support': config_host.has_key('CONFIG_LIBCAP_NG')}
2127summary_info += {'vhost-kernel support': config_host.has_key('CONFIG_VHOST_KERNEL')}
2128summary_info += {'vhost-net support': config_host.has_key('CONFIG_VHOST_NET')}
2129summary_info += {'vhost-crypto support': config_host.has_key('CONFIG_VHOST_CRYPTO')}
2130summary_info += {'vhost-scsi support': config_host.has_key('CONFIG_VHOST_SCSI')}
2131summary_info += {'vhost-vsock support': config_host.has_key('CONFIG_VHOST_VSOCK')}
2132summary_info += {'vhost-user support': config_host.has_key('CONFIG_VHOST_USER')}
2133summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
2134summary_info += {'vhost-user-fs support': config_host.has_key('CONFIG_VHOST_USER_FS')}
2135summary_info += {'vhost-vdpa support': config_host.has_key('CONFIG_VHOST_VDPA')}
2136summary_info += {'Trace backends':    config_host['TRACE_BACKENDS']}
2137if config_host['TRACE_BACKENDS'].split().contains('simple')
2138  summary_info += {'Trace output file': config_host['CONFIG_TRACE_FILE'] + '-<pid>'}
2139endif
2140# TODO: add back protocol and server version
2141summary_info += {'spice support':     config_host.has_key('CONFIG_SPICE')}
2142summary_info += {'rbd support':       config_host.has_key('CONFIG_RBD')}
2143summary_info += {'xfsctl support':    config_host.has_key('CONFIG_XFS')}
2144summary_info += {'smartcard support': config_host.has_key('CONFIG_SMARTCARD')}
2145summary_info += {'U2F support':       u2f.found()}
2146summary_info += {'libusb':            config_host.has_key('CONFIG_USB_LIBUSB')}
2147summary_info += {'usb net redir':     config_host.has_key('CONFIG_USB_REDIR')}
2148summary_info += {'OpenGL support':    config_host.has_key('CONFIG_OPENGL')}
2149summary_info += {'OpenGL dmabufs':    config_host.has_key('CONFIG_OPENGL_DMABUF')}
2150summary_info += {'libiscsi support':  config_host.has_key('CONFIG_LIBISCSI')}
2151summary_info += {'libnfs support':    config_host.has_key('CONFIG_LIBNFS')}
2152summary_info += {'build guest agent': config_host.has_key('CONFIG_GUEST_AGENT')}
2153if targetos == 'windows'
2154  if 'WIN_SDK' in config_host
2155    summary_info += {'Windows SDK':       config_host['WIN_SDK']}
2156  endif
2157  summary_info += {'QGA VSS support':   config_host.has_key('CONFIG_QGA_VSS')}
2158  summary_info += {'QGA w32 disk info': config_host.has_key('CONFIG_QGA_NTDDSCSI')}
2159  summary_info += {'QGA MSI support':   config_host.has_key('CONFIG_QGA_MSI')}
2160endif
2161summary_info += {'seccomp support':   config_host.has_key('CONFIG_SECCOMP')}
2162summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']}
2163summary_info += {'coroutine pool':    config_host['CONFIG_COROUTINE_POOL'] == '1'}
2164summary_info += {'debug stack usage': config_host.has_key('CONFIG_DEBUG_STACK_USAGE')}
2165summary_info += {'mutex debugging':   config_host.has_key('CONFIG_DEBUG_MUTEX')}
2166summary_info += {'crypto afalg':      config_host.has_key('CONFIG_AF_ALG')}
2167summary_info += {'GlusterFS support': config_host.has_key('CONFIG_GLUSTERFS')}
2168summary_info += {'gcov':              get_option('b_coverage')}
2169summary_info += {'TPM support':       config_host.has_key('CONFIG_TPM')}
2170summary_info += {'libssh support':    config_host.has_key('CONFIG_LIBSSH')}
2171summary_info += {'QOM debugging':     config_host.has_key('CONFIG_QOM_CAST_DEBUG')}
2172summary_info += {'Live block migration': config_host.has_key('CONFIG_LIVE_BLOCK_MIGRATION')}
2173summary_info += {'lzo support':       config_host.has_key('CONFIG_LZO')}
2174summary_info += {'snappy support':    config_host.has_key('CONFIG_SNAPPY')}
2175summary_info += {'bzip2 support':     config_host.has_key('CONFIG_BZIP2')}
2176summary_info += {'lzfse support':     config_host.has_key('CONFIG_LZFSE')}
2177summary_info += {'zstd support':      config_host.has_key('CONFIG_ZSTD')}
2178summary_info += {'NUMA host support': config_host.has_key('CONFIG_NUMA')}
2179summary_info += {'libxml2':           config_host.has_key('CONFIG_LIBXML2')}
2180summary_info += {'memory allocator':  get_option('malloc')}
2181summary_info += {'avx2 optimization': config_host.has_key('CONFIG_AVX2_OPT')}
2182summary_info += {'avx512f optimization': config_host.has_key('CONFIG_AVX512F_OPT')}
2183summary_info += {'replication support': config_host.has_key('CONFIG_REPLICATION')}
2184summary_info += {'bochs support':     config_host.has_key('CONFIG_BOCHS')}
2185summary_info += {'cloop support':     config_host.has_key('CONFIG_CLOOP')}
2186summary_info += {'dmg support':       config_host.has_key('CONFIG_DMG')}
2187summary_info += {'qcow v1 support':   config_host.has_key('CONFIG_QCOW1')}
2188summary_info += {'vdi support':       config_host.has_key('CONFIG_VDI')}
2189summary_info += {'vvfat support':     config_host.has_key('CONFIG_VVFAT')}
2190summary_info += {'qed support':       config_host.has_key('CONFIG_QED')}
2191summary_info += {'parallels support': config_host.has_key('CONFIG_PARALLELS')}
2192summary_info += {'sheepdog support':  config_host.has_key('CONFIG_SHEEPDOG')}
2193summary_info += {'capstone':          capstone_opt == 'disabled' ? false : capstone_opt}
2194summary_info += {'libpmem support':   config_host.has_key('CONFIG_LIBPMEM')}
2195summary_info += {'libdaxctl support': config_host.has_key('CONFIG_LIBDAXCTL')}
2196summary_info += {'libudev':           libudev.found()}
2197summary_info += {'default devices':   config_host['CONFIG_MINIKCONF_MODE'] == '--defconfig'}
2198summary_info += {'plugin support':    config_host.has_key('CONFIG_PLUGIN')}
2199summary_info += {'fuzzing support':   config_host.has_key('CONFIG_FUZZ')}
2200if config_host.has_key('HAVE_GDB_BIN')
2201  summary_info += {'gdb':             config_host['HAVE_GDB_BIN']}
2202endif
2203summary_info += {'thread sanitizer':  config_host.has_key('CONFIG_TSAN')}
2204summary_info += {'rng-none':          config_host.has_key('CONFIG_RNG_NONE')}
2205summary_info += {'Linux keyring':     config_host.has_key('CONFIG_SECRET_KEYRING')}
2206summary(summary_info, bool_yn: true)
2207
2208if not supported_cpus.contains(cpu)
2209  message()
2210  warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!')
2211  message()
2212  message('CPU host architecture ' + cpu + ' support is not currently maintained.')
2213  message('The QEMU project intends to remove support for this host CPU in')
2214  message('a future release if nobody volunteers to maintain it and to')
2215  message('provide a build host for our continuous integration setup.')
2216  message('configure has succeeded and you can continue to build, but')
2217  message('if you care about QEMU on this platform you should contact')
2218  message('us upstream at qemu-devel@nongnu.org.')
2219endif
2220
2221if not supported_oses.contains(targetos)
2222  message()
2223  warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!')
2224  message()
2225  message('Host OS ' + targetos + 'support is not currently maintained.')
2226  message('The QEMU project intends to remove support for this host OS in')
2227  message('a future release if nobody volunteers to maintain it and to')
2228  message('provide a build host for our continuous integration setup.')
2229  message('configure has succeeded and you can continue to build, but')
2230  message('if you care about QEMU on this platform you should contact')
2231  message('us upstream at qemu-devel@nongnu.org.')
2232endif
2233