CI: do not retry the qemu runs
[platform/upstream/libinput.git] / meson.build
1 project('libinput', 'c',
2         version : '1.21.0',
3         license : 'MIT/Expat',
4         default_options : [ 'c_std=gnu99', 'warning_level=2' ],
5         meson_version : '>= 0.49.0')
6
7 libinput_version = meson.project_version().split('.')
8
9 dir_data        = get_option('prefix') / get_option('datadir') / 'libinput'
10 dir_etc         = get_option('prefix') / get_option('sysconfdir')
11 dir_overrides   = get_option('prefix') / get_option('sysconfdir') / 'libinput'
12 dir_libexec     = get_option('prefix') / get_option('libexecdir') / 'libinput'
13 dir_lib         = get_option('prefix') / get_option('libdir')
14 dir_man1        = get_option('prefix') / get_option('mandir') / 'man1'
15 dir_system_udev = get_option('prefix') / 'lib' / 'udev'
16 dir_src_quirks  = meson.current_source_dir() / 'quirks'
17 dir_src_test    = meson.current_source_dir() / 'test'
18 dir_src         = meson.current_source_dir() / 'src'
19 dir_gitlab_ci   = meson.current_source_dir() / '.gitlab-ci'
20
21 dir_udev = get_option('udev-dir')
22 if dir_udev == ''
23         dir_udev = dir_system_udev
24 endif
25 dir_udev_callouts = dir_udev
26 dir_udev_rules    = dir_udev / 'rules.d'
27
28 # Collection of man pages, we'll append to that
29 src_man = files()
30
31 # We use libtool-version numbers because it's easier to understand.
32 # Before making a release, the libinput_so_*
33 # numbers should be modified. The components are of the form C:R:A.
34 # a) If binary compatibility has been broken (eg removed or changed interfaces)
35 #    change to C+1:0:0.
36 # b) If interfaces have been changed or added, but binary compatibility has
37 #    been preserved, change to C+1:0:A+1
38 # c) If the interface is the same as the previous version, change to C:R+1:A
39 libinput_lt_c=23
40 libinput_lt_r=0
41 libinput_lt_a=13
42
43 # convert to soname
44 libinput_so_version = '@0@.@1@.@2@'.format((libinput_lt_c - libinput_lt_a),
45                                             libinput_lt_a, libinput_lt_r)
46
47 # Compiler setup
48 cc = meson.get_compiler('c')
49 cflags = [
50         '-Wno-unused-parameter',
51         '-Wmissing-prototypes',
52         '-Wstrict-prototypes',
53         '-Wundef',
54         '-Wlogical-op',
55         '-Wpointer-arith',
56         '-Wuninitialized',
57         '-Winit-self',
58         '-Wstrict-prototypes',
59         '-Wimplicit-fallthrough',
60         '-Wredundant-decls',
61         '-Wincompatible-pointer-types',
62         '-Wformat=2',
63         '-Wno-missing-field-initializers',
64         '-Wmissing-declarations',
65
66         '-fvisibility=hidden',
67 ]
68 add_project_arguments(cc.get_supported_arguments(cflags), language : 'c')
69
70 # config.h
71 config_h = configuration_data()
72
73 doc_url_base = 'https://wayland.freedesktop.org/libinput/doc'
74 if libinput_version[2].to_int() >= 90
75         doc_url = '@0@/latest'.format(doc_url_base)
76 else
77         doc_url = '@0@/@1@'.format(doc_url_base, meson.project_version())
78 endif
79 config_h.set_quoted('HTTP_DOC_LINK', doc_url)
80
81 config_h.set('_GNU_SOURCE', '1')
82 if get_option('buildtype') == 'debug' or get_option('buildtype') == 'debugoptimized'
83         config_h.set_quoted('MESON_BUILD_ROOT', meson.current_build_dir())
84 else
85         config_h.set_quoted('MESON_BUILD_ROOT', '')
86 endif
87
88 prefix = '''#define _GNU_SOURCE 1
89 #include <assert.h>
90 '''
91 if cc.get_define('static_assert', prefix : prefix) == ''
92         config_h.set('static_assert(...)', '/* */')
93 endif
94
95 # Coverity breaks because it doesn't define _Float128 correctly, you'll end
96 # up with a bunch of messages in the form:
97 # "/usr/include/stdlib.h", line 133: error #20: identifier "_Float128" is
98 #           undefined
99 #   extern _Float128 strtof128 (const char *__restrict __nptr,
100 #          ^
101 # We don't use float128 ourselves, it gets pulled in from math.h or
102 # something, so let's just define it as uint128 and move on.
103 # Unfortunately we can't detect the coverity build at meson configure
104 # time, we only know it fails at runtime. So make this an option instead, to
105 # be removed when coverity fixes this again.
106 if get_option('coverity')
107         config_h.set('_Float128', '__uint128_t')
108         config_h.set('_Float32', 'int')
109         config_h.set('_Float32x', 'int')
110         config_h.set('_Float64', 'long')
111         config_h.set('_Float64x', 'long')
112 endif
113
114 if cc.has_header_symbol('dirent.h', 'versionsort', prefix : prefix)
115         config_h.set('HAVE_VERSIONSORT', '1')
116 endif
117
118 if not cc.has_header_symbol('errno.h', 'program_invocation_short_name', prefix : prefix)
119         if cc.has_header_symbol('stdlib.h', 'getprogname')
120                 config_h.set('program_invocation_short_name', 'getprogname()')
121         endif
122 endif
123
124 if cc.has_header('xlocale.h')
125         config_h.set('HAVE_XLOCALE_H', '1')
126 endif
127
128 code = '''
129 #include <locale.h>
130 void main(void) { newlocale(LC_NUMERIC_MASK, "C", (locale_t)0); }
131 '''
132 if cc.links(code, name : 'locale.h')
133         config_h.set('HAVE_LOCALE_H', '1')
134 endif
135
136 if not cc.has_header_symbol('sys/ptrace.h', 'PTRACE_ATTACH', prefix : prefix)
137         config_h.set('PTRACE_ATTACH', 'PT_ATTACH')
138         config_h.set('PTRACE_CONT', 'PT_CONTINUE')
139         config_h.set('PTRACE_DETACH', 'PT_DETACH')
140 endif
141
142 config_h.set10('HAVE_INSTALLED_TESTS', get_option('install-tests'))
143
144 # Dependencies
145 pkgconfig = import('pkgconfig')
146 dep_udev = dependency('libudev')
147 dep_mtdev = dependency('mtdev', version : '>= 1.1.0')
148 dep_libevdev = dependency('libevdev')
149 config_h.set10('HAVE_LIBEVDEV_DISABLE_PROPERTY',
150                 dep_libevdev.version().version_compare('>= 1.9.902'))
151
152 dep_lm = cc.find_library('m', required : false)
153 dep_rt = cc.find_library('rt', required : false)
154
155 # Include directories
156 includes_include = include_directories('include')
157 includes_src = include_directories('src')
158
159 ############ libwacom configuration ############
160
161 have_libwacom = get_option('libwacom')
162 config_h.set10('HAVE_LIBWACOM', have_libwacom)
163 if have_libwacom
164         dep_libwacom = dependency('libwacom', version : '>= 0.27')
165 else
166         dep_libwacom = declare_dependency()
167 endif
168
169 ############ udev bits ############
170
171 executable('libinput-device-group',
172            'udev/libinput-device-group.c',
173            dependencies : [dep_udev, dep_libwacom],
174            include_directories : [includes_src, includes_include],
175            install : true,
176            install_dir : dir_udev_callouts)
177 executable('libinput-fuzz-extract',
178            'udev/libinput-fuzz-extract.c',
179            'src/util-strings.c',
180            'src/util-prop-parsers.c',
181            dependencies : [dep_udev, dep_libevdev, dep_lm],
182            include_directories : [includes_src, includes_include],
183            install : true,
184            install_dir : dir_udev_callouts)
185 executable('libinput-fuzz-to-zero',
186            'udev/libinput-fuzz-to-zero.c',
187            dependencies : [dep_udev, dep_libevdev],
188            include_directories : [includes_src, includes_include],
189            install : true,
190            install_dir : dir_udev_callouts)
191
192 udev_rules_config = configuration_data()
193 udev_rules_config.set('UDEV_TEST_PATH', '')
194 configure_file(input : 'udev/80-libinput-device-groups.rules.in',
195                output : '80-libinput-device-groups.rules',
196                install_dir : dir_udev_rules,
197                configuration : udev_rules_config)
198 configure_file(input : 'udev/90-libinput-fuzz-override.rules.in',
199                output : '90-libinput-fuzz-override.rules',
200                install_dir : dir_udev_rules,
201                configuration : udev_rules_config)
202
203 litest_udev_rules_config = configuration_data()
204 litest_udev_rules_config.set('UDEV_TEST_PATH', meson.current_build_dir() + '/')
205 litest_groups_rules_file = configure_file(input : 'udev/80-libinput-device-groups.rules.in',
206                output : '80-libinput-device-groups-litest.rules',
207                configuration : litest_udev_rules_config)
208 litest_fuzz_override_file = configure_file(input : 'udev/90-libinput-fuzz-override.rules.in',
209                                            output : '90-libinput-fuzz-override-litest.rules',
210                                            configuration : litest_udev_rules_config)
211
212 ############ Check for leftover udev rules ########
213
214 # This test should be defined first so we don't waste time testing anything
215 # else if we're about to fail anyway. ninja test will execute tests in the
216 # order of them defined in meson.build
217
218 if get_option('tests')
219         test('leftover-rules',
220              find_program('test/check-leftover-udev-rules.sh'),
221              is_parallel : false,
222              suite : ['all'])
223 endif
224
225 ############ libepoll-shim (BSD) ############
226
227 if cc.has_header_symbol('sys/epoll.h', 'epoll_create1', prefix : prefix)
228         # epoll is built-in (Linux, illumos)
229         dep_libepoll = declare_dependency()
230 else
231         # epoll is implemented in userspace by libepoll-shim (FreeBSD)
232         dir_libepoll = get_option('epoll-dir')
233         if dir_libepoll == ''
234                 dir_libepoll = get_option('prefix')
235         endif
236         includes_epoll = include_directories(dir_libepoll / 'include' / 'libepoll-shim')
237         dep_libepoll = cc.find_library('epoll-shim', dirs : dir_libepoll / 'lib')
238         code = '''
239         #include <sys/epoll.h>
240         int main(void) { epoll_create1(0); }
241         '''
242         if not cc.links(code,
243                 name : 'libepoll-shim check',
244                 dependencies : [dep_libepoll, dep_rt],
245                 include_directories : includes_epoll) # note: wants an include_directories object
246                 error('No built-in epoll or libepoll-shim found.')
247         endif
248         dep_libepoll = declare_dependency(
249                 include_directories : includes_epoll,
250                 dependencies : [dep_libepoll, dep_rt])
251 endif
252
253 ############ libinput-util.a ############
254
255 # Basic compilation test to make sure the headers include and define all the
256 # necessary bits.
257 util_headers = [
258                 'util-bits.h',
259                 'util-input-event.h',
260                 'util-list.h',
261                 'util-macros.h',
262                 'util-matrix.h',
263                 'util-prop-parsers.h',
264                 'util-ratelimit.h',
265                 'util-strings.h',
266                 'util-time.h',
267 ]
268 foreach h: util_headers
269         c = configuration_data()
270         c.set_quoted('FILE', h)
271         testfile = configure_file(input : 'test/test-util-includes.c',
272                                   output : 'test-util-includes-@0@.c'.format(h),
273                                   configuration : c)
274         executable('test-build-@0@'.format(h),
275                    testfile,
276                    include_directories : [includes_src, includes_include],
277                    install : false)
278 endforeach
279
280 src_libinput_util = [
281         'src/util-list.c',
282         'src/util-ratelimit.c',
283         'src/util-strings.c',
284         'src/util-prop-parsers.c',
285 ]
286 libinput_util = static_library('libinput-util',
287                                src_libinput_util,
288                                dependencies : [dep_udev, dep_libevdev, dep_libwacom],
289                                include_directories : includes_include)
290 dep_libinput_util = declare_dependency(link_with : libinput_util)
291
292 ############ libfilter.a ############
293 src_libfilter = [
294                 'src/filter.c',
295                 'src/filter-flat.c',
296                 'src/filter-low-dpi.c',
297                 'src/filter-mouse.c',
298                 'src/filter-touchpad.c',
299                 'src/filter-touchpad-flat.c',
300                 'src/filter-touchpad-x230.c',
301                 'src/filter-tablet.c',
302                 'src/filter-trackpoint.c',
303 ]
304 libfilter = static_library('filter', src_libfilter,
305                            dependencies : [dep_udev, dep_libwacom],
306                            include_directories : includes_include)
307 dep_libfilter = declare_dependency(link_with : libfilter)
308
309 ############ libquirks.a #############
310 libinput_data_path = dir_data
311 libinput_data_override_path = dir_overrides / 'local-overrides.quirks'
312 config_h.set_quoted('LIBINPUT_QUIRKS_DIR', dir_data)
313 config_h.set_quoted('LIBINPUT_QUIRKS_OVERRIDE_FILE', libinput_data_override_path)
314
315 config_h.set_quoted('LIBINPUT_QUIRKS_SRCDIR', dir_src_quirks)
316 install_subdir('quirks',
317                exclude_files: ['README.md'],
318                install_dir : dir_data,
319                strip_directory : true)
320
321 src_libquirks = [
322         'src/quirks.c',
323 ]
324
325 deps_libquirks = [dep_udev, dep_libwacom, dep_libinput_util]
326 libquirks = static_library('quirks', src_libquirks,
327                            dependencies : deps_libquirks,
328                            include_directories : includes_include)
329 dep_libquirks = declare_dependency(link_with : libquirks)
330
331 # Create /etc/libinput
332 if meson.version().version_compare('>= 0.60')
333         install_emptydir(dir_etc / 'libinput')
334 else
335         install_subdir('libinput', install_dir : dir_etc)
336 endif
337
338 ############ libinput.so ############
339 install_headers('src/libinput.h')
340 src_libinput = src_libfilter + [
341         'src/libinput.c',
342         'src/libinput-private-config.c',
343         'src/evdev.c',
344         'src/evdev-debounce.c',
345         'src/evdev-fallback.c',
346         'src/evdev-totem.c',
347         'src/evdev-middle-button.c',
348         'src/evdev-mt-touchpad.c',
349         'src/evdev-mt-touchpad-tap.c',
350         'src/evdev-mt-touchpad-thumb.c',
351         'src/evdev-mt-touchpad-buttons.c',
352         'src/evdev-mt-touchpad-edge-scroll.c',
353         'src/evdev-mt-touchpad-gestures.c',
354         'src/evdev-tablet.c',
355         'src/evdev-tablet-pad.c',
356         'src/evdev-tablet-pad-leds.c',
357         'src/evdev-wheel.c',
358         'src/path-seat.c',
359         'src/udev-seat.c',
360         'src/timer.c',
361 ]
362
363 deps_libinput = [
364         dep_mtdev,
365         dep_udev,
366         dep_libevdev,
367         dep_libepoll,
368         dep_lm,
369         dep_rt,
370         dep_libwacom,
371         dep_libinput_util,
372         dep_libquirks
373 ]
374
375 libinput_version_h_config = configuration_data()
376 libinput_version_h_config.set('LIBINPUT_VERSION_MAJOR', libinput_version[0])
377 libinput_version_h_config.set('LIBINPUT_VERSION_MINOR', libinput_version[1])
378 libinput_version_h_config.set('LIBINPUT_VERSION_MICRO', libinput_version[2])
379 libinput_version_h_config.set('LIBINPUT_VERSION', meson.project_version())
380
381 libinput_version_h = configure_file(
382                 input : 'src/libinput-version.h.in',
383                 output : 'libinput-version.h',
384                 configuration : libinput_version_h_config,
385 )
386
387 mapfile = dir_src / 'libinput.sym'
388 version_flag = '-Wl,--version-script,@0@'.format(mapfile)
389 lib_libinput = shared_library('input',
390                 src_libinput,
391                 include_directories : [include_directories('.'), includes_include],
392                 dependencies : deps_libinput,
393                 version : libinput_so_version,
394                 link_args : version_flag,
395                 link_depends : mapfile,
396                 install : true
397                 )
398
399 dep_libinput = declare_dependency(
400                 link_with : lib_libinput,
401                 dependencies : deps_libinput)
402
403 pkgconfig.generate(
404         filebase : 'libinput',
405         name : 'Libinput',
406         description : 'Input device library',
407         version : meson.project_version(),
408         libraries : lib_libinput
409 )
410
411 git_version_h = vcs_tag(command : ['git', 'describe'],
412                         fallback : 'unknown',
413                         input : 'src/libinput-git-version.h.in',
414                         output :'libinput-git-version.h')
415
416 ############ documentation ############
417
418 if get_option('documentation')
419         subdir('doc/api')
420         subdir('doc/user')
421 endif
422
423 ############ shell completion #########
424
425 subdir('completion/zsh')
426
427 ############ tools ############
428 libinput_tool_path = dir_libexec
429 config_h.set_quoted('LIBINPUT_TOOL_PATH', libinput_tool_path)
430 tools_shared_sources = [ 'tools/shared.c' ]
431 deps_tools_shared = [ dep_libinput, dep_libevdev ]
432 lib_tools_shared = static_library('tools_shared',
433                                   tools_shared_sources,
434                                   include_directories : [includes_src, includes_include],
435                                   dependencies : deps_tools_shared)
436 dep_tools_shared = declare_dependency(link_with : lib_tools_shared,
437                                       dependencies : deps_tools_shared)
438
439 deps_tools = [ dep_tools_shared, dep_libinput ]
440 libinput_debug_events_sources = [
441         'tools/libinput-debug-events.c',
442         libinput_version_h,
443 ]
444 executable('libinput-debug-events',
445            libinput_debug_events_sources,
446            dependencies : deps_tools,
447            include_directories : [includes_src, includes_include],
448            install_dir : libinput_tool_path,
449            install : true
450            )
451
452 libinput_debug_tablet_sources = [ 'tools/libinput-debug-tablet.c' ]
453 executable('libinput-debug-tablet',
454            libinput_debug_tablet_sources,
455            dependencies : deps_tools,
456            include_directories : [includes_src, includes_include],
457            install_dir : libinput_tool_path,
458            install : true)
459
460
461 libinput_quirks_sources = [ 'tools/libinput-quirks.c' ]
462 libinput_quirks = executable('libinput-quirks',
463                              libinput_quirks_sources,
464                              dependencies : [dep_libquirks, dep_tools_shared, dep_libinput],
465                              include_directories : [includes_src, includes_include],
466                              install_dir : libinput_tool_path,
467                              install : true
468                             )
469 test('validate-quirks',
470      libinput_quirks,
471      args: ['validate', '--data-dir=@0@'.format(dir_src_quirks)],
472      suite : ['all']
473      )
474
475 libinput_list_devices_sources = [ 'tools/libinput-list-devices.c' ]
476 libinput_list_devices = executable('libinput-list-devices',
477                                    libinput_list_devices_sources,
478                                    dependencies : deps_tools,
479                                    include_directories : [includes_src, includes_include],
480                                    install_dir : libinput_tool_path,
481                                    install : true,
482                                   )
483 test('list-devices',
484      libinput_list_devices,
485      suite : ['all', 'root', 'hardware'])
486
487 libinput_measure_sources = [ 'tools/libinput-measure.c' ]
488 executable('libinput-measure',
489            libinput_measure_sources,
490            dependencies : deps_tools,
491            include_directories : [includes_src, includes_include],
492            install_dir : libinput_tool_path,
493            install : true,
494            )
495
496 libinput_analyze_sources = [ 'tools/libinput-analyze.c' ]
497 executable('libinput-analyze',
498            libinput_analyze_sources,
499            dependencies : deps_tools,
500            include_directories : [includes_src, includes_include],
501            install_dir : libinput_tool_path,
502            install : true,
503            )
504
505 src_python_tools = files(
506               'tools/libinput-analyze-per-slot-delta.py',
507               'tools/libinput-analyze-recording.py',
508               'tools/libinput-analyze-touch-down-state.py',
509               'tools/libinput-measure-fuzz.py',
510               'tools/libinput-measure-touchpad-size.py',
511               'tools/libinput-measure-touchpad-tap.py',
512               'tools/libinput-measure-touchpad-pressure.py',
513               'tools/libinput-measure-touch-size.py',
514               'tools/libinput-replay.py'
515 )
516
517 foreach t : src_python_tools
518         configure_file(input: t,
519                        output: '@BASENAME@',
520                        copy: true,
521                        install_dir : libinput_tool_path
522                       )
523 endforeach
524
525 libinput_record_sources = [ 'tools/libinput-record.c', git_version_h ]
526 executable('libinput-record',
527            libinput_record_sources,
528            dependencies : deps_tools + [dep_udev],
529            include_directories : [includes_src, includes_include],
530            install_dir : libinput_tool_path,
531            install : true,
532            )
533
534 if get_option('debug-gui')
535         dep_gtk = dependency('gtk4', version : '>= 4.0', required : false)
536         config_h.set10('HAVE_GTK4', dep_gtk.found())
537         if not dep_gtk.found()
538                 dep_gtk = dependency('gtk+-3.0', version : '>= 3.20')
539                 config_h.set10('HAVE_GTK3', dep_gtk.found())
540         endif
541
542         gtk_targets = dep_gtk.get_pkgconfig_variable('targets')
543         have_gtk_wayland = gtk_targets.contains('wayland')
544         have_gtk_x11 = gtk_targets.contains('x11')
545
546         dep_cairo = dependency('cairo')
547         dep_glib = dependency('glib-2.0')
548         dep_x11 = dependency('x11', required : false)
549         dep_wayland_client = dependency('wayland-client', required : false)
550         dep_wayland_protocols = dependency('wayland-protocols', required : false)
551
552         config_h.set10('HAVE_GTK_X11', have_gtk_x11 and dep_x11.found())
553
554         debug_gui_sources = [ 'tools/libinput-debug-gui.c' ]
555
556         if have_gtk_wayland and dep_wayland_client.found() and dep_wayland_protocols.found()
557                 wayland_scanner = find_program('wayland-scanner')
558                 wlproto_dir = dep_wayland_protocols.get_pkgconfig_variable('pkgdatadir')
559
560                 proto_name = 'pointer-constraints-unstable-v1'
561                 input = files(wlproto_dir / 'unstable' / 'pointer-constraints' / '@0@.xml'.format(proto_name))
562
563                 wayland_headers = custom_target('@0@ client header'.format(proto_name),
564                         input: input,
565                         output: '@0@-client-protocol.h'.format(proto_name),
566                         command: [wayland_scanner, 'client-header', '@INPUT@', '@OUTPUT@'],
567                 )
568
569                 wayland_sources = custom_target('@0@ source'.format(proto_name),
570                         input: input,
571                         output: '@0@-protocol.c'.format(proto_name),
572                         command: [wayland_scanner, 'private-code', '@INPUT@', '@OUTPUT@'],
573                 )
574
575                 debug_gui_sources += [ wayland_headers, wayland_sources ]
576                 config_h.set10('HAVE_GTK_WAYLAND', true)
577         endif
578
579         deps_debug_gui = [
580                         dep_gtk,
581                         dep_cairo,
582                         dep_glib,
583                         dep_wayland_client,
584                         dep_wayland_protocols,
585                         dep_x11,
586                         ] + deps_tools
587         executable('libinput-debug-gui',
588                    debug_gui_sources,
589                    dependencies : deps_debug_gui,
590                    include_directories : [includes_src, includes_include],
591                    install_dir : libinput_tool_path,
592                    install : true
593                    )
594         src_man += files('tools/libinput-debug-gui.man')
595 endif
596
597 libinput_sources = [ 'tools/libinput-tool.c' ]
598
599 libinput_tool = executable('libinput',
600                            libinput_sources,
601                            dependencies : deps_tools,
602                            include_directories : [includes_src, includes_include],
603                            install : true
604                           )
605
606 ptraccel_debug_sources = [ 'tools/ptraccel-debug.c' ]
607 executable('ptraccel-debug',
608            ptraccel_debug_sources,
609            dependencies : [ dep_libfilter, dep_libinput ],
610            include_directories : [includes_src, includes_include],
611            install : false
612            )
613
614 # Don't run the test during a release build because we rely on the magic
615 # subtool lookup
616 if get_option('buildtype') == 'debug' or get_option('buildtype') == 'debugoptimized'
617         config_tool_option_test = configuration_data()
618         config_tool_option_test.set('DISABLE_WARNING', 'yes')
619         config_tool_option_test.set('MESON_ENABLED_DEBUG_GUI', get_option('debug-gui'))
620         config_tool_option_test.set('MESON_BUILD_ROOT', meson.current_build_dir())
621         config_tool_option_test.set('TOOL_PATH', libinput_tool.full_path())
622         tool_option_test = configure_file(input: 'tools/test_tool_option_parsing.py',
623                                           output: '@PLAINNAME@',
624                                           configuration : config_tool_option_test)
625         test('tool-option-parsing',
626              tool_option_test,
627              args : [tool_option_test, '-n', 'auto'],
628              suite : ['all', 'root'],
629              timeout : 240)
630 endif
631
632 # the libinput tools check whether we execute from the builddir, this is
633 # the test to verify that lookup. We test twice, once as normal test
634 # run from the builddir, once after copying to /tmp
635 test_builddir_lookup = executable('test-builddir-lookup',
636                                   'test/test-builddir-lookup.c',
637                                   dependencies : [ dep_tools_shared],
638                                   include_directories : [includes_src, includes_include],
639                                   install : false)
640 test('tools-builddir-lookup',
641      test_builddir_lookup,
642      args : ['--builddir-is-set'],
643      suite : ['all'])
644 test('tools-builddir-lookup-installed',
645      find_program('test/helper-copy-and-exec-from-tmp.sh'),
646      args : [test_builddir_lookup.full_path(), '--builddir-is-null'],
647      env : ['LD_LIBRARY_PATH=@0@'.format(meson.current_build_dir())],
648      suite : ['all'],
649      workdir : '/tmp')
650
651 ############ tests ############
652
653 test('symbols-leak-test',
654      find_program('test/symbols-leak-test'),
655      args : [ dir_src / 'libinput.sym', dir_src],
656      suite : ['all'])
657
658 # build-test only
659 executable('test-build-pedantic',
660            'test/build-pedantic.c',
661            dependencies : [dep_udev],
662            include_directories : [includes_src, includes_include],
663            c_args : ['-std=c99', '-pedantic', '-Werror'],
664            install : false)
665 # build-test only
666 executable('test-build-std-gnuc90',
667            'test/build-pedantic.c',
668            dependencies : [dep_udev],
669            include_directories : [includes_src, includes_include],
670            c_args : ['-std=gnu89', '-Werror'],
671            install : false)
672 # test for linking with the minimal linker flags
673 executable('test-build-linker',
674            'test/build-pedantic.c',
675            include_directories : [includes_src, includes_include],
676            dependencies : [ dep_libinput, dep_libinput_util ],
677            install : false)
678 # test including from C++ (in case CPP compiler is available)
679 if add_languages('cpp', required: false)
680         executable('test-build-cxx',
681                    'test/build-cxx.cc',
682                    dependencies : [dep_udev],
683                    include_directories : [includes_src, includes_include],
684                    install : false)
685 endif
686
687 libinput_test_sources = [ 'tools/libinput-test.c' ]
688 executable('libinput-test',
689            libinput_test_sources,
690            dependencies : deps_tools,
691            include_directories : [includes_src, includes_include],
692            install_dir : libinput_tool_path,
693            install : true,
694            )
695
696 # This is the test suite runner, we allow disabling that one because of
697 # dependencies
698 if get_option('tests')
699         dep_check = dependency('check', version : '>= 0.9.10')
700
701         gstack = find_program('gstack', required : false)
702         config_h.set10('HAVE_GSTACK', gstack.found())
703
704         # for inhibit support during test run
705         dep_libsystemd = dependency('libsystemd', version : '>= 221', required : false)
706         config_h.set10('HAVE_LIBSYSTEMD', dep_libsystemd.found())
707
708         litest_sources = [
709                 'src/libinput-private-config.c',
710                 'test/litest-device-absinfo-override.c',
711                 'test/litest-device-acer-hawaii-keyboard.c',
712                 'test/litest-device-acer-hawaii-touchpad.c',
713                 'test/litest-device-aiptek-tablet.c',
714                 'test/litest-device-alps-3fg.c',
715                 'test/litest-device-alps-semi-mt.c',
716                 'test/litest-device-alps-dualpoint.c',
717                 'test/litest-device-anker-mouse-kbd.c',
718                 'test/litest-device-apple-appletouch.c',
719                 'test/litest-device-apple-internal-keyboard.c',
720                 'test/litest-device-apple-magicmouse.c',
721                 'test/litest-device-asus-rog-gladius.c',
722                 'test/litest-device-atmel-hover.c',
723                 'test/litest-device-bcm5974.c',
724                 'test/litest-device-calibrated-touchscreen.c',
725                 'test/litest-device-cyborg-rat-5.c',
726                 'test/litest-device-dell-canvas-totem.c',
727                 'test/litest-device-dell-canvas-totem-touch.c',
728                 'test/litest-device-elantech-touchpad.c',
729                 'test/litest-device-elan-tablet.c',
730                 'test/litest-device-format-string.c',
731                 'test/litest-device-generic-pressurepad.c',
732                 'test/litest-device-generic-singletouch.c',
733                 'test/litest-device-gpio-keys.c',
734                 'test/litest-device-huion-pentablet.c',
735                 'test/litest-device-hp-wmi-hotkeys.c',
736                 'test/litest-device-ignored-mouse.c',
737                 'test/litest-device-keyboard.c',
738                 'test/litest-device-keyboard-all-codes.c',
739                 'test/litest-device-keyboard-quirked.c',
740                 'test/litest-device-keyboard-razer-blackwidow.c',
741                 'test/litest-device-keyboard-razer-blade-stealth.c',
742                 'test/litest-device-keyboard-razer-blade-stealth-videoswitch.c',
743                 'test/litest-device-lenovo-scrollpoint.c',
744                 'test/litest-device-lid-switch.c',
745                 'test/litest-device-lid-switch-surface3.c',
746                 'test/litest-device-logitech-media-keyboard-elite.c',
747                 'test/litest-device-logitech-trackball.c',
748                 'test/litest-device-nexus4-touch-screen.c',
749                 'test/litest-device-magic-trackpad.c',
750                 'test/litest-device-mouse.c',
751                 'test/litest-device-mouse-wheel-tilt.c',
752                 'test/litest-device-mouse-roccat.c',
753                 'test/litest-device-mouse-low-dpi.c',
754                 'test/litest-device-mouse-wheel-click-angle.c',
755                 'test/litest-device-mouse-wheel-click-count.c',
756                 'test/litest-device-ms-nano-transceiver-mouse.c',
757                 'test/litest-device-ms-surface-cover.c',
758                 'test/litest-device-protocol-a-touch-screen.c',
759                 'test/litest-device-qemu-usb-tablet.c',
760                 'test/litest-device-sony-vaio-keys.c',
761                 'test/litest-device-synaptics-x220.c',
762                 'test/litest-device-synaptics-hover.c',
763                 'test/litest-device-synaptics-i2c.c',
764                 'test/litest-device-synaptics-pressurepad.c',
765                 'test/litest-device-synaptics-rmi4.c',
766                 'test/litest-device-synaptics-st.c',
767                 'test/litest-device-synaptics-t440.c',
768                 'test/litest-device-synaptics-x1-carbon-3rd.c',
769                 'test/litest-device-tablet-mode-switch.c',
770                 'test/litest-device-thinkpad-extrabuttons.c',
771                 'test/litest-device-trackpoint.c',
772                 'test/litest-device-touch-screen.c',
773                 'test/litest-device-touchscreen-invalid-range.c',
774                 'test/litest-device-touchscreen-fuzz.c',
775                 'test/litest-device-touchscreen-mt-tool.c',
776                 'test/litest-device-uclogic-tablet.c',
777                 'test/litest-device-wacom-bamboo-2fg-finger.c',
778                 'test/litest-device-wacom-bamboo-2fg-pad.c',
779                 'test/litest-device-wacom-bamboo-2fg-pen.c',
780                 'test/litest-device-wacom-bamboo-16fg-pen.c',
781                 'test/litest-device-wacom-cintiq-12wx-pen.c',
782                 'test/litest-device-wacom-cintiq-13hdt-finger.c',
783                 'test/litest-device-wacom-cintiq-13hdt-pad.c',
784                 'test/litest-device-wacom-cintiq-13hdt-pen.c',
785                 'test/litest-device-wacom-cintiq-24hd-pen.c',
786                 'test/litest-device-wacom-cintiq-24hdt-pad.c',
787                 'test/litest-device-wacom-cintiq-pro-16-finger.c',
788                 'test/litest-device-wacom-cintiq-pro-16-pad.c',
789                 'test/litest-device-wacom-cintiq-pro-16-pen.c',
790                 'test/litest-device-wacom-ekr.c',
791                 'test/litest-device-wacom-hid4800-pen.c',
792                 'test/litest-device-wacom-intuos3-pad.c',
793                 'test/litest-device-wacom-intuos5-finger.c',
794                 'test/litest-device-wacom-intuos5-pad.c',
795                 'test/litest-device-wacom-intuos5-pen.c',
796                 'test/litest-device-wacom-isdv4-4200-pen.c',
797                 'test/litest-device-wacom-isdv4-524c-pen.c',
798                 'test/litest-device-wacom-isdv4-e6-pen.c',
799                 'test/litest-device-wacom-isdv4-e6-finger.c',
800                 'test/litest-device-wacom-mobilestudio-pro-pad.c',
801                 'test/litest-device-waltop-tablet.c',
802                 'test/litest-device-wheel-only.c',
803                 'test/litest-device-xen-virtual-pointer.c',
804                 'test/litest-device-vmware-virtual-usb-mouse.c',
805                 'test/litest-device-yubikey.c',
806                 'test/litest.c',
807         ]
808
809         dep_dl = cc.find_library('dl')
810         deps_litest = [
811                 dep_libinput,
812                 dep_check,
813                 dep_udev,
814                 dep_libevdev,
815                 dep_dl,
816                 dep_lm,
817                 dep_libsystemd,
818                 dep_libquirks,
819         ]
820
821         litest_config_h = configuration_data()
822         litest_config_h.set_quoted('LIBINPUT_DEVICE_GROUPS_RULES_FILE',
823                                    meson.current_build_dir() /
824                                    '80-libinput-device-groups-litest.rules')
825         litest_config_h.set_quoted('LIBINPUT_FUZZ_OVERRIDE_UDEV_RULES_FILE',
826                                    meson.current_build_dir() /
827                                    '90-libinput-fuzz-override-litest.rules')
828
829         def_no_main = '-DLITEST_NO_MAIN'
830         def_disable_backtrace = '-DLITEST_DISABLE_BACKTRACE_LOGGING'
831         defs_litest_selftest = [
832                 def_no_main,
833                 def_disable_backtrace,
834                 '-Wno-unused',
835         ]
836         test_litest_selftest_sources = [
837                 'test/litest-selftest.c',
838                 'test/litest.c',
839         ]
840         test_litest_selftest = executable('test-litest-selftest',
841                                           test_litest_selftest_sources,
842                                           include_directories : [includes_src, includes_include],
843                                           dependencies : deps_litest,
844                                           c_args : defs_litest_selftest,
845                                           install : false)
846         test('test-litest-selftest',
847              test_litest_selftest,
848              suite : ['all'],
849              timeout : 100)
850
851         def_LT_VERSION = '-DLIBINPUT_LT_VERSION="@0@:@1@:@2@"'.format(libinput_lt_c, libinput_lt_r, libinput_lt_a)
852         test_library_version = executable('test-library-version',
853                                           ['test/test-library-version.c'],
854                                           c_args : [ def_LT_VERSION ],
855                                           install : false)
856         test('test-library-version',
857              test_library_version,
858              suite : ['all'])
859
860         test_utils_sources = [
861                 'test/test-utils.c',
862         ]
863         test_utils = executable('libinput-test-utils',
864                                 test_utils_sources,
865                                 include_directories : [includes_src, includes_include],
866                                 dependencies : deps_litest,
867                                 install_dir : libinput_tool_path,
868                                 install : get_option('install-tests'))
869         test('test-utils',
870              test_utils,
871              suite : ['all'])
872
873         # When adding new files to this list, update the CI
874         tests_sources = [
875                 'test/test-udev.c',
876                 'test/test-path.c',
877                 'test/test-pointer.c',
878                 'test/test-touch.c',
879                 'test/test-log.c',
880                 'test/test-tablet.c',
881                 'test/test-totem.c',
882                 'test/test-pad.c',
883                 'test/test-touchpad.c',
884                 'test/test-touchpad-tap.c',
885                 'test/test-touchpad-buttons.c',
886                 'test/test-trackpoint.c',
887                 'test/test-trackball.c',
888                 'test/test-misc.c',
889                 'test/test-keyboard.c',
890                 'test/test-device.c',
891                 'test/test-gestures.c',
892                 'test/test-switch.c',
893                 'test/test-quirks.c',
894         ]
895         libinput_test_runner_sources = litest_sources + tests_sources
896         libinput_test_runner = executable('libinput-test-suite',
897                                           libinput_test_runner_sources,
898                                           include_directories : [includes_src, includes_include],
899                                           dependencies : deps_litest,
900                                           install_dir : libinput_tool_path,
901                                           install : get_option('install-tests'))
902
903         src_man += 'test/libinput-test-suite.man'
904
905         foreach testfile : tests_sources
906                 tfile = testfile.split('test/test-')[1]
907                 group = tfile.split('.c')[0]
908                 test('libinput-test-suite-@0@'.format(group),
909                      libinput_test_runner,
910                      suite : ['all', 'valgrind', 'root', 'hardware'],
911                      args : ['--filter-group=@0@'.format(group),
912                              '--xml-output=junit-@0@-XXXXXX.xml'.format(group)],
913                      is_parallel : false,
914                      timeout : 1200)
915         endforeach
916
917         test('libinput-test-deviceless',
918              libinput_test_runner,
919              suite : ['all', 'valgrind'],
920              args: ['--filter-deviceless',
921                     '--xml-output=junit-deviceless-XXXXXX.xml'])
922
923         valgrind = find_program('valgrind', required : false)
924         if valgrind.found()
925                 valgrind_env = environment()
926                 valgrind_suppressions_file = dir_src_test / 'valgrind.suppressions'
927                 add_test_setup('valgrind',
928                                 exe_wrapper : [ valgrind,
929                                                 '--leak-check=full',
930                                                 '--gen-suppressions=all',
931                                                 '--error-exitcode=3',
932                                                 '--suppressions=' + valgrind_suppressions_file ],
933                                 env :  valgrind_env,
934                                 timeout_multiplier : 100)
935         else
936                 message('valgrind not found, disabling valgrind test suite')
937         endif
938         configure_file(output : 'litest-config.h',
939                        configuration : litest_config_h)
940 endif
941
942
943 ############ man pages ############
944 man_config = configuration_data()
945 man_config.set('LIBINPUT_VERSION', meson.project_version())
946 man_config.set('LIBINPUT_DATA_DIR', dir_data)
947 if get_option('install-tests')
948         man_config.set('HAVE_INSTALLED_TESTS', '.\"')
949 else
950         man_config.set('HAVE_INSTALLED_TESTS', '')
951 endif
952 src_man += files(
953         'tools/libinput.man',
954         'tools/libinput-analyze.man',
955         'tools/libinput-analyze-per-slot-delta.man',
956         'tools/libinput-analyze-recording.man',
957         'tools/libinput-analyze-touch-down-state.man',
958         'tools/libinput-debug-events.man',
959         'tools/libinput-debug-tablet.man',
960         'tools/libinput-list-devices.man',
961         'tools/libinput-measure.man',
962         'tools/libinput-measure-fuzz.man',
963         'tools/libinput-measure-touchpad-size.man',
964         'tools/libinput-measure-touchpad-tap.man',
965         'tools/libinput-measure-touchpad-pressure.man',
966         'tools/libinput-measure-touch-size.man',
967         'tools/libinput-quirks.man',
968         'tools/libinput-record.man',
969         'tools/libinput-replay.man',
970         'tools/libinput-test.man',
971 )
972
973 foreach m : src_man
974         configure_file(input : m,
975                        output : '@BASENAME@.1',
976                        configuration : man_config,
977                        install_dir : dir_man1)
978 endforeach
979
980 # Same man page for the subtools to stay consistent with the other tools
981 configure_file(input : 'tools/libinput-quirks.man',
982                output : 'libinput-quirks-list.1',
983                configuration : man_config,
984                install_dir : dir_man1,
985                )
986 configure_file(input : 'tools/libinput-quirks.man',
987                output : 'libinput-quirks-validate.1',
988                configuration : man_config,
989                install_dir : dir_man1,
990                )
991
992 ############ output files ############
993 configure_file(output : 'config.h', configuration : config_h)