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