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