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