meson.build revision f8cc1056
1# Copyright © 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  'pixman',
23  ['c'],
24  version : '0.38.4',
25  license : 'MIT',
26  meson_version : '>= 0.47.2',
27  default_options : ['buildtype=debugoptimized'],
28)
29
30config = configuration_data()
31cc = meson.get_compiler('c')
32null_dep = dependency('', required : false)
33
34add_project_arguments(
35  cc.get_supported_arguments([
36    '-Wdeclaration-after-statement',
37    '-fno-strict-aliasing',
38    '-fvisibility=hidden',
39  ]),
40  language : ['c']
41)
42
43# GCC and Clang both ignore -Wno options that they don't recognize, so test for
44# -W<opt>, then add -Wno-<opt> if it's ignored
45foreach opt : ['unused-local-typedefs']
46  if cc.has_argument('-W' + opt)
47    add_project_arguments(['-Wno-' + opt], language : ['c'])
48  endif
49endforeach
50
51use_loongson_mmi = get_option('loongson-mmi')
52have_loongson_mmi = false
53loongson_mmi_flags = ['-march=loongson2f']
54if not use_loongson_mmi.disabled()
55  if host_machine.cpu_family() == 'mips64' and cc.compiles('''
56      #ifndef __mips_loongson_vector_rev
57      #error "Loongson Multimedia Instructions are only available on Loongson"
58      #endif
59      #if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 4))
60      #error "Need GCC >= 4.4 for Loongson MMI compilation"
61      #endif
62      #include "pixman/loongson-mmintrin.h"
63      int main () {
64        union {
65          __m64 v;
66          char c[8];
67        } a = { .c = {1, 2, 3, 4, 5, 6, 7, 8} };
68        int b = 4;
69        __m64 c = _mm_srli_pi16 (a.v, b);
70        return 0;
71      }''',
72      args : loongson_mmi_flags,
73      include_directories : include_directories('.'),
74      name : 'Loongson MMI Intrinsic Support')
75    have_loongson_mmi = true
76  endif
77endif
78
79if have_loongson_mmi
80  config.set10('USE_LOONGSON_MMI', true)
81elif use_loongson_mmi.enabled()
82  error('Loongson MMI Support unavailable, but required')
83endif
84
85use_mmx = get_option('mmx')
86have_mmx = false
87mmx_flags = ['-mmmx', '-Winline']
88if not use_mmx.disabled()
89  if host_machine.cpu_family() == 'x86_64'
90    have_mmx = true
91  elif host_machine.cpu_family() == 'x86' and cc.compiles('''
92      #include <mmintrin.h>
93      #include <stdint.h>
94
95      /* Check support for block expressions */
96      #define _mm_shuffle_pi16(A, N)                    \
97        ({                                              \
98        __m64 ret;                                      \
99                                                        \
100        /* Some versions of clang will choke on K */    \
101        asm ("pshufw %2, %1, %0\n\t"                    \
102             : "=y" (ret)                               \
103             : "y" (A), "K" ((const int8_t)N)           \
104        );                                              \
105                                                        \
106        ret;                                            \
107        })
108
109      int main () {
110          __m64 v = _mm_cvtsi32_si64 (1);
111          __m64 w;
112
113          w = _mm_shuffle_pi16(v, 5);
114
115          /* Some versions of clang will choke on this */
116          asm ("pmulhuw %1, %0\n\t"
117               : "+y" (w)
118               : "y" (v)
119          );
120
121          return _mm_cvtsi64_si32 (v);
122      }''',
123      args : mmx_flags,
124      name : 'MMX Intrinsic Support')
125    have_mmx = true
126  endif
127endif
128
129if have_mmx
130  config.set10('USE_X86_MMX', true)
131elif use_mmx.enabled()
132  error('MMX Support unavailable, but required')
133endif
134
135use_sse2 = get_option('sse2')
136have_sse2 = false
137sse2_flags = ['-msse2', '-Winline']
138if not use_sse2.disabled()
139  if host_machine.cpu_family() == 'x86'
140    if cc.compiles('''
141        #if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 2))
142        #   if !defined(__amd64__) && !defined(__x86_64__)
143        #      error "Need GCC >= 4.2 for SSE2 intrinsics on x86"
144        #   endif
145        #endif
146        #include <mmintrin.h>
147        #include <xmmintrin.h>
148        #include <emmintrin.h>
149        int param;
150        int main () {
151          __m128i a = _mm_set1_epi32 (param), b = _mm_set1_epi32 (param + 1), c;
152          c = _mm_xor_si128 (a, b);
153          return _mm_cvtsi128_si32(c);
154        }''',
155        args : sse2_flags,
156        name : 'SSE2 Intrinsic Support')
157      have_sse2 = true
158    endif
159  elif host_machine.cpu_family() == 'x86_64'
160    have_sse2 = true
161  endif
162endif
163
164if have_sse2
165  config.set10('USE_SSE2', true)
166elif use_sse2.enabled()
167  error('sse2 Support unavailable, but required')
168endif
169
170use_ssse3 = get_option('ssse3')
171have_ssse3 = false
172ssse3_flags =['-mssse3', '-Winline']
173if not use_ssse3.disabled()
174  if host_machine.cpu_family().startswith('x86')
175    if cc.compiles('''
176        #include <mmintrin.h>
177        #include <xmmintrin.h>
178        #include <emmintrin.h>
179        int param;
180        int main () {
181          __m128i a = _mm_set1_epi32 (param), b = _mm_set1_epi32 (param + 1), c;
182          c = _mm_xor_si128 (a, b);
183          return _mm_cvtsi128_si32(c);
184        }''',
185        args : ssse3_flags,
186        name : 'SSSE3 Intrinsic Support')
187      have_ssse3 = true
188    endif
189  endif
190endif
191
192if have_ssse3
193  config.set10('USE_SSSE3', true)
194elif use_ssse3.enabled()
195  error('ssse3 Support unavailable, but required')
196endif
197
198use_vmx = get_option('vmx')
199have_vmx = false
200vmx_flags = ['-maltivec', '-mabi=altivec']
201if not use_vmx.disabled()
202  if host_machine.cpu_family().startswith('ppc')
203    if cc.compiles('''
204        #include <altivec.h>
205        int main () {
206            vector unsigned int v = vec_splat_u32 (1);
207            v = vec_sub (v, v);
208            return 0;
209        }''',
210        args : vmx_flags,
211        name : 'VMX/Altivec Intrinsic Support')
212      have_vmx = true
213    endif
214  endif
215endif
216
217if have_vmx
218  config.set10('USE_VMX', true)
219elif use_vmx.enabled()
220  error('vmx Support unavailable, but required')
221endif
222
223use_armv6_simd = get_option('arm-simd')
224have_armv6_simd = false
225if not use_armv6_simd.disabled()
226  if host_machine.cpu_family() == 'arm'
227    if cc.compiles(files('arm-simd-test.S'), name : 'ARMv6 SIMD Intrinsic Support')
228      have_armv6_simd = true
229    endif
230  endif
231endif
232
233if have_armv6_simd
234  config.set10('USE_ARM_SIMD', true)
235elif use_armv6_simd.enabled()
236  error('ARMv6 SIMD Support unavailable, but required')
237endif
238
239use_neon = get_option('neon')
240have_neon = false
241if not use_neon.disabled()
242  if host_machine.cpu_family() == 'arm'
243    if cc.compiles(files('neon-test.S'), name : 'NEON Intrinsic Support')
244      have_neon = true
245    endif
246  endif
247endif
248
249if have_neon
250  config.set10('USE_ARM_NEON', true)
251elif use_neon.enabled()
252  error('NEON Support unavailable, but required')
253endif
254
255use_iwmmxt = get_option('iwmmxt')
256have_iwmmxt = false
257iwmmxt_flags = ['-flax-vector-conversions', '-Winline']
258if not use_iwmmxt.disabled()
259  if get_option('iwmmxt2')
260    iwmmxt_flags += '-march=iwmmxt2'
261  else
262    iwmmxt_flags += '-march=iwmmxt'
263  endif
264
265  if host_machine.cpu_family() == 'arm'
266    if cc.compiles('''
267        #ifndef __IWMMXT__
268        #error "IWMMXT not enabled (with -march=iwmmxt)"
269        #endif
270        #if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8))
271        #error "Need GCC >= 4.8 for IWMMXT intrinsics"
272        #endif
273        #include <mmintrin.h>
274        int main () {
275          union {
276            __m64 v;
277            char c[8];
278          } a = { .c = {1, 2, 3, 4, 5, 6, 7, 8} };
279          int b = 4;
280          __m64 c = _mm_srli_si64 (a.v, b);
281        }
282        ''',
283        args : iwmmxt_flags,
284        name : 'IWMMXT Intrinsic Support')
285      have_iwmmxt = true
286    endif
287  endif
288endif
289
290if have_iwmmxt
291  config.set10('USE_ARM_IWMMXT', true)
292elif use_iwmmxt.enabled()
293  error('IWMMXT Support unavailable, but required')
294endif
295
296use_mips_dspr2 = get_option('mips-dspr2')
297have_mips_dspr2 = false
298mips_dspr2_flags = ['-mdspr2']
299if not use_mips_dspr2.disabled()
300  if host_machine.cpu_family() == 'mips32'
301    if cc.compiles('''
302        #if !(defined(__mips__) &&  __mips_isa_rev >= 2)
303        #error MIPS DSPr2 is currently only available on MIPS32r2 platforms.
304        #endif
305        int
306        main ()
307        {
308            int c = 0, a = 0, b = 0;
309            __asm__ __volatile__ (
310                "precr.qb.ph %[c], %[a], %[b]          \n\t"
311                : [c] "=r" (c)
312                : [a] "r" (a), [b] "r" (b)
313            );
314            return c;
315        }''',
316        args : mipds_dspr2_flags,
317        name : 'DSPr2 Intrinsic Support')
318      have_mips_dspr2 = true
319    endif
320  endif
321endif
322
323if have_mips_dspr2
324  config.set10('USE_MIPS_DSPR2', true)
325elif use_mips_dspr2.enabled()
326  error('MIPS DSPr2 Support unavailable, but required')
327endif
328
329use_gnu_asm = get_option('gnu-inline-asm')
330if not use_gnu_asm.disabled()
331  if cc.compiles('''
332      int main () {
333        /* Most modern architectures have a NOP instruction, so this is a fairly generic test. */
334        asm volatile ( "\tnop\n" : : : "cc", "memory" );
335        return 0;
336      }
337      ''',
338      name : 'GNU Inline ASM support.')
339    config.set10('USE_GCC_INLINE_ASM', true)
340  elif use_gnu_asm.enabled()
341    error('GNU inline assembly support missing but required.')
342  endif
343endif
344
345if get_option('timers')
346  config.set('PIXMAN_TIMERS', 1)
347endif
348if get_option('gnuplot')
349  config.set('PIXMAN_GNUPLOT', 1)
350endif
351
352dep_openmp = dependency('openmp', required : get_option('openmp'))
353if dep_openmp.found()
354  config.set10('USE_OPENMP', true)
355elif meson.version().version_compare('<0.51.0')
356# In versions of meson before 0.51 the openmp dependency can still
357# inject arguments in the the auto case when it is not found, the
358# detection does work correctly in that case however, so we just
359# replace dep_openmp with null_dep to work around this.
360  dep_openmp = null_dep
361endif
362
363dep_gtk = dependency('gtk+-2.0', version : '>= 2.16', required : get_option('gtk'))
364dep_glib = dependency('glib-2.0', required : get_option('gtk'))
365dep_pixman = dependency('pixman-1', required : get_option('gtk'),
366                        version : '>= ' + meson.project_version())
367dep_png = dependency('libpng', required : get_option('libpng'))
368if dep_png.found()
369  config.set('HAVE_LIBPNG', 1)
370endif
371dep_m = cc.find_library('m', required : false)
372dep_threads = dependency('threads')
373if dep_threads.found()
374  config.set('HAVE_PTHREADS', 1)
375endif
376
377funcs = ['sigaction', 'alarm', 'mprotect', 'getpagesize', 'mmap']
378# mingw claimes to have posix_memalign, but it doesn't
379if host_machine.system() != 'windows'
380  funcs += 'posix_memalign'
381endif
382
383foreach f : funcs
384  if cc.has_function(f)
385    config.set('HAVE_@0@'.format(f.to_upper()), 1)
386  endif
387endforeach
388
389if cc.has_function('gettimeofday')
390  config.set('HAVE_GETTIMEOFDAY', 1)
391endif
392
393# This is only used in one test, that defines _GNU_SOURCE
394if cc.has_function('feenableexcept',
395                   prefix : '#define _GNU_SOURCE\n#include <fenv.h>',
396                   dependencies : dep_m)
397  config.set('HAVE_FEENABLEEXCEPT', 1)
398endif
399
400if cc.has_header_symbol('fenv.h', 'FE_DIVBYZERO')
401  config.set('HAVE_FEDIVBYZERO', 1)
402endif
403
404foreach h : ['sys/mman.h', 'fenv.h', 'unistd.h']
405  if cc.check_header(h)
406    config.set('HAVE_@0@'.format(h.underscorify().to_upper()), 1)
407  endif
408endforeach
409
410if (host_machine.system() == 'windows' and
411    cc.compiles('int __declspec(thread) foo;', name : 'TLS via __declspec(thread)'))
412  config.set('TLS', '__declspec(thread)')
413elif cc.compiles('int __thread foo;', name : 'TLS via __thread')
414  config.set('TLS', '__thread')
415endif
416
417if cc.links('''
418    static int x = 1;
419    static void __attribute__((constructor)) constructor_function () { x = 0; }
420    int main (void) { return x; }
421    ''',
422    name : '__attribute__((constructor))')
423  config.set('TOOLCHAIN_SUPPORTS_ATTRIBUTE_CONSTRUCTOR', 1)
424endif
425
426if cc.links(
427    ' __float128 a = 1.0Q, b = 2.0Q; int main (void) { return a + b; }',
428    name : 'Has float128 support')
429  config.set('HAVE_FLOAT128', 1)
430endif
431
432if cc.has_function('clz')
433  config.set('HAVE_BUILTIN_CLZ', 1)
434endif
435
436if cc.links('''
437    unsigned int __attribute__ ((vector_size(16))) e, a, b;
438    int main (void) { e = a - ((b << 27) + (b >> (32 - 27))) + 1; return e[0]; }
439    ''',
440    name : 'Support for GCC vector extensions')
441  config.set('HAVE_GCC_VECTOR_EXTENSIONS', 1)
442endif
443
444if host_machine.endian() == 'big'
445  config.set('WORDS_BIGENDIAN', 1)
446endif
447
448# Required to make pixman-private.h
449config.set('PACKAGE', 'foo')
450
451version_conf = configuration_data()
452split = meson.project_version().split('.')
453version_conf.set('PIXMAN_VERSION_MAJOR', split[0])
454version_conf.set('PIXMAN_VERSION_MINOR', split[1])
455version_conf.set('PIXMAN_VERSION_MICRO', split[2])
456
457add_project_arguments('-DHAVE_CONFIG_H', language : ['c'])
458
459subdir('pixman')
460subdir('test')
461subdir('demos')
462
463pkg = import('pkgconfig')
464pkg.generate(
465  name : 'Pixman',
466  filebase : 'pixman-1',
467  description : 'The pixman library (version 1)',
468  libraries : libpixman,
469  subdirs: 'pixman-1',
470  version : meson.project_version(),
471)
472