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