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