meson: extend libmpathpersist test for static linking
[qemu.git] / meson.build
1 project('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
6 not_found = dependency('', required: false)
7 if meson.version().version_compare('>=0.56.0')
8   keyval = import('keyval')
9 else
10   keyval = import('unstable-keyval')
11 endif
12 ss = import('sourceset')
13
14 sh = find_program('sh')
15 cc = meson.get_compiler('c')
16 config_host = keyval.load(meson.current_build_dir() / 'config-host.mak')
17 enable_modules = 'CONFIG_MODULES' in config_host
18 enable_static = 'CONFIG_STATIC' in config_host
19 build_docs = 'BUILD_DOCS' in config_host
20
21 if get_option('qemu_suffix').startswith('/')
22   error('qemu_suffix cannot start with a /')
23 endif
24
25 qemu_datadir = get_option('datadir') / get_option('qemu_suffix')
26 qemu_docdir = get_option('docdir') / get_option('qemu_suffix')
27 config_host_data = configuration_data()
28 genh = []
29
30 target_dirs = config_host['TARGET_DIRS'].split()
31 have_user = false
32 have_system = false
33 foreach target : target_dirs
34   have_user = have_user or target.endswith('-user')
35   have_system = have_system or target.endswith('-softmmu')
36 endforeach
37 have_tools = 'CONFIG_TOOLS' in config_host
38 have_block = have_system or have_tools
39
40 python = import('python').find_installation()
41
42 supported_oses = ['windows', 'freebsd', 'netbsd', 'openbsd', 'darwin', 'sunos', 'linux']
43 supported_cpus = ['ppc', 'ppc64', 's390x', 'sparc64', 'riscv32', 'riscv64', 'x86', 'x86_64',
44   'arm', 'aarch64', 'mips', 'mips64', 'sparc', 'sparc64']
45
46 cpu = host_machine.cpu_family()
47 targetos = host_machine.system()
48
49 configure_file(input: files('scripts/ninjatool.py'),
50                output: 'ninjatool',
51                configuration: config_host)
52
53 ##################
54 # Compiler flags #
55 ##################
56
57 add_project_arguments(config_host['QEMU_CFLAGS'].split(),
58                       native: false, language: ['c', 'objc'])
59 add_project_arguments(config_host['QEMU_CXXFLAGS'].split(),
60                       native: false, language: 'cpp')
61 add_project_link_arguments(config_host['QEMU_LDFLAGS'].split(),
62                            native: false, language: ['c', 'cpp', 'objc'])
63 add_project_arguments(config_host['QEMU_INCLUDES'].split(),
64                       language: ['c', 'cpp', 'objc'])
65
66 # Specify linker-script with add_project_link_arguments so that it is not placed
67 # within a linker --start-group/--end-group pair
68 if 'CONFIG_FUZZ' in config_host
69    add_project_link_arguments(['-Wl,-T,',
70                                (meson.current_source_dir() / 'tests/qtest/fuzz/fork_fuzz.ld')],
71                               native: false, language: ['c', 'cpp', 'objc'])
72 endif
73
74 link_language = meson.get_external_property('link_language', 'cpp')
75 if link_language == 'cpp'
76   add_languages('cpp', required: true, native: false)
77 endif
78 if host_machine.system() == 'darwin'
79   add_languages('objc', required: false, native: false)
80 endif
81
82 if 'SPARSE_CFLAGS' in config_host
83   run_target('sparse',
84              command: [find_program('scripts/check_sparse.py'),
85                        config_host['SPARSE_CFLAGS'].split(),
86                        'compile_commands.json'])
87 endif
88
89 ###########################################
90 # Target-specific checks and dependencies #
91 ###########################################
92
93 if targetos != 'linux' and get_option('mpath').enabled()
94   error('Multipath is supported only on Linux')
95 endif
96
97 m = cc.find_library('m', required: false)
98 util = cc.find_library('util', required: false)
99 winmm = []
100 socket = []
101 version_res = []
102 coref = []
103 iokit = []
104 cocoa = []
105 hvf = []
106 if targetos == 'windows'
107   socket = cc.find_library('ws2_32')
108   winmm = cc.find_library('winmm')
109
110   win = import('windows')
111   version_res = win.compile_resources('version.rc',
112                                       depend_files: files('pc-bios/qemu-nsis.ico'),
113                                       include_directories: include_directories('.'))
114 elif targetos == 'darwin'
115   coref = dependency('appleframeworks', modules: 'CoreFoundation')
116   iokit = dependency('appleframeworks', modules: 'IOKit')
117   cocoa = dependency('appleframeworks', modules: 'Cocoa')
118   hvf = dependency('appleframeworks', modules: 'Hypervisor')
119 elif targetos == 'sunos'
120   socket = [cc.find_library('socket'),
121             cc.find_library('nsl'),
122             cc.find_library('resolv')]
123 elif targetos == 'haiku'
124   socket = [cc.find_library('posix_error_mapper'),
125             cc.find_library('network'),
126             cc.find_library('bsd')]
127 endif
128
129 ################
130 # Dependencies #
131 ################
132
133 # The path to glib.h is added to all compilation commands.  This was
134 # grandfathered in from the QEMU Makefiles.
135 add_project_arguments(config_host['GLIB_CFLAGS'].split(),
136                       native: false, language: ['c', 'cpp', 'objc'])
137 glib = declare_dependency(link_args: config_host['GLIB_LIBS'].split())
138 gio = not_found
139 if 'CONFIG_GIO' in config_host
140   gio = declare_dependency(compile_args: config_host['GIO_CFLAGS'].split(),
141                            link_args: config_host['GIO_LIBS'].split())
142 endif
143 lttng = not_found
144 if 'CONFIG_TRACE_UST' in config_host
145   lttng = declare_dependency(link_args: config_host['LTTNG_UST_LIBS'].split())
146 endif
147 urcubp = not_found
148 if 'CONFIG_TRACE_UST' in config_host
149   urcubp = declare_dependency(link_args: config_host['URCU_BP_LIBS'].split())
150 endif
151 gcrypt = not_found
152 if 'CONFIG_GCRYPT' in config_host
153   gcrypt = declare_dependency(compile_args: config_host['GCRYPT_CFLAGS'].split(),
154                               link_args: config_host['GCRYPT_LIBS'].split())
155 endif
156 nettle = not_found
157 if 'CONFIG_NETTLE' in config_host
158   nettle = declare_dependency(compile_args: config_host['NETTLE_CFLAGS'].split(),
159                               link_args: config_host['NETTLE_LIBS'].split())
160 endif
161 gnutls = not_found
162 if 'CONFIG_GNUTLS' in config_host
163   gnutls = declare_dependency(compile_args: config_host['GNUTLS_CFLAGS'].split(),
164                               link_args: config_host['GNUTLS_LIBS'].split())
165 endif
166 pixman = not_found
167 if have_system or have_tools
168   pixman = dependency('pixman-1', required: have_system, version:'>=0.21.8',
169                       method: 'pkg-config', static: enable_static)
170 endif
171 pam = not_found
172 if 'CONFIG_AUTH_PAM' in config_host
173   pam = cc.find_library('pam')
174 endif
175 libaio = cc.find_library('aio', required: false)
176 zlib = dependency('zlib', required: true, static: enable_static)
177 linux_io_uring = not_found
178 if 'CONFIG_LINUX_IO_URING' in config_host
179   linux_io_uring = declare_dependency(compile_args: config_host['LINUX_IO_URING_CFLAGS'].split(),
180                                       link_args: config_host['LINUX_IO_URING_LIBS'].split())
181 endif
182 libxml2 = not_found
183 if 'CONFIG_LIBXML2' in config_host
184   libxml2 = declare_dependency(compile_args: config_host['LIBXML2_CFLAGS'].split(),
185                                link_args: config_host['LIBXML2_LIBS'].split())
186 endif
187 libnfs = not_found
188 if 'CONFIG_LIBNFS' in config_host
189   libnfs = declare_dependency(link_args: config_host['LIBNFS_LIBS'].split())
190 endif
191 libattr = not_found
192 if 'CONFIG_ATTR' in config_host
193   libattr = declare_dependency(link_args: config_host['LIBATTR_LIBS'].split())
194 endif
195 seccomp = not_found
196 if 'CONFIG_SECCOMP' in config_host
197   seccomp = declare_dependency(compile_args: config_host['SECCOMP_CFLAGS'].split(),
198                                link_args: config_host['SECCOMP_LIBS'].split())
199 endif
200 libcap_ng = not_found
201 if 'CONFIG_LIBCAP_NG' in config_host
202   libcap_ng = declare_dependency(link_args: config_host['LIBCAP_NG_LIBS'].split())
203 endif
204 if get_option('xkbcommon').auto() and not have_system and not have_tools
205   xkbcommon = not_found
206 else
207   xkbcommon = dependency('xkbcommon', required: get_option('xkbcommon'),
208                          method: 'pkg-config', static: enable_static)
209 endif
210 slirp = not_found
211 if config_host.has_key('CONFIG_SLIRP')
212   slirp = declare_dependency(compile_args: config_host['SLIRP_CFLAGS'].split(),
213                              link_args: config_host['SLIRP_LIBS'].split())
214 endif
215 vde = not_found
216 if config_host.has_key('CONFIG_VDE')
217   vde = declare_dependency(link_args: config_host['VDE_LIBS'].split())
218 endif
219 pulse = not_found
220 if 'CONFIG_LIBPULSE' in config_host
221   pulse = declare_dependency(compile_args: config_host['PULSE_CFLAGS'].split(),
222                              link_args: config_host['PULSE_LIBS'].split())
223 endif
224 alsa = not_found
225 if 'CONFIG_ALSA' in config_host
226   alsa = declare_dependency(compile_args: config_host['ALSA_CFLAGS'].split(),
227                             link_args: config_host['ALSA_LIBS'].split())
228 endif
229 jack = not_found
230 if 'CONFIG_LIBJACK' in config_host
231   jack = declare_dependency(link_args: config_host['JACK_LIBS'].split())
232 endif
233 spice = not_found
234 if 'CONFIG_SPICE' in config_host
235   spice = declare_dependency(compile_args: config_host['SPICE_CFLAGS'].split(),
236                              link_args: config_host['SPICE_LIBS'].split())
237 endif
238 rt = cc.find_library('rt', required: false)
239 libdl = not_found
240 if 'CONFIG_PLUGIN' in config_host
241   libdl = cc.find_library('dl', required: true)
242 endif
243 libiscsi = not_found
244 if 'CONFIG_LIBISCSI' in config_host
245   libiscsi = declare_dependency(compile_args: config_host['LIBISCSI_CFLAGS'].split(),
246                                 link_args: config_host['LIBISCSI_LIBS'].split())
247 endif
248 zstd = not_found
249 if 'CONFIG_ZSTD' in config_host
250   zstd = declare_dependency(compile_args: config_host['ZSTD_CFLAGS'].split(),
251                             link_args: config_host['ZSTD_LIBS'].split())
252 endif
253 gbm = not_found
254 if 'CONFIG_GBM' in config_host
255   gbm = declare_dependency(compile_args: config_host['GBM_CFLAGS'].split(),
256                            link_args: config_host['GBM_LIBS'].split())
257 endif
258 virgl = not_found
259 if 'CONFIG_VIRGL' in config_host
260   virgl = declare_dependency(compile_args: config_host['VIRGL_CFLAGS'].split(),
261                              link_args: config_host['VIRGL_LIBS'].split())
262 endif
263 curl = not_found
264 if 'CONFIG_CURL' in config_host
265   curl = declare_dependency(compile_args: config_host['CURL_CFLAGS'].split(),
266                             link_args: config_host['CURL_LIBS'].split())
267 endif
268 libudev = not_found
269 if targetos == 'linux' and (have_system or have_tools)
270   libudev = dependency('libudev',
271                        required: get_option('mpath').enabled(),
272                        static: enable_static)
273 endif
274
275 mpathpersist = not_found
276 mpathpersist_new_api = false
277 if targetos == 'linux' and have_tools and not get_option('mpath').disabled()
278   mpath_test_source_new = '''
279     #include <libudev.h>
280     #include <mpath_persist.h>
281     unsigned mpath_mx_alloc_len = 1024;
282     int logsink;
283     static struct config *multipath_conf;
284     extern struct udev *udev;
285     extern struct config *get_multipath_config(void);
286     extern void put_multipath_config(struct config *conf);
287     struct udev *udev;
288     struct config *get_multipath_config(void) { return multipath_conf; }
289     void put_multipath_config(struct config *conf) { }
290     int main(void) {
291         udev = udev_new();
292         multipath_conf = mpath_lib_init();
293         return 0;
294     }'''
295   mpath_test_source_old = '''
296       #include <libudev.h>
297       #include <mpath_persist.h>
298       unsigned mpath_mx_alloc_len = 1024;
299       int logsink;
300       int main(void) {
301           struct udev *udev = udev_new();
302           mpath_lib_init(udev);
303           return 0;
304       }'''
305   mpathlibs = [libudev]
306   if enable_static
307     mpathlibs += cc.find_library('devmapper',
308                                    required: get_option('mpath'),
309                                    static: enable_static)
310   endif
311   mpathlibs += cc.find_library('multipath',
312                                required: get_option('mpath'),
313                                static: enable_static)
314   mpathlibs += cc.find_library('mpathpersist',
315                                required: get_option('mpath'),
316                                static: enable_static)
317   foreach lib: mpathlibs
318     if not lib.found()
319       mpathlibs = []
320       break
321     endif
322   endforeach
323   if mpathlibs.length() > 0
324     if cc.links(mpath_test_source_new, dependencies: mpathlibs)
325       mpathpersist = declare_dependency(dependencies: mpathlibs)
326       mpathpersist_new_api = true
327     elif cc.links(mpath_test_source_old, dependencies: mpathlibs)
328       mpathpersist = declare_dependency(dependencies: mpathlibs)
329     else
330       if get_option('mpath').enabled()
331         error('Cannot detect libmpathpersist API')
332       else
333         warning('Cannot detect libmpathpersist API, disabling')
334       endif
335     endif
336   endif
337 endif
338
339 brlapi = not_found
340 if 'CONFIG_BRLAPI' in config_host
341   brlapi = declare_dependency(link_args: config_host['BRLAPI_LIBS'].split())
342 endif
343
344 sdl = not_found
345 if have_system
346   sdl = dependency('sdl2', required: get_option('sdl'), static: enable_static)
347   sdl_image = not_found
348 endif
349 if sdl.found()
350   # work around 2.0.8 bug
351   sdl = declare_dependency(compile_args: '-Wno-undef',
352                            dependencies: sdl)
353   sdl_image = dependency('SDL2_image', required: get_option('sdl_image'),
354                          method: 'pkg-config', static: enable_static)
355 else
356   if get_option('sdl_image').enabled()
357     error('sdl-image required, but SDL was @0@'.format(
358           get_option('sdl').disabled() ? 'disabled' : 'not found'))
359   endif
360   sdl_image = not_found
361 endif
362
363 rbd = not_found
364 if 'CONFIG_RBD' in config_host
365   rbd = declare_dependency(link_args: config_host['RBD_LIBS'].split())
366 endif
367 glusterfs = not_found
368 if 'CONFIG_GLUSTERFS' in config_host
369   glusterfs = declare_dependency(compile_args: config_host['GLUSTERFS_CFLAGS'].split(),
370                                  link_args: config_host['GLUSTERFS_LIBS'].split())
371 endif
372 libssh = not_found
373 if 'CONFIG_LIBSSH' in config_host
374   libssh = declare_dependency(compile_args: config_host['LIBSSH_CFLAGS'].split(),
375                               link_args: config_host['LIBSSH_LIBS'].split())
376 endif
377 libbzip2 = not_found
378 if 'CONFIG_BZIP2' in config_host
379   libbzip2 = declare_dependency(link_args: config_host['BZIP2_LIBS'].split())
380 endif
381 liblzfse = not_found
382 if 'CONFIG_LZFSE' in config_host
383   liblzfse = declare_dependency(link_args: config_host['LZFSE_LIBS'].split())
384 endif
385 oss = not_found
386 if 'CONFIG_AUDIO_OSS' in config_host
387   oss = declare_dependency(link_args: config_host['OSS_LIBS'].split())
388 endif
389 dsound = not_found
390 if 'CONFIG_AUDIO_DSOUND' in config_host
391   dsound = declare_dependency(link_args: config_host['DSOUND_LIBS'].split())
392 endif
393 coreaudio = not_found
394 if 'CONFIG_AUDIO_COREAUDIO' in config_host
395   coreaudio = declare_dependency(link_args: config_host['COREAUDIO_LIBS'].split())
396 endif
397 opengl = not_found
398 if 'CONFIG_OPENGL' in config_host
399   opengl = declare_dependency(compile_args: config_host['OPENGL_CFLAGS'].split(),
400                               link_args: config_host['OPENGL_LIBS'].split())
401 endif
402 gtk = not_found
403 if 'CONFIG_GTK' in config_host
404   gtk = declare_dependency(compile_args: config_host['GTK_CFLAGS'].split(),
405                               link_args: config_host['GTK_LIBS'].split())
406 endif
407 vte = not_found
408 if 'CONFIG_VTE' in config_host
409   vte = declare_dependency(compile_args: config_host['VTE_CFLAGS'].split(),
410                            link_args: config_host['VTE_LIBS'].split())
411 endif
412 x11 = not_found
413 if 'CONFIG_X11' in config_host
414   x11 = declare_dependency(compile_args: config_host['X11_CFLAGS'].split(),
415                            link_args: config_host['X11_LIBS'].split())
416 endif
417 curses = not_found
418 if 'CONFIG_CURSES' in config_host
419   curses = declare_dependency(compile_args: config_host['CURSES_CFLAGS'].split(),
420                               link_args: config_host['CURSES_LIBS'].split())
421 endif
422 iconv = not_found
423 if 'CONFIG_ICONV' in config_host
424   iconv = declare_dependency(compile_args: config_host['ICONV_CFLAGS'].split(),
425                              link_args: config_host['ICONV_LIBS'].split())
426 endif
427 vnc = not_found
428 png = not_found
429 jpeg = not_found
430 sasl = not_found
431 if get_option('vnc').enabled()
432   vnc = declare_dependency() # dummy dependency
433   png = dependency('libpng', required: get_option('vnc_png'),
434                    method: 'pkg-config', static: enable_static)
435   jpeg = cc.find_library('jpeg', has_headers: ['jpeglib.h'],
436                          required: get_option('vnc_jpeg'),
437                          static: enable_static)
438   sasl = cc.find_library('sasl2', has_headers: ['sasl/sasl.h'],
439                          required: get_option('vnc_sasl'),
440                          static: enable_static)
441   if sasl.found()
442     sasl = declare_dependency(dependencies: sasl,
443                               compile_args: '-DSTRUCT_IOVEC_DEFINED')
444   endif
445 endif
446 fdt = not_found
447 if 'CONFIG_FDT' in config_host
448   fdt = declare_dependency(compile_args: config_host['FDT_CFLAGS'].split(),
449                            link_args: config_host['FDT_LIBS'].split())
450 endif
451 snappy = not_found
452 if 'CONFIG_SNAPPY' in config_host
453   snappy = declare_dependency(link_args: config_host['SNAPPY_LIBS'].split())
454 endif
455 lzo = not_found
456 if 'CONFIG_LZO' in config_host
457   lzo = declare_dependency(link_args: config_host['LZO_LIBS'].split())
458 endif
459 rdma = not_found
460 if 'CONFIG_RDMA' in config_host
461   rdma = declare_dependency(link_args: config_host['RDMA_LIBS'].split())
462 endif
463 numa = not_found
464 if 'CONFIG_NUMA' in config_host
465   numa = declare_dependency(link_args: config_host['NUMA_LIBS'].split())
466 endif
467 xen = not_found
468 if 'CONFIG_XEN_BACKEND' in config_host
469   xen = declare_dependency(compile_args: config_host['XEN_CFLAGS'].split(),
470                            link_args: config_host['XEN_LIBS'].split())
471 endif
472 cacard = not_found
473 if 'CONFIG_SMARTCARD' in config_host
474   cacard = declare_dependency(compile_args: config_host['SMARTCARD_CFLAGS'].split(),
475                               link_args: config_host['SMARTCARD_LIBS'].split())
476 endif
477 u2f = not_found
478 if have_system
479   u2f = dependency('u2f-emu', required: get_option('u2f'),
480                    method: 'pkg-config',
481                    static: enable_static)
482 endif
483 usbredir = not_found
484 if 'CONFIG_USB_REDIR' in config_host
485   usbredir = declare_dependency(compile_args: config_host['USB_REDIR_CFLAGS'].split(),
486                                 link_args: config_host['USB_REDIR_LIBS'].split())
487 endif
488 libusb = not_found
489 if 'CONFIG_USB_LIBUSB' in config_host
490   libusb = declare_dependency(compile_args: config_host['LIBUSB_CFLAGS'].split(),
491                               link_args: config_host['LIBUSB_LIBS'].split())
492 endif
493 capstone = not_found
494 if 'CONFIG_CAPSTONE' in config_host
495   capstone = declare_dependency(compile_args: config_host['CAPSTONE_CFLAGS'].split(),
496                                 link_args: config_host['CAPSTONE_LIBS'].split())
497 endif
498 libpmem = not_found
499 if 'CONFIG_LIBPMEM' in config_host
500   libpmem = declare_dependency(compile_args: config_host['LIBPMEM_CFLAGS'].split(),
501                                link_args: config_host['LIBPMEM_LIBS'].split())
502 endif
503 libdaxctl = not_found
504 if 'CONFIG_LIBDAXCTL' in config_host
505   libdaxctl = declare_dependency(link_args: config_host['LIBDAXCTL_LIBS'].split())
506 endif
507 tasn1 = not_found
508 if 'CONFIG_TASN1' in config_host
509   tasn1 = declare_dependency(compile_args: config_host['TASN1_CFLAGS'].split(),
510                              link_args: config_host['TASN1_LIBS'].split())
511 endif
512 keyutils = dependency('libkeyutils', required: false,
513                       method: 'pkg-config', static: enable_static)
514
515 has_gettid = cc.has_function('gettid')
516
517 # Create config-host.h
518
519 config_host_data.set('CONFIG_LIBUDEV', libudev.found())
520 config_host_data.set('CONFIG_MPATH', mpathpersist.found())
521 config_host_data.set('CONFIG_MPATH_NEW_API', mpathpersist_new_api)
522 config_host_data.set('CONFIG_SDL', sdl.found())
523 config_host_data.set('CONFIG_SDL_IMAGE', sdl_image.found())
524 config_host_data.set('CONFIG_VNC', vnc.found())
525 config_host_data.set('CONFIG_VNC_JPEG', jpeg.found())
526 config_host_data.set('CONFIG_VNC_PNG', png.found())
527 config_host_data.set('CONFIG_VNC_SASL', sasl.found())
528 config_host_data.set('CONFIG_XKBCOMMON', xkbcommon.found())
529 config_host_data.set('CONFIG_KEYUTILS', keyutils.found())
530 config_host_data.set('CONFIG_GETTID', has_gettid)
531 config_host_data.set('QEMU_VERSION', '"@0@"'.format(meson.project_version()))
532 config_host_data.set('QEMU_VERSION_MAJOR', meson.project_version().split('.')[0])
533 config_host_data.set('QEMU_VERSION_MINOR', meson.project_version().split('.')[1])
534 config_host_data.set('QEMU_VERSION_MICRO', meson.project_version().split('.')[2])
535
536 arrays = ['CONFIG_AUDIO_DRIVERS', 'CONFIG_BDRV_RW_WHITELIST', 'CONFIG_BDRV_RO_WHITELIST']
537 strings = ['HOST_DSOSUF', 'CONFIG_IASL', 'qemu_confdir', 'qemu_datadir',
538            'qemu_moddir', 'qemu_localstatedir', 'qemu_helperdir', 'qemu_localedir',
539            'qemu_icondir', 'qemu_desktopdir', 'qemu_firmwarepath']
540 foreach k, v: config_host
541   if arrays.contains(k)
542     if v != ''
543       v = '"' + '", "'.join(v.split()) + '", '
544     endif
545     config_host_data.set(k, v)
546   elif k == 'ARCH'
547     config_host_data.set('HOST_' + v.to_upper(), 1)
548   elif strings.contains(k)
549     if not k.startswith('CONFIG_')
550       k = 'CONFIG_' + k.to_upper()
551     endif
552     config_host_data.set_quoted(k, v)
553   elif k.startswith('CONFIG_') or k.startswith('HAVE_') or k.startswith('HOST_')
554     config_host_data.set(k, v == 'y' ? 1 : v)
555   endif
556 endforeach
557 genh += configure_file(output: 'config-host.h', configuration: config_host_data)
558
559 minikconf = find_program('scripts/minikconf.py')
560 config_all_devices = {}
561 config_all_disas = {}
562 config_devices_mak_list = []
563 config_devices_h = {}
564 config_target_h = {}
565 config_target_mak = {}
566
567 disassemblers = {
568   'alpha' : ['CONFIG_ALPHA_DIS'],
569   'arm' : ['CONFIG_ARM_DIS'],
570   'avr' : ['CONFIG_AVR_DIS'],
571   'cris' : ['CONFIG_CRIS_DIS'],
572   'hppa' : ['CONFIG_HPPA_DIS'],
573   'i386' : ['CONFIG_I386_DIS'],
574   'x86_64' : ['CONFIG_I386_DIS'],
575   'x32' : ['CONFIG_I386_DIS'],
576   'lm32' : ['CONFIG_LM32_DIS'],
577   'm68k' : ['CONFIG_M68K_DIS'],
578   'microblaze' : ['CONFIG_MICROBLAZE_DIS'],
579   'mips' : ['CONFIG_MIPS_DIS'],
580   'moxie' : ['CONFIG_MOXIE_DIS'],
581   'nios2' : ['CONFIG_NIOS2_DIS'],
582   'or1k' : ['CONFIG_OPENRISC_DIS'],
583   'ppc' : ['CONFIG_PPC_DIS'],
584   'riscv' : ['CONFIG_RISCV_DIS'],
585   'rx' : ['CONFIG_RX_DIS'],
586   's390' : ['CONFIG_S390_DIS'],
587   'sh4' : ['CONFIG_SH4_DIS'],
588   'sparc' : ['CONFIG_SPARC_DIS'],
589   'xtensa' : ['CONFIG_XTENSA_DIS'],
590 }
591 if link_language == 'cpp'
592   disassemblers += {
593     'aarch64' : [ 'CONFIG_ARM_A64_DIS'],
594     'arm' : [ 'CONFIG_ARM_DIS', 'CONFIG_ARM_A64_DIS'],
595     'mips' : [ 'CONFIG_MIPS_DIS', 'CONFIG_NANOMIPS_DIS'],
596   }
597 endif
598
599 kconfig_external_symbols = [
600   'CONFIG_KVM',
601   'CONFIG_XEN',
602   'CONFIG_TPM',
603   'CONFIG_SPICE',
604   'CONFIG_IVSHMEM',
605   'CONFIG_OPENGL',
606   'CONFIG_X11',
607   'CONFIG_VHOST_USER',
608   'CONFIG_VHOST_VDPA',
609   'CONFIG_VHOST_KERNEL',
610   'CONFIG_VIRTFS',
611   'CONFIG_LINUX',
612   'CONFIG_PVRDMA',
613 ]
614 ignored = ['TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_DIRS']
615
616 foreach target : target_dirs
617   config_target = keyval.load(meson.current_build_dir() / target / 'config-target.mak')
618
619   foreach k, v: disassemblers
620     if config_host['ARCH'].startswith(k) or config_target['TARGET_BASE_ARCH'].startswith(k)
621       foreach sym: v
622         config_target += { sym: 'y' }
623         config_all_disas += { sym: 'y' }
624       endforeach
625     endif
626   endforeach
627
628   config_target_data = configuration_data()
629   foreach k, v: config_target
630     if not k.startswith('TARGET_') and not k.startswith('CONFIG_')
631       # do nothing
632     elif ignored.contains(k)
633       # do nothing
634     elif k == 'TARGET_BASE_ARCH'
635       config_target_data.set('TARGET_' + v.to_upper(), 1)
636     elif k == 'TARGET_NAME'
637       config_target_data.set_quoted(k, v)
638     elif v == 'y'
639       config_target_data.set(k, 1)
640     else
641       config_target_data.set(k, v)
642     endif
643   endforeach
644   config_target_h += {target: configure_file(output: target + '-config-target.h',
645                                                configuration: config_target_data)}
646
647   if target.endswith('-softmmu')
648     base_kconfig = []
649     foreach sym : kconfig_external_symbols
650       if sym in config_target or sym in config_host
651         base_kconfig += '@0@=y'.format(sym)
652       endif
653     endforeach
654
655     config_devices_mak = target + '-config-devices.mak'
656     config_devices_mak = configure_file(
657       input: ['default-configs' / target + '.mak', 'Kconfig'],
658       output: config_devices_mak,
659       depfile: config_devices_mak + '.d',
660       capture: true,
661       command: [minikconf, config_host['CONFIG_MINIKCONF_MODE'],
662                 config_devices_mak, '@DEPFILE@', '@INPUT@',
663                 base_kconfig])
664
665     config_devices_data = configuration_data()
666     config_devices = keyval.load(config_devices_mak)
667     foreach k, v: config_devices
668       config_devices_data.set(k, 1)
669     endforeach
670     config_devices_mak_list += config_devices_mak
671     config_devices_h += {target: configure_file(output: target + '-config-devices.h',
672                                                 configuration: config_devices_data)}
673     config_target += config_devices
674     config_all_devices += config_devices
675   endif
676   config_target_mak += {target: config_target}
677 endforeach
678
679 # This configuration is used to build files that are shared by
680 # multiple binaries, and then extracted out of the "common"
681 # static_library target.
682 #
683 # We do not use all_sources()/all_dependencies(), because it would
684 # build literally all source files, including devices only used by
685 # targets that are not built for this compilation.  The CONFIG_ALL
686 # pseudo symbol replaces it.
687
688 config_all = config_all_devices
689 config_all += config_host
690 config_all += config_all_disas
691 config_all += {
692   'CONFIG_XEN': config_host.has_key('CONFIG_XEN_BACKEND'),
693   'CONFIG_SOFTMMU': have_system,
694   'CONFIG_USER_ONLY': have_user,
695   'CONFIG_ALL': true,
696 }
697
698 # Generators
699
700 hxtool = find_program('scripts/hxtool')
701 shaderinclude = find_program('scripts/shaderinclude.pl')
702 qapi_gen = find_program('scripts/qapi-gen.py')
703 qapi_gen_depends = [ meson.source_root() / 'scripts/qapi/__init__.py',
704                      meson.source_root() / 'scripts/qapi/commands.py',
705                      meson.source_root() / 'scripts/qapi/common.py',
706                      meson.source_root() / 'scripts/qapi/error.py',
707                      meson.source_root() / 'scripts/qapi/events.py',
708                      meson.source_root() / 'scripts/qapi/expr.py',
709                      meson.source_root() / 'scripts/qapi/gen.py',
710                      meson.source_root() / 'scripts/qapi/introspect.py',
711                      meson.source_root() / 'scripts/qapi/parser.py',
712                      meson.source_root() / 'scripts/qapi/schema.py',
713                      meson.source_root() / 'scripts/qapi/source.py',
714                      meson.source_root() / 'scripts/qapi/types.py',
715                      meson.source_root() / 'scripts/qapi/visit.py',
716                      meson.source_root() / 'scripts/qapi/common.py',
717                      meson.source_root() / 'scripts/qapi-gen.py'
718 ]
719
720 tracetool = [
721   python, files('scripts/tracetool.py'),
722    '--backend=' + config_host['TRACE_BACKENDS']
723 ]
724
725 qemu_version_cmd = [find_program('scripts/qemu-version.sh'),
726                     meson.current_source_dir(),
727                     config_host['PKGVERSION'], meson.project_version()]
728 qemu_version = custom_target('qemu-version.h',
729                              output: 'qemu-version.h',
730                              command: qemu_version_cmd,
731                              capture: true,
732                              build_by_default: true,
733                              build_always_stale: true)
734 genh += qemu_version
735
736 hxdep = []
737 hx_headers = [
738   ['qemu-options.hx', 'qemu-options.def'],
739   ['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
740 ]
741 if have_system
742   hx_headers += [
743     ['hmp-commands.hx', 'hmp-commands.h'],
744     ['hmp-commands-info.hx', 'hmp-commands-info.h'],
745   ]
746 endif
747 foreach d : hx_headers
748   hxdep += custom_target(d[1],
749                 input: files(d[0]),
750                 output: d[1],
751                 capture: true,
752                 build_by_default: true, # to be removed when added to a target
753                 command: [hxtool, '-h', '@INPUT0@'])
754 endforeach
755 genh += hxdep
756
757 SPHINX_ARGS = [config_host['SPHINX_BUILD'],
758                '-Dversion=' + meson.project_version(),
759                '-Drelease=' + config_host['PKGVERSION']]
760
761 if get_option('werror')
762   SPHINX_ARGS += [ '-W' ]
763 endif
764
765 sphinx_extn_depends = [ meson.source_root() / 'docs/sphinx/depfile.py',
766                         meson.source_root() / 'docs/sphinx/hxtool.py',
767                         meson.source_root() / 'docs/sphinx/kerneldoc.py',
768                         meson.source_root() / 'docs/sphinx/kernellog.py',
769                         meson.source_root() / 'docs/sphinx/qapidoc.py',
770                         meson.source_root() / 'docs/sphinx/qmp_lexer.py',
771                         qapi_gen_depends ]
772
773 # Collect sourcesets.
774
775 util_ss = ss.source_set()
776 stub_ss = ss.source_set()
777 trace_ss = ss.source_set()
778 block_ss = ss.source_set()
779 blockdev_ss = ss.source_set()
780 qmp_ss = ss.source_set()
781 common_ss = ss.source_set()
782 softmmu_ss = ss.source_set()
783 user_ss = ss.source_set()
784 bsd_user_ss = ss.source_set()
785 linux_user_ss = ss.source_set()
786 specific_ss = ss.source_set()
787 specific_fuzz_ss = ss.source_set()
788
789 modules = {}
790 hw_arch = {}
791 target_arch = {}
792 target_softmmu_arch = {}
793
794 ###############
795 # Trace files #
796 ###############
797
798 # TODO: add each directory to the subdirs from its own meson.build, once
799 # we have those
800 trace_events_subdirs = [
801   'accel/kvm',
802   'accel/tcg',
803   'crypto',
804   'monitor',
805 ]
806 if have_user
807   trace_events_subdirs += [ 'linux-user' ]
808 endif
809 if have_block
810   trace_events_subdirs += [
811     'authz',
812     'block',
813     'io',
814     'nbd',
815     'scsi',
816   ]
817 endif
818 if have_system
819   trace_events_subdirs += [
820     'audio',
821     'backends',
822     'backends/tpm',
823     'chardev',
824     'hw/9pfs',
825     'hw/acpi',
826     'hw/alpha',
827     'hw/arm',
828     'hw/audio',
829     'hw/block',
830     'hw/block/dataplane',
831     'hw/char',
832     'hw/display',
833     'hw/dma',
834     'hw/hppa',
835     'hw/hyperv',
836     'hw/i2c',
837     'hw/i386',
838     'hw/i386/xen',
839     'hw/ide',
840     'hw/input',
841     'hw/intc',
842     'hw/isa',
843     'hw/mem',
844     'hw/mips',
845     'hw/misc',
846     'hw/misc/macio',
847     'hw/net',
848     'hw/nvram',
849     'hw/pci',
850     'hw/pci-host',
851     'hw/ppc',
852     'hw/rdma',
853     'hw/rdma/vmw',
854     'hw/rtc',
855     'hw/s390x',
856     'hw/scsi',
857     'hw/sd',
858     'hw/sparc',
859     'hw/sparc64',
860     'hw/ssi',
861     'hw/timer',
862     'hw/tpm',
863     'hw/usb',
864     'hw/vfio',
865     'hw/virtio',
866     'hw/watchdog',
867     'hw/xen',
868     'hw/gpio',
869     'migration',
870     'net',
871     'softmmu',
872     'ui',
873   ]
874 endif
875 trace_events_subdirs += [
876   'hw/core',
877   'qapi',
878   'qom',
879   'target/arm',
880   'target/hppa',
881   'target/i386',
882   'target/mips',
883   'target/ppc',
884   'target/riscv',
885   'target/s390x',
886   'target/sparc',
887   'util',
888 ]
889
890 subdir('qapi')
891 subdir('qobject')
892 subdir('stubs')
893 subdir('trace')
894 subdir('util')
895 subdir('qom')
896 subdir('authz')
897 subdir('crypto')
898 subdir('ui')
899
900
901 if enable_modules
902   libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
903   modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
904 endif
905
906 # Build targets from sourcesets
907
908 stub_ss = stub_ss.apply(config_all, strict: false)
909
910 util_ss.add_all(trace_ss)
911 util_ss = util_ss.apply(config_all, strict: false)
912 libqemuutil = static_library('qemuutil',
913                              sources: util_ss.sources() + stub_ss.sources() + genh,
914                              dependencies: [util_ss.dependencies(), m, glib, socket])
915 qemuutil = declare_dependency(link_with: libqemuutil,
916                               sources: genh + version_res)
917
918 decodetree = generator(find_program('scripts/decodetree.py'),
919                        output: 'decode-@BASENAME@.c.inc',
920                        arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
921
922 subdir('audio')
923 subdir('io')
924 subdir('chardev')
925 subdir('fsdev')
926 subdir('libdecnumber')
927 subdir('target')
928 subdir('dump')
929
930 block_ss.add(files(
931   'block.c',
932   'blockjob.c',
933   'job.c',
934   'qemu-io-cmds.c',
935 ))
936 block_ss.add(when: 'CONFIG_REPLICATION', if_true: files('replication.c'))
937
938 subdir('nbd')
939 subdir('scsi')
940 subdir('block')
941
942 blockdev_ss.add(files(
943   'blockdev.c',
944   'blockdev-nbd.c',
945   'iothread.c',
946   'job-qmp.c',
947 ))
948
949 # os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
950 # os-win32.c does not
951 blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c'))
952 softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')])
953
954 softmmu_ss.add_all(blockdev_ss)
955 softmmu_ss.add(files(
956   'bootdevice.c',
957   'dma-helpers.c',
958   'qdev-monitor.c',
959 ), sdl)
960
961 softmmu_ss.add(when: 'CONFIG_TPM', if_true: files('tpm.c'))
962 softmmu_ss.add(when: 'CONFIG_SECCOMP', if_true: [files('qemu-seccomp.c'), seccomp])
963 softmmu_ss.add(when: ['CONFIG_FDT', fdt],  if_true: [files('device_tree.c')])
964
965 common_ss.add(files('cpus-common.c'))
966
967 subdir('softmmu')
968
969 specific_ss.add(files('disas.c', 'exec.c', 'gdbstub.c'), capstone, libpmem, libdaxctl)
970 specific_ss.add(files('exec-vary.c'))
971 specific_ss.add(when: 'CONFIG_TCG', if_true: files(
972   'fpu/softfloat.c',
973   'tcg/optimize.c',
974   'tcg/tcg-common.c',
975   'tcg/tcg-op-gvec.c',
976   'tcg/tcg-op-vec.c',
977   'tcg/tcg-op.c',
978   'tcg/tcg.c',
979 ))
980 specific_ss.add(when: 'CONFIG_TCG_INTERPRETER', if_true: files('disas/tci.c', 'tcg/tci.c'))
981
982 subdir('backends')
983 subdir('disas')
984 subdir('migration')
985 subdir('monitor')
986 subdir('net')
987 subdir('replay')
988 subdir('hw')
989 subdir('accel')
990 subdir('plugins')
991 subdir('bsd-user')
992 subdir('linux-user')
993
994 bsd_user_ss.add(files('gdbstub.c'))
995 specific_ss.add_all(when: 'CONFIG_BSD_USER', if_true: bsd_user_ss)
996
997 linux_user_ss.add(files('gdbstub.c', 'thunk.c'))
998 specific_ss.add_all(when: 'CONFIG_LINUX_USER', if_true: linux_user_ss)
999
1000 # needed for fuzzing binaries
1001 subdir('tests/qtest/libqos')
1002 subdir('tests/qtest/fuzz')
1003
1004 block_mods = []
1005 softmmu_mods = []
1006 foreach d, list : modules
1007   foreach m, module_ss : list
1008     if enable_modules and targetos != 'windows'
1009       module_ss = module_ss.apply(config_all, strict: false)
1010       sl = static_library(d + '-' + m, [genh, module_ss.sources()],
1011                           dependencies: [modulecommon, module_ss.dependencies()], pic: true)
1012       if d == 'block'
1013         block_mods += sl
1014       else
1015         softmmu_mods += sl
1016       endif
1017     else
1018       if d == 'block'
1019         block_ss.add_all(module_ss)
1020       else
1021         softmmu_ss.add_all(module_ss)
1022       endif
1023     endif
1024   endforeach
1025 endforeach
1026
1027 nm = find_program('nm')
1028 undefsym = find_program('scripts/undefsym.py')
1029 block_syms = custom_target('block.syms', output: 'block.syms',
1030                              input: [libqemuutil, block_mods],
1031                              capture: true,
1032                              command: [undefsym, nm, '@INPUT@'])
1033 qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
1034                              input: [libqemuutil, softmmu_mods],
1035                              capture: true,
1036                              command: [undefsym, nm, '@INPUT@'])
1037
1038 block_ss = block_ss.apply(config_host, strict: false)
1039 libblock = static_library('block', block_ss.sources() + genh,
1040                           dependencies: block_ss.dependencies(),
1041                           link_depends: block_syms,
1042                           name_suffix: 'fa',
1043                           build_by_default: false)
1044
1045 block = declare_dependency(link_whole: [libblock],
1046                            link_args: '@block.syms',
1047                            dependencies: [crypto, io])
1048
1049 qmp_ss = qmp_ss.apply(config_host, strict: false)
1050 libqmp = static_library('qmp', qmp_ss.sources() + genh,
1051                         dependencies: qmp_ss.dependencies(),
1052                         name_suffix: 'fa',
1053                         build_by_default: false)
1054
1055 qmp = declare_dependency(link_whole: [libqmp])
1056
1057 foreach m : block_mods + softmmu_mods
1058   shared_module(m.name(),
1059                 name_prefix: '',
1060                 link_whole: m,
1061                 install: true,
1062                 install_dir: config_host['qemu_moddir'])
1063 endforeach
1064
1065 softmmu_ss.add(authz, block, chardev, crypto, io, qmp)
1066 common_ss.add(qom, qemuutil)
1067
1068 common_ss.add_all(when: 'CONFIG_SOFTMMU', if_true: [softmmu_ss])
1069 common_ss.add_all(when: 'CONFIG_USER_ONLY', if_true: user_ss)
1070
1071 common_all = common_ss.apply(config_all, strict: false)
1072 common_all = static_library('common',
1073                             build_by_default: false,
1074                             sources: common_all.sources() + genh,
1075                             dependencies: common_all.dependencies(),
1076                             name_suffix: 'fa')
1077
1078 feature_to_c = find_program('scripts/feature_to_c.sh')
1079
1080 emulators = []
1081 foreach target : target_dirs
1082   config_target = config_target_mak[target]
1083   target_name = config_target['TARGET_NAME']
1084   arch = config_target['TARGET_BASE_ARCH']
1085   arch_srcs = [config_target_h[target]]
1086   arch_deps = []
1087   c_args = ['-DNEED_CPU_H',
1088             '-DCONFIG_TARGET="@0@-config-target.h"'.format(target),
1089             '-DCONFIG_DEVICES="@0@-config-devices.h"'.format(target)]
1090   link_args = []
1091
1092   config_target += config_host
1093   target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])]
1094   if targetos == 'linux'
1095     target_inc += include_directories('linux-headers', is_system: true)
1096   endif
1097   if target.endswith('-softmmu')
1098     qemu_target_name = 'qemu-system-' + target_name
1099     target_type='system'
1100     t = target_softmmu_arch[arch].apply(config_target, strict: false)
1101     arch_srcs += t.sources()
1102     arch_deps += t.dependencies()
1103
1104     hw_dir = target_name == 'sparc64' ? 'sparc64' : arch
1105     hw = hw_arch[hw_dir].apply(config_target, strict: false)
1106     arch_srcs += hw.sources()
1107     arch_deps += hw.dependencies()
1108
1109     arch_srcs += config_devices_h[target]
1110     link_args += ['@block.syms', '@qemu.syms']
1111   else
1112     abi = config_target['TARGET_ABI_DIR']
1113     target_type='user'
1114     qemu_target_name = 'qemu-' + target_name
1115     if 'CONFIG_LINUX_USER' in config_target
1116       base_dir = 'linux-user'
1117       target_inc += include_directories('linux-user/host/' / config_host['ARCH'])
1118     else
1119       base_dir = 'bsd-user'
1120     endif
1121     target_inc += include_directories(
1122       base_dir,
1123       base_dir / abi,
1124     )
1125     if 'CONFIG_LINUX_USER' in config_target
1126       dir = base_dir / abi
1127       arch_srcs += files(dir / 'signal.c', dir / 'cpu_loop.c')
1128       if config_target.has_key('TARGET_SYSTBL_ABI')
1129         arch_srcs += \
1130           syscall_nr_generators[abi].process(base_dir / abi / config_target['TARGET_SYSTBL'],
1131                                              extra_args : config_target['TARGET_SYSTBL_ABI'])
1132       endif
1133     endif
1134   endif
1135
1136   if 'TARGET_XML_FILES' in config_target
1137     gdbstub_xml = custom_target(target + '-gdbstub-xml.c',
1138                                 output: target + '-gdbstub-xml.c',
1139                                 input: files(config_target['TARGET_XML_FILES'].split()),
1140                                 command: [feature_to_c, '@INPUT@'],
1141                                 capture: true)
1142     arch_srcs += gdbstub_xml
1143   endif
1144
1145   t = target_arch[arch].apply(config_target, strict: false)
1146   arch_srcs += t.sources()
1147   arch_deps += t.dependencies()
1148
1149   target_common = common_ss.apply(config_target, strict: false)
1150   objects = common_all.extract_objects(target_common.sources())
1151   deps = target_common.dependencies()
1152
1153   target_specific = specific_ss.apply(config_target, strict: false)
1154   arch_srcs += target_specific.sources()
1155   arch_deps += target_specific.dependencies()
1156
1157   lib = static_library('qemu-' + target,
1158                  sources: arch_srcs + genh,
1159                  dependencies: arch_deps,
1160                  objects: objects,
1161                  include_directories: target_inc,
1162                  c_args: c_args,
1163                  build_by_default: false,
1164                  name_suffix: 'fa')
1165
1166   if target.endswith('-softmmu')
1167     execs = [{
1168       'name': 'qemu-system-' + target_name,
1169       'gui': false,
1170       'sources': files('softmmu/main.c'),
1171       'dependencies': []
1172     }]
1173     if targetos == 'windows' and (sdl.found() or gtk.found())
1174       execs += [{
1175         'name': 'qemu-system-' + target_name + 'w',
1176         'gui': true,
1177         'sources': files('softmmu/main.c'),
1178         'dependencies': []
1179       }]
1180     endif
1181     if config_host.has_key('CONFIG_FUZZ')
1182       specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
1183       execs += [{
1184         'name': 'qemu-fuzz-' + target_name,
1185         'gui': false,
1186         'sources': specific_fuzz.sources(),
1187         'dependencies': specific_fuzz.dependencies(),
1188       }]
1189     endif
1190   else
1191     execs = [{
1192       'name': 'qemu-' + target_name,
1193       'gui': false,
1194       'sources': [],
1195       'dependencies': []
1196     }]
1197   endif
1198   foreach exe: execs
1199     emulators += executable(exe['name'], exe['sources'],
1200                install: true,
1201                c_args: c_args,
1202                dependencies: arch_deps + deps + exe['dependencies'],
1203                objects: lib.extract_all_objects(recursive: true),
1204                link_language: link_language,
1205                link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
1206                link_args: link_args,
1207                gui_app: exe['gui'])
1208
1209     if 'CONFIG_TRACE_SYSTEMTAP' in config_host
1210       foreach stp: [
1211         {'ext': '.stp-build', 'fmt': 'stap', 'bin': meson.current_build_dir() / exe['name'], 'install': false},
1212         {'ext': '.stp', 'fmt': 'stap', 'bin': get_option('prefix') / get_option('bindir') / exe['name'], 'install': true},
1213         {'ext': '-simpletrace.stp', 'fmt': 'simpletrace-stap', 'bin': '', 'install': true},
1214         {'ext': '-log.stp', 'fmt': 'log-stap', 'bin': '', 'install': true},
1215       ]
1216         custom_target(exe['name'] + stp['ext'],
1217                       input: trace_events_all,
1218                       output: exe['name'] + stp['ext'],
1219                       capture: true,
1220                       install: stp['install'],
1221                       install_dir: qemu_datadir / '../systemtap/tapset',
1222                       command: [
1223                         tracetool, '--group=all', '--format=' + stp['fmt'],
1224                         '--binary=' + stp['bin'],
1225                         '--target-name=' + target_name,
1226                         '--target-type=' + target_type,
1227                         '--probe-prefix=qemu.' + target_type + '.' + target_name,
1228                         '@INPUT@',
1229                       ])
1230       endforeach
1231     endif
1232   endforeach
1233 endforeach
1234
1235 # Other build targets
1236
1237 if 'CONFIG_PLUGIN' in config_host
1238   install_headers('include/qemu/qemu-plugin.h')
1239 endif
1240
1241 if 'CONFIG_GUEST_AGENT' in config_host
1242   subdir('qga')
1243 endif
1244
1245 # Don't build qemu-keymap if xkbcommon is not explicitly enabled
1246 # when we don't build tools or system
1247 if xkbcommon.found()
1248   # used for the update-keymaps target, so include rules even if !have_tools
1249   qemu_keymap = executable('qemu-keymap', files('qemu-keymap.c', 'ui/input-keymap.c') + genh,
1250                            dependencies: [qemuutil, xkbcommon], install: have_tools)
1251 endif
1252
1253 qemu_block_tools = []
1254 if have_tools
1255   qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
1256              dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
1257   qemu_io = executable('qemu-io', files('qemu-io.c'),
1258              dependencies: [block, qemuutil], install: true)
1259   qemu_nbd = executable('qemu-nbd', files('qemu-nbd.c'),
1260                dependencies: [block, qemuutil], install: true)
1261
1262   subdir('storage-daemon')
1263   subdir('contrib/rdmacm-mux')
1264   subdir('contrib/elf2dmp')
1265
1266   executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
1267              dependencies: qemuutil,
1268              install: true)
1269
1270   if 'CONFIG_VHOST_USER' in config_host
1271     subdir('contrib/libvhost-user')
1272     subdir('contrib/vhost-user-blk')
1273     subdir('contrib/vhost-user-gpu')
1274     subdir('contrib/vhost-user-input')
1275     subdir('contrib/vhost-user-scsi')
1276   endif
1277
1278   if targetos == 'linux'
1279     executable('qemu-bridge-helper', files('qemu-bridge-helper.c'),
1280                dependencies: [qemuutil, libcap_ng],
1281                install: true,
1282                install_dir: get_option('libexecdir'))
1283
1284     executable('qemu-pr-helper', files('scsi/qemu-pr-helper.c', 'scsi/utils.c'),
1285                dependencies: [authz, crypto, io, qom, qemuutil,
1286                               libcap_ng, mpathpersist],
1287                install: true)
1288   endif
1289
1290   if 'CONFIG_IVSHMEM' in config_host
1291     subdir('contrib/ivshmem-client')
1292     subdir('contrib/ivshmem-server')
1293   endif
1294 endif
1295
1296 subdir('scripts')
1297 subdir('tools')
1298 subdir('pc-bios')
1299 subdir('tests')
1300 subdir('docs')
1301 if 'CONFIG_GTK' in config_host
1302   subdir('po')
1303 endif
1304
1305 if host_machine.system() == 'windows'
1306   nsis_cmd = [
1307     find_program('scripts/nsis.py'),
1308     '@OUTPUT@',
1309     get_option('prefix'),
1310     meson.current_source_dir(),
1311     host_machine.cpu_family(),
1312     '--',
1313     '-DDISPLAYVERSION=' + meson.project_version(),
1314   ]
1315   if build_docs
1316     nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
1317   endif
1318   if 'CONFIG_GTK' in config_host
1319     nsis_cmd += '-DCONFIG_GTK=y'
1320   endif
1321
1322   nsis = custom_target('nsis',
1323                        output: 'qemu-setup-' + meson.project_version() + '.exe',
1324                        input: files('qemu.nsi'),
1325                        build_always_stale: true,
1326                        command: nsis_cmd + ['@INPUT@'])
1327   alias_target('installer', nsis)
1328 endif
1329
1330 summary_info = {}
1331 summary_info += {'Install prefix':    config_host['prefix']}
1332 summary_info += {'BIOS directory':    config_host['qemu_datadir']}
1333 summary_info += {'firmware path':     config_host['qemu_firmwarepath']}
1334 summary_info += {'binary directory':  config_host['bindir']}
1335 summary_info += {'library directory': config_host['libdir']}
1336 summary_info += {'module directory':  config_host['qemu_moddir']}
1337 summary_info += {'libexec directory': config_host['libexecdir']}
1338 summary_info += {'include directory': config_host['includedir']}
1339 summary_info += {'config directory':  config_host['sysconfdir']}
1340 if targetos != 'windows'
1341   summary_info += {'local state directory': config_host['qemu_localstatedir']}
1342   summary_info += {'Manual directory':      get_option('mandir')}
1343 else
1344   summary_info += {'local state directory': 'queried at runtime'}
1345 endif
1346 summary_info += {'Doc directory':     get_option('docdir')}
1347 summary_info += {'Build directory':   meson.current_build_dir()}
1348 summary_info += {'Source path':       meson.current_source_dir()}
1349 summary_info += {'GIT binary':        config_host['GIT']}
1350 summary_info += {'GIT submodules':    config_host['GIT_SUBMODULES']}
1351 summary_info += {'C compiler':        meson.get_compiler('c').cmd_array()[0]}
1352 summary_info += {'Host C compiler':   meson.get_compiler('c', native: true).cmd_array()[0]}
1353 if link_language == 'cpp'
1354   summary_info += {'C++ compiler':      meson.get_compiler('cpp').cmd_array()[0]}
1355 else
1356   summary_info += {'C++ compiler':      false}
1357 endif
1358 if targetos == 'darwin'
1359   summary_info += {'Objective-C compiler': meson.get_compiler('objc').cmd_array()[0]}
1360 endif
1361 summary_info += {'ARFLAGS':           config_host['ARFLAGS']}
1362 summary_info += {'CFLAGS':            config_host['CFLAGS']}
1363 summary_info += {'QEMU_CFLAGS':       config_host['QEMU_CFLAGS']}
1364 summary_info += {'QEMU_LDFLAGS':      config_host['QEMU_LDFLAGS']}
1365 summary_info += {'make':              config_host['MAKE']}
1366 summary_info += {'python':            '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
1367 summary_info += {'sphinx-build':      config_host['SPHINX_BUILD']}
1368 summary_info += {'genisoimage':       config_host['GENISOIMAGE']}
1369 # TODO: add back version
1370 summary_info += {'slirp support':     config_host.has_key('CONFIG_SLIRP')}
1371 if config_host.has_key('CONFIG_SLIRP')
1372   summary_info += {'smbd':            config_host['CONFIG_SMBD_COMMAND']}
1373 endif
1374 summary_info += {'module support':    config_host.has_key('CONFIG_MODULES')}
1375 if config_host.has_key('CONFIG_MODULES')
1376   summary_info += {'alternative module path': config_host.has_key('CONFIG_MODULE_UPGRADES')}
1377 endif
1378 summary_info += {'host CPU':          cpu}
1379 summary_info += {'host endianness':   build_machine.endian()}
1380 summary_info += {'target list':       config_host['TARGET_DIRS']}
1381 summary_info += {'gprof enabled':     config_host.has_key('CONFIG_GPROF')}
1382 summary_info += {'sparse enabled':    meson.get_compiler('c').cmd_array().contains('cgcc')}
1383 summary_info += {'strip binaries':    get_option('strip')}
1384 summary_info += {'profiler':          config_host.has_key('CONFIG_PROFILER')}
1385 summary_info += {'static build':      config_host.has_key('CONFIG_STATIC')}
1386 if targetos == 'darwin'
1387   summary_info += {'Cocoa support': config_host.has_key('CONFIG_COCOA')}
1388 endif
1389 # TODO: add back version
1390 summary_info += {'SDL support':       sdl.found()}
1391 summary_info += {'SDL image support': sdl_image.found()}
1392 # TODO: add back version
1393 summary_info += {'GTK support':       config_host.has_key('CONFIG_GTK')}
1394 summary_info += {'GTK GL support':    config_host.has_key('CONFIG_GTK_GL')}
1395 summary_info += {'pixman':            pixman.found()}
1396 # TODO: add back version
1397 summary_info += {'VTE support':       config_host.has_key('CONFIG_VTE')}
1398 summary_info += {'TLS priority':      config_host['CONFIG_TLS_PRIORITY']}
1399 summary_info += {'GNUTLS support':    config_host.has_key('CONFIG_GNUTLS')}
1400 # TODO: add back version
1401 summary_info += {'libgcrypt':         config_host.has_key('CONFIG_GCRYPT')}
1402 if config_host.has_key('CONFIG_GCRYPT')
1403    summary_info += {'  hmac':            config_host.has_key('CONFIG_GCRYPT_HMAC')}
1404    summary_info += {'  XTS':             not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')}
1405 endif
1406 # TODO: add back version
1407 summary_info += {'nettle':            config_host.has_key('CONFIG_NETTLE')}
1408 if config_host.has_key('CONFIG_NETTLE')
1409    summary_info += {'  XTS':             not config_host.has_key('CONFIG_QEMU_PRIVATE_XTS')}
1410 endif
1411 summary_info += {'libtasn1':          config_host.has_key('CONFIG_TASN1')}
1412 summary_info += {'PAM':               config_host.has_key('CONFIG_AUTH_PAM')}
1413 summary_info += {'iconv support':     config_host.has_key('CONFIG_ICONV')}
1414 summary_info += {'curses support':    config_host.has_key('CONFIG_CURSES')}
1415 # TODO: add back version
1416 summary_info += {'virgl support':     config_host.has_key('CONFIG_VIRGL')}
1417 summary_info += {'curl support':      config_host.has_key('CONFIG_CURL')}
1418 summary_info += {'mingw32 support':   targetos == 'windows'}
1419 summary_info += {'Audio drivers':     config_host['CONFIG_AUDIO_DRIVERS']}
1420 summary_info += {'Block whitelist (rw)': config_host['CONFIG_BDRV_RW_WHITELIST']}
1421 summary_info += {'Block whitelist (ro)': config_host['CONFIG_BDRV_RO_WHITELIST']}
1422 summary_info += {'VirtFS support':    config_host.has_key('CONFIG_VIRTFS')}
1423 summary_info += {'Multipath support': mpathpersist.found()}
1424 summary_info += {'VNC support':       vnc.found()}
1425 if vnc.found()
1426   summary_info += {'VNC SASL support':  sasl.found()}
1427   summary_info += {'VNC JPEG support':  jpeg.found()}
1428   summary_info += {'VNC PNG support':   png.found()}
1429 endif
1430 summary_info += {'xen support':       config_host.has_key('CONFIG_XEN_BACKEND')}
1431 if config_host.has_key('CONFIG_XEN_BACKEND')
1432   summary_info += {'xen ctrl version':  config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']}
1433 endif
1434 summary_info += {'brlapi support':    config_host.has_key('CONFIG_BRLAPI')}
1435 summary_info += {'Documentation':     config_host.has_key('BUILD_DOCS')}
1436 summary_info += {'PIE':               get_option('b_pie')}
1437 summary_info += {'vde support':       config_host.has_key('CONFIG_VDE')}
1438 summary_info += {'netmap support':    config_host.has_key('CONFIG_NETMAP')}
1439 summary_info += {'Linux AIO support': config_host.has_key('CONFIG_LINUX_AIO')}
1440 summary_info += {'Linux io_uring support': config_host.has_key('CONFIG_LINUX_IO_URING')}
1441 summary_info += {'ATTR/XATTR support': config_host.has_key('CONFIG_ATTR')}
1442 summary_info += {'Install blobs':     config_host.has_key('INSTALL_BLOBS')}
1443 # TODO: add back KVM/HAX/HVF/WHPX/TCG
1444 #summary_info += {'KVM support':       have_kvm'}
1445 #summary_info += {'HAX support':       have_hax'}
1446 #summary_info += {'HVF support':       have_hvf'}
1447 #summary_info += {'WHPX support':      have_whpx'}
1448 #summary_info += {'TCG support':       have_tcg'}
1449 #if get_option('tcg')
1450 #  summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')}
1451 #  summary_info += {'TCG interpreter':   config_host.has_key('CONFIG_TCG_INTERPRETER')}
1452 #endif
1453 summary_info += {'malloc trim support': config_host.has_key('CONFIG_MALLOC_TRIM')}
1454 summary_info += {'RDMA support':      config_host.has_key('CONFIG_RDMA')}
1455 summary_info += {'PVRDMA support':    config_host.has_key('CONFIG_PVRDMA')}
1456 summary_info += {'fdt support':       config_host.has_key('CONFIG_FDT')}
1457 summary_info += {'membarrier':        config_host.has_key('CONFIG_MEMBARRIER')}
1458 summary_info += {'preadv support':    config_host.has_key('CONFIG_PREADV')}
1459 summary_info += {'fdatasync':         config_host.has_key('CONFIG_FDATASYNC')}
1460 summary_info += {'madvise':           config_host.has_key('CONFIG_MADVISE')}
1461 summary_info += {'posix_madvise':     config_host.has_key('CONFIG_POSIX_MADVISE')}
1462 summary_info += {'posix_memalign':    config_host.has_key('CONFIG_POSIX_MEMALIGN')}
1463 summary_info += {'libcap-ng support': config_host.has_key('CONFIG_LIBCAP_NG')}
1464 summary_info += {'vhost-net support': config_host.has_key('CONFIG_VHOST_NET')}
1465 summary_info += {'vhost-crypto support': config_host.has_key('CONFIG_VHOST_CRYPTO')}
1466 summary_info += {'vhost-scsi support': config_host.has_key('CONFIG_VHOST_SCSI')}
1467 summary_info += {'vhost-vsock support': config_host.has_key('CONFIG_VHOST_VSOCK')}
1468 summary_info += {'vhost-user support': config_host.has_key('CONFIG_VHOST_KERNEL')}
1469 summary_info += {'vhost-user-fs support': config_host.has_key('CONFIG_VHOST_USER_FS')}
1470 summary_info += {'vhost-vdpa support': config_host.has_key('CONFIG_VHOST_VDPA')}
1471 summary_info += {'Trace backends':    config_host['TRACE_BACKENDS']}
1472 if config_host['TRACE_BACKENDS'].split().contains('simple')
1473   summary_info += {'Trace output file': config_host['CONFIG_TRACE_FILE'] + '-<pid>'}
1474 endif
1475 # TODO: add back protocol and server version
1476 summary_info += {'spice support':     config_host.has_key('CONFIG_SPICE')}
1477 summary_info += {'rbd support':       config_host.has_key('CONFIG_RBD')}
1478 summary_info += {'xfsctl support':    config_host.has_key('CONFIG_XFS')}
1479 summary_info += {'smartcard support': config_host.has_key('CONFIG_SMARTCARD')}
1480 summary_info += {'U2F support':       u2f.found()}
1481 summary_info += {'libusb':            config_host.has_key('CONFIG_USB_LIBUSB')}
1482 summary_info += {'usb net redir':     config_host.has_key('CONFIG_USB_REDIR')}
1483 summary_info += {'OpenGL support':    config_host.has_key('CONFIG_OPENGL')}
1484 summary_info += {'OpenGL dmabufs':    config_host.has_key('CONFIG_OPENGL_DMABUF')}
1485 summary_info += {'libiscsi support':  config_host.has_key('CONFIG_LIBISCSI')}
1486 summary_info += {'libnfs support':    config_host.has_key('CONFIG_LIBNFS')}
1487 summary_info += {'build guest agent': config_host.has_key('CONFIG_GUEST_AGENT')}
1488 if targetos == 'windows'
1489   if 'WIN_SDK' in config_host
1490     summary_info += {'Windows SDK':       config_host['WIN_SDK']}
1491   endif
1492   summary_info += {'QGA VSS support':   config_host.has_key('CONFIG_QGA_VSS')}
1493   summary_info += {'QGA w32 disk info': config_host.has_key('CONFIG_QGA_NTDDSCSI')}
1494   summary_info += {'QGA MSI support':   config_host.has_key('CONFIG_QGA_MSI')}
1495 endif
1496 summary_info += {'seccomp support':   config_host.has_key('CONFIG_SECCOMP')}
1497 summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']}
1498 summary_info += {'coroutine pool':    config_host['CONFIG_COROUTINE_POOL'] == '1'}
1499 summary_info += {'debug stack usage': config_host.has_key('CONFIG_DEBUG_STACK_USAGE')}
1500 summary_info += {'mutex debugging':   config_host.has_key('CONFIG_DEBUG_MUTEX')}
1501 summary_info += {'crypto afalg':      config_host.has_key('CONFIG_AF_ALG')}
1502 summary_info += {'GlusterFS support': config_host.has_key('CONFIG_GLUSTERFS')}
1503 summary_info += {'gcov':              get_option('b_coverage')}
1504 summary_info += {'TPM support':       config_host.has_key('CONFIG_TPM')}
1505 summary_info += {'libssh support':    config_host.has_key('CONFIG_LIBSSH')}
1506 summary_info += {'QOM debugging':     config_host.has_key('CONFIG_QOM_CAST_DEBUG')}
1507 summary_info += {'Live block migration': config_host.has_key('CONFIG_LIVE_BLOCK_MIGRATION')}
1508 summary_info += {'lzo support':       config_host.has_key('CONFIG_LZO')}
1509 summary_info += {'snappy support':    config_host.has_key('CONFIG_SNAPPY')}
1510 summary_info += {'bzip2 support':     config_host.has_key('CONFIG_BZIP2')}
1511 summary_info += {'lzfse support':     config_host.has_key('CONFIG_LZFSE')}
1512 summary_info += {'zstd support':      config_host.has_key('CONFIG_ZSTD')}
1513 summary_info += {'NUMA host support': config_host.has_key('CONFIG_NUMA')}
1514 summary_info += {'libxml2':           config_host.has_key('CONFIG_LIBXML2')}
1515 summary_info += {'tcmalloc support':  config_host.has_key('CONFIG_TCMALLOC')}
1516 summary_info += {'jemalloc support':  config_host.has_key('CONFIG_JEMALLOC')}
1517 summary_info += {'avx2 optimization': config_host.has_key('CONFIG_AVX2_OPT')}
1518 summary_info += {'avx512f optimization': config_host.has_key('CONFIG_AVX512F_OPT')}
1519 summary_info += {'replication support': config_host.has_key('CONFIG_REPLICATION')}
1520 summary_info += {'bochs support':     config_host.has_key('CONFIG_BOCHS')}
1521 summary_info += {'cloop support':     config_host.has_key('CONFIG_CLOOP')}
1522 summary_info += {'dmg support':       config_host.has_key('CONFIG_DMG')}
1523 summary_info += {'qcow v1 support':   config_host.has_key('CONFIG_QCOW1')}
1524 summary_info += {'vdi support':       config_host.has_key('CONFIG_VDI')}
1525 summary_info += {'vvfat support':     config_host.has_key('CONFIG_VVFAT')}
1526 summary_info += {'qed support':       config_host.has_key('CONFIG_QED')}
1527 summary_info += {'parallels support': config_host.has_key('CONFIG_PARALLELS')}
1528 summary_info += {'sheepdog support':  config_host.has_key('CONFIG_SHEEPDOG')}
1529 summary_info += {'capstone':          config_host.has_key('CONFIG_CAPSTONE')}
1530 summary_info += {'libpmem support':   config_host.has_key('CONFIG_LIBPMEM')}
1531 summary_info += {'libdaxctl support': config_host.has_key('CONFIG_LIBDAXCTL')}
1532 summary_info += {'libudev':           libudev.found()}
1533 summary_info += {'default devices':   config_host['CONFIG_MINIKCONF_MODE'] == '--defconfig'}
1534 summary_info += {'plugin support':    config_host.has_key('CONFIG_PLUGIN')}
1535 summary_info += {'fuzzing support':   config_host.has_key('CONFIG_FUZZ')}
1536 if config_host.has_key('HAVE_GDB_BIN')
1537   summary_info += {'gdb':             config_host['HAVE_GDB_BIN']}
1538 endif
1539 summary_info += {'thread sanitizer':  config_host.has_key('CONFIG_TSAN')}
1540 summary_info += {'rng-none':          config_host.has_key('CONFIG_RNG_NONE')}
1541 summary_info += {'Linux keyring':     config_host.has_key('CONFIG_SECRET_KEYRING')}
1542 summary(summary_info, bool_yn: true)
1543
1544 if not supported_cpus.contains(cpu)
1545   message()
1546   warning('SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!')
1547   message()
1548   message('CPU host architecture ' + cpu + ' support is not currently maintained.')
1549   message('The QEMU project intends to remove support for this host CPU in')
1550   message('a future release if nobody volunteers to maintain it and to')
1551   message('provide a build host for our continuous integration setup.')
1552   message('configure has succeeded and you can continue to build, but')
1553   message('if you care about QEMU on this platform you should contact')
1554   message('us upstream at qemu-devel@nongnu.org.')
1555 endif
1556
1557 if not supported_oses.contains(targetos)
1558   message()
1559   warning('WARNING: SUPPORT FOR THIS HOST OS WILL GO AWAY IN FUTURE RELEASES!')
1560   message()
1561   message('Host OS ' + targetos + 'support is not currently maintained.')
1562   message('The QEMU project intends to remove support for this host OS in')
1563   message('a future release if nobody volunteers to maintain it and to')
1564   message('provide a build host for our continuous integration setup.')
1565   message('configure has succeeded and you can continue to build, but')
1566   message('if you care about QEMU on this platform you should contact')
1567   message('us upstream at qemu-devel@nongnu.org.')
1568 endif