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
21project(
22  'libdrm',
23  ['c'],
24  version : '2.4.100',
25  license : 'MIT',
26  meson_version : '>= 0.43',
27  default_options : ['buildtype=debugoptimized', 'c_std=gnu99'],
28)
29
30pkg = import('pkgconfig')
31
32config = configuration_data()
33
34config.set10('UDEV', get_option('udev'))
35with_freedreno_kgsl = get_option('freedreno-kgsl')
36with_install_tests = get_option('install-test-programs')
37
38if ['freebsd', 'dragonfly', 'netbsd'].contains(host_machine.system())
39  dep_pthread_stubs = dependency('pthread-stubs', version : '>= 0.4')
40else
41  dep_pthread_stubs = []
42endif
43dep_threads = dependency('threads')
44
45cc = meson.get_compiler('c')
46
47# Check for atomics
48intel_atomics = false
49lib_atomics = false
50
51dep_atomic_ops = dependency('atomic_ops', required : false)
52if cc.compiles('''
53    int atomic_add(int *i) { return __sync_add_and_fetch (i, 1); }
54    int atomic_cmpxchg(int *i, int j, int k) { return __sync_val_compare_and_swap (i, j, k); }
55    ''',
56    name : 'Intel Atomics')
57  intel_atomics = true
58  with_atomics = true
59  dep_atomic_ops = []
60elif dep_atomic_ops.found()
61  lib_atomics = true
62  with_atomics = true
63elif cc.has_function('atomic_cas_uint')
64  with_atomics = true
65else
66  with_atomics = false
67endif
68
69config.set10('HAVE_LIBDRM_ATOMIC_PRIMITIVES', intel_atomics)
70config.set10('HAVE_LIB_ATOMIC_OPS', lib_atomics)
71
72with_intel = false
73_intel = get_option('intel')
74if _intel != 'false'
75  if _intel == 'true' and not with_atomics
76    error('libdrm_intel requires atomics.')
77  else
78    with_intel = _intel == 'true' or host_machine.cpu_family().startswith('x86')
79  endif
80endif
81
82with_radeon = false
83_radeon = get_option('radeon')
84if _radeon != 'false'
85  if _radeon == 'true' and not with_atomics
86    error('libdrm_radeon requires atomics.')
87  endif
88  with_radeon = true
89endif
90
91with_amdgpu = false
92_amdgpu = get_option('amdgpu')
93if _amdgpu != 'false'
94  if _amdgpu == 'true' and not with_atomics
95    error('libdrm_amdgpu requires atomics.')
96  endif
97  with_amdgpu = true
98endif
99
100with_nouveau = false
101_nouveau = get_option('nouveau')
102if _nouveau != 'false'
103  if _nouveau == 'true' and not with_atomics
104    error('libdrm_nouveau requires atomics.')
105  endif
106  with_nouveau = true
107endif
108
109with_vmwgfx = false
110_vmwgfx = get_option('vmwgfx')
111if _vmwgfx != 'false'
112  with_vmwgfx = true
113endif
114
115with_omap = false
116_omap = get_option('omap')
117if _omap == 'true'
118  if not with_atomics
119    error('libdrm_omap requires atomics.')
120  endif
121  with_omap = true
122endif
123
124with_freedreno = false
125_freedreno = get_option('freedreno')
126if _freedreno != 'false'
127  if _freedreno == 'true' and not with_atomics
128    error('libdrm_freedreno requires atomics.')
129  else
130    with_freedreno = _freedreno == 'true' or ['arm', 'aarch64'].contains(host_machine.cpu_family())
131  endif
132endif
133
134with_tegra = false
135_tegra = get_option('tegra')
136if _tegra == 'true'
137  if not with_atomics
138    error('libdrm_tegra requires atomics.')
139  endif
140  with_tegra = true
141endif
142
143with_etnaviv = false
144_etnaviv = get_option('etnaviv')
145if _etnaviv == 'true'
146  if not with_atomics
147    error('libdrm_etnaviv requires atomics.')
148  endif
149  with_etnaviv = true
150endif
151
152with_exynos = get_option('exynos') == 'true'
153
154with_vc4 = false
155_vc4 = get_option('vc4')
156if _vc4 != 'false'
157  with_vc4 = _vc4 == 'true' or ['arm', 'aarch64'].contains(host_machine.cpu_family())
158endif
159
160# XXX: Apparently only freebsd and dragonfly bsd actually need this (and
161# gnu/kfreebsd), not openbsd and netbsd
162with_libkms = false
163_libkms = get_option('libkms')
164if _libkms != 'false'
165  with_libkms = _libkms == 'true' or ['linux', 'freebsd', 'dragonfly'].contains(host_machine.system())
166endif
167
168# Among others FreeBSD does not have a separate dl library.
169if not cc.has_function('dlsym')
170  dep_dl = cc.find_library('dl', required : with_nouveau)
171else
172  dep_dl = []
173endif
174# clock_gettime might require -rt, or it might not. find out
175if not cc.has_function('clock_gettime', prefix : '#define _GNU_SOURCE\n#include <time.h>')
176  # XXX: untested
177  dep_rt = cc.find_library('rt')
178else
179  dep_rt = []
180endif
181dep_m = cc.find_library('m', required : false)
182# From Niclas Zeising:
183# FreeBSD requires sys/types.h for sys/sysctl.h, add it as part of the
184# includes when checking for headers.
185foreach header : ['sys/sysctl.h', 'sys/select.h', 'alloca.h']
186  config.set('HAVE_' + header.underscorify().to_upper(),
187    cc.compiles('#include <sys/types.h>\n#include <@0@>'.format(header), name : '@0@ works'.format(header)))
188endforeach
189if (cc.has_header_symbol('sys/sysmacros.h', 'major') and
190  cc.has_header_symbol('sys/sysmacros.h', 'minor') and
191  cc.has_header_symbol('sys/sysmacros.h', 'makedev'))
192  config.set10('MAJOR_IN_SYSMACROS', true)
193endif
194if (cc.has_header_symbol('sys/mkdev.h', 'major') and
195  cc.has_header_symbol('sys/mkdev.h', 'minor') and
196  cc.has_header_symbol('sys/mkdev.h', 'makedev'))
197  config.set10('MAJOR_IN_MKDEV', true)
198endif
199config.set10('HAVE_OPEN_MEMSTREAM', cc.has_function('open_memstream'))
200
201warn_c_args = []
202foreach a : ['-Wall', '-Wextra', '-Wsign-compare', '-Werror=undef',
203             '-Werror=implicit-function-declaration', '-Wpointer-arith',
204             '-Wwrite-strings', '-Wstrict-prototypes', '-Wmissing-prototypes',
205             '-Wmissing-declarations', '-Wnested-externs', '-Wpacked',
206             '-Wswitch-enum', '-Wmissing-format-attribute',
207             '-Wstrict-aliasing=2', '-Winit-self', '-Winline', '-Wshadow',
208             '-Wdeclaration-after-statement', '-Wold-style-definition']
209  if cc.has_argument(a)
210    warn_c_args += a
211  endif
212endforeach
213# GCC will never error for -Wno-*, so check for -W* then add -Wno-* to the list
214# of options
215foreach a : ['unused-parameter', 'attributes', 'long-long',
216             'missing-field-initializers']
217  if cc.has_argument('-W@0@'.format(a))
218    warn_c_args += '-Wno-@0@'.format(a)
219  endif
220endforeach
221
222# all c args:
223libdrm_c_args = warn_c_args + ['-fvisibility=hidden']
224
225
226dep_pciaccess = dependency('pciaccess', version : '>= 0.10', required : with_intel)
227dep_cunit = dependency('cunit', version : '>= 2.1', required : false)
228_cairo_tests = get_option('cairo-tests')
229if _cairo_tests != 'false'
230  dep_cairo = dependency('cairo', required : _cairo_tests == 'true')
231  with_cairo_tests = dep_cairo.found()
232else
233  dep_cairo = []
234  with_cairo_tests = false
235endif
236_valgrind = get_option('valgrind')
237if _valgrind != 'false'
238  dep_valgrind = dependency('valgrind', required : _valgrind == 'true')
239  with_valgrind = dep_valgrind.found()
240else
241  dep_valgrind = []
242  with_valgrind = false
243endif
244
245with_man_pages = get_option('man-pages')
246prog_xslt = find_program('xsltproc', required : with_man_pages == 'true')
247prog_sed = find_program('sed', required : with_man_pages == 'true')
248manpage_style = 'http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl'
249if prog_xslt.found()
250  if run_command(prog_xslt, '--nonet', manpage_style).returncode() != 0
251    if with_man_pages == 'true'
252      error('Manpage style sheet cannot be found')
253    endif
254    with_man_pages = 'false'
255  endif
256endif
257with_man_pages = with_man_pages != 'false' and prog_xslt.found() and prog_sed.found()
258
259config.set10('HAVE_VISIBILITY',
260  cc.compiles('''int foo_hidden(void) __attribute__((visibility(("hidden"))));''',
261              name : 'compiler supports __attribute__(("hidden"))'))
262
263foreach t : [
264             [with_exynos, 'EXYNOS'],
265             [with_freedreno_kgsl, 'FREEDRENO_KGSL'],
266             [with_intel, 'INTEL'],
267             [with_nouveau, 'NOUVEAU'],
268             [with_radeon, 'RADEON'],
269             [with_vc4, 'VC4'],
270             [with_vmwgfx, 'VMWGFX'],
271             [with_cairo_tests, 'CAIRO'],
272             [with_valgrind, 'VALGRIND'],
273            ]
274  config.set10('HAVE_@0@'.format(t[1]), t[0])
275endforeach
276if with_freedreno_kgsl and not with_freedreno
277  error('cannot enable freedreno-kgsl without freedreno support')
278endif
279config.set10('_GNU_SOURCE', true)
280config_file = configure_file(
281  configuration : config,
282  output : 'config.h',
283)
284add_project_arguments('-include', 'config.h', language : 'c')
285
286inc_root = include_directories('.')
287inc_drm = include_directories('include/drm')
288
289libdrm = shared_library(
290  'drm',
291  [files(
292     'xf86drm.c', 'xf86drmHash.c', 'xf86drmRandom.c', 'xf86drmSL.c',
293     'xf86drmMode.c'
294   ),
295   config_file,
296  ],
297  c_args : libdrm_c_args,
298  dependencies : [dep_valgrind, dep_rt, dep_m],
299  include_directories : inc_drm,
300  version : '2.4.0',
301  install : true,
302)
303
304ext_libdrm = declare_dependency(
305  link_with : libdrm,
306  include_directories : [inc_root, inc_drm],
307)
308
309install_headers('libsync.h', 'xf86drm.h', 'xf86drmMode.h')
310install_headers(
311  'include/drm/drm.h', 'include/drm/drm_fourcc.h', 'include/drm/drm_mode.h',
312  'include/drm/drm_sarea.h', 'include/drm/i915_drm.h',
313  'include/drm/mach64_drm.h', 'include/drm/mga_drm.h',
314  'include/drm/msm_drm.h', 'include/drm/nouveau_drm.h',
315  'include/drm/qxl_drm.h', 'include/drm/r128_drm.h',
316  'include/drm/radeon_drm.h', 'include/drm/amdgpu_drm.h',
317  'include/drm/savage_drm.h', 'include/drm/sis_drm.h',
318  'include/drm/tegra_drm.h', 'include/drm/vc4_drm.h',
319  'include/drm/via_drm.h', 'include/drm/virtgpu_drm.h',
320  subdir : 'libdrm',
321)
322if with_vmwgfx
323  install_headers('include/drm/vmwgfx_drm.h', subdir : 'libdrm')
324endif
325
326pkg.generate(
327  name : 'libdrm',
328  libraries : libdrm,
329  subdirs : ['.', 'libdrm'],
330  version : meson.project_version(),
331  description : 'Userspace interface to kernel DRM services',
332)
333
334env_test = environment()
335env_test.set('NM', find_program('nm').path())
336
337if with_libkms
338  subdir('libkms')
339endif
340if with_intel
341  subdir('intel')
342endif
343if with_nouveau
344  subdir('nouveau')
345endif
346if with_radeon
347  subdir('radeon')
348endif
349if with_amdgpu
350  subdir('amdgpu')
351endif
352if with_omap
353  subdir('omap')
354endif
355if with_exynos
356  subdir('exynos')
357endif
358if with_freedreno
359  subdir('freedreno')
360endif
361if with_tegra
362  subdir('tegra')
363endif
364if with_vc4
365  subdir('vc4')
366endif
367if with_etnaviv
368  subdir('etnaviv')
369endif
370if with_man_pages
371  subdir('man')
372endif
373subdir('data')
374subdir('tests')
375
376message('')
377message('@0@ will be compiled with:'.format(meson.project_name()))
378message('')
379message('  libkms         @0@'.format(with_libkms))
380message('  Intel API      @0@'.format(with_intel))
381message('  vmwgfx API     @0@'.format(with_vmwgfx))
382message('  Radeon API     @0@'.format(with_radeon))
383message('  AMDGPU API     @0@'.format(with_amdgpu))
384message('  Nouveau API    @0@'.format(with_nouveau))
385message('  OMAP API       @0@'.format(with_omap))
386message('  EXYNOS API     @0@'.format(with_exynos))
387message('  Freedreno API  @0@ (kgsl: @1@)'.format(with_freedreno, with_freedreno_kgsl))
388message('  Tegra API      @0@'.format(with_tegra))
389message('  VC4 API        @0@'.format(with_vc4))
390message('  Etnaviv API    @0@'.format(with_etnaviv))
391message('')
392