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