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