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