1project('opus', 'c', 2 version: run_command('meson/get-version.py', '--package-version', check: true).stdout().strip(), 3 meson_version: '>=0.54.0', 4 default_options: ['warning_level=2', 5 'c_std=gnu99', 6 'buildtype=debugoptimized']) 7 8libversion = run_command('meson/get-version.py', '--libtool-version', check: true).stdout().strip() 9macosversion = run_command('meson/get-version.py', '--darwin-version', check: true).stdout().strip() 10 11cc = meson.get_compiler('c') 12host_system = host_machine.system() 13host_cpu_family = host_machine.cpu_family() 14top_srcdir = meson.current_source_dir() 15top_builddir = meson.current_build_dir() 16 17opus_includes = include_directories('.', 'include', 'celt', 'silk', 'dnn') 18opus_public_includes = include_directories('include') 19 20add_project_arguments('-DOPUS_BUILD', language: 'c') 21add_project_arguments('-DHAVE_CONFIG_H', language: 'c') 22 23if host_system == 'windows' 24 if cc.get_argument_syntax() == 'msvc' 25 add_project_arguments('-D_CRT_SECURE_NO_WARNINGS', language: 'c') 26 endif 27endif 28 29if cc.get_argument_syntax() == 'gnu' 30 add_project_arguments('-D_FORTIFY_SOURCE=2', language: 'c') 31endif 32 33# Check for extra compiler args 34additional_c_args = [] 35if cc.get_argument_syntax() != 'msvc' 36 additional_c_args += [ 37 '-fvisibility=hidden', 38 '-Wcast-align', 39 '-Wnested-externs', 40 '-Wshadow', 41 '-Wstrict-prototypes', 42 ] 43 44 # On Windows, -fstack-protector-strong adds a libssp-0.dll dependency and 45 # prevents static linking 46 if host_system != 'windows' 47 additional_c_args += ['-fstack-protector-strong'] 48 endif 49endif 50 51foreach arg : additional_c_args 52 if cc.has_argument(arg) 53 add_project_arguments(arg, language: 'c') 54 endif 55endforeach 56 57# Windows MSVC warnings 58if cc.get_id() == 'msvc' 59 # Ignore several spurious warnings. 60 # If a warning is completely useless and spammy, use '/wdXXXX' to suppress it 61 # If a warning is harmless but hard to fix, use '/woXXXX' so it's shown once 62 # NOTE: Only add warnings here if you are sure they're spurious 63 add_project_arguments('/wd4035', '/wd4715', '/wd4116', '/wd4046', '/wd4068', 64 '/wd4820', '/wd4244', '/wd4255', '/wd4668', 65 language : 'c') 66endif 67 68opus_version = meson.project_version() 69 70opus_conf = configuration_data() 71opus_conf.set('PACKAGE_BUGREPORT', '"[email protected]"') 72opus_conf.set('PACKAGE_NAME', '"opus"') 73opus_conf.set('PACKAGE_STRING', '"opus @0@"'.format(opus_version)) 74opus_conf.set('PACKAGE_TARNAME', '"opus"') 75opus_conf.set('PACKAGE_URL', '""') 76opus_conf.set('PACKAGE_VERSION', '"@0@"'.format(opus_version)) 77 78# FIXME: optional Ne10 dependency 79have_arm_ne10 = false 80 81libm = cc.find_library('m', required : false) 82 83opus_conf.set('HAVE_LRINTF', cc.has_function('lrintf', prefix: '#include <math.h>', dependencies: libm)) 84opus_conf.set('HAVE_LRINT', cc.has_function('lrint', prefix: '#include <math.h>', dependencies: libm)) 85opus_conf.set('HAVE___MALLOC_HOOK', cc.has_function('__malloc_hook', prefix: '#include <malloc.h>')) 86opus_conf.set('HAVE_STDINT_H', cc.check_header('stdint.h')) 87 88# Check for restrict keyword 89restrict_tmpl = ''' 90typedef int * int_ptr; 91int foo (int_ptr @0@ ip, int * @0@ baz[]) { 92 return ip[0]; 93} 94int main (int argc, char ** argv) { 95 int s[1]; 96 int * @0@ t = s; 97 t[0] = 0; 98 return foo(t, (void *)0); 99}''' 100# Define restrict to the equivalent of the C99 restrict keyword, or to 101# nothing if this is not supported. Do not define if restrict is 102# supported directly. 103if not cc.compiles(restrict_tmpl.format('restrict'), name : 'restrict keyword') 104 if cc.compiles(restrict_tmpl.format('__restrict'), name : '__restrict') 105 opus_conf.set('restrict', '__restrict') 106 elif cc.compiles(restrict_tmpl.format('__restrict__'), name : '__restrict__') 107 opus_conf.set('restrict', '__restrict') 108 elif cc.compiles(restrict_tmpl.format('_Restrict'), name : '_Restrict') 109 opus_conf.set('restrict', '_Restrict') 110 else 111 opus_conf.set('restrict', '/**/') 112 endif 113endif 114 115# Check for C99 variable-size arrays, or alloca() as fallback 116msg_use_alloca = false 117if cc.compiles('''static int x; 118 char some_func (void) { 119 char a[++x]; 120 a[sizeof a - 1] = 0; 121 int N; 122 return a[0]; 123 }''', name : 'C99 variable-size arrays') 124 opus_conf.set('VAR_ARRAYS', 1) 125 msg_use_alloca = 'NO (using C99 variable-size arrays instead)' 126elif cc.compiles('''#include <alloca.h> 127 void some_func (void) { 128 int foo=10; 129 int * array = alloca(foo); 130 }''', name : 'alloca (alloca.h)') 131 opus_conf.set('USE_ALLOCA', true) 132 opus_conf.set('HAVE_ALLOCA_H', true) 133 msg_use_alloca = true 134elif cc.compiles('''#include <malloc.h> 135 #include <stdlib.h> 136 void some_func (void) { 137 int foo=10; 138 int * array = alloca(foo); 139 }''', name : 'alloca (std)') 140 opus_conf.set('USE_ALLOCA', true) 141 msg_use_alloca = true 142endif 143 144opts = [ 145 [ 'fixed-point', 'FIXED_POINT' ], 146 [ 'fixed-point-debug', 'FIXED_DEBUG' ], 147 [ 'custom-modes', 'CUSTOM_MODES' ], 148 [ 'float-approx', 'FLOAT_APPROX' ], 149 [ 'enable-deep-plc', 'ENABLE_DEEP_PLC' ], 150 [ 'enable-dred', 'ENABLE_DRED' ], 151 [ 'enable-osce', 'ENABLE_OSCE' ], 152 [ 'assertions', 'ENABLE_ASSERTIONS' ], 153 [ 'hardening', 'ENABLE_HARDENING' ], 154 [ 'fuzzing', 'FUZZING' ], 155 [ 'check-asm', 'OPUS_CHECK_ASM' ], 156] 157 158foreach opt : opts 159 # we assume these are all boolean options 160 opt_foo = get_option(opt[0]) 161 if opt_foo 162 opus_conf.set(opt[1], 1) 163 endif 164 set_variable('opt_' + opt[0].underscorify(), opt_foo) 165endforeach 166 167opt_asm = get_option('asm') 168opt_rtcd = get_option('rtcd') 169opt_intrinsics = get_option('intrinsics') 170extra_programs = get_option('extra-programs') 171opt_tests = get_option('tests') 172 173disable_float_api = not get_option('float-api') 174if disable_float_api 175 opus_conf.set('DISABLE_FLOAT_API', 1) 176endif 177 178if not get_option('enable-dnn-debug-float') 179 opus_conf.set('DISABLE_DEBUG_FLOAT', 1) 180endif 181 182# This is for the description in the pkg-config .pc file 183if opt_fixed_point 184 pc_build = 'fixed-point' 185else 186 pc_build = 'floating-point' 187endif 188if opt_custom_modes 189 pc_build = pc_build + ', custom modes' 190endif 191 192rtcd_support = [] 193# With GCC, Clang, ICC, etc, we differentiate between 'may support this SIMD' 194# and 'presume we have this SIMD' by checking whether the SIMD / intrinsics can 195# be compiled by the compiler as-is (presume) or with SIMD cflags (may have). 196# With MSVC, the compiler will always build SIMD/intrinsics targeting all 197# specific instruction sets supported by that version of the compiler. No 198# special arguments are ever needed. If runtime CPU detection is not disabled, 199# we must always assume that we only 'may have' it. 200opus_can_presume_simd = true 201if cc.get_argument_syntax() == 'msvc' 202 if opt_rtcd.disabled() 203 warning('Building with an MSVC-like compiler and runtime CPU detection is disabled. Outputs may not run on all @0@ CPUs.'.format(host_cpu_family)) 204 else 205 opus_can_presume_simd = false 206 endif 207endif 208 209opus_arm_external_asm = false 210 211asm_tmpl = ''' 212int main (int argc, char ** argv) { 213 __asm__("@0@"); 214 return 0; 215}''' 216 217asm_optimization = [] 218inline_optimization = [] 219if not opt_asm.disabled() 220 # Currently we only have inline asm for fixed-point 221 if host_cpu_family == 'arm' and opt_fixed_point 222 opus_conf.set('OPUS_ARM_ASM', true) 223 224 # Check if compiler supports gcc-style inline assembly 225 if cc.compiles('''#ifdef __GNUC_MINOR__ 226 #if (__GNUC__ * 1000 + __GNUC_MINOR__) < 3004 227 #error GCC before 3.4 has critical bugs compiling inline assembly 228 #endif 229 #endif 230 __asm__ (""::)''', 231 name : 'compiler supports gcc-style inline assembly') 232 233 opus_conf.set('OPUS_ARM_INLINE_ASM', 1) 234 235 # AS_ASM_ARM_EDSP 236 if cc.compiles(asm_tmpl.format('qadd r3,r3,r3'), 237 name : 'assembler supports EDSP instructions on ARM') 238 opus_conf.set('OPUS_ARM_INLINE_EDSP', 1) 239 inline_optimization += ['ESDP'] 240 endif 241 242 # AS_ASM_ARM_MEDIA 243 if cc.compiles(asm_tmpl.format('shadd8 r3,r3,r3'), 244 name : 'assembler supports ARMv6 media instructions on ARM') 245 opus_conf.set('OPUS_ARM_INLINE_MEDIA', 1) 246 inline_optimization += ['Media'] 247 endif 248 249 # AS_ASM_ARM_NEON 250 if cc.compiles(asm_tmpl.format('vorr d0,d0,d0'), 251 name : 'assembler supports NEON instructions on ARM') 252 opus_conf.set('OPUS_ARM_INLINE_NEON', 1) 253 inline_optimization += ['NEON'] 254 endif 255 endif 256 257 # We need Perl to translate RVCT-syntax asm to gas syntax 258 perl = find_program('perl', required: get_option('asm')) 259 if perl.found() 260 opus_arm_external_asm = true 261 # opus_arm_presume_* mean we can and will use those instructions 262 # directly without doing runtime CPU detection. 263 # opus_arm_may_have_* mean we can emit those instructions, but we can 264 # only use them after runtime detection. 265 # The same rules apply for x86 assembly and intrinsics. 266 267 opus_arm_may_have_edsp = opus_conf.has('OPUS_ARM_INLINE_EDSP') 268 opus_arm_presume_edsp = opus_arm_may_have_edsp and opus_can_presume_simd 269 270 opus_arm_may_have_media = opus_conf.has('OPUS_ARM_INLINE_MEDIA') 271 opus_arm_presume_media = opus_arm_may_have_media and opus_can_presume_simd 272 273 opus_arm_may_have_neon = opus_conf.has('OPUS_ARM_INLINE_NEON') 274 opus_arm_presume_neon = opus_arm_may_have_neon and opus_can_presume_simd 275 276 if not opt_rtcd.disabled() 277 if not opus_arm_may_have_edsp 278 message('Trying to force-enable armv5e EDSP instructions...') 279 # AS_ASM_ARM_EDSP_FORCE 280 opus_arm_may_have_edsp = cc.compiles(asm_tmpl.format('.arch armv5te\n.object_arch armv4t\nqadd r3,r3,r3'), 281 name : 'Assembler supports EDSP instructions on ARM (forced)') 282 endif 283 if not opus_arm_may_have_media 284 message('Trying to force-enable ARMv6 media instructions...') 285 opus_arm_may_have_media = cc.compiles(asm_tmpl.format('.arch armv6\n.object_arch armv4t\nshadd8 r3,r3,r3'), 286 name : 'Assembler supports ARMv6 media instructions on ARM (forced)') 287 endif 288 if not opus_arm_may_have_neon 289 message('Trying to force-enable NEON instructions...') 290 opus_arm_may_have_neon = cc.compiles(asm_tmpl.format('.arch armv7-a\n.fpu neon\n.object_arch armv4t\nvorr d0,d0,d0'), 291 name : 'Assembler supports NEON instructions on ARM (forced)') 292 endif 293 endif 294 295 if opus_arm_may_have_edsp 296 opus_conf.set('OPUS_ARM_MAY_HAVE_EDSP', 1) 297 if opus_arm_presume_edsp 298 opus_conf.set('OPUS_ARM_PRESUME_EDSP', 1) 299 asm_optimization += ['EDSP'] 300 else 301 rtcd_support += ['EDSP'] 302 endif 303 endif 304 if opus_arm_may_have_media 305 opus_conf.set('OPUS_ARM_MAY_HAVE_MEDIA', 1) 306 if opus_arm_presume_media 307 opus_conf.set('OPUS_ARM_PRESUME_MEDIA', 1) 308 asm_optimization += ['Media'] 309 else 310 rtcd_support += ['Media'] 311 endif 312 endif 313 if opus_arm_may_have_neon 314 opus_conf.set('OPUS_ARM_MAY_HAVE_NEON', 1) 315 if opus_arm_presume_neon 316 opus_conf.set('OPUS_ARM_PRESUME_NEON', 1) 317 asm_optimization += ['NEON'] 318 else 319 rtcd_support += ['NEON'] 320 endif 321 endif 322 if opus_arm_may_have_dotprod 323 opus_conf.set('OPUS_ARM_MAY_HAVE_DOTPROD', 1) 324 if opus_arm_presume_dotprod 325 opus_conf.set('OPUS_ARM_PRESUME_DOTPROD', 1) 326 asm_optimization += ['DOTPROD'] 327 else 328 rtcd_support += ['DOTPROD'] 329 endif 330 endif 331 332 if cc.get_define('__APPLE__') != '' 333 arm2gnu_args = ['--apple'] 334 else 335 arm2gnu_args = [] 336 endif 337 endif # found perl 338 else # arm + enable fixed point 339 if opt_asm.enabled() 340 error('asm option is enabled, but no assembly support for ' + host_cpu_family) 341 endif 342 endif 343endif # enable asm 344 345# Check whether we require assembly and we support assembly on this arch, 346# but none were detected. Can happen because of incorrect compiler flags, such 347# as missing -mfloat-abi=softfp on ARM32 softfp architectures. 348if opt_asm.enabled() and (asm_optimization.length() + inline_optimization.length()) == 0 349 error('asm option was enabled, but no assembly support was detected') 350endif 351 352# XXX: NEON has hardfp vs softfp compiler configuration issues 353# When targeting ARM32 softfp, we sometimes need to explicitly pass 354# -mfloat-abi=softfp to enable NEON. F.ex., on Android. It should 355# be set in the cross file. 356arm_neon_intr_link_args = ['-mfpu=neon'] 357arm_dotprod_intr_link_args = ['-march=armv8.2-a+dotprod'] 358 359have_sse = false 360have_sse2 = false 361have_sse4_1 = false 362have_avx2 = false 363have_neon_intr = false 364have_dotprod_intr = false 365 366intrinsics_support = [] 367if not opt_intrinsics.disabled() 368 if host_cpu_family in ['arm', 'aarch64'] 369 # Check for ARMv7/AArch64 neon intrinsics 370 intrin_check = ''' 371 #include <arm_neon.h> 372 int main (void) { 373 static float32x4_t A0, A1, SUMM; 374 SUMM = vmlaq_f32(SUMM, A0, A1); 375 return (int)vgetq_lane_f32(SUMM, 0); 376 }''' 377 intrin_name = 'ARMv7/AArch64 NEON' 378 if cc.links(intrin_check, 379 name: 'compiler supports @0@ intrinsics'.format(intrin_name)) 380 opus_arm_presume_neon_intr = opus_can_presume_simd 381 opus_arm_may_have_neon_intr = true 382 else 383 opus_arm_presume_neon_intr = false 384 if cc.links(intrin_check, 385 args: arm_neon_intr_link_args, 386 name: 'compiler supports @0@ intrinsics with @1@'.format(intrin_name, ' '.join(arm_neon_intr_link_args))) 387 opus_arm_may_have_neon_intr = true 388 else 389 opus_arm_may_have_neon_intr = false 390 endif 391 endif 392 393 if opus_arm_may_have_neon_intr 394 have_neon_intr = true 395 intrinsics_support += [intrin_name] 396 opus_conf.set('OPUS_ARM_MAY_HAVE_NEON_INTR', 1) 397 if opus_arm_presume_neon_intr 398 opus_conf.set('OPUS_ARM_PRESUME_NEON_INTR', 1) 399 else 400 rtcd_support += [intrin_name] 401 opus_neon_intr_args = arm_neon_intr_link_args 402 endif 403 else 404 message('Compiler does not support @0@ intrinsics'.format(intrin_name)) 405 endif 406 407 # Check for aarch64 neon intrinsics 408 intrin_check = ''' 409 #include <arm_neon.h> 410 int main (void) { 411 static int32_t IN; 412 static int16_t OUT; 413 OUT = vqmovns_s32(IN); 414 }''' 415 intrin_name = 'AArch64 NEON' 416 if cc.links(intrin_check, 417 name: 'compiler supports @0@ intrinsics'.format(intrin_name)) 418 opus_arm_presume_aarch64_neon_intr = opus_can_presume_simd 419 opus_arm_may_have_aarch64_neon_intr = true 420 else 421 opus_arm_presume_aarch64_neon_intr = false 422 if cc.links(intrin_check, 423 args: arm_neon_intr_link_args, 424 name: 'compiler supports @0@ intrinsics with @1@'.format(intrin_name, ' '.join(arm_neon_intr_link_args))) 425 opus_arm_may_have_aarch64_neon_intr = true 426 else 427 opus_arm_may_have_aarch64_neon_intr = false 428 endif 429 endif 430 431 if opus_arm_may_have_aarch64_neon_intr 432 intrinsics_support += [intrin_name] 433 opus_conf.set('OPUS_X86_MAY_HAVE_AARCH64_NEON_INTR', 1) 434 if opus_arm_presume_aarch64_neon_intr 435 opus_conf.set('OPUS_X86_PRESUME_AARCH64_NEON_INTR', 1) 436 endif 437 else 438 message('Compiler does not support @0@ intrinsics'.format(intrin_name)) 439 endif 440 441 # Check for ARMv8.2 dotprod intrinsics 442 intrin_check = ''' 443 #include <arm_neon.h> 444 int main (void) { 445 static int8x16_t a, b; 446 static int32x4_t SUMM; 447 SUMM = vdotq_s32(SUMM, a, b); 448 return (int)vgetq_lane_s32(SUMM, 0); 449 }''' 450 intrin_name = 'AArch64 DOTPROD' 451 if cc.links(intrin_check, 452 name: 'compiler supports @0@ intrinsics'.format(intrin_name)) 453 opus_arm_presume_dotprod_intr = opus_can_presume_simd 454 opus_arm_may_have_dotprod_intr = true 455 else 456 opus_arm_presume_dotprod_intr = false 457 if cc.links(intrin_check, 458 args: arm_dotprod_intr_link_args, 459 name: 'compiler supports @0@ intrinsics with @1@'.format(intrin_name, ' '.join(arm_dotprod_intr_link_args))) 460 opus_arm_may_have_dotprod_intr = true 461 else 462 opus_arm_may_have_dotprod_intr = false 463 endif 464 endif 465 466 if opus_arm_may_have_dotprod_intr 467 have_dotprod_intr = true 468 intrinsics_support += [intrin_name] 469 opus_conf.set('OPUS_ARM_MAY_HAVE_DOTPROD', 1) 470 if opus_arm_presume_dotprod_intr 471 opus_conf.set('OPUS_ARM_PRESUME_DOTPROD', 1) 472 else 473 rtcd_support += [intrin_name] 474 opus_dotprod_intr_args = arm_dotprod_intr_link_args 475 endif 476 else 477 message('Compiler does not support @0@ intrinsics'.format(intrin_name)) 478 endif 479 480 elif host_cpu_family in ['x86', 'x86_64'] 481 # XXX: allow external override/specification of the flags 482 x86_intrinsics = [ 483 [ 'SSE', 'xmmintrin.h', '__m128', '_mm_setzero_ps()', ['-msse'] ], 484 [ 'SSE2', 'emmintrin.h', '__m128i', '_mm_setzero_si128()', ['-msse2'] ], 485 [ 'SSE4.1', 'smmintrin.h', '__m128i', '_mm_setzero_si128(); mtest = _mm_cmpeq_epi64(mtest, mtest)', ['-msse4.1'] ], 486 [ 'AVX2', 'immintrin.h', '__m256i', '_mm256_abs_epi32(_mm256_setzero_si256())', ['-mavx', '-mfma', '-mavx2'] ], 487 ] 488 489 foreach intrin : x86_intrinsics 490 intrin_check = '''#include <@0@> 491 int main (int argc, char ** argv) { 492 static @1@ mtest; 493 mtest = @2@; 494 return *((unsigned char *) &mtest) != 0; 495 }'''.format(intrin[1],intrin[2],intrin[3]) 496 intrin_name = intrin[0] 497 # Intrinsics arguments are not available with MSVC-like compilers 498 intrin_args = cc.get_argument_syntax() == 'msvc' ? [] : intrin[4] 499 if cc.links(intrin_check, name : 'compiler supports @0@ intrinsics'.format(intrin_name)) 500 may_have_intrin = true 501 presume_intrin = opus_can_presume_simd 502 elif intrin_args.length() > 0 503 presume_intrin = false 504 if cc.links(intrin_check, 505 args : intrin_args, 506 name : 'compiler supports @0@ intrinsics with @1@'.format(intrin_name, ' '.join(intrin_args))) 507 may_have_intrin = true 508 else 509 may_have_intrin = false 510 endif 511 endif 512 if may_have_intrin 513 intrinsics_support += [intrin_name] 514 intrin_lower_name = intrin_name.to_lower().underscorify() 515 set_variable('have_' + intrin_lower_name, true) 516 opus_conf.set('OPUS_X86_MAY_HAVE_' + intrin_name.underscorify(), 1) 517 if presume_intrin 518 opus_conf.set('OPUS_X86_PRESUME_' + intrin_name.underscorify(), 1) 519 else 520 rtcd_support += [intrin_name] 521 set_variable('opus_@0@_args'.format(intrin_lower_name), intrin_args) 522 endif 523 else 524 message('Compiler does not support @0@ intrinsics'.format(intrin_name)) 525 endif 526 endforeach 527 528 if not opt_rtcd.disabled() 529 get_cpuid_by_asm = false 530 cpuid_asm_code = ''' 531 #include <stdio.h> 532 int main (int argc, char ** argv) { 533 unsigned int CPUInfo0; 534 unsigned int CPUInfo1; 535 unsigned int CPUInfo2; 536 unsigned int CPUInfo3; 537 unsigned int InfoType; 538 #if defined(__i386__) && defined(__PIC__) 539 __asm__ __volatile__ ( 540 "xchg %%ebx, %1\n" 541 "cpuid\n" 542 "xchg %%ebx, %1\n": 543 "=a" (CPUInfo0), 544 "=r" (CPUInfo1), 545 "=c" (CPUInfo2), 546 "=d" (CPUInfo3) : 547 "a" (InfoType), "c" (0) 548 ); 549 #else 550 __asm__ __volatile__ ( 551 "cpuid": 552 "=a" (CPUInfo0), 553 "=b" (CPUInfo1), 554 "=c" (CPUInfo2), 555 "=d" (CPUInfo3) : 556 "a" (InfoType), "c" (0) 557 ); 558 #endif 559 return 0; 560 }''' 561 cpuid_c_code = ''' 562 #include <cpuid.h> 563 int main (int argc, char ** argv) { 564 unsigned int CPUInfo0; 565 unsigned int CPUInfo1; 566 unsigned int CPUInfo2; 567 unsigned int CPUInfo3; 568 unsigned int InfoType; 569 __get_cpuid(InfoType, &CPUInfo0, &CPUInfo1, &CPUInfo2, &CPUInfo3); 570 return 0; 571 }''' 572 cpuid_msvc_code = ''' 573 #include <intrin.h> 574 int main (void) { 575 int CPUInfo, InfoType; 576 __cpuid(&CPUInfo, InfoType); 577 }''' 578 if cc.links(cpuid_asm_code, name : 'Get X86 CPU info via inline assembly') 579 opus_conf.set('CPU_INFO_BY_ASM', 1) 580 elif cc.links(cpuid_c_code, name : 'Get X86 CPU info via C method') 581 opus_conf.set('CPU_INFO_BY_C', 1) 582 elif cc.get_define('_MSC_VER') != '' and cc.links(cpuid_msvc_code) 583 message('Getting X86 CPU info via __cpuid') 584 else 585 if opt_intrinsics.enabled() and opt_rtcd.enabled() 586 error('intrinsics and rtcd options are enabled, but no Get CPU Info method detected') 587 endif 588 warning('Get CPU Info method not detected, no rtcd for intrinsics') 589 endif 590 endif # opt_rtcd 591 else 592 if opt_intrinsics.enabled() 593 error('intrinsics option enabled, but no intrinsics support for ' + host_cpu_family) 594 endif 595 warning('No intrinsics support for ' + host_cpu_family) 596 endif 597endif 598 599# Check whether we require intrinsics and we support intrinsics on this arch, 600# but none were detected. Can happen because of incorrect compiler flags, such 601# as missing -mfloat-abi=softfp on ARM32 softfp architectures. 602if opt_intrinsics.enabled() and intrinsics_support.length() == 0 603 error('intrinsics option was enabled, but none were detected') 604endif 605 606if opt_rtcd.disabled() 607 rtcd_support = 'disabled' 608else 609 if rtcd_support.length() > 0 610 opus_conf.set('OPUS_HAVE_RTCD', 1) 611 else 612 if intrinsics_support.length() == 0 613 rtcd_support = 'none' 614 if opt_rtcd.enabled() 615 error('rtcd option is enabled, but no support for intrinsics or assembly is available') 616 endif 617 else 618 rtcd_support = 'not needed' 619 endif 620 endif 621endif 622 623# extract source file lists from .mk files 624mk_files = [ 625 'opus_headers.mk', 'opus_sources.mk', 626 'silk_headers.mk', 'silk_sources.mk', 627 'celt_sources.mk', 'celt_headers.mk', 628 'lpcnet_headers.mk', 'lpcnet_sources.mk', 629] 630lines = run_command('meson/read-sources-list.py', mk_files, check: true).stdout().strip().split('\n') 631sources = {} 632foreach l : lines 633 a = l.split(' = ') 634 var_name = a[0] 635 file_list = a[1].split() 636 sources += {var_name: files(file_list)} 637endforeach 638 639subdir('include') 640subdir('celt') 641subdir('silk') 642subdir('dnn') 643subdir('src') 644 645configure_file(output: 'config.h', configuration: opus_conf) 646 647if not opt_tests.disabled() 648 subdir('celt/tests') 649 subdir('silk/tests') 650 subdir('tests') 651endif 652 653# pkg-config files (not using pkg module so we can use the existing .pc.in file) 654pkgconf = configuration_data() 655 656pkgconf.set('prefix', join_paths(get_option('prefix'))) 657pkgconf.set('exec_prefix', '${prefix}') 658pkgconf.set('libdir', '${prefix}/@0@'.format(get_option('libdir'))) 659pkgconf.set('includedir', '${prefix}/@0@'.format(get_option('includedir'))) 660pkgconf.set('VERSION', opus_version) 661pkgconf.set('PC_BUILD', pc_build) 662pkgconf.set('LIBM', libm.found() ? '-lm' : '') 663 664pkg_install_dir = '@0@/pkgconfig'.format(get_option('libdir')) 665 666configure_file(input : 'opus.pc.in', 667 output : 'opus.pc', 668 configuration : pkgconf, 669 install_dir : pkg_install_dir) 670 671# The uninstalled one has hardcoded libtool + static lib stuff, skip it for now 672#configure_file(input : 'opus-uninstalled.pc.in', 673# output : 'opus-uninstalled.pc', 674# configuration : pkgconf, 675# install : false) 676 677doxygen = find_program('doxygen', required: get_option('docs')) 678if doxygen.found() 679 subdir('doc') 680endif 681 682summary( 683 { 684 'C99 var arrays': opus_conf.has('VAR_ARRAYS'), 685 'C99 lrintf': opus_conf.has('HAVE_LRINTF'), 686 'Use alloca': msg_use_alloca, 687 }, 688 section: 'Compiler support', 689 bool_yn: true, 690 list_sep: ', ', 691) 692 693# Parse optimization status 694foreach status : [['inline_optimization', opt_asm], 695 ['asm_optimization', opt_asm], 696 ['intrinsics_support', opt_intrinsics]] 697 res = status[0] 698 opt = status[1] 699 resval = get_variable(res) 700 if opt.disabled() 701 set_variable(res, 'disabled') 702 elif resval.length() == 0 703 if host_cpu_family not in ['arm', 'aarch64', 'x86', 'x86_64'] 704 set_variable(res, 'No optimizations for your platform, please send patches') 705 else 706 set_variable(res, 'none') 707 endif 708 endif 709endforeach 710 711summary( 712 { 713 'Floating point support': not opt_fixed_point, 714 'Fast float approximations': opt_float_approx, 715 'Fixed point debugging': opt_fixed_point_debug, 716 'Inline assembly optimizations': inline_optimization, 717 'External assembly optimizations': asm_optimization, 718 'Intrinsics optimizations': intrinsics_support, 719 'Run-time CPU detection': rtcd_support, 720 }, 721 section: 'Optimizations', 722 bool_yn: true, 723 list_sep: ', ', 724) 725summary( 726 { 727 'Custom modes': opt_custom_modes, 728 'Assertions': opt_assertions, 729 'Hardening': opt_hardening, 730 'Fuzzing': opt_fuzzing, 731 'Check ASM': opt_check_asm, 732 'API documentation': doxygen.found(), 733 'Extra programs': not extra_programs.disabled(), 734 'Tests': not opt_tests.disabled(), 735 }, 736 section: 'General configuration', 737 bool_yn: true, 738 list_sep: ', ', 739) 740