xref: /openbmc/qemu/meson.build (revision 5ade579b)
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 = dependency('libjpeg', required: get_option('vnc_jpeg'),
658                    method: 'pkg-config', static: enable_static)
659  sasl = cc.find_library('sasl2', has_headers: ['sasl/sasl.h'],
660                         required: get_option('vnc_sasl'),
661                         static: enable_static)
662  if sasl.found()
663    sasl = declare_dependency(dependencies: sasl,
664                              compile_args: '-DSTRUCT_IOVEC_DEFINED')
665  endif
666endif
667snappy = not_found
668if 'CONFIG_SNAPPY' in config_host
669  snappy = declare_dependency(link_args: config_host['SNAPPY_LIBS'].split())
670endif
671lzo = not_found
672if 'CONFIG_LZO' in config_host
673  lzo = declare_dependency(link_args: config_host['LZO_LIBS'].split())
674endif
675rdma = not_found
676if 'CONFIG_RDMA' in config_host
677  rdma = declare_dependency(link_args: config_host['RDMA_LIBS'].split())
678endif
679numa = not_found
680if 'CONFIG_NUMA' in config_host
681  numa = declare_dependency(link_args: config_host['NUMA_LIBS'].split())
682endif
683xen = not_found
684if 'CONFIG_XEN_BACKEND' in config_host
685  xen = declare_dependency(compile_args: config_host['XEN_CFLAGS'].split(),
686                           link_args: config_host['XEN_LIBS'].split())
687endif
688cacard = not_found
689if 'CONFIG_SMARTCARD' in config_host
690  cacard = declare_dependency(compile_args: config_host['SMARTCARD_CFLAGS'].split(),
691                              link_args: config_host['SMARTCARD_LIBS'].split())
692endif
693u2f = not_found
694if have_system
695  u2f = dependency('u2f-emu', required: get_option('u2f'),
696                   method: 'pkg-config',
697                   static: enable_static)
698endif
699usbredir = not_found
700if 'CONFIG_USB_REDIR' in config_host
701  usbredir = declare_dependency(compile_args: config_host['USB_REDIR_CFLAGS'].split(),
702                                link_args: config_host['USB_REDIR_LIBS'].split())
703endif
704libusb = not_found
705if 'CONFIG_USB_LIBUSB' in config_host
706  libusb = declare_dependency(compile_args: config_host['LIBUSB_CFLAGS'].split(),
707                              link_args: config_host['LIBUSB_LIBS'].split())
708endif
709libpmem = not_found
710if 'CONFIG_LIBPMEM' in config_host
711  libpmem = declare_dependency(compile_args: config_host['LIBPMEM_CFLAGS'].split(),
712                               link_args: config_host['LIBPMEM_LIBS'].split())
713endif
714libdaxctl = not_found
715if 'CONFIG_LIBDAXCTL' in config_host
716  libdaxctl = declare_dependency(link_args: config_host['LIBDAXCTL_LIBS'].split())
717endif
718tasn1 = not_found
719if 'CONFIG_TASN1' in config_host
720  tasn1 = declare_dependency(compile_args: config_host['TASN1_CFLAGS'].split(),
721                             link_args: config_host['TASN1_LIBS'].split())
722endif
723keyutils = dependency('libkeyutils', required: false,
724                      method: 'pkg-config', static: enable_static)
725
726has_gettid = cc.has_function('gettid')
727
728# Malloc tests
729
730malloc = []
731if get_option('malloc') == 'system'
732  has_malloc_trim = \
733    not get_option('malloc_trim').disabled() and \
734    cc.links('''#include <malloc.h>
735                int main(void) { malloc_trim(0); return 0; }''')
736else
737  has_malloc_trim = false
738  malloc = cc.find_library(get_option('malloc'), required: true)
739endif
740if not has_malloc_trim and get_option('malloc_trim').enabled()
741  if get_option('malloc') == 'system'
742    error('malloc_trim not available on this platform.')
743  else
744    error('malloc_trim not available with non-libc memory allocator')
745  endif
746endif
747
748# Check whether the glibc provides statx()
749
750statx_test = '''
751  #ifndef _GNU_SOURCE
752  #define _GNU_SOURCE
753  #endif
754  #include <sys/stat.h>
755  int main(void) {
756    struct statx statxbuf;
757    statx(0, "", 0, STATX_BASIC_STATS, &statxbuf);
758    return 0;
759  }'''
760
761has_statx = cc.links(statx_test)
762
763have_vhost_user_blk_server = (targetos == 'linux' and
764    'CONFIG_VHOST_USER' in config_host)
765
766if get_option('vhost_user_blk_server').enabled()
767    if targetos != 'linux'
768        error('vhost_user_blk_server requires linux')
769    elif 'CONFIG_VHOST_USER' not in config_host
770        error('vhost_user_blk_server requires vhost-user support')
771    endif
772elif get_option('vhost_user_blk_server').disabled() or not have_system
773    have_vhost_user_blk_server = false
774endif
775
776#################
777# config-host.h #
778#################
779
780config_host_data.set_quoted('CONFIG_BINDIR', get_option('prefix') / get_option('bindir'))
781config_host_data.set_quoted('CONFIG_PREFIX', get_option('prefix'))
782config_host_data.set_quoted('CONFIG_QEMU_CONFDIR', get_option('prefix') / qemu_confdir)
783config_host_data.set_quoted('CONFIG_QEMU_DATADIR', get_option('prefix') / qemu_datadir)
784config_host_data.set_quoted('CONFIG_QEMU_DESKTOPDIR', get_option('prefix') / qemu_desktopdir)
785config_host_data.set_quoted('CONFIG_QEMU_FIRMWAREPATH', get_option('qemu_firmwarepath'))
786config_host_data.set_quoted('CONFIG_QEMU_HELPERDIR', get_option('prefix') / get_option('libexecdir'))
787config_host_data.set_quoted('CONFIG_QEMU_ICONDIR', get_option('prefix') / qemu_icondir)
788config_host_data.set_quoted('CONFIG_QEMU_LOCALEDIR', get_option('prefix') / get_option('localedir'))
789config_host_data.set_quoted('CONFIG_QEMU_LOCALSTATEDIR', get_option('prefix') / get_option('localstatedir'))
790config_host_data.set_quoted('CONFIG_QEMU_MODDIR', get_option('prefix') / qemu_moddir)
791config_host_data.set_quoted('CONFIG_SYSCONFDIR', get_option('prefix') / get_option('sysconfdir'))
792
793config_host_data.set('CONFIG_COCOA', cocoa.found())
794config_host_data.set('CONFIG_LIBUDEV', libudev.found())
795config_host_data.set('CONFIG_MPATH', mpathpersist.found())
796config_host_data.set('CONFIG_MPATH_NEW_API', mpathpersist_new_api)
797config_host_data.set('CONFIG_CURSES', curses.found())
798config_host_data.set('CONFIG_SDL', sdl.found())
799config_host_data.set('CONFIG_SDL_IMAGE', sdl_image.found())
800config_host_data.set('CONFIG_VHOST_USER_BLK_SERVER', have_vhost_user_blk_server)
801config_host_data.set('CONFIG_VNC', vnc.found())
802config_host_data.set('CONFIG_VNC_JPEG', jpeg.found())
803config_host_data.set('CONFIG_VNC_PNG', png.found())
804config_host_data.set('CONFIG_VNC_SASL', sasl.found())
805config_host_data.set('CONFIG_XKBCOMMON', xkbcommon.found())
806config_host_data.set('CONFIG_KEYUTILS', keyutils.found())
807config_host_data.set('CONFIG_GETTID', has_gettid)
808config_host_data.set('CONFIG_MALLOC_TRIM', has_malloc_trim)
809config_host_data.set('CONFIG_STATX', has_statx)
810config_host_data.set('QEMU_VERSION', '"@0@"'.format(meson.project_version()))
811config_host_data.set('QEMU_VERSION_MAJOR', meson.project_version().split('.')[0])
812config_host_data.set('QEMU_VERSION_MINOR', meson.project_version().split('.')[1])
813config_host_data.set('QEMU_VERSION_MICRO', meson.project_version().split('.')[2])
814
815config_host_data.set('HAVE_SYS_IOCCOM_H', cc.has_header('sys/ioccom.h'))
816
817ignored = ['CONFIG_QEMU_INTERP_PREFIX'] # actually per-target
818arrays = ['CONFIG_AUDIO_DRIVERS', 'CONFIG_BDRV_RW_WHITELIST', 'CONFIG_BDRV_RO_WHITELIST']
819strings = ['HOST_DSOSUF', 'CONFIG_IASL']
820foreach k, v: config_host
821  if ignored.contains(k)
822    # do nothing
823  elif arrays.contains(k)
824    if v != ''
825      v = '"' + '", "'.join(v.split()) + '", '
826    endif
827    config_host_data.set(k, v)
828  elif k == 'ARCH'
829    config_host_data.set('HOST_' + v.to_upper(), 1)
830  elif strings.contains(k)
831    if not k.startswith('CONFIG_')
832      k = 'CONFIG_' + k.to_upper()
833    endif
834    config_host_data.set_quoted(k, v)
835  elif k.startswith('CONFIG_') or k.startswith('HAVE_') or k.startswith('HOST_')
836    config_host_data.set(k, v == 'y' ? 1 : v)
837  endif
838endforeach
839
840########################
841# Target configuration #
842########################
843
844minikconf = find_program('scripts/minikconf.py')
845config_all = {}
846config_all_devices = {}
847config_all_disas = {}
848config_devices_mak_list = []
849config_devices_h = {}
850config_target_h = {}
851config_target_mak = {}
852
853disassemblers = {
854  'alpha' : ['CONFIG_ALPHA_DIS'],
855  'arm' : ['CONFIG_ARM_DIS'],
856  'avr' : ['CONFIG_AVR_DIS'],
857  'cris' : ['CONFIG_CRIS_DIS'],
858  'hppa' : ['CONFIG_HPPA_DIS'],
859  'i386' : ['CONFIG_I386_DIS'],
860  'x86_64' : ['CONFIG_I386_DIS'],
861  'x32' : ['CONFIG_I386_DIS'],
862  'lm32' : ['CONFIG_LM32_DIS'],
863  'm68k' : ['CONFIG_M68K_DIS'],
864  'microblaze' : ['CONFIG_MICROBLAZE_DIS'],
865  'mips' : ['CONFIG_MIPS_DIS'],
866  'moxie' : ['CONFIG_MOXIE_DIS'],
867  'nios2' : ['CONFIG_NIOS2_DIS'],
868  'or1k' : ['CONFIG_OPENRISC_DIS'],
869  'ppc' : ['CONFIG_PPC_DIS'],
870  'riscv' : ['CONFIG_RISCV_DIS'],
871  'rx' : ['CONFIG_RX_DIS'],
872  's390' : ['CONFIG_S390_DIS'],
873  'sh4' : ['CONFIG_SH4_DIS'],
874  'sparc' : ['CONFIG_SPARC_DIS'],
875  'xtensa' : ['CONFIG_XTENSA_DIS'],
876}
877if link_language == 'cpp'
878  disassemblers += {
879    'aarch64' : [ 'CONFIG_ARM_A64_DIS'],
880    'arm' : [ 'CONFIG_ARM_DIS', 'CONFIG_ARM_A64_DIS'],
881    'mips' : [ 'CONFIG_MIPS_DIS', 'CONFIG_NANOMIPS_DIS'],
882  }
883endif
884
885kconfig_external_symbols = [
886  'CONFIG_KVM',
887  'CONFIG_XEN',
888  'CONFIG_TPM',
889  'CONFIG_SPICE',
890  'CONFIG_IVSHMEM',
891  'CONFIG_OPENGL',
892  'CONFIG_X11',
893  'CONFIG_VHOST_USER',
894  'CONFIG_VHOST_VDPA',
895  'CONFIG_VHOST_KERNEL',
896  'CONFIG_VIRTFS',
897  'CONFIG_LINUX',
898  'CONFIG_PVRDMA',
899]
900ignored = [ 'TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_ARCH' ]
901
902default_targets = 'CONFIG_DEFAULT_TARGETS' in config_host
903actual_target_dirs = []
904fdt_required = []
905foreach target : target_dirs
906  config_target = { 'TARGET_NAME': target.split('-')[0] }
907  if target.endswith('linux-user')
908    if targetos != 'linux'
909      if default_targets
910        continue
911      endif
912      error('Target @0@ is only available on a Linux host'.format(target))
913    endif
914    config_target += { 'CONFIG_LINUX_USER': 'y' }
915  elif target.endswith('bsd-user')
916    if 'CONFIG_BSD' not in config_host
917      if default_targets
918        continue
919      endif
920      error('Target @0@ is only available on a BSD host'.format(target))
921    endif
922    config_target += { 'CONFIG_BSD_USER': 'y' }
923  elif target.endswith('softmmu')
924    config_target += { 'CONFIG_SOFTMMU': 'y' }
925  endif
926  if target.endswith('-user')
927    config_target += {
928      'CONFIG_USER_ONLY': 'y',
929      'CONFIG_QEMU_INTERP_PREFIX':
930        config_host['CONFIG_QEMU_INTERP_PREFIX'].format(config_target['TARGET_NAME'])
931    }
932  endif
933
934  have_accel = false
935  foreach sym: accelerators
936    if sym == 'CONFIG_TCG' or target in accelerator_targets.get(sym, [])
937      config_target += { sym: 'y' }
938      config_all += { sym: 'y' }
939      if sym == 'CONFIG_XEN' and have_xen_pci_passthrough
940        config_target += { 'CONFIG_XEN_PCI_PASSTHROUGH': 'y' }
941      endif
942      have_accel = true
943    endif
944  endforeach
945  if not have_accel
946    if default_targets
947      continue
948    endif
949    error('No accelerator available for target @0@'.format(target))
950  endif
951
952  actual_target_dirs += target
953  config_target += keyval.load('default-configs/targets' / target + '.mak')
954  config_target += { 'TARGET_' + config_target['TARGET_ARCH'].to_upper(): 'y' }
955
956  if 'TARGET_NEED_FDT' in config_target
957    fdt_required += target
958  endif
959
960  # Add default keys
961  if 'TARGET_BASE_ARCH' not in config_target
962    config_target += {'TARGET_BASE_ARCH': config_target['TARGET_ARCH']}
963  endif
964  if 'TARGET_ABI_DIR' not in config_target
965    config_target += {'TARGET_ABI_DIR': config_target['TARGET_ARCH']}
966  endif
967
968  foreach k, v: disassemblers
969    if config_host['ARCH'].startswith(k) or config_target['TARGET_BASE_ARCH'].startswith(k)
970      foreach sym: v
971        config_target += { sym: 'y' }
972        config_all_disas += { sym: 'y' }
973      endforeach
974    endif
975  endforeach
976
977  config_target_data = configuration_data()
978  foreach k, v: config_target
979    if not k.startswith('TARGET_') and not k.startswith('CONFIG_')
980      # do nothing
981    elif ignored.contains(k)
982      # do nothing
983    elif k == 'TARGET_BASE_ARCH'
984      # Note that TARGET_BASE_ARCH ends up in config-target.h but it is
985      # not used to select files from sourcesets.
986      config_target_data.set('TARGET_' + v.to_upper(), 1)
987    elif k == 'TARGET_NAME' or k == 'CONFIG_QEMU_INTERP_PREFIX'
988      config_target_data.set_quoted(k, v)
989    elif v == 'y'
990      config_target_data.set(k, 1)
991    else
992      config_target_data.set(k, v)
993    endif
994  endforeach
995  config_target_h += {target: configure_file(output: target + '-config-target.h',
996                                               configuration: config_target_data)}
997
998  if target.endswith('-softmmu')
999    base_kconfig = []
1000    foreach sym : kconfig_external_symbols
1001      if sym in config_target or sym in config_host
1002        base_kconfig += '@0@=y'.format(sym)
1003      endif
1004    endforeach
1005
1006    config_devices_mak = target + '-config-devices.mak'
1007    config_devices_mak = configure_file(
1008      input: ['default-configs/devices' / target + '.mak', 'Kconfig'],
1009      output: config_devices_mak,
1010      depfile: config_devices_mak + '.d',
1011      capture: true,
1012      command: [minikconf, config_host['CONFIG_MINIKCONF_MODE'],
1013                config_devices_mak, '@DEPFILE@', '@INPUT@',
1014                base_kconfig])
1015
1016    config_devices_data = configuration_data()
1017    config_devices = keyval.load(config_devices_mak)
1018    foreach k, v: config_devices
1019      config_devices_data.set(k, 1)
1020    endforeach
1021    config_devices_mak_list += config_devices_mak
1022    config_devices_h += {target: configure_file(output: target + '-config-devices.h',
1023                                                configuration: config_devices_data)}
1024    config_target += config_devices
1025    config_all_devices += config_devices
1026  endif
1027  config_target_mak += {target: config_target}
1028endforeach
1029target_dirs = actual_target_dirs
1030
1031# This configuration is used to build files that are shared by
1032# multiple binaries, and then extracted out of the "common"
1033# static_library target.
1034#
1035# We do not use all_sources()/all_dependencies(), because it would
1036# build literally all source files, including devices only used by
1037# targets that are not built for this compilation.  The CONFIG_ALL
1038# pseudo symbol replaces it.
1039
1040config_all += config_all_devices
1041config_all += config_host
1042config_all += config_all_disas
1043config_all += {
1044  'CONFIG_XEN': config_host.has_key('CONFIG_XEN_BACKEND'),
1045  'CONFIG_SOFTMMU': have_system,
1046  'CONFIG_USER_ONLY': have_user,
1047  'CONFIG_ALL': true,
1048}
1049
1050##############
1051# Submodules #
1052##############
1053
1054capstone = not_found
1055capstone_opt = get_option('capstone')
1056if capstone_opt in ['enabled', 'auto', 'system']
1057  have_internal = fs.exists(meson.current_source_dir() / 'capstone/Makefile')
1058  capstone = dependency('capstone', version: '>=4.0',
1059                        static: enable_static, method: 'pkg-config',
1060                        required: capstone_opt == 'system' or
1061                                  capstone_opt == 'enabled' and not have_internal)
1062  if capstone.found()
1063    capstone_opt = 'system'
1064  elif have_internal
1065    capstone_opt = 'internal'
1066  else
1067    capstone_opt = 'disabled'
1068  endif
1069endif
1070if capstone_opt == 'internal'
1071  capstone_data = configuration_data()
1072  capstone_data.set('CAPSTONE_USE_SYS_DYN_MEM', '1')
1073
1074  capstone_files = files(
1075    'capstone/cs.c',
1076    'capstone/MCInst.c',
1077    'capstone/MCInstrDesc.c',
1078    'capstone/MCRegisterInfo.c',
1079    'capstone/SStream.c',
1080    'capstone/utils.c'
1081  )
1082
1083  if 'CONFIG_ARM_DIS' in config_all_disas
1084    capstone_data.set('CAPSTONE_HAS_ARM', '1')
1085    capstone_files += files(
1086      'capstone/arch/ARM/ARMDisassembler.c',
1087      'capstone/arch/ARM/ARMInstPrinter.c',
1088      'capstone/arch/ARM/ARMMapping.c',
1089      'capstone/arch/ARM/ARMModule.c'
1090    )
1091  endif
1092
1093  # FIXME: This config entry currently depends on a c++ compiler.
1094  # Which is needed for building libvixl, but not for capstone.
1095  if 'CONFIG_ARM_A64_DIS' in config_all_disas
1096    capstone_data.set('CAPSTONE_HAS_ARM64', '1')
1097    capstone_files += files(
1098      'capstone/arch/AArch64/AArch64BaseInfo.c',
1099      'capstone/arch/AArch64/AArch64Disassembler.c',
1100      'capstone/arch/AArch64/AArch64InstPrinter.c',
1101      'capstone/arch/AArch64/AArch64Mapping.c',
1102      'capstone/arch/AArch64/AArch64Module.c'
1103    )
1104  endif
1105
1106  if 'CONFIG_PPC_DIS' in config_all_disas
1107    capstone_data.set('CAPSTONE_HAS_POWERPC', '1')
1108    capstone_files += files(
1109      'capstone/arch/PowerPC/PPCDisassembler.c',
1110      'capstone/arch/PowerPC/PPCInstPrinter.c',
1111      'capstone/arch/PowerPC/PPCMapping.c',
1112      'capstone/arch/PowerPC/PPCModule.c'
1113    )
1114  endif
1115
1116  if 'CONFIG_S390_DIS' in config_all_disas
1117    capstone_data.set('CAPSTONE_HAS_SYSZ', '1')
1118    capstone_files += files(
1119      'capstone/arch/SystemZ/SystemZDisassembler.c',
1120      'capstone/arch/SystemZ/SystemZInstPrinter.c',
1121      'capstone/arch/SystemZ/SystemZMapping.c',
1122      'capstone/arch/SystemZ/SystemZModule.c',
1123      'capstone/arch/SystemZ/SystemZMCTargetDesc.c'
1124    )
1125  endif
1126
1127  if 'CONFIG_I386_DIS' in config_all_disas
1128    capstone_data.set('CAPSTONE_HAS_X86', 1)
1129    capstone_files += files(
1130      'capstone/arch/X86/X86Disassembler.c',
1131      'capstone/arch/X86/X86DisassemblerDecoder.c',
1132      'capstone/arch/X86/X86ATTInstPrinter.c',
1133      'capstone/arch/X86/X86IntelInstPrinter.c',
1134      'capstone/arch/X86/X86InstPrinterCommon.c',
1135      'capstone/arch/X86/X86Mapping.c',
1136      'capstone/arch/X86/X86Module.c'
1137    )
1138  endif
1139
1140  configure_file(output: 'capstone-defs.h', configuration: capstone_data)
1141
1142  capstone_cargs = [
1143    # FIXME: There does not seem to be a way to completely replace the c_args
1144    # that come from add_project_arguments() -- we can only add to them.
1145    # So: disable all warnings with a big hammer.
1146    '-Wno-error', '-w',
1147
1148    # Include all configuration defines via a header file, which will wind up
1149    # as a dependency on the object file, and thus changes here will result
1150    # in a rebuild.
1151    '-include', 'capstone-defs.h'
1152  ]
1153
1154  libcapstone = static_library('capstone',
1155                               sources: capstone_files,
1156                               c_args: capstone_cargs,
1157                               include_directories: 'capstone/include')
1158  capstone = declare_dependency(link_with: libcapstone,
1159                                include_directories: 'capstone/include/capstone')
1160endif
1161
1162slirp = not_found
1163slirp_opt = 'disabled'
1164if have_system
1165  slirp_opt = get_option('slirp')
1166  if slirp_opt in ['enabled', 'auto', 'system']
1167    have_internal = fs.exists(meson.current_source_dir() / 'slirp/meson.build')
1168    slirp = dependency('slirp', static: enable_static,
1169                       method: 'pkg-config',
1170                       required: slirp_opt == 'system' or
1171                                 slirp_opt == 'enabled' and not have_internal)
1172    if slirp.found()
1173      slirp_opt = 'system'
1174    elif have_internal
1175      slirp_opt = 'internal'
1176    else
1177      slirp_opt = 'disabled'
1178    endif
1179  endif
1180  if slirp_opt == 'internal'
1181    slirp_deps = []
1182    if targetos == 'windows'
1183      slirp_deps = cc.find_library('iphlpapi')
1184    endif
1185    slirp_conf = configuration_data()
1186    slirp_conf.set('SLIRP_MAJOR_VERSION', meson.project_version().split('.')[0])
1187    slirp_conf.set('SLIRP_MINOR_VERSION', meson.project_version().split('.')[1])
1188    slirp_conf.set('SLIRP_MICRO_VERSION', meson.project_version().split('.')[2])
1189    slirp_conf.set_quoted('SLIRP_VERSION_STRING', meson.project_version())
1190    slirp_cargs = ['-DG_LOG_DOMAIN="Slirp"']
1191    slirp_files = [
1192      'slirp/src/arp_table.c',
1193      'slirp/src/bootp.c',
1194      'slirp/src/cksum.c',
1195      'slirp/src/dhcpv6.c',
1196      'slirp/src/dnssearch.c',
1197      'slirp/src/if.c',
1198      'slirp/src/ip6_icmp.c',
1199      'slirp/src/ip6_input.c',
1200      'slirp/src/ip6_output.c',
1201      'slirp/src/ip_icmp.c',
1202      'slirp/src/ip_input.c',
1203      'slirp/src/ip_output.c',
1204      'slirp/src/mbuf.c',
1205      'slirp/src/misc.c',
1206      'slirp/src/ncsi.c',
1207      'slirp/src/ndp_table.c',
1208      'slirp/src/sbuf.c',
1209      'slirp/src/slirp.c',
1210      'slirp/src/socket.c',
1211      'slirp/src/state.c',
1212      'slirp/src/stream.c',
1213      'slirp/src/tcp_input.c',
1214      'slirp/src/tcp_output.c',
1215      'slirp/src/tcp_subr.c',
1216      'slirp/src/tcp_timer.c',
1217      'slirp/src/tftp.c',
1218      'slirp/src/udp.c',
1219      'slirp/src/udp6.c',
1220      'slirp/src/util.c',
1221      'slirp/src/version.c',
1222      'slirp/src/vmstate.c',
1223    ]
1224
1225    configure_file(
1226      input : 'slirp/src/libslirp-version.h.in',
1227      output : 'libslirp-version.h',
1228      configuration: slirp_conf)
1229
1230    slirp_inc = include_directories('slirp', 'slirp/src')
1231    libslirp = static_library('slirp',
1232                              sources: slirp_files,
1233                              c_args: slirp_cargs,
1234                              include_directories: slirp_inc)
1235    slirp = declare_dependency(link_with: libslirp,
1236                               dependencies: slirp_deps,
1237                               include_directories: slirp_inc)
1238  endif
1239endif
1240
1241fdt = not_found
1242fdt_opt = get_option('fdt')
1243if have_system
1244  if fdt_opt in ['enabled', 'auto', 'system']
1245    have_internal = fs.exists(meson.current_source_dir() / 'dtc/libfdt/Makefile.libfdt')
1246    fdt = cc.find_library('fdt', static: enable_static,
1247                          required: fdt_opt == 'system' or
1248                                    fdt_opt == 'enabled' and not have_internal)
1249    if fdt.found() and cc.links('''
1250       #include <libfdt.h>
1251       #include <libfdt_env.h>
1252       int main(void) { fdt_check_full(NULL, 0); return 0; }''',
1253         dependencies: fdt)
1254      fdt_opt = 'system'
1255    elif have_internal
1256      fdt_opt = 'internal'
1257    else
1258      fdt_opt = 'disabled'
1259    endif
1260  endif
1261  if fdt_opt == 'internal'
1262    fdt_files = files(
1263      'dtc/libfdt/fdt.c',
1264      'dtc/libfdt/fdt_ro.c',
1265      'dtc/libfdt/fdt_wip.c',
1266      'dtc/libfdt/fdt_sw.c',
1267      'dtc/libfdt/fdt_rw.c',
1268      'dtc/libfdt/fdt_strerror.c',
1269      'dtc/libfdt/fdt_empty_tree.c',
1270      'dtc/libfdt/fdt_addresses.c',
1271      'dtc/libfdt/fdt_overlay.c',
1272      'dtc/libfdt/fdt_check.c',
1273    )
1274
1275    fdt_inc = include_directories('dtc/libfdt')
1276    libfdt = static_library('fdt',
1277                            sources: fdt_files,
1278                            include_directories: fdt_inc)
1279    fdt = declare_dependency(link_with: libfdt,
1280                             include_directories: fdt_inc)
1281  endif
1282endif
1283if not fdt.found() and fdt_required.length() > 0
1284  error('fdt not available but required by targets ' + ', '.join(fdt_required))
1285endif
1286
1287config_host_data.set('CONFIG_CAPSTONE', capstone.found())
1288config_host_data.set('CONFIG_FDT', fdt.found())
1289config_host_data.set('CONFIG_SLIRP', slirp.found())
1290
1291#####################
1292# Generated sources #
1293#####################
1294
1295genh += configure_file(output: 'config-host.h', configuration: config_host_data)
1296
1297hxtool = find_program('scripts/hxtool')
1298shaderinclude = find_program('scripts/shaderinclude.pl')
1299qapi_gen = find_program('scripts/qapi-gen.py')
1300qapi_gen_depends = [ meson.source_root() / 'scripts/qapi/__init__.py',
1301                     meson.source_root() / 'scripts/qapi/commands.py',
1302                     meson.source_root() / 'scripts/qapi/common.py',
1303                     meson.source_root() / 'scripts/qapi/error.py',
1304                     meson.source_root() / 'scripts/qapi/events.py',
1305                     meson.source_root() / 'scripts/qapi/expr.py',
1306                     meson.source_root() / 'scripts/qapi/gen.py',
1307                     meson.source_root() / 'scripts/qapi/introspect.py',
1308                     meson.source_root() / 'scripts/qapi/parser.py',
1309                     meson.source_root() / 'scripts/qapi/schema.py',
1310                     meson.source_root() / 'scripts/qapi/source.py',
1311                     meson.source_root() / 'scripts/qapi/types.py',
1312                     meson.source_root() / 'scripts/qapi/visit.py',
1313                     meson.source_root() / 'scripts/qapi/common.py',
1314                     meson.source_root() / 'scripts/qapi-gen.py'
1315]
1316
1317tracetool = [
1318  python, files('scripts/tracetool.py'),
1319   '--backend=' + config_host['TRACE_BACKENDS']
1320]
1321
1322qemu_version_cmd = [find_program('scripts/qemu-version.sh'),
1323                    meson.current_source_dir(),
1324                    config_host['PKGVERSION'], meson.project_version()]
1325qemu_version = custom_target('qemu-version.h',
1326                             output: 'qemu-version.h',
1327                             command: qemu_version_cmd,
1328                             capture: true,
1329                             build_by_default: true,
1330                             build_always_stale: true)
1331genh += qemu_version
1332
1333hxdep = []
1334hx_headers = [
1335  ['qemu-options.hx', 'qemu-options.def'],
1336  ['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
1337]
1338if have_system
1339  hx_headers += [
1340    ['hmp-commands.hx', 'hmp-commands.h'],
1341    ['hmp-commands-info.hx', 'hmp-commands-info.h'],
1342  ]
1343endif
1344foreach d : hx_headers
1345  hxdep += custom_target(d[1],
1346                input: files(d[0]),
1347                output: d[1],
1348                capture: true,
1349                build_by_default: true, # to be removed when added to a target
1350                command: [hxtool, '-h', '@INPUT0@'])
1351endforeach
1352genh += hxdep
1353
1354###################
1355# Collect sources #
1356###################
1357
1358authz_ss = ss.source_set()
1359blockdev_ss = ss.source_set()
1360block_ss = ss.source_set()
1361bsd_user_ss = ss.source_set()
1362chardev_ss = ss.source_set()
1363common_ss = ss.source_set()
1364crypto_ss = ss.source_set()
1365io_ss = ss.source_set()
1366linux_user_ss = ss.source_set()
1367qmp_ss = ss.source_set()
1368qom_ss = ss.source_set()
1369softmmu_ss = ss.source_set()
1370specific_fuzz_ss = ss.source_set()
1371specific_ss = ss.source_set()
1372stub_ss = ss.source_set()
1373trace_ss = ss.source_set()
1374user_ss = ss.source_set()
1375util_ss = ss.source_set()
1376
1377modules = {}
1378hw_arch = {}
1379target_arch = {}
1380target_softmmu_arch = {}
1381
1382###############
1383# Trace files #
1384###############
1385
1386# TODO: add each directory to the subdirs from its own meson.build, once
1387# we have those
1388trace_events_subdirs = [
1389  'accel/kvm',
1390  'accel/tcg',
1391  'crypto',
1392  'monitor',
1393]
1394if have_user
1395  trace_events_subdirs += [ 'linux-user' ]
1396endif
1397if have_block
1398  trace_events_subdirs += [
1399    'authz',
1400    'block',
1401    'io',
1402    'nbd',
1403    'scsi',
1404  ]
1405endif
1406if have_system
1407  trace_events_subdirs += [
1408    'audio',
1409    'backends',
1410    'backends/tpm',
1411    'chardev',
1412    'hw/9pfs',
1413    'hw/acpi',
1414    'hw/alpha',
1415    'hw/arm',
1416    'hw/audio',
1417    'hw/block',
1418    'hw/block/dataplane',
1419    'hw/char',
1420    'hw/display',
1421    'hw/dma',
1422    'hw/hppa',
1423    'hw/hyperv',
1424    'hw/i2c',
1425    'hw/i386',
1426    'hw/i386/xen',
1427    'hw/ide',
1428    'hw/input',
1429    'hw/intc',
1430    'hw/isa',
1431    'hw/mem',
1432    'hw/mips',
1433    'hw/misc',
1434    'hw/misc/macio',
1435    'hw/net',
1436    'hw/net/can',
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
1479vhost_user = not_found
1480if 'CONFIG_VHOST_USER' in config_host
1481  libvhost_user = subproject('libvhost-user')
1482  vhost_user = libvhost_user.get_variable('vhost_user_dep')
1483endif
1484
1485subdir('qapi')
1486subdir('qobject')
1487subdir('stubs')
1488subdir('trace')
1489subdir('util')
1490subdir('qom')
1491subdir('authz')
1492subdir('crypto')
1493subdir('ui')
1494
1495
1496if enable_modules
1497  libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
1498  modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
1499endif
1500
1501stub_ss = stub_ss.apply(config_all, strict: false)
1502
1503util_ss.add_all(trace_ss)
1504util_ss = util_ss.apply(config_all, strict: false)
1505libqemuutil = static_library('qemuutil',
1506                             sources: util_ss.sources() + stub_ss.sources() + genh,
1507                             dependencies: [util_ss.dependencies(), m, glib, socket, malloc])
1508qemuutil = declare_dependency(link_with: libqemuutil,
1509                              sources: genh + version_res)
1510
1511decodetree = generator(find_program('scripts/decodetree.py'),
1512                       output: 'decode-@BASENAME@.c.inc',
1513                       arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
1514
1515subdir('audio')
1516subdir('io')
1517subdir('chardev')
1518subdir('fsdev')
1519subdir('libdecnumber')
1520subdir('target')
1521subdir('dump')
1522
1523block_ss.add(files(
1524  'block.c',
1525  'blockjob.c',
1526  'job.c',
1527  'qemu-io-cmds.c',
1528))
1529block_ss.add(when: 'CONFIG_REPLICATION', if_true: files('replication.c'))
1530
1531subdir('nbd')
1532subdir('scsi')
1533subdir('block')
1534
1535blockdev_ss.add(files(
1536  'blockdev.c',
1537  'blockdev-nbd.c',
1538  'iothread.c',
1539  'job-qmp.c',
1540))
1541
1542# os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
1543# os-win32.c does not
1544blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c'))
1545softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')])
1546
1547common_ss.add(files('cpus-common.c'))
1548
1549subdir('softmmu')
1550
1551common_ss.add(capstone)
1552specific_ss.add(files('cpu.c', 'disas.c', 'gdbstub.c'), capstone)
1553specific_ss.add(files('exec-vary.c'))
1554specific_ss.add(when: 'CONFIG_TCG', if_true: files(
1555  'fpu/softfloat.c',
1556  'tcg/optimize.c',
1557  'tcg/tcg-common.c',
1558  'tcg/tcg-op-gvec.c',
1559  'tcg/tcg-op-vec.c',
1560  'tcg/tcg-op.c',
1561  'tcg/tcg.c',
1562))
1563specific_ss.add(when: 'CONFIG_TCG_INTERPRETER', if_true: files('disas/tci.c', 'tcg/tci.c'))
1564
1565subdir('backends')
1566subdir('disas')
1567subdir('migration')
1568subdir('monitor')
1569subdir('net')
1570subdir('replay')
1571subdir('hw')
1572subdir('accel')
1573subdir('plugins')
1574subdir('bsd-user')
1575subdir('linux-user')
1576
1577bsd_user_ss.add(files('gdbstub.c'))
1578specific_ss.add_all(when: 'CONFIG_BSD_USER', if_true: bsd_user_ss)
1579
1580linux_user_ss.add(files('gdbstub.c', 'thunk.c'))
1581specific_ss.add_all(when: 'CONFIG_LINUX_USER', if_true: linux_user_ss)
1582
1583# needed for fuzzing binaries
1584subdir('tests/qtest/libqos')
1585subdir('tests/qtest/fuzz')
1586
1587########################
1588# Library dependencies #
1589########################
1590
1591block_mods = []
1592softmmu_mods = []
1593foreach d, list : modules
1594  foreach m, module_ss : list
1595    if enable_modules and targetos != 'windows'
1596      module_ss = module_ss.apply(config_all, strict: false)
1597      sl = static_library(d + '-' + m, [genh, module_ss.sources()],
1598                          dependencies: [modulecommon, module_ss.dependencies()], pic: true)
1599      if d == 'block'
1600        block_mods += sl
1601      else
1602        softmmu_mods += sl
1603      endif
1604    else
1605      if d == 'block'
1606        block_ss.add_all(module_ss)
1607      else
1608        softmmu_ss.add_all(module_ss)
1609      endif
1610    endif
1611  endforeach
1612endforeach
1613
1614nm = find_program('nm')
1615undefsym = find_program('scripts/undefsym.py')
1616block_syms = custom_target('block.syms', output: 'block.syms',
1617                             input: [libqemuutil, block_mods],
1618                             capture: true,
1619                             command: [undefsym, nm, '@INPUT@'])
1620qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
1621                             input: [libqemuutil, softmmu_mods],
1622                             capture: true,
1623                             command: [undefsym, nm, '@INPUT@'])
1624
1625qom_ss = qom_ss.apply(config_host, strict: false)
1626libqom = static_library('qom', qom_ss.sources() + genh,
1627                        dependencies: [qom_ss.dependencies()],
1628                        name_suffix: 'fa')
1629
1630qom = declare_dependency(link_whole: libqom)
1631
1632authz_ss = authz_ss.apply(config_host, strict: false)
1633libauthz = static_library('authz', authz_ss.sources() + genh,
1634                          dependencies: [authz_ss.dependencies()],
1635                          name_suffix: 'fa',
1636                          build_by_default: false)
1637
1638authz = declare_dependency(link_whole: libauthz,
1639                           dependencies: qom)
1640
1641crypto_ss = crypto_ss.apply(config_host, strict: false)
1642libcrypto = static_library('crypto', crypto_ss.sources() + genh,
1643                           dependencies: [crypto_ss.dependencies()],
1644                           name_suffix: 'fa',
1645                           build_by_default: false)
1646
1647crypto = declare_dependency(link_whole: libcrypto,
1648                            dependencies: [authz, qom])
1649
1650io_ss = io_ss.apply(config_host, strict: false)
1651libio = static_library('io', io_ss.sources() + genh,
1652                       dependencies: [io_ss.dependencies()],
1653                       link_with: libqemuutil,
1654                       name_suffix: 'fa',
1655                       build_by_default: false)
1656
1657io = declare_dependency(link_whole: libio, dependencies: [crypto, qom])
1658
1659libmigration = static_library('migration', sources: migration_files + genh,
1660                              name_suffix: 'fa',
1661                              build_by_default: false)
1662migration = declare_dependency(link_with: libmigration,
1663                               dependencies: [zlib, qom, io])
1664softmmu_ss.add(migration)
1665
1666block_ss = block_ss.apply(config_host, strict: false)
1667libblock = static_library('block', block_ss.sources() + genh,
1668                          dependencies: block_ss.dependencies(),
1669                          link_depends: block_syms,
1670                          name_suffix: 'fa',
1671                          build_by_default: false)
1672
1673block = declare_dependency(link_whole: [libblock],
1674                           link_args: '@block.syms',
1675                           dependencies: [crypto, io])
1676
1677blockdev_ss = blockdev_ss.apply(config_host, strict: false)
1678libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
1679                             dependencies: blockdev_ss.dependencies(),
1680                             name_suffix: 'fa',
1681                             build_by_default: false)
1682
1683blockdev = declare_dependency(link_whole: [libblockdev],
1684                              dependencies: [block])
1685
1686qmp_ss = qmp_ss.apply(config_host, strict: false)
1687libqmp = static_library('qmp', qmp_ss.sources() + genh,
1688                        dependencies: qmp_ss.dependencies(),
1689                        name_suffix: 'fa',
1690                        build_by_default: false)
1691
1692qmp = declare_dependency(link_whole: [libqmp])
1693
1694libchardev = static_library('chardev', chardev_ss.sources() + genh,
1695                            name_suffix: 'fa',
1696                            build_by_default: false)
1697
1698chardev = declare_dependency(link_whole: libchardev)
1699
1700libhwcore = static_library('hwcore', sources: hwcore_files + genh,
1701                           name_suffix: 'fa',
1702                           build_by_default: false)
1703hwcore = declare_dependency(link_whole: libhwcore)
1704common_ss.add(hwcore)
1705
1706###########
1707# Targets #
1708###########
1709
1710foreach m : block_mods + softmmu_mods
1711  shared_module(m.name(),
1712                name_prefix: '',
1713                link_whole: m,
1714                install: true,
1715                install_dir: qemu_moddir)
1716endforeach
1717
1718softmmu_ss.add(authz, blockdev, chardev, crypto, io, qmp)
1719common_ss.add(qom, qemuutil)
1720
1721common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss])
1722common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
1723
1724common_all = common_ss.apply(config_all, strict: false)
1725common_all = static_library('common',
1726                            build_by_default: false,
1727                            sources: common_all.sources() + genh,
1728                            dependencies: common_all.dependencies(),
1729                            name_suffix: 'fa')
1730
1731feature_to_c = find_program('scripts/feature_to_c.sh')
1732
1733emulators = {}
1734foreach target : target_dirs
1735  config_target = config_target_mak[target]
1736  target_name = config_target['TARGET_NAME']
1737  arch = config_target['TARGET_BASE_ARCH']
1738  arch_srcs = [config_target_h[target]]
1739  arch_deps = []
1740  c_args = ['-DNEED_CPU_H',
1741            '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
1742            '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
1743  link_args = emulator_link_args
1744
1745  config_target += config_host
1746  target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
1747  if targetos == 'linux'
1748    target_inc += include_directories('linux-headers', is_system: true)
1749  endif
1750  if target.endswith('-softmmu')
1751    qemu_target_name = 'qemu-system-' + target_name
1752    target_type='system'
1753    t = target_softmmu_arch[arch].apply(config_target, strict: false)
1754    arch_srcs += t.sources()
1755    arch_deps += t.dependencies()
1756
1757    hw_dir = target_name == 'sparc64' ? 'sparc64' : arch
1758    hw = hw_arch[hw_dir].apply(config_target, strict: false)
1759    arch_srcs += hw.sources()
1760    arch_deps += hw.dependencies()
1761
1762    arch_srcs += config_devices_h[target]
1763    link_args += ['@block.syms', '@qemu.syms']
1764  else
1765    abi = config_target['TARGET_ABI_DIR']
1766    target_type='user'
1767    qemu_target_name = 'qemu-' + target_name
1768    if 'CONFIG_LINUX_USER' in config_target
1769      base_dir = 'linux-user'
1770      target_inc += include_directories('linux-user/host/' / config_host['ARCH'])
1771    else
1772      base_dir = 'bsd-user'
1773    endif
1774    target_inc += include_directories(
1775      base_dir,
1776      base_dir / abi,
1777    )
1778    if 'CONFIG_LINUX_USER' in config_target
1779      dir = base_dir / abi
1780      arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
1781      if config_target.has_key('TARGET_SYSTBL_ABI')
1782        arch_srcs += \
1783          syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
1784                                             extra_args : config_target['TARGET_SYSTBL_ABI'])
1785      endif
1786    endif
1787  endif
1788
1789  if 'TARGET_XML_FILES' in config_target
1790    gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
1791                                output: target + '-gdbstub-xml.c',
1792                                input: files(config_target['TARGET_XML_FILES'].split()),
1793                                command: [feature_to_c, '@INPUT@'],
1794                                capture: true)
1795    arch_srcs += gdbstub_xml
1796  endif
1797
1798  t = target_arch[arch].apply(config_target, strict: false)
1799  arch_srcs += t.sources()
1800  arch_deps += t.dependencies()
1801
1802  target_common = common_ss.apply(config_target, strict: false)
1803  objects = common_all.extract_objects(target_common.sources())
1804  deps = target_common.dependencies()
1805
1806  target_specific = specific_ss.apply(config_target, strict: false)
1807  arch_srcs += target_specific.sources()
1808  arch_deps += target_specific.dependencies()
1809
1810  lib = static_library('qemu-' + target,
1811                 sources: arch_srcs + genh,
1812                 dependencies: arch_deps,
1813                 objects: objects,
1814                 include_directories: target_inc,
1815                 c_args: c_args,
1816                 build_by_default: false,
1817                 name_suffix: 'fa')
1818
1819  if target.endswith('-softmmu')
1820    execs = [{
1821      'name': 'qemu-system-' + target_name,
1822      'gui': false,
1823      'sources': files('softmmu/main.c'),
1824      'dependencies': []
1825    }]
1826    if targetos == 'windows' and (sdl.found() or gtk.found())
1827      execs += [{
1828        'name': 'qemu-system-' + target_name + 'w',
1829        'gui': true,
1830        'sources': files('softmmu/main.c'),
1831        'dependencies': []
1832      }]
1833    endif
1834    if config_host.has_key('CONFIG_FUZZ')
1835      specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
1836      execs += [{
1837        'name': 'qemu-fuzz-' + target_name,
1838        'gui': false,
1839        'sources': specific_fuzz.sources(),
1840        'dependencies': specific_fuzz.dependencies(),
1841      }]
1842    endif
1843  else
1844    execs = [{
1845      'name': 'qemu-' + target_name,
1846      'gui': false,
1847      'sources': [],
1848      'dependencies': []
1849    }]
1850  endif
1851  foreach exe: execs
1852    emulators += {exe['name']:
1853         executable(exe['name'], exe['sources'],
1854               install: true,
1855               c_args: c_args,
1856               dependencies: arch_deps + deps + exe['dependencies'],
1857               objects: lib.extract_all_objects(recursive: true),
1858               link_language: link_language,
1859               link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
1860               link_args: link_args,
1861               gui_app: exe['gui'])
1862    }
1863
1864    if 'CONFIG_TRACE_SYSTEMTAP' in config_host
1865      foreach stp: [
1866        {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
1867        {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
1868        {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
1869        {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
1870      ]
1871        custom_target(exe['name'] + stp['ext'],
1872                      input: trace_events_all,
1873                      output: exe['name'] + stp['ext'],
1874                      capture: true,
1875                      install: stp['install'],
1876                      install_dir: get_option('datadir') / 'systemtap/tapset',
1877                      command: [
1878                        tracetool, '--group=all', '--format=' + stp['fmt'],
1879                        '--binary=' + stp['bin'],
1880                        '--target-name=' + target_name,
1881                        '--target-type=' + target_type,
1882                        '--probe-prefix=qemu.' + target_type + '.' + target_name,
1883                        '@INPUT@',
1884                      ])
1885      endforeach
1886    endif
1887  endforeach
1888endforeach
1889
1890# Other build targets
1891
1892if 'CONFIG_PLUGIN' in config_host
1893  install_headers('include/qemu/qemu-plugin.h')
1894endif
1895
1896if 'CONFIG_GUEST_AGENT' in config_host
1897  subdir('qga')
1898endif
1899
1900# Don't build qemu-keymap if xkbcommon is not explicitly enabled
1901# when we don't build tools or system
1902if xkbcommon.found()
1903  # used for the update-keymaps target, so include rules even if !have_tools
1904  qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
1905                           dependencies: [qemuutil, xkbcommon], install: have_tools)
1906endif
1907
1908if have_tools
1909  qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
1910             dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
1911  qemu_io = executable('qemu-io', files('qemu-io.c'),
1912             dependencies: [block, qemuutil], install: true)
1913  qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
1914               dependencies: [blockdev, qemuutil], install: true)
1915
1916  subdir('storage-daemon')
1917  subdir('contrib/rdmacm-mux')
1918  subdir('contrib/elf2dmp')
1919
1920  executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
1921             dependencies: qemuutil,
1922             install: true)
1923
1924  if 'CONFIG_VHOST_USER' in config_host
1925    subdir('contrib/vhost-user-blk')
1926    subdir('contrib/vhost-user-gpu')
1927    subdir('contrib/vhost-user-input')
1928    subdir('contrib/vhost-user-scsi')
1929  endif
1930
1931  if targetos == 'linux'
1932    executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
1933               dependencies: [qemuutil, libcap_ng],
1934               install: true,
1935               install_dir: get_option('libexecdir'))
1936
1937    executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
1938               dependencies: [authz, crypto, io, qom, qemuutil,
1939                              libcap_ng, mpathpersist],
1940               install: true)
1941  endif
1942
1943  if 'CONFIG_IVSHMEM' in config_host
1944    subdir('contrib/ivshmem-client')
1945    subdir('contrib/ivshmem-server')
1946  endif
1947endif
1948
1949subdir('scripts')
1950subdir('tools')
1951subdir('pc-bios')
1952subdir('docs')
1953subdir('tests')
1954if 'CONFIG_GTK' in config_host
1955  subdir('po')
1956endif
1957
1958if host_machine.system() == 'windows'
1959  nsis_cmd = [
1960    find_program('scripts/nsis.py'),
1961    '@OUTPUT@',
1962    get_option('prefix'),
1963    meson.current_source_dir(),
1964    host_machine.cpu(),
1965    '--',
1966    '-DDISPLAYVERSION=' + meson.project_version(),
1967  ]
1968  if build_docs
1969    nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
1970  endif
1971  if 'CONFIG_GTK' in config_host
1972    nsis_cmd += '-DCONFIG_GTK=y'
1973  endif
1974
1975  nsis = custom_target('nsis',
1976                       output: 'qemu-setup-' + meson.project_version() + '.exe',
1977                       input: files('qemu.nsi'),
1978                       build_always_stale: true,
1979                       command: nsis_cmd + ['@INPUT@'])
1980  alias_target('installer', nsis)
1981endif
1982
1983#########################
1984# Configuration summary #
1985#########################
1986
1987summary_info = {}
1988summary_info += {'Install prefix':    get_option('prefix')}
1989summary_info += {'BIOS directory':    qemu_datadir}
1990summary_info += {'firmware path':     get_option('qemu_firmwarepath')}
1991summary_info += {'binary directory':  get_option('bindir')}
1992summary_info += {'library directory': get_option('libdir')}
1993summary_info += {'module directory':  qemu_moddir}
1994summary_info += {'libexec directory': get_option('libexecdir')}
1995summary_info += {'include directory': get_option('includedir')}
1996summary_info += {'config directory':  get_option('sysconfdir')}
1997if targetos != 'windows'
1998  summary_info += {'local state directory': get_option('localstatedir')}
1999  summary_info += {'Manual directory':      get_option('mandir')}
2000else
2001  summary_info += {'local state directory': 'queried at runtime'}
2002endif
2003summary_info += {'Doc directory':     get_option('docdir')}
2004summary_info += {'Build directory':   meson.current_build_dir()}
2005summary_info += {'Source path':       meson.current_source_dir()}
2006summary_info += {'GIT binary':        config_host['GIT']}
2007summary_info += {'GIT submodules':    config_host['GIT_SUBMODULES']}
2008summary_info += {'C compiler':        meson.get_compiler('c').cmd_array()[0]}
2009summary_info += {'Host C compiler':   meson.get_compiler('c', native: true).cmd_array()[0]}
2010if link_language == 'cpp'
2011  summary_info += {'C++ compiler':      meson.get_compiler('cpp').cmd_array()[0]}
2012else
2013  summary_info += {'C++ compiler':      false}
2014endif
2015if targetos == 'darwin'
2016  summary_info += {'Objective-C compiler': meson.get_compiler('objc').cmd_array()[0]}
2017endif
2018summary_info += {'ARFLAGS':           config_host['ARFLAGS']}
2019summary_info += {'CFLAGS':            ' '.join(get_option('c_args')
2020                                               + ['-O' + get_option('optimization')]
2021                                               + (get_option('debug') ? ['-g'] : []))}
2022if link_language == 'cpp'
2023  summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args')
2024                                               + ['-O' + get_option('optimization')]
2025                                               + (get_option('debug') ? ['-g'] : []))}
2026endif
2027link_args = get_option(link_language + '_link_args')
2028if link_args.length() > 0
2029  summary_info += {'LDFLAGS':         ' '.join(link_args)}
2030endif
2031summary_info += {'QEMU_CFLAGS':       config_host['QEMU_CFLAGS']}
2032summary_info += {'QEMU_LDFLAGS':      config_host['QEMU_LDFLAGS']}
2033summary_info += {'make':              config_host['MAKE']}
2034summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
2035summary_info += {'sphinx-build':      sphinx_build.found()}
2036summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
2037# TODO: add back version
2038summary_info += {'slirp support':     slirp_opt == 'disabled' ? false : slirp_opt}
2039if slirp_opt != 'disabled'
2040  summary_info += {'smbd':            config_host['CONFIG_SMBD_COMMAND']}
2041endif
2042summary_info += {'module support':    config_host.has_key('CONFIG_MODULES')}
2043if config_host.has_key('CONFIG_MODULES')
2044  summary_info += {'alternative module path': config_host.has_key('CONFIG_MODULE_UPGRADES')}
2045endif
2046summary_info += {'host CPU':          cpu}
2047summary_info += {'host endianness':   build_machine.endian()}
2048summary_info += {'target list':       ' '.join(target_dirs)}
2049summary_info += {'gprof enabled':     config_host.has_key('CONFIG_GPROF')}
2050summary_info += {'sparse enabled':    sparse.found()}
2051summary_info += {'strip binaries':    get_option('strip')}
2052summary_info += {'profiler':          config_host.has_key('CONFIG_PROFILER')}
2053summary_info += {'static build':      config_host.has_key('CONFIG_STATIC')}
2054if targetos == 'darwin'
2055  summary_info += {'Cocoa support': config_host.has_key('CONFIG_COCOA')}
2056endif
2057# TODO: add back version
2058summary_info += {'SDL support':       sdl.found()}
2059summary_info += {'SDL image support': sdl_image.found()}
2060# TODO: add back version
2061summary_info += {'GTK support':       config_host.has_key('CONFIG_GTK')}
2062summary_info += {'GTK GL support':    config_host.has_key('CONFIG_GTK_GL')}
2063summary_info += {'pixman':            pixman.found()}
2064# TODO: add back version
2065summary_info += {'VTE support':       config_host.has_key('CONFIG_VTE')}
2066summary_info += {'TLS priority':      config_host['CONFIG_TLS_PRIORITY']}
2067summary_info += {'GNUTLS support':    config_host.has_key('CONFIG_GNUTLS')}
2068# TODO: add back version
2069summary_info += {'libgcrypt':         config_host.has_key('CONFIG_GCRYPT')}
2070if config_host.has_key('CONFIG_GCRYPT')
2071   summary_info += {'  hmac':            config_host.has_key('CONFIG_GCRYPT_HMAC')}
2072   summary_info += {'  XTS':             not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')}
2073endif
2074# TODO: add back version
2075summary_info += {'nettle':            config_host.has_key('CONFIG_NETTLE')}
2076if config_host.has_key('CONFIG_NETTLE')
2077   summary_info += {'  XTS':             not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')}
2078endif
2079summary_info += {'libtasn1':          config_host.has_key('CONFIG_TASN1')}
2080summary_info += {'PAM':               config_host.has_key('CONFIG_AUTH_PAM')}
2081summary_info += {'iconv support':     iconv.found()}
2082summary_info += {'curses support':    curses.found()}
2083# TODO: add back version
2084summary_info += {'virgl support':     config_host.has_key('CONFIG_VIRGL')}
2085summary_info += {'curl support':      config_host.has_key('CONFIG_CURL')}
2086summary_info += {'mingw32 support':   targetos == 'windows'}
2087summary_info += {'Audio drivers':     config_host['CONFIG_AUDIO_DRIVERS']}
2088summary_info += {'Block whitelist (rw)': config_host['CONFIG_BDRV_RW_WHITELIST']}
2089summary_info += {'Block whitelist (ro)': config_host['CONFIG_BDRV_RO_WHITELIST']}
2090summary_info += {'VirtFS support':    config_host.has_key('CONFIG_VIRTFS')}
2091summary_info += {'build virtiofs daemon': have_virtiofsd}
2092summary_info += {'Multipath support': mpathpersist.found()}
2093summary_info += {'VNC support':       vnc.found()}
2094if vnc.found()
2095  summary_info += {'VNC SASL support':  sasl.found()}
2096  summary_info += {'VNC JPEG support':  jpeg.found()}
2097  summary_info += {'VNC PNG support':   png.found()}
2098endif
2099summary_info += {'xen support':       config_host.has_key('CONFIG_XEN_BACKEND')}
2100if config_host.has_key('CONFIG_XEN_BACKEND')
2101  summary_info += {'xen ctrl version':  config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']}
2102endif
2103summary_info += {'brlapi support':    config_host.has_key('CONFIG_BRLAPI')}
2104summary_info += {'Documentation':     build_docs}
2105summary_info += {'PIE':               get_option('b_pie')}
2106summary_info += {'vde support':       config_host.has_key('CONFIG_VDE')}
2107summary_info += {'netmap support':    config_host.has_key('CONFIG_NETMAP')}
2108summary_info += {'Linux AIO support': config_host.has_key('CONFIG_LINUX_AIO')}
2109summary_info += {'Linux io_uring support': config_host.has_key('CONFIG_LINUX_IO_URING')}
2110summary_info += {'ATTR/XATTR support': config_host.has_key('CONFIG_ATTR')}
2111summary_info += {'Install blobs':     get_option('install_blobs')}
2112summary_info += {'KVM support':       config_all.has_key('CONFIG_KVM')}
2113summary_info += {'HAX support':       config_all.has_key('CONFIG_HAX')}
2114summary_info += {'HVF support':       config_all.has_key('CONFIG_HVF')}
2115summary_info += {'WHPX support':      config_all.has_key('CONFIG_WHPX')}
2116summary_info += {'TCG support':       config_all.has_key('CONFIG_TCG')}
2117if config_all.has_key('CONFIG_TCG')
2118  summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')}
2119  summary_info += {'TCG interpreter':   config_host.has_key('CONFIG_TCG_INTERPRETER')}
2120endif
2121summary_info += {'malloc trim support': has_malloc_trim}
2122summary_info += {'RDMA support':      config_host.has_key('CONFIG_RDMA')}
2123summary_info += {'PVRDMA support':    config_host.has_key('CONFIG_PVRDMA')}
2124summary_info += {'fdt support':       fdt_opt == 'disabled' ? false : fdt_opt}
2125summary_info += {'membarrier':        config_host.has_key('CONFIG_MEMBARRIER')}
2126summary_info += {'preadv support':    config_host.has_key('CONFIG_PREADV')}
2127summary_info += {'fdatasync':         config_host.has_key('CONFIG_FDATASYNC')}
2128summary_info += {'madvise':           config_host.has_key('CONFIG_MADVISE')}
2129summary_info += {'posix_madvise':     config_host.has_key('CONFIG_POSIX_MADVISE')}
2130summary_info += {'posix_memalign':    config_host.has_key('CONFIG_POSIX_MEMALIGN')}
2131summary_info += {'libcap-ng support': config_host.has_key('CONFIG_LIBCAP_NG')}
2132summary_info += {'vhost-kernel support': config_host.has_key('CONFIG_VHOST_KERNEL')}
2133summary_info += {'vhost-net support': config_host.has_key('CONFIG_VHOST_NET')}
2134summary_info += {'vhost-crypto support': config_host.has_key('CONFIG_VHOST_CRYPTO')}
2135summary_info += {'vhost-scsi support': config_host.has_key('CONFIG_VHOST_SCSI')}
2136summary_info += {'vhost-vsock support': config_host.has_key('CONFIG_VHOST_VSOCK')}
2137summary_info += {'vhost-user support': config_host.has_key('CONFIG_VHOST_USER')}
2138summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
2139summary_info += {'vhost-user-fs support': config_host.has_key('CONFIG_VHOST_USER_FS')}
2140summary_info += {'vhost-vdpa support': config_host.has_key('CONFIG_VHOST_VDPA')}
2141summary_info += {'Trace backends':    config_host['TRACE_BACKENDS']}
2142if config_host['TRACE_BACKENDS'].split().contains('simple')
2143  summary_info += {'Trace output file': config_host['CONFIG_TRACE_FILE'] + '-<pid>'}
2144endif
2145# TODO: add back protocol and server version
2146summary_info += {'spice support':     config_host.has_key('CONFIG_SPICE')}
2147summary_info += {'rbd support':       config_host.has_key('CONFIG_RBD')}
2148summary_info += {'xfsctl support':    config_host.has_key('CONFIG_XFS')}
2149summary_info += {'smartcard support': config_host.has_key('CONFIG_SMARTCARD')}
2150summary_info += {'U2F support':       u2f.found()}
2151summary_info += {'libusb':            config_host.has_key('CONFIG_USB_LIBUSB')}
2152summary_info += {'usb net redir':     config_host.has_key('CONFIG_USB_REDIR')}
2153summary_info += {'OpenGL support':    config_host.has_key('CONFIG_OPENGL')}
2154summary_info += {'OpenGL dmabufs':    config_host.has_key('CONFIG_OPENGL_DMABUF')}
2155summary_info += {'libiscsi support':  config_host.has_key('CONFIG_LIBISCSI')}
2156summary_info += {'libnfs support':    config_host.has_key('CONFIG_LIBNFS')}
2157summary_info += {'build guest agent': config_host.has_key('CONFIG_GUEST_AGENT')}
2158if targetos == 'windows'
2159  if 'WIN_SDK' in config_host
2160    summary_info += {'Windows SDK':       config_host['WIN_SDK']}
2161  endif
2162  summary_info += {'QGA VSS support':   config_host.has_key('CONFIG_QGA_VSS')}
2163  summary_info += {'QGA w32 disk info': config_host.has_key('CONFIG_QGA_NTDDSCSI')}
2164  summary_info += {'QGA MSI support':   config_host.has_key('CONFIG_QGA_MSI')}
2165endif
2166summary_info += {'seccomp support':   config_host.has_key('CONFIG_SECCOMP')}
2167summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']}
2168summary_info += {'coroutine pool':    config_host['CONFIG_COROUTINE_POOL'] == '1'}
2169summary_info += {'debug stack usage': config_host.has_key('CONFIG_DEBUG_STACK_USAGE')}
2170summary_info += {'mutex debugging':   config_host.has_key('CONFIG_DEBUG_MUTEX')}
2171summary_info += {'crypto afalg':      config_host.has_key('CONFIG_AF_ALG')}
2172summary_info += {'GlusterFS support': config_host.has_key('CONFIG_GLUSTERFS')}
2173summary_info += {'gcov':              get_option('b_coverage')}
2174summary_info += {'TPM support':       config_host.has_key('CONFIG_TPM')}
2175summary_info += {'libssh support':    config_host.has_key('CONFIG_LIBSSH')}
2176summary_info += {'QOM debugging':     config_host.has_key('CONFIG_QOM_CAST_DEBUG')}
2177summary_info += {'Live block migration': config_host.has_key('CONFIG_LIVE_BLOCK_MIGRATION')}
2178summary_info += {'lzo support':       config_host.has_key('CONFIG_LZO')}
2179summary_info += {'snappy support':    config_host.has_key('CONFIG_SNAPPY')}
2180summary_info += {'bzip2 support':     config_host.has_key('CONFIG_BZIP2')}
2181summary_info += {'lzfse support':     config_host.has_key('CONFIG_LZFSE')}
2182summary_info += {'zstd support':      config_host.has_key('CONFIG_ZSTD')}
2183summary_info += {'NUMA host support': config_host.has_key('CONFIG_NUMA')}
2184summary_info += {'libxml2':           config_host.has_key('CONFIG_LIBXML2')}
2185summary_info += {'memory allocator':  get_option('malloc')}
2186summary_info += {'avx2 optimization': config_host.has_key('CONFIG_AVX2_OPT')}
2187summary_info += {'avx512f optimization': config_host.has_key('CONFIG_AVX512F_OPT')}
2188summary_info += {'replication support': config_host.has_key('CONFIG_REPLICATION')}
2189summary_info += {'bochs support':     config_host.has_key('CONFIG_BOCHS')}
2190summary_info += {'cloop support':     config_host.has_key('CONFIG_CLOOP')}
2191summary_info += {'dmg support':       config_host.has_key('CONFIG_DMG')}
2192summary_info += {'qcow v1 support':   config_host.has_key('CONFIG_QCOW1')}
2193summary_info += {'vdi support':       config_host.has_key('CONFIG_VDI')}
2194summary_info += {'vvfat support':     config_host.has_key('CONFIG_VVFAT')}
2195summary_info += {'qed support':       config_host.has_key('CONFIG_QED')}
2196summary_info += {'parallels support': config_host.has_key('CONFIG_PARALLELS')}
2197summary_info += {'sheepdog support':  config_host.has_key('CONFIG_SHEEPDOG')}
2198summary_info += {'capstone':          capstone_opt == 'disabled' ? false : capstone_opt}
2199summary_info += {'libpmem support':   config_host.has_key('CONFIG_LIBPMEM')}
2200summary_info += {'libdaxctl support': config_host.has_key('CONFIG_LIBDAXCTL')}
2201summary_info += {'libudev':           libudev.found()}
2202summary_info += {'default devices':   config_host['CONFIG_MINIKCONF_MODE'] == '--defconfig'}
2203summary_info += {'plugin support':    config_host.has_key('CONFIG_PLUGIN')}
2204summary_info += {'fuzzing support':   config_host.has_key('CONFIG_FUZZ')}
2205if config_host.has_key('HAVE_GDB_BIN')
2206  summary_info += {'gdb':             config_host['HAVE_GDB_BIN']}
2207endif
2208summary_info += {'thread sanitizer':  config_host.has_key('CONFIG_TSAN')}
2209summary_info += {'rng-none':          config_host.has_key('CONFIG_RNG_NONE')}
2210summary_info += {'Linux keyring':     config_host.has_key('CONFIG_SECRET_KEYRING')}
2211summary(summary_info, bool_yn: true)
2212
2213if not supported_cpus.contains(cpu)
2214  message()
2215  warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!')
2216  message()
2217  message('CPU host architecture ' + cpu + ' support is not currently maintained.')
2218  message('The QEMU project intends to remove support for this host CPU in')
2219  message('a future release if nobody volunteers to maintain it and to')
2220  message('provide a build host for our continuous integration setup.')
2221  message('configure has succeeded and you can continue to build, but')
2222  message('if you care about QEMU on this platform you should contact')
2223  message('us upstream at qemu-devel@nongnu.org.')
2224endif
2225
2226if not supported_oses.contains(targetos)
2227  message()
2228  warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!')
2229  message()
2230  message('Host OS ' + targetos + 'support is not currently maintained.')
2231  message('The QEMU project intends to remove support for this host OS in')
2232  message('a future release if nobody volunteers to maintain it and to')
2233  message('provide a build host for our continuous integration setup.')
2234  message('configure has succeeded and you can continue to build, but')
2235  message('if you care about QEMU on this platform you should contact')
2236  message('us upstream at qemu-devel@nongnu.org.')
2237endif
2238