xref: /openbmc/qemu/meson.build (revision e2487e40)
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/nvram',
1437    'hw/pci',
1438    'hw/pci-host',
1439    'hw/ppc',
1440    'hw/rdma',
1441    'hw/rdma/vmw',
1442    'hw/rtc',
1443    'hw/s390x',
1444    'hw/scsi',
1445    'hw/sd',
1446    'hw/sparc',
1447    'hw/sparc64',
1448    'hw/ssi',
1449    'hw/timer',
1450    'hw/tpm',
1451    'hw/usb',
1452    'hw/vfio',
1453    'hw/virtio',
1454    'hw/watchdog',
1455    'hw/xen',
1456    'hw/gpio',
1457    'migration',
1458    'net',
1459    'softmmu',
1460    'ui',
1461  ]
1462endif
1463trace_events_subdirs += [
1464  'hw/core',
1465  'qapi',
1466  'qom',
1467  'target/arm',
1468  'target/hppa',
1469  'target/i386',
1470  'target/mips',
1471  'target/ppc',
1472  'target/riscv',
1473  'target/s390x',
1474  'target/sparc',
1475  'util',
1476]
1477
1478vhost_user = not_found
1479if 'CONFIG_VHOST_USER' in config_host
1480  libvhost_user = subproject('libvhost-user')
1481  vhost_user = libvhost_user.get_variable('vhost_user_dep')
1482endif
1483
1484subdir('qapi')
1485subdir('qobject')
1486subdir('stubs')
1487subdir('trace')
1488subdir('util')
1489subdir('qom')
1490subdir('authz')
1491subdir('crypto')
1492subdir('ui')
1493
1494
1495if enable_modules
1496  libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
1497  modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
1498endif
1499
1500stub_ss = stub_ss.apply(config_all, strict: false)
1501
1502util_ss.add_all(trace_ss)
1503util_ss = util_ss.apply(config_all, strict: false)
1504libqemuutil = static_library('qemuutil',
1505                             sources: util_ss.sources() + stub_ss.sources() + genh,
1506                             dependencies: [util_ss.dependencies(), m, glib, socket, malloc])
1507qemuutil = declare_dependency(link_with: libqemuutil,
1508                              sources: genh + version_res)
1509
1510decodetree = generator(find_program('scripts/decodetree.py'),
1511                       output: 'decode-@BASENAME@.c.inc',
1512                       arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
1513
1514subdir('audio')
1515subdir('io')
1516subdir('chardev')
1517subdir('fsdev')
1518subdir('libdecnumber')
1519subdir('target')
1520subdir('dump')
1521
1522block_ss.add(files(
1523  'block.c',
1524  'blockjob.c',
1525  'job.c',
1526  'qemu-io-cmds.c',
1527))
1528block_ss.add(when: 'CONFIG_REPLICATION', if_true: files('replication.c'))
1529
1530subdir('nbd')
1531subdir('scsi')
1532subdir('block')
1533
1534blockdev_ss.add(files(
1535  'blockdev.c',
1536  'blockdev-nbd.c',
1537  'iothread.c',
1538  'job-qmp.c',
1539))
1540
1541# os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
1542# os-win32.c does not
1543blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c'))
1544softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')])
1545
1546common_ss.add(files('cpus-common.c'))
1547
1548subdir('softmmu')
1549
1550common_ss.add(capstone)
1551specific_ss.add(files('cpu.c', 'disas.c', 'gdbstub.c'), capstone)
1552specific_ss.add(files('exec-vary.c'))
1553specific_ss.add(when: 'CONFIG_TCG', if_true: files(
1554  'fpu/softfloat.c',
1555  'tcg/optimize.c',
1556  'tcg/tcg-common.c',
1557  'tcg/tcg-op-gvec.c',
1558  'tcg/tcg-op-vec.c',
1559  'tcg/tcg-op.c',
1560  'tcg/tcg.c',
1561))
1562specific_ss.add(when: 'CONFIG_TCG_INTERPRETER', if_true: files('disas/tci.c', 'tcg/tci.c'))
1563
1564subdir('backends')
1565subdir('disas')
1566subdir('migration')
1567subdir('monitor')
1568subdir('net')
1569subdir('replay')
1570subdir('hw')
1571subdir('accel')
1572subdir('plugins')
1573subdir('bsd-user')
1574subdir('linux-user')
1575
1576bsd_user_ss.add(files('gdbstub.c'))
1577specific_ss.add_all(when: 'CONFIG_BSD_USER', if_true: bsd_user_ss)
1578
1579linux_user_ss.add(files('gdbstub.c', 'thunk.c'))
1580specific_ss.add_all(when: 'CONFIG_LINUX_USER', if_true: linux_user_ss)
1581
1582# needed for fuzzing binaries
1583subdir('tests/qtest/libqos')
1584subdir('tests/qtest/fuzz')
1585
1586########################
1587# Library dependencies #
1588########################
1589
1590block_mods = []
1591softmmu_mods = []
1592foreach d, list : modules
1593  foreach m, module_ss : list
1594    if enable_modules and targetos != 'windows'
1595      module_ss = module_ss.apply(config_all, strict: false)
1596      sl = static_library(d + '-' + m, [genh, module_ss.sources()],
1597                          dependencies: [modulecommon, module_ss.dependencies()], pic: true)
1598      if d == 'block'
1599        block_mods += sl
1600      else
1601        softmmu_mods += sl
1602      endif
1603    else
1604      if d == 'block'
1605        block_ss.add_all(module_ss)
1606      else
1607        softmmu_ss.add_all(module_ss)
1608      endif
1609    endif
1610  endforeach
1611endforeach
1612
1613nm = find_program('nm')
1614undefsym = find_program('scripts/undefsym.py')
1615block_syms = custom_target('block.syms', output: 'block.syms',
1616                             input: [libqemuutil, block_mods],
1617                             capture: true,
1618                             command: [undefsym, nm, '@INPUT@'])
1619qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
1620                             input: [libqemuutil, softmmu_mods],
1621                             capture: true,
1622                             command: [undefsym, nm, '@INPUT@'])
1623
1624qom_ss = qom_ss.apply(config_host, strict: false)
1625libqom = static_library('qom', qom_ss.sources() + genh,
1626                        dependencies: [qom_ss.dependencies()],
1627                        name_suffix: 'fa')
1628
1629qom = declare_dependency(link_whole: libqom)
1630
1631authz_ss = authz_ss.apply(config_host, strict: false)
1632libauthz = static_library('authz', authz_ss.sources() + genh,
1633                          dependencies: [authz_ss.dependencies()],
1634                          name_suffix: 'fa',
1635                          build_by_default: false)
1636
1637authz = declare_dependency(link_whole: libauthz,
1638                           dependencies: qom)
1639
1640crypto_ss = crypto_ss.apply(config_host, strict: false)
1641libcrypto = static_library('crypto', crypto_ss.sources() + genh,
1642                           dependencies: [crypto_ss.dependencies()],
1643                           name_suffix: 'fa',
1644                           build_by_default: false)
1645
1646crypto = declare_dependency(link_whole: libcrypto,
1647                            dependencies: [authz, qom])
1648
1649io_ss = io_ss.apply(config_host, strict: false)
1650libio = static_library('io', io_ss.sources() + genh,
1651                       dependencies: [io_ss.dependencies()],
1652                       link_with: libqemuutil,
1653                       name_suffix: 'fa',
1654                       build_by_default: false)
1655
1656io = declare_dependency(link_whole: libio, dependencies: [crypto, qom])
1657
1658libmigration = static_library('migration', sources: migration_files + genh,
1659                              name_suffix: 'fa',
1660                              build_by_default: false)
1661migration = declare_dependency(link_with: libmigration,
1662                               dependencies: [zlib, qom, io])
1663softmmu_ss.add(migration)
1664
1665block_ss = block_ss.apply(config_host, strict: false)
1666libblock = static_library('block', block_ss.sources() + genh,
1667                          dependencies: block_ss.dependencies(),
1668                          link_depends: block_syms,
1669                          name_suffix: 'fa',
1670                          build_by_default: false)
1671
1672block = declare_dependency(link_whole: [libblock],
1673                           link_args: '@block.syms',
1674                           dependencies: [crypto, io])
1675
1676blockdev_ss = blockdev_ss.apply(config_host, strict: false)
1677libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
1678                             dependencies: blockdev_ss.dependencies(),
1679                             name_suffix: 'fa',
1680                             build_by_default: false)
1681
1682blockdev = declare_dependency(link_whole: [libblockdev],
1683                              dependencies: [block])
1684
1685qmp_ss = qmp_ss.apply(config_host, strict: false)
1686libqmp = static_library('qmp', qmp_ss.sources() + genh,
1687                        dependencies: qmp_ss.dependencies(),
1688                        name_suffix: 'fa',
1689                        build_by_default: false)
1690
1691qmp = declare_dependency(link_whole: [libqmp])
1692
1693libchardev = static_library('chardev', chardev_ss.sources() + genh,
1694                            name_suffix: 'fa',
1695                            build_by_default: false)
1696
1697chardev = declare_dependency(link_whole: libchardev)
1698
1699libhwcore = static_library('hwcore', sources: hwcore_files + genh,
1700                           name_suffix: 'fa',
1701                           build_by_default: false)
1702hwcore = declare_dependency(link_whole: libhwcore)
1703common_ss.add(hwcore)
1704
1705###########
1706# Targets #
1707###########
1708
1709foreach m : block_mods + softmmu_mods
1710  shared_module(m.name(),
1711                name_prefix: '',
1712                link_whole: m,
1713                install: true,
1714                install_dir: qemu_moddir)
1715endforeach
1716
1717softmmu_ss.add(authz, blockdev, chardev, crypto, io, qmp)
1718common_ss.add(qom, qemuutil)
1719
1720common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss])
1721common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
1722
1723common_all = common_ss.apply(config_all, strict: false)
1724common_all = static_library('common',
1725                            build_by_default: false,
1726                            sources: common_all.sources() + genh,
1727                            dependencies: common_all.dependencies(),
1728                            name_suffix: 'fa')
1729
1730feature_to_c = find_program('scripts/feature_to_c.sh')
1731
1732emulators = {}
1733foreach target : target_dirs
1734  config_target = config_target_mak[target]
1735  target_name = config_target['TARGET_NAME']
1736  arch = config_target['TARGET_BASE_ARCH']
1737  arch_srcs = [config_target_h[target]]
1738  arch_deps = []
1739  c_args = ['-DNEED_CPU_H',
1740            '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
1741            '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
1742  link_args = emulator_link_args
1743
1744  config_target += config_host
1745  target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
1746  if targetos == 'linux'
1747    target_inc += include_directories('linux-headers', is_system: true)
1748  endif
1749  if target.endswith('-softmmu')
1750    qemu_target_name = 'qemu-system-' + target_name
1751    target_type='system'
1752    t = target_softmmu_arch[arch].apply(config_target, strict: false)
1753    arch_srcs += t.sources()
1754    arch_deps += t.dependencies()
1755
1756    hw_dir = target_name == 'sparc64' ? 'sparc64' : arch
1757    hw = hw_arch[hw_dir].apply(config_target, strict: false)
1758    arch_srcs += hw.sources()
1759    arch_deps += hw.dependencies()
1760
1761    arch_srcs += config_devices_h[target]
1762    link_args += ['@block.syms', '@qemu.syms']
1763  else
1764    abi = config_target['TARGET_ABI_DIR']
1765    target_type='user'
1766    qemu_target_name = 'qemu-' + target_name
1767    if 'CONFIG_LINUX_USER' in config_target
1768      base_dir = 'linux-user'
1769      target_inc += include_directories('linux-user/host/' / config_host['ARCH'])
1770    else
1771      base_dir = 'bsd-user'
1772    endif
1773    target_inc += include_directories(
1774      base_dir,
1775      base_dir / abi,
1776    )
1777    if 'CONFIG_LINUX_USER' in config_target
1778      dir = base_dir / abi
1779      arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
1780      if config_target.has_key('TARGET_SYSTBL_ABI')
1781        arch_srcs += \
1782          syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
1783                                             extra_args : config_target['TARGET_SYSTBL_ABI'])
1784      endif
1785    endif
1786  endif
1787
1788  if 'TARGET_XML_FILES' in config_target
1789    gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
1790                                output: target + '-gdbstub-xml.c',
1791                                input: files(config_target['TARGET_XML_FILES'].split()),
1792                                command: [feature_to_c, '@INPUT@'],
1793                                capture: true)
1794    arch_srcs += gdbstub_xml
1795  endif
1796
1797  t = target_arch[arch].apply(config_target, strict: false)
1798  arch_srcs += t.sources()
1799  arch_deps += t.dependencies()
1800
1801  target_common = common_ss.apply(config_target, strict: false)
1802  objects = common_all.extract_objects(target_common.sources())
1803  deps = target_common.dependencies()
1804
1805  target_specific = specific_ss.apply(config_target, strict: false)
1806  arch_srcs += target_specific.sources()
1807  arch_deps += target_specific.dependencies()
1808
1809  lib = static_library('qemu-' + target,
1810                 sources: arch_srcs + genh,
1811                 dependencies: arch_deps,
1812                 objects: objects,
1813                 include_directories: target_inc,
1814                 c_args: c_args,
1815                 build_by_default: false,
1816                 name_suffix: 'fa')
1817
1818  if target.endswith('-softmmu')
1819    execs = [{
1820      'name': 'qemu-system-' + target_name,
1821      'gui': false,
1822      'sources': files('softmmu/main.c'),
1823      'dependencies': []
1824    }]
1825    if targetos == 'windows' and (sdl.found() or gtk.found())
1826      execs += [{
1827        'name': 'qemu-system-' + target_name + 'w',
1828        'gui': true,
1829        'sources': files('softmmu/main.c'),
1830        'dependencies': []
1831      }]
1832    endif
1833    if config_host.has_key('CONFIG_FUZZ')
1834      specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
1835      execs += [{
1836        'name': 'qemu-fuzz-' + target_name,
1837        'gui': false,
1838        'sources': specific_fuzz.sources(),
1839        'dependencies': specific_fuzz.dependencies(),
1840      }]
1841    endif
1842  else
1843    execs = [{
1844      'name': 'qemu-' + target_name,
1845      'gui': false,
1846      'sources': [],
1847      'dependencies': []
1848    }]
1849  endif
1850  foreach exe: execs
1851    emulators += {exe['name']:
1852         executable(exe['name'], exe['sources'],
1853               install: true,
1854               c_args: c_args,
1855               dependencies: arch_deps + deps + exe['dependencies'],
1856               objects: lib.extract_all_objects(recursive: true),
1857               link_language: link_language,
1858               link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
1859               link_args: link_args,
1860               gui_app: exe['gui'])
1861    }
1862
1863    if 'CONFIG_TRACE_SYSTEMTAP' in config_host
1864      foreach stp: [
1865        {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
1866        {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
1867        {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
1868        {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
1869      ]
1870        custom_target(exe['name'] + stp['ext'],
1871                      input: trace_events_all,
1872                      output: exe['name'] + stp['ext'],
1873                      capture: true,
1874                      install: stp['install'],
1875                      install_dir: get_option('datadir') / 'systemtap/tapset',
1876                      command: [
1877                        tracetool, '--group=all', '--format=' + stp['fmt'],
1878                        '--binary=' + stp['bin'],
1879                        '--target-name=' + target_name,
1880                        '--target-type=' + target_type,
1881                        '--probe-prefix=qemu.' + target_type + '.' + target_name,
1882                        '@INPUT@',
1883                      ])
1884      endforeach
1885    endif
1886  endforeach
1887endforeach
1888
1889# Other build targets
1890
1891if 'CONFIG_PLUGIN' in config_host
1892  install_headers('include/qemu/qemu-plugin.h')
1893endif
1894
1895if 'CONFIG_GUEST_AGENT' in config_host
1896  subdir('qga')
1897endif
1898
1899# Don't build qemu-keymap if xkbcommon is not explicitly enabled
1900# when we don't build tools or system
1901if xkbcommon.found()
1902  # used for the update-keymaps target, so include rules even if !have_tools
1903  qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
1904                           dependencies: [qemuutil, xkbcommon], install: have_tools)
1905endif
1906
1907if have_tools
1908  qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
1909             dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
1910  qemu_io = executable('qemu-io', files('qemu-io.c'),
1911             dependencies: [block, qemuutil], install: true)
1912  qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
1913               dependencies: [blockdev, qemuutil], install: true)
1914
1915  subdir('storage-daemon')
1916  subdir('contrib/rdmacm-mux')
1917  subdir('contrib/elf2dmp')
1918
1919  executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
1920             dependencies: qemuutil,
1921             install: true)
1922
1923  if 'CONFIG_VHOST_USER' in config_host
1924    subdir('contrib/vhost-user-blk')
1925    subdir('contrib/vhost-user-gpu')
1926    subdir('contrib/vhost-user-input')
1927    subdir('contrib/vhost-user-scsi')
1928  endif
1929
1930  if targetos == 'linux'
1931    executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
1932               dependencies: [qemuutil, libcap_ng],
1933               install: true,
1934               install_dir: get_option('libexecdir'))
1935
1936    executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
1937               dependencies: [authz, crypto, io, qom, qemuutil,
1938                              libcap_ng, mpathpersist],
1939               install: true)
1940  endif
1941
1942  if 'CONFIG_IVSHMEM' in config_host
1943    subdir('contrib/ivshmem-client')
1944    subdir('contrib/ivshmem-server')
1945  endif
1946endif
1947
1948subdir('scripts')
1949subdir('tools')
1950subdir('pc-bios')
1951subdir('docs')
1952subdir('tests')
1953if 'CONFIG_GTK' in config_host
1954  subdir('po')
1955endif
1956
1957if host_machine.system() == 'windows'
1958  nsis_cmd = [
1959    find_program('scripts/nsis.py'),
1960    '@OUTPUT@',
1961    get_option('prefix'),
1962    meson.current_source_dir(),
1963    host_machine.cpu(),
1964    '--',
1965    '-DDISPLAYVERSION=' + meson.project_version(),
1966  ]
1967  if build_docs
1968    nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
1969  endif
1970  if 'CONFIG_GTK' in config_host
1971    nsis_cmd += '-DCONFIG_GTK=y'
1972  endif
1973
1974  nsis = custom_target('nsis',
1975                       output: 'qemu-setup-' + meson.project_version() + '.exe',
1976                       input: files('qemu.nsi'),
1977                       build_always_stale: true,
1978                       command: nsis_cmd + ['@INPUT@'])
1979  alias_target('installer', nsis)
1980endif
1981
1982#########################
1983# Configuration summary #
1984#########################
1985
1986summary_info = {}
1987summary_info += {'Install prefix':    get_option('prefix')}
1988summary_info += {'BIOS directory':    qemu_datadir}
1989summary_info += {'firmware path':     get_option('qemu_firmwarepath')}
1990summary_info += {'binary directory':  get_option('bindir')}
1991summary_info += {'library directory': get_option('libdir')}
1992summary_info += {'module directory':  qemu_moddir}
1993summary_info += {'libexec directory': get_option('libexecdir')}
1994summary_info += {'include directory': get_option('includedir')}
1995summary_info += {'config directory':  get_option('sysconfdir')}
1996if targetos != 'windows'
1997  summary_info += {'local state directory': get_option('localstatedir')}
1998  summary_info += {'Manual directory':      get_option('mandir')}
1999else
2000  summary_info += {'local state directory': 'queried at runtime'}
2001endif
2002summary_info += {'Doc directory':     get_option('docdir')}
2003summary_info += {'Build directory':   meson.current_build_dir()}
2004summary_info += {'Source path':       meson.current_source_dir()}
2005summary_info += {'GIT binary':        config_host['GIT']}
2006summary_info += {'GIT submodules':    config_host['GIT_SUBMODULES']}
2007summary_info += {'C compiler':        meson.get_compiler('c').cmd_array()[0]}
2008summary_info += {'Host C compiler':   meson.get_compiler('c', native: true).cmd_array()[0]}
2009if link_language == 'cpp'
2010  summary_info += {'C++ compiler':      meson.get_compiler('cpp').cmd_array()[0]}
2011else
2012  summary_info += {'C++ compiler':      false}
2013endif
2014if targetos == 'darwin'
2015  summary_info += {'Objective-C compiler': meson.get_compiler('objc').cmd_array()[0]}
2016endif
2017summary_info += {'ARFLAGS':           config_host['ARFLAGS']}
2018summary_info += {'CFLAGS':            ' '.join(get_option('c_args')
2019                                               + ['-O' + get_option('optimization')]
2020                                               + (get_option('debug') ? ['-g'] : []))}
2021if link_language == 'cpp'
2022  summary_info += {'CXXFLAGS':        ' '.join(get_option('cpp_args')
2023                                               + ['-O' + get_option('optimization')]
2024                                               + (get_option('debug') ? ['-g'] : []))}
2025endif
2026link_args = get_option(link_language + '_link_args')
2027if link_args.length() > 0
2028  summary_info += {'LDFLAGS':         ' '.join(link_args)}
2029endif
2030summary_info += {'QEMU_CFLAGS':       config_host['QEMU_CFLAGS']}
2031summary_info += {'QEMU_LDFLAGS':      config_host['QEMU_LDFLAGS']}
2032summary_info += {'make':              config_host['MAKE']}
2033summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
2034summary_info += {'sphinx-build':      sphinx_build.found()}
2035summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
2036# TODO: add back version
2037summary_info += {'slirp support':     slirp_opt == 'disabled' ? false : slirp_opt}
2038if slirp_opt != 'disabled'
2039  summary_info += {'smbd':            config_host['CONFIG_SMBD_COMMAND']}
2040endif
2041summary_info += {'module support':    config_host.has_key('CONFIG_MODULES')}
2042if config_host.has_key('CONFIG_MODULES')
2043  summary_info += {'alternative module path': config_host.has_key('CONFIG_MODULE_UPGRADES')}
2044endif
2045summary_info += {'host CPU':          cpu}
2046summary_info += {'host endianness':   build_machine.endian()}
2047summary_info += {'target list':       ' '.join(target_dirs)}
2048summary_info += {'gprof enabled':     config_host.has_key('CONFIG_GPROF')}
2049summary_info += {'sparse enabled':    sparse.found()}
2050summary_info += {'strip binaries':    get_option('strip')}
2051summary_info += {'profiler':          config_host.has_key('CONFIG_PROFILER')}
2052summary_info += {'static build':      config_host.has_key('CONFIG_STATIC')}
2053if targetos == 'darwin'
2054  summary_info += {'Cocoa support': config_host.has_key('CONFIG_COCOA')}
2055endif
2056# TODO: add back version
2057summary_info += {'SDL support':       sdl.found()}
2058summary_info += {'SDL image support': sdl_image.found()}
2059# TODO: add back version
2060summary_info += {'GTK support':       config_host.has_key('CONFIG_GTK')}
2061summary_info += {'GTK GL support':    config_host.has_key('CONFIG_GTK_GL')}
2062summary_info += {'pixman':            pixman.found()}
2063# TODO: add back version
2064summary_info += {'VTE support':       config_host.has_key('CONFIG_VTE')}
2065summary_info += {'TLS priority':      config_host['CONFIG_TLS_PRIORITY']}
2066summary_info += {'GNUTLS support':    config_host.has_key('CONFIG_GNUTLS')}
2067# TODO: add back version
2068summary_info += {'libgcrypt':         config_host.has_key('CONFIG_GCRYPT')}
2069if config_host.has_key('CONFIG_GCRYPT')
2070   summary_info += {'  hmac':            config_host.has_key('CONFIG_GCRYPT_HMAC')}
2071   summary_info += {'  XTS':             not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')}
2072endif
2073# TODO: add back version
2074summary_info += {'nettle':            config_host.has_key('CONFIG_NETTLE')}
2075if config_host.has_key('CONFIG_NETTLE')
2076   summary_info += {'  XTS':             not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')}
2077endif
2078summary_info += {'libtasn1':          config_host.has_key('CONFIG_TASN1')}
2079summary_info += {'PAM':               config_host.has_key('CONFIG_AUTH_PAM')}
2080summary_info += {'iconv support':     iconv.found()}
2081summary_info += {'curses support':    curses.found()}
2082# TODO: add back version
2083summary_info += {'virgl support':     config_host.has_key('CONFIG_VIRGL')}
2084summary_info += {'curl support':      config_host.has_key('CONFIG_CURL')}
2085summary_info += {'mingw32 support':   targetos == 'windows'}
2086summary_info += {'Audio drivers':     config_host['CONFIG_AUDIO_DRIVERS']}
2087summary_info += {'Block whitelist (rw)': config_host['CONFIG_BDRV_RW_WHITELIST']}
2088summary_info += {'Block whitelist (ro)': config_host['CONFIG_BDRV_RO_WHITELIST']}
2089summary_info += {'VirtFS support':    config_host.has_key('CONFIG_VIRTFS')}
2090summary_info += {'build virtiofs daemon': have_virtiofsd}
2091summary_info += {'Multipath support': mpathpersist.found()}
2092summary_info += {'VNC support':       vnc.found()}
2093if vnc.found()
2094  summary_info += {'VNC SASL support':  sasl.found()}
2095  summary_info += {'VNC JPEG support':  jpeg.found()}
2096  summary_info += {'VNC PNG support':   png.found()}
2097endif
2098summary_info += {'xen support':       config_host.has_key('CONFIG_XEN_BACKEND')}
2099if config_host.has_key('CONFIG_XEN_BACKEND')
2100  summary_info += {'xen ctrl version':  config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']}
2101endif
2102summary_info += {'brlapi support':    config_host.has_key('CONFIG_BRLAPI')}
2103summary_info += {'Documentation':     build_docs}
2104summary_info += {'PIE':               get_option('b_pie')}
2105summary_info += {'vde support':       config_host.has_key('CONFIG_VDE')}
2106summary_info += {'netmap support':    config_host.has_key('CONFIG_NETMAP')}
2107summary_info += {'Linux AIO support': config_host.has_key('CONFIG_LINUX_AIO')}
2108summary_info += {'Linux io_uring support': config_host.has_key('CONFIG_LINUX_IO_URING')}
2109summary_info += {'ATTR/XATTR support': config_host.has_key('CONFIG_ATTR')}
2110summary_info += {'Install blobs':     get_option('install_blobs')}
2111summary_info += {'KVM support':       config_all.has_key('CONFIG_KVM')}
2112summary_info += {'HAX support':       config_all.has_key('CONFIG_HAX')}
2113summary_info += {'HVF support':       config_all.has_key('CONFIG_HVF')}
2114summary_info += {'WHPX support':      config_all.has_key('CONFIG_WHPX')}
2115summary_info += {'TCG support':       config_all.has_key('CONFIG_TCG')}
2116if config_all.has_key('CONFIG_TCG')
2117  summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')}
2118  summary_info += {'TCG interpreter':   config_host.has_key('CONFIG_TCG_INTERPRETER')}
2119endif
2120summary_info += {'malloc trim support': has_malloc_trim}
2121summary_info += {'RDMA support':      config_host.has_key('CONFIG_RDMA')}
2122summary_info += {'PVRDMA support':    config_host.has_key('CONFIG_PVRDMA')}
2123summary_info += {'fdt support':       fdt_opt == 'disabled' ? false : fdt_opt}
2124summary_info += {'membarrier':        config_host.has_key('CONFIG_MEMBARRIER')}
2125summary_info += {'preadv support':    config_host.has_key('CONFIG_PREADV')}
2126summary_info += {'fdatasync':         config_host.has_key('CONFIG_FDATASYNC')}
2127summary_info += {'madvise':           config_host.has_key('CONFIG_MADVISE')}
2128summary_info += {'posix_madvise':     config_host.has_key('CONFIG_POSIX_MADVISE')}
2129summary_info += {'posix_memalign':    config_host.has_key('CONFIG_POSIX_MEMALIGN')}
2130summary_info += {'libcap-ng support': config_host.has_key('CONFIG_LIBCAP_NG')}
2131summary_info += {'vhost-kernel support': config_host.has_key('CONFIG_VHOST_KERNEL')}
2132summary_info += {'vhost-net support': config_host.has_key('CONFIG_VHOST_NET')}
2133summary_info += {'vhost-crypto support': config_host.has_key('CONFIG_VHOST_CRYPTO')}
2134summary_info += {'vhost-scsi support': config_host.has_key('CONFIG_VHOST_SCSI')}
2135summary_info += {'vhost-vsock support': config_host.has_key('CONFIG_VHOST_VSOCK')}
2136summary_info += {'vhost-user support': config_host.has_key('CONFIG_VHOST_USER')}
2137summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server}
2138summary_info += {'vhost-user-fs support': config_host.has_key('CONFIG_VHOST_USER_FS')}
2139summary_info += {'vhost-vdpa support': config_host.has_key('CONFIG_VHOST_VDPA')}
2140summary_info += {'Trace backends':    config_host['TRACE_BACKENDS']}
2141if config_host['TRACE_BACKENDS'].split().contains('simple')
2142  summary_info += {'Trace output file': config_host['CONFIG_TRACE_FILE'] + '-<pid>'}
2143endif
2144# TODO: add back protocol and server version
2145summary_info += {'spice support':     config_host.has_key('CONFIG_SPICE')}
2146summary_info += {'rbd support':       config_host.has_key('CONFIG_RBD')}
2147summary_info += {'xfsctl support':    config_host.has_key('CONFIG_XFS')}
2148summary_info += {'smartcard support': config_host.has_key('CONFIG_SMARTCARD')}
2149summary_info += {'U2F support':       u2f.found()}
2150summary_info += {'libusb':            config_host.has_key('CONFIG_USB_LIBUSB')}
2151summary_info += {'usb net redir':     config_host.has_key('CONFIG_USB_REDIR')}
2152summary_info += {'OpenGL support':    config_host.has_key('CONFIG_OPENGL')}
2153summary_info += {'OpenGL dmabufs':    config_host.has_key('CONFIG_OPENGL_DMABUF')}
2154summary_info += {'libiscsi support':  config_host.has_key('CONFIG_LIBISCSI')}
2155summary_info += {'libnfs support':    config_host.has_key('CONFIG_LIBNFS')}
2156summary_info += {'build guest agent': config_host.has_key('CONFIG_GUEST_AGENT')}
2157if targetos == 'windows'
2158  if 'WIN_SDK' in config_host
2159    summary_info += {'Windows SDK':       config_host['WIN_SDK']}
2160  endif
2161  summary_info += {'QGA VSS support':   config_host.has_key('CONFIG_QGA_VSS')}
2162  summary_info += {'QGA w32 disk info': config_host.has_key('CONFIG_QGA_NTDDSCSI')}
2163  summary_info += {'QGA MSI support':   config_host.has_key('CONFIG_QGA_MSI')}
2164endif
2165summary_info += {'seccomp support':   config_host.has_key('CONFIG_SECCOMP')}
2166summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']}
2167summary_info += {'coroutine pool':    config_host['CONFIG_COROUTINE_POOL'] == '1'}
2168summary_info += {'debug stack usage': config_host.has_key('CONFIG_DEBUG_STACK_USAGE')}
2169summary_info += {'mutex debugging':   config_host.has_key('CONFIG_DEBUG_MUTEX')}
2170summary_info += {'crypto afalg':      config_host.has_key('CONFIG_AF_ALG')}
2171summary_info += {'GlusterFS support': config_host.has_key('CONFIG_GLUSTERFS')}
2172summary_info += {'gcov':              get_option('b_coverage')}
2173summary_info += {'TPM support':       config_host.has_key('CONFIG_TPM')}
2174summary_info += {'libssh support':    config_host.has_key('CONFIG_LIBSSH')}
2175summary_info += {'QOM debugging':     config_host.has_key('CONFIG_QOM_CAST_DEBUG')}
2176summary_info += {'Live block migration': config_host.has_key('CONFIG_LIVE_BLOCK_MIGRATION')}
2177summary_info += {'lzo support':       config_host.has_key('CONFIG_LZO')}
2178summary_info += {'snappy support':    config_host.has_key('CONFIG_SNAPPY')}
2179summary_info += {'bzip2 support':     config_host.has_key('CONFIG_BZIP2')}
2180summary_info += {'lzfse support':     config_host.has_key('CONFIG_LZFSE')}
2181summary_info += {'zstd support':      config_host.has_key('CONFIG_ZSTD')}
2182summary_info += {'NUMA host support': config_host.has_key('CONFIG_NUMA')}
2183summary_info += {'libxml2':           config_host.has_key('CONFIG_LIBXML2')}
2184summary_info += {'memory allocator':  get_option('malloc')}
2185summary_info += {'avx2 optimization': config_host.has_key('CONFIG_AVX2_OPT')}
2186summary_info += {'avx512f optimization': config_host.has_key('CONFIG_AVX512F_OPT')}
2187summary_info += {'replication support': config_host.has_key('CONFIG_REPLICATION')}
2188summary_info += {'bochs support':     config_host.has_key('CONFIG_BOCHS')}
2189summary_info += {'cloop support':     config_host.has_key('CONFIG_CLOOP')}
2190summary_info += {'dmg support':       config_host.has_key('CONFIG_DMG')}
2191summary_info += {'qcow v1 support':   config_host.has_key('CONFIG_QCOW1')}
2192summary_info += {'vdi support':       config_host.has_key('CONFIG_VDI')}
2193summary_info += {'vvfat support':     config_host.has_key('CONFIG_VVFAT')}
2194summary_info += {'qed support':       config_host.has_key('CONFIG_QED')}
2195summary_info += {'parallels support': config_host.has_key('CONFIG_PARALLELS')}
2196summary_info += {'sheepdog support':  config_host.has_key('CONFIG_SHEEPDOG')}
2197summary_info += {'capstone':          capstone_opt == 'disabled' ? false : capstone_opt}
2198summary_info += {'libpmem support':   config_host.has_key('CONFIG_LIBPMEM')}
2199summary_info += {'libdaxctl support': config_host.has_key('CONFIG_LIBDAXCTL')}
2200summary_info += {'libudev':           libudev.found()}
2201summary_info += {'default devices':   config_host['CONFIG_MINIKCONF_MODE'] == '--defconfig'}
2202summary_info += {'plugin support':    config_host.has_key('CONFIG_PLUGIN')}
2203summary_info += {'fuzzing support':   config_host.has_key('CONFIG_FUZZ')}
2204if config_host.has_key('HAVE_GDB_BIN')
2205  summary_info += {'gdb':             config_host['HAVE_GDB_BIN']}
2206endif
2207summary_info += {'thread sanitizer':  config_host.has_key('CONFIG_TSAN')}
2208summary_info += {'rng-none':          config_host.has_key('CONFIG_RNG_NONE')}
2209summary_info += {'Linux keyring':     config_host.has_key('CONFIG_SECRET_KEYRING')}
2210summary(summary_info, bool_yn: true)
2211
2212if not supported_cpus.contains(cpu)
2213  message()
2214  warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!')
2215  message()
2216  message('CPU host architecture ' + cpu + ' support is not currently maintained.')
2217  message('The QEMU project intends to remove support for this host CPU in')
2218  message('a future release if nobody volunteers to maintain it and to')
2219  message('provide a build host for our continuous integration setup.')
2220  message('configure has succeeded and you can continue to build, but')
2221  message('if you care about QEMU on this platform you should contact')
2222  message('us upstream at qemu-devel@nongnu.org.')
2223endif
2224
2225if not supported_oses.contains(targetos)
2226  message()
2227  warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!')
2228  message()
2229  message('Host OS ' + targetos + 'support is not currently maintained.')
2230  message('The QEMU project intends to remove support for this host OS in')
2231  message('a future release if nobody volunteers to maintain it and to')
2232  message('provide a build host for our continuous integration setup.')
2233  message('configure has succeeded and you can continue to build, but')
2234  message('if you care about QEMU on this platform you should contact')
2235  message('us upstream at qemu-devel@nongnu.org.')
2236endif
2237