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