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