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