1project('libevdev', 'c',
2	version: '1.13.0', # change autotools version too
3	license: 'MIT/Expat',
4	default_options: [ 'c_std=gnu99', 'warning_level=2' ],
5	meson_version: '>= 0.56.0')
6
7libevdev_version = meson.project_version().split('.')
8
9dir_root        = meson.project_source_root()
10dir_src         = dir_root / 'libevdev'
11dir_src_test    = dir_root / 'test'
12
13# Include directories
14includes_include = include_directories('include')
15
16# DO NOT MODIFY THIS
17# Use symbol versioning instead.
18libevdev_lt_c=5
19libevdev_lt_r=0
20libevdev_lt_a=3
21
22# convert to soname
23libevdev_so_version = '@0@.@1@.@2@'.format((libevdev_lt_c - libevdev_lt_a),
24					   libevdev_lt_a, libevdev_lt_r)
25
26
27# Compiler setup
28cc = meson.get_compiler('c')
29cppflags = ['-Wno-unused-parameter', '-fvisibility=hidden']
30cflags = cppflags + ['-Wmissing-prototypes', '-Wstrict-prototypes']
31add_project_arguments(cflags, language: 'c')
32add_project_arguments(cppflags, language: 'cpp')
33
34# config.h
35config_h = configuration_data()
36config_h.set('_GNU_SOURCE', '1')
37
38# Dependencies
39pkgconfig = import('pkgconfig')
40dep_lm = cc.find_library('m')
41dep_rt = cc.find_library('rt')
42
43input_h = dir_root / 'include' / 'linux' / host_machine.system() / 'input.h'
44input_event_codes_h = dir_root / 'include' / 'linux' / host_machine.system() / 'input-event-codes.h'
45
46# event-names.h
47make_event_names = find_program('libevdev/make-event-names.py')
48event_names_h = configure_file(input: 'libevdev/libevdev.h',
49			       output: 'event-names.h',
50			       command: [make_event_names, input_h, input_event_codes_h],
51			       capture: true)
52
53
54# libevdev.so
55install_headers('libevdev/libevdev.h',
56		'libevdev/libevdev-uinput.h',
57		subdir: 'libevdev-1.0/libevdev')
58src_libevdev = [
59	event_names_h,
60	'libevdev/libevdev.h',
61	'libevdev/libevdev-int.h',
62	'libevdev/libevdev-util.h',
63	'libevdev/libevdev-uinput.c',
64	'libevdev/libevdev-uinput.h',
65	'libevdev/libevdev-uinput-int.h',
66	'libevdev/libevdev.c',
67	'libevdev/libevdev-names.c',
68	'include/linux/input.h',
69	'include/linux/uinput.h',
70]
71
72mapfile = dir_src / 'libevdev.sym'
73version_flag = '-Wl,--version-script,@0@'.format(mapfile)
74lib_libevdev = library('evdev',
75	src_libevdev,
76	include_directories: [includes_include],
77	dependencies: [dep_rt],
78	version: libevdev_so_version,
79	link_args: version_flag,
80	link_depends: mapfile,
81	install: true
82)
83
84dep_libevdev = declare_dependency(link_with: lib_libevdev)
85
86pkgconfig.generate(
87	filebase: 'libevdev',
88	name: 'libevdev',
89	description: 'Handler library for evdev events',
90	version: meson.project_version(),
91	libraries: lib_libevdev,
92	subdirs: 'libevdev-1.0',
93)
94
95man_config = configuration_data()
96man_config.set('PACKAGE_VERSION', meson.project_version())
97manpage = configure_file(input: 'doc/libevdev.man.in',
98                         output: 'libevdev.3',
99                         configuration: man_config)
100install_man(manpage)
101
102
103# tools
104executable('libevdev-events',
105	   sources: ['tools/libevdev-events.c'],
106	   include_directories: [includes_include],
107	   dependencies: dep_libevdev,
108	   install: false)
109executable('libevdev-list-codes',
110	   sources: ['tools/libevdev-list-codes.c'],
111	   include_directories: [includes_include],
112	   dependencies: dep_libevdev,
113	   install: false)
114executable('touchpad-edge-detector',
115	   sources: ['tools/touchpad-edge-detector.c'],
116	   include_directories: [includes_include],
117	   dependencies: [dep_libevdev, dep_lm],
118           install: true)
119executable('mouse-dpi-tool',
120	   sources: ['tools/mouse-dpi-tool.c'],
121	   include_directories: [includes_include],
122	   dependencies: dep_libevdev,
123           install: true)
124executable('libevdev-tweak-device',
125	   sources: ['tools/libevdev-tweak-device.c'],
126	   include_directories: [includes_include],
127	   dependencies: dep_libevdev,
128	   install: true)
129install_man('tools/libevdev-tweak-device.1',
130	    'tools/touchpad-edge-detector.1',
131	    'tools/mouse-dpi-tool.1')
132
133# tests
134dep_check = dependency('check', version: '>= 0.9.9',
135		       required: get_option('tests'))
136if dep_check.found()
137	executable('test-link',
138		   sources: ['test/test-link.c'],
139		   include_directories: [includes_include],
140		   dependencies: dep_libevdev,
141		   install: false)
142	executable('test-compile-pedantic',
143		   sources: ['test/test-compile-pedantic.c'],
144		   c_args: ['-pedantic', '-Werror', '-std=c89'],
145		   include_directories: [includes_include],
146		   dependencies: dep_libevdev,
147		   install: false)
148
149	src_common = [
150		'test/test-common-uinput.c',
151		'test/test-common-uinput.h',
152		'test/test-common.c',
153		'test/test-common.h',
154		'test/test-main.c',
155	]
156	test_event_codes = executable('test-event-codes',
157				      sources: src_common + [
158					'test/test-event-codes.c',
159					'test/test-event-names.c',
160					'test/test-context.c',
161				      ],
162				      include_directories: [includes_include],
163				      dependencies: [dep_libevdev, dep_check],
164				      install: false)
165	test('test-event-codes', test_event_codes, suite: 'library')
166
167	test_internals = executable('test-internals',
168				    sources: src_common + [
169					'test/test-int-queue.c',
170				    ],
171				    include_directories: [includes_include],
172				    dependencies: [dep_libevdev, dep_check],
173				    install: false)
174	test('test-internals', test_internals, suite: 'library')
175
176	test_uinput = executable('test-uinput',
177				 sources: src_common + [
178					'test/test-uinput.c',
179				 ],
180				 include_directories: [includes_include],
181				 dependencies: [dep_libevdev, dep_check],
182				 install: false)
183	test('test-uinput', test_uinput, suite: 'library')
184
185	test_libevdev = executable('test-libevdev',
186				   sources: src_common + [
187					'test/test-libevdev-init.c',
188					'test/test-libevdev-has-event.c',
189					'test/test-libevdev-events.c',
190				   ],
191				   include_directories: [includes_include],
192				   dependencies: [dep_libevdev, dep_check],
193				   install: false)
194	test('test-libevdev', test_libevdev, suite: 'library', env: ['CK_DEFAULT_TIMEOUT=10'])
195
196	test_kernel = executable('test-kernel',
197				 sources: src_common + [
198					'test/test-kernel.c',
199				 ],
200				 include_directories: [includes_include],
201				 dependencies: [dep_libevdev, dep_check],
202				 install: false)
203	test('test-kernel', test_kernel, suite: 'kernel')
204
205
206	valgrind = find_program('valgrind', required: false)
207	if valgrind.found()
208		valgrind_env = environment()
209		valgrind_env.set('CK_TIMEOUT_MULTIPLIER', '10')
210		valgrind_env.set('CK_FORK', 'no')
211		valgrind_env.set('RUNNING_ON_VALGRIND', '1')
212		valgrind_suppressions_file = dir_src_test / 'valgrind.suppressions'
213		add_test_setup('valgrind',
214				exe_wrapper: [ valgrind,
215						'--leak-check=full',
216						'--gen-suppressions=all',
217						'--error-exitcode=3',
218						'--suppressions=' + valgrind_suppressions_file ],
219				env: valgrind_env,
220				timeout_multiplier: 100)
221	else
222		message('valgrind not found, disabling valgrind test suite')
223	endif
224
225	test_static_link = find_program('test/test-static-symbols-leak.sh')
226	test('static-symbols-leak', test_static_link,
227	     args: [meson.current_build_dir()],
228	     suite: 'static')
229endif
230
231doxygen = find_program('doxygen', required: get_option('documentation'))
232if doxygen.found()
233	doxygen = find_program('doxygen')
234
235	src_doxygen = files(
236		# source files
237		dir_src / 'libevdev.h',
238		dir_src / 'libevdev-uinput.h',
239		# style files
240		'doc/style/bootstrap.css',
241		'doc/style/customdoxygen.css',
242		'doc/style/doxy-boot.js',
243		'doc/style/dynsections.js',
244		'doc/style/footer.html',
245		'doc/style/header.html',
246		'doc/style/layout.xml',
247		'doc/style/libevdevdoxygen.css',
248		'doc/style/LICENSE',
249		'doc/style/README.md',
250		'doc/style/style.css',
251	)
252	doxyfiles = []
253	foreach f: src_doxygen
254		df = configure_file(input: f,
255				    output: '@PLAINNAME@',
256				    copy: true)
257		doxyfiles += [df]
258	endforeach
259
260	doc_config = configuration_data()
261	doc_config.set('PACKAGE_NAME', meson.project_name())
262	doc_config.set('PACKAGE_VERSION', meson.project_version())
263	doc_config.set('builddir', meson.current_build_dir())
264	doc_config.set('top_srcdir', dir_root)
265	doc_config.set('srcdir', dir_root / 'doc')
266
267	doxyfile = configure_file(input: 'doc/libevdev.doxygen.in',
268				  output: 'libevdev.doxygen',
269				  configuration: doc_config)
270	custom_target('doxygen',
271		      input: [doxyfiles, doxyfile] + src_doxygen,
272		      output: ['.'],
273		      command: [doxygen, doxyfile],
274		      install: false,
275		      build_by_default: true)
276endif
277
278# Coverity breaks because it doesn't define _Float128 correctly, you'll end
279# up with a bunch of messages in the form:
280# "/usr/include/stdlib.h", line 133: error #20: identifier "_Float128" is
281#           undefined
282#   extern _Float128 strtof128 (const char *__restrict __nptr,
283#          ^
284# We don't use float128 ourselves, it gets pulled in from math.h or
285# something, so let's just define it as uint128 and move on.
286# Unfortunately we can't detect the coverity build at meson configure
287# time, we only know it fails at runtime. So make this an option instead, to
288# be removed when coverity fixes this again.
289if get_option('coverity')
290        config_h.set('_Float128', '__uint128_t')
291        config_h.set('_Float32', 'int')
292        config_h.set('_Float32x', 'int')
293        config_h.set('_Float64', 'long')
294        config_h.set('_Float64x', 'long')
295endif
296
297############ output files ############
298configure_file(output: 'config.h', configuration: config_h)
299