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