1# Copyright © 2017-2018 Intel Corporation
2
3# Permission is hereby granted, free of charge, to any person obtaining a copy
4# of this software and associated documentation files (the "Software"), to deal
5# in the Software without restriction, including without limitation the rights
6# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7# copies of the Software, and to permit persons to whom the Software is
8# furnished to do so, subject to the following conditions:
9
10# The above copyright notice and this permission notice shall be included in
11# all copies or substantial portions of the Software.
12
13# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19# SOFTWARE.
20
21# The versioning should always stay at 2.4.x. If bumping away from this,
22# you must ensure that all users of patch_ver are changed such that DSO versions
23# continuously increment (e.g. blindly bumping from 2.4.122 to 2.5.0 would
24# roll the libdrm DSO versioning from libdrm.so.2.122.0 back to libdrm.so.2.0.0
25# which would be bad)
26project(
27  'libdrm',
28  ['c'],
29  version : '2.4.124',
30  license : 'MIT',
31  meson_version : '>= 0.59',
32  default_options : ['buildtype=debugoptimized', 'c_std=c11'],
33)
34
35patch_ver = meson.project_version().split('.')[2]
36
37if ['windows', 'darwin'].contains(host_machine.system())
38  error('unsupported OS: @0@'.format(host_machine.system()))
39endif
40
41pkg = import('pkgconfig')
42
43config = configuration_data()
44
45config.set10('UDEV', get_option('udev'))
46with_freedreno_kgsl = get_option('freedreno-kgsl')
47with_install_tests = get_option('install-test-programs')
48with_tests = get_option('tests')
49
50dep_threads = dependency('threads')
51
52cc = meson.get_compiler('c')
53
54android = cc.compiles('''int func() { return __ANDROID__; }''')
55
56# Solaris / Illumos
57if host_machine.system() == 'sunos'
58  add_global_arguments('-D__EXTENSIONS__', language : 'c')
59  add_global_arguments('-D_POSIX_C_SOURCE=3', language : 'c')
60endif
61
62symbols_check = find_program('symbols-check.py')
63prog_nm = find_program('nm')
64
65# Check for atomics
66intel_atomics = false
67lib_atomics = false
68
69python3 = import('python').find_installation()
70format_mod_static_table = custom_target(
71  'format_mod_static_table',
72  output : 'generated_static_table_fourcc.h',
73  input : 'include/drm/drm_fourcc.h',
74  command : [python3, files('gen_table_fourcc.py'), '@INPUT@', '@OUTPUT@'])
75
76dep_atomic_ops = dependency('atomic_ops', required : false)
77if cc.links('''
78    int atomic_add(int *i) { return __sync_add_and_fetch (i, 1); }
79    int atomic_cmpxchg(int *i, int j, int k) { return __sync_val_compare_and_swap (i, j, k); }
80    int main() { }
81    ''',
82    name : 'Intel Atomics')
83  intel_atomics = true
84  with_atomics = true
85  dep_atomic_ops = []
86elif dep_atomic_ops.found()
87  lib_atomics = true
88  with_atomics = true
89elif cc.has_function('atomic_cas_uint')
90  with_atomics = true
91else
92  with_atomics = false
93endif
94
95config.set10('HAVE_LIBDRM_ATOMIC_PRIMITIVES', intel_atomics)
96config.set10('HAVE_LIB_ATOMIC_OPS', lib_atomics)
97
98dep_pciaccess = dependency('pciaccess', version : '>= 0.10', required : get_option('intel'))
99
100with_intel = get_option('intel') \
101  .require(with_atomics, error_message : 'libdrm_intel requires atomics') \
102  .require(dep_pciaccess.found(), error_message : 'libdrm_intel requires libpciaccess') \
103  .disable_auto_if(not host_machine.cpu_family().startswith('x86')) \
104  .allowed()
105summary('Intel', with_intel)
106
107with_radeon = get_option('radeon') \
108  .require(with_atomics, error_message : 'libdrm_radeon requires atomics') \
109  .allowed()
110summary('Radeon', with_radeon)
111
112with_amdgpu = get_option('amdgpu') \
113  .require(with_atomics, error_message : 'libdrm_amdgpu requires atomics') \
114  .allowed()
115summary('AMDGPU', with_amdgpu)
116
117with_nouveau = get_option('nouveau') \
118  .require(with_atomics, error_message : 'libdrm_nouveau requires atomics') \
119  .allowed()
120summary('Nouveau', with_nouveau)
121
122with_vmwgfx = get_option('vmwgfx').allowed()
123summary('vmwgfx', with_vmwgfx)
124
125with_omap = get_option('omap') \
126  .require(with_atomics, error_message : 'libdrm_omap requires atomics') \
127  .enabled()
128summary('OMAP', with_omap)
129
130with_freedreno = get_option('freedreno') \
131  .require(with_atomics, error_message : 'libdrm_freedreno requires atomics') \
132  .disable_auto_if(not ['arm', 'aarch64'].contains(host_machine.cpu_family())) \
133  .allowed()
134summary('Freedreno', with_freedreno)
135summary('Freedreon-kgsl', with_freedreno_kgsl)
136
137with_tegra = get_option('tegra') \
138  .require(with_atomics, error_message : 'libdrm_tegra requires atomics') \
139  .disable_auto_if(not ['arm', 'aarch64'].contains(host_machine.cpu_family())) \
140  .enabled()
141summary('Tegra', with_tegra)
142
143with_etnaviv = get_option('etnaviv') \
144  .require(with_atomics, error_message : 'libdrm_etnaviv requires atomics') \
145  .disable_auto_if(not ['arm', 'aarch64', 'arc', 'mips', 'mips64', 'loongarch64'].contains(host_machine.cpu_family())) \
146  .allowed()
147summary('Etnaviv', with_etnaviv)
148
149with_exynos = get_option('exynos').enabled()
150summary('EXYNOS', with_exynos)
151
152with_vc4 = get_option('vc4') \
153  .disable_auto_if(not ['arm', 'aarch64'].contains(host_machine.cpu_family())) \
154  .allowed()
155summary('VC4', with_vc4)
156
157# Among others FreeBSD does not have a separate dl library.
158if not cc.has_function('dlsym')
159  dep_dl = cc.find_library('dl', required : with_nouveau)
160else
161  dep_dl = []
162endif
163# clock_gettime might require -rt, or it might not. find out
164if not cc.has_function('clock_gettime', prefix : '#define _GNU_SOURCE\n#include <time.h>')
165  # XXX: untested
166  dep_rt = cc.find_library('rt')
167else
168  dep_rt = []
169endif
170
171# The header is not required on Linux, and is in fact deprecated in glibc 2.30+
172if host_machine.system() == 'linux'
173  config.set10('HAVE_SYS_SYSCTL_H', false)
174else
175  # From Niclas Zeising:
176  # FreeBSD requires sys/types.h for sys/sysctl.h, so add it as part of
177  # the includes when checking for headers.
178  config.set10('HAVE_SYS_SYSCTL_H',
179    cc.compiles('#include <sys/types.h>\n#include <sys/sysctl.h>', name : 'sys/sysctl.h works'))
180endif
181
182foreach header : ['sys/select.h', 'alloca.h']
183  config.set10('HAVE_' + header.underscorify().to_upper(), cc.check_header(header))
184endforeach
185
186if (cc.has_header_symbol('sys/sysmacros.h', 'major') and
187  cc.has_header_symbol('sys/sysmacros.h', 'minor') and
188  cc.has_header_symbol('sys/sysmacros.h', 'makedev'))
189  config.set10('MAJOR_IN_SYSMACROS', true)
190endif
191if (cc.has_header_symbol('sys/mkdev.h', 'major') and
192  cc.has_header_symbol('sys/mkdev.h', 'minor') and
193  cc.has_header_symbol('sys/mkdev.h', 'makedev'))
194  config.set10('MAJOR_IN_MKDEV', true)
195endif
196config.set10('HAVE_OPEN_MEMSTREAM', cc.has_function('open_memstream'))
197
198libdrm_c_args = cc.get_supported_arguments([
199  '-Wsign-compare', '-Werror=undef', '-Werror=implicit-function-declaration',
200  '-Wpointer-arith', '-Wwrite-strings', '-Wstrict-prototypes',
201  '-Wmissing-prototypes', '-Wmissing-declarations', '-Wnested-externs',
202  '-Wpacked', '-Wswitch-enum', '-Wmissing-format-attribute',
203  '-Wstrict-aliasing=2', '-Winit-self', '-Winline', '-Wshadow',
204  '-Wdeclaration-after-statement', '-Wold-style-definition',
205  '-Wno-unused-parameter', '-Wno-attributes', '-Wno-long-long',
206  '-Wno-missing-field-initializers'])
207
208dep_cunit = dependency('cunit', version : '>= 2.1', required : false)
209dep_cairo = dependency('cairo', required : get_option('cairo-tests'))
210with_cairo_tests = dep_cairo.found()
211
212valgrind_version = []
213if with_freedreno
214  valgrind_version = '>=3.10.0'
215endif
216dep_valgrind = dependency('valgrind', required : get_option('valgrind'), version : valgrind_version)
217with_valgrind = dep_valgrind.found()
218
219prog_rst2man = find_program('rst2man', 'rst2man.py', required: get_option('man-pages'))
220with_man_pages = prog_rst2man.found()
221
222config.set10('HAVE_VISIBILITY', cc.has_function_attribute('visibility:hidden'))
223
224foreach t : [
225             [with_exynos, 'EXYNOS'],
226             [with_freedreno_kgsl, 'FREEDRENO_KGSL'],
227             [with_intel, 'INTEL'],
228             [with_nouveau, 'NOUVEAU'],
229             [with_radeon, 'RADEON'],
230             [with_vc4, 'VC4'],
231             [with_vmwgfx, 'VMWGFX'],
232             [with_cairo_tests, 'CAIRO'],
233             [with_valgrind, 'VALGRIND'],
234            ]
235  config.set10('HAVE_@0@'.format(t[1]), t[0])
236endforeach
237if with_freedreno_kgsl and not with_freedreno
238  error('cannot enable freedreno-kgsl without freedreno support')
239endif
240config.set10('_GNU_SOURCE', true)
241
242if target_machine.endian() == 'big'
243  config.set('HAVE_BIG_ENDIAN', 1)
244endif
245
246if android
247  config.set('BIONIC_IOCTL_NO_SIGNEDNESS_OVERLOAD', 1)
248endif
249
250config_file = configure_file(
251  configuration : config,
252  output : 'config.h',
253)
254add_project_arguments('-include', meson.current_build_dir() / 'config.h', language : 'c')
255
256inc_root = include_directories('.')
257inc_drm = include_directories('include/drm')
258
259libdrm_files = [files(
260   'xf86drm.c', 'xf86drmHash.c', 'xf86drmRandom.c', 'xf86drmSL.c',
261   'xf86drmMode.c'
262  ),
263  config_file, format_mod_static_table
264]
265
266# Build an unversioned so on android
267if android
268  libdrm_kw = {}
269else
270  libdrm_kw = { 'version' : '2.@0@.0'.format(patch_ver) }
271endif
272
273libdrm = library(
274  'drm',
275  libdrm_files,
276  c_args : libdrm_c_args,
277  dependencies : [dep_valgrind, dep_rt],
278  include_directories : inc_drm,
279  install : true,
280  kwargs : libdrm_kw,
281  gnu_symbol_visibility : 'hidden',
282)
283
284test(
285  'core-symbols-check',
286  symbols_check,
287  args : [
288    '--lib', libdrm,
289    '--symbols-file', files('core-symbols.txt'),
290    '--nm', prog_nm.full_path(),
291  ],
292)
293
294ext_libdrm = declare_dependency(
295  link_with : libdrm,
296  include_directories : [inc_root, inc_drm],
297)
298
299if meson.version().version_compare('>= 0.54.0')
300  meson.override_dependency('libdrm', ext_libdrm)
301endif
302
303install_headers('libsync.h', 'xf86drm.h', 'xf86drmMode.h')
304install_headers(
305  'include/drm/drm.h', 'include/drm/drm_fourcc.h', 'include/drm/drm_mode.h',
306  'include/drm/drm_sarea.h', 'include/drm/i915_drm.h',
307  'include/drm/mach64_drm.h', 'include/drm/mga_drm.h',
308  'include/drm/msm_drm.h', 'include/drm/nouveau_drm.h',
309  'include/drm/qxl_drm.h', 'include/drm/r128_drm.h',
310  'include/drm/radeon_drm.h', 'include/drm/amdgpu_drm.h',
311  'include/drm/savage_drm.h', 'include/drm/sis_drm.h',
312  'include/drm/tegra_drm.h', 'include/drm/vc4_drm.h',
313  'include/drm/via_drm.h', 'include/drm/virtgpu_drm.h',
314  subdir : 'libdrm',
315)
316if with_vmwgfx
317  install_headers('include/drm/vmwgfx_drm.h', subdir : 'libdrm')
318endif
319
320pkg.generate(
321  libdrm,
322  name : 'libdrm',
323  subdirs : ['.', 'libdrm'],
324  description : 'Userspace interface to kernel DRM services',
325)
326
327if with_intel
328  subdir('intel')
329endif
330if with_nouveau
331  subdir('nouveau')
332endif
333if with_radeon
334  subdir('radeon')
335endif
336if with_amdgpu
337  subdir('amdgpu')
338endif
339if with_omap
340  subdir('omap')
341endif
342if with_exynos
343  subdir('exynos')
344endif
345if with_freedreno
346  subdir('freedreno')
347endif
348if with_tegra
349  subdir('tegra')
350endif
351if with_vc4
352  subdir('vc4')
353endif
354if with_etnaviv
355  subdir('etnaviv')
356endif
357if with_man_pages
358  subdir('man')
359endif
360subdir('data')
361if with_tests
362  subdir('tests')
363endif
364