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