• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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')
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', '"opus@xiph.org"')
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  [ 'assertions', 'ENABLE_ASSERTIONS' ],
150  [ 'hardening', 'ENABLE_HARDENING' ],
151  [ 'fuzzing', 'FUZZING' ],
152  [ 'check-asm', 'OPUS_CHECK_ASM' ],
153]
154
155foreach opt : opts
156  # we assume these are all boolean options
157  opt_foo = get_option(opt[0])
158  if opt_foo
159    opus_conf.set(opt[1], 1)
160  endif
161  set_variable('opt_' + opt[0].underscorify(), opt_foo)
162endforeach
163
164opt_asm = get_option('asm')
165opt_rtcd = get_option('rtcd')
166opt_intrinsics = get_option('intrinsics')
167extra_programs = get_option('extra-programs')
168opt_tests = get_option('tests')
169
170disable_float_api = not get_option('float-api')
171if disable_float_api
172  opus_conf.set('DISABLE_FLOAT_API', 1)
173endif
174
175# This is for the description in the pkg-config .pc file
176if opt_fixed_point
177  pc_build = 'fixed-point'
178else
179  pc_build = 'floating-point'
180endif
181if opt_custom_modes
182  pc_build = pc_build + ', custom modes'
183endif
184
185rtcd_support = []
186# With GCC, Clang, ICC, etc, we differentiate between 'may support this SIMD'
187# and 'presume we have this SIMD' by checking whether the SIMD / intrinsics can
188# be compiled by the compiler as-is (presume) or with SIMD cflags (may have).
189# With MSVC, the compiler will always build SIMD/intrinsics targeting all
190# specific instruction sets supported by that version of the compiler. No
191# special arguments are ever needed. If runtime CPU detection is not disabled,
192# we must always assume that we only 'may have' it.
193opus_can_presume_simd = true
194if cc.get_argument_syntax() == 'msvc'
195  if opt_rtcd.disabled()
196    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))
197  else
198    opus_can_presume_simd = false
199  endif
200endif
201
202opus_arm_external_asm = false
203
204asm_tmpl = '''
205int main (int argc, char ** argv) {
206  __asm__("@0@");
207  return 0;
208}'''
209
210asm_optimization = []
211inline_optimization = []
212if not opt_asm.disabled()
213  # Currently we only have inline asm for fixed-point
214  if host_cpu_family == 'arm' and opt_fixed_point
215    opus_conf.set('OPUS_ARM_ASM', true)
216
217    # Check if compiler supports gcc-style inline assembly
218    if cc.compiles('''#ifdef __GNUC_MINOR__
219                      #if (__GNUC__ * 1000 + __GNUC_MINOR__) < 3004
220                      #error GCC before 3.4 has critical bugs compiling inline assembly
221                      #endif
222                      #endif
223                      __asm__ (""::)''',
224                   name : 'compiler supports gcc-style inline assembly')
225
226      opus_conf.set('OPUS_ARM_INLINE_ASM', 1)
227
228      # AS_ASM_ARM_EDSP
229      if cc.compiles(asm_tmpl.format('qadd r3,r3,r3'),
230                     name : 'assembler supports EDSP instructions on ARM')
231        opus_conf.set('OPUS_ARM_INLINE_EDSP', 1)
232        inline_optimization += ['ESDP']
233      endif
234
235      # AS_ASM_ARM_MEDIA
236      if cc.compiles(asm_tmpl.format('shadd8 r3,r3,r3'),
237                     name : 'assembler supports ARMv6 media instructions on ARM')
238        opus_conf.set('OPUS_ARM_INLINE_MEDIA', 1)
239        inline_optimization += ['Media']
240      endif
241
242      # AS_ASM_ARM_NEON
243      if cc.compiles(asm_tmpl.format('vorr d0,d0,d0'),
244                     name : 'assembler supports NEON instructions on ARM')
245        opus_conf.set('OPUS_ARM_INLINE_NEON', 1)
246        inline_optimization += ['NEON']
247      endif
248    endif
249
250    # We need Perl to translate RVCT-syntax asm to gas syntax
251    perl = find_program('perl', required: get_option('asm'))
252    if perl.found()
253      opus_arm_external_asm = true
254      # opus_arm_presume_* mean we can and will use those instructions
255      # directly without doing runtime CPU detection.
256      # opus_arm_may_have_* mean we can emit those instructions, but we can
257      # only use them after runtime detection.
258      # The same rules apply for x86 assembly and intrinsics.
259
260      opus_arm_may_have_edsp = opus_conf.has('OPUS_ARM_INLINE_EDSP')
261      opus_arm_presume_edsp = opus_arm_may_have_edsp and opus_can_presume_simd
262
263      opus_arm_may_have_media = opus_conf.has('OPUS_ARM_INLINE_MEDIA')
264      opus_arm_presume_media = opus_arm_may_have_media and opus_can_presume_simd
265
266      opus_arm_may_have_neon = opus_conf.has('OPUS_ARM_INLINE_NEON')
267      opus_arm_presume_neon = opus_arm_may_have_neon and opus_can_presume_simd
268
269      if not opt_rtcd.disabled()
270        if not opus_arm_may_have_edsp
271          message('Trying to force-enable armv5e EDSP instructions...')
272          # AS_ASM_ARM_EDSP_FORCE
273          opus_arm_may_have_edsp = cc.compiles(asm_tmpl.format('.arch armv5te\n.object_arch armv4t\nqadd r3,r3,r3'),
274                                               name : 'Assembler supports EDSP instructions on ARM (forced)')
275        endif
276        if not opus_arm_may_have_media
277          message('Trying to force-enable ARMv6 media instructions...')
278          opus_arm_may_have_media = cc.compiles(asm_tmpl.format('.arch armv6\n.object_arch armv4t\nshadd8 r3,r3,r3'),
279                                                name : 'Assembler supports ARMv6 media instructions on ARM (forced)')
280        endif
281        if not opus_arm_may_have_neon
282          message('Trying to force-enable NEON instructions...')
283          opus_arm_may_have_neon = cc.compiles(asm_tmpl.format('.arch armv7-a\n.fpu neon\n.object_arch armv4t\nvorr d0,d0,d0'),
284                                               name : 'Assembler supports NEON instructions on ARM (forced)')
285        endif
286      endif
287
288      if opus_arm_may_have_edsp
289        opus_conf.set('OPUS_ARM_MAY_HAVE_EDSP', 1)
290        if opus_arm_presume_edsp
291          opus_conf.set('OPUS_ARM_PRESUME_EDSP', 1)
292          asm_optimization += ['EDSP']
293        else
294          rtcd_support += ['EDSP']
295        endif
296      endif
297      if opus_arm_may_have_media
298        opus_conf.set('OPUS_ARM_MAY_HAVE_MEDIA', 1)
299        if opus_arm_presume_media
300          opus_conf.set('OPUS_ARM_PRESUME_MEDIA', 1)
301          asm_optimization += ['Media']
302        else
303          rtcd_support += ['Media']
304        endif
305      endif
306      if opus_arm_may_have_neon
307        opus_conf.set('OPUS_ARM_MAY_HAVE_NEON', 1)
308        if opus_arm_presume_neon
309          opus_conf.set('OPUS_ARM_PRESUME_NEON', 1)
310          asm_optimization += ['NEON']
311        else
312          rtcd_support += ['NEON']
313        endif
314      endif
315
316      if cc.get_define('__APPLE__')
317        arm2gnu_args = ['--apple']
318      else
319        arm2gnu_args = []
320      endif
321    endif # found perl
322  else # arm + enable fixed point
323    if opt_asm.enabled()
324      error('asm option is enabled, but no assembly support for ' + host_cpu_family)
325    endif
326  endif
327endif # enable asm
328
329# Check whether we require assembly and we support assembly on this arch,
330# but none were detected. Can happen because of incorrect compiler flags, such
331# as missing -mfloat-abi=softfp on ARM32 softfp architectures.
332if opt_asm.enabled() and (asm_optimization.length() + inline_optimization.length()) == 0
333  error('asm option was enabled, but no assembly support was detected')
334endif
335
336# XXX: NEON has hardfp vs softfp compiler configuration issues
337# When targeting ARM32 softfp, we sometimes need to explicitly pass
338# -mfloat-abi=softfp to enable NEON. F.ex., on Android. It should
339# be set in the cross file.
340arm_neon_intr_link_args = ['-mfpu=neon']
341
342have_sse = false
343have_sse2 = false
344have_sse4_1 = false
345have_avx = false # no avx opus code yet
346have_neon_intr = false
347
348intrinsics_support = []
349if not opt_intrinsics.disabled()
350  if host_cpu_family in ['arm', 'aarch64']
351    # Check for ARMv7/AArch64 neon intrinsics
352    intrin_check = '''
353    #include <arm_neon.h>
354      int main (void) {
355        static float32x4_t A0, A1, SUMM;
356        SUMM = vmlaq_f32(SUMM, A0, A1);
357        return (int)vgetq_lane_f32(SUMM, 0);
358      }'''
359    intrin_name = 'ARMv7/AArch64 NEON'
360    if cc.links(intrin_check,
361                name: 'compiler supports @0@ intrinsics'.format(intrin_name))
362      opus_arm_presume_neon_intr = opus_can_presume_simd
363      opus_arm_may_have_neon_intr = true
364    else
365      opus_arm_presume_neon_intr = false
366      if cc.links(intrin_check,
367                  args: arm_neon_intr_link_args,
368                  name: 'compiler supports @0@ intrinsics with @1@'.format(intrin_name, ' '.join(arm_neon_intr_link_args)))
369        opus_arm_may_have_neon_intr = true
370      else
371        opus_arm_may_have_neon_intr = false
372      endif
373    endif
374
375    if opus_arm_may_have_neon_intr
376      have_neon_intr = true
377      intrinsics_support += [intrin_name]
378      opus_conf.set('OPUS_ARM_MAY_HAVE_NEON_INTR', 1)
379      if opus_arm_presume_neon_intr
380        opus_conf.set('OPUS_ARM_PRESUME_NEON_INTR', 1)
381      else
382        rtcd_support += [intrin_name]
383        opus_neon_intr_args = arm_neon_intr_link_args
384      endif
385    else
386      message('Compiler does not support @0@ intrinsics'.format(intrin_name))
387    endif
388
389    # Check for aarch64 neon intrinsics
390    intrin_check = '''
391    #include <arm_neon.h>
392      int main (void) {
393        static int32_t IN;
394        static int16_t OUT;
395        OUT = vqmovns_s32(IN);
396      }'''
397    intrin_name = 'AArch64 NEON'
398    if cc.links(intrin_check,
399                name: 'compiler supports @0@ intrinsics'.format(intrin_name))
400      opus_arm_presume_aarch64_neon_intr = opus_can_presume_simd
401      opus_arm_may_have_aarch64_neon_intr = true
402    else
403      opus_arm_presume_aarch64_neon_intr = false
404      if cc.links(intrin_check,
405                  args: arm_neon_intr_link_args,
406                  name: 'compiler supports @0@ intrinsics with @1@'.format(intrin_name, ' '.join(arm_neon_intr_link_args)))
407        opus_arm_may_have_aarch64_neon_intr = true
408      else
409        opus_arm_may_have_aarch64_neon_intr = false
410      endif
411    endif
412
413    if opus_arm_may_have_aarch64_neon_intr
414      intrinsics_support += [intrin_name]
415      opus_conf.set('OPUS_X86_MAY_HAVE_AARCH64_NEON_INTR', 1)
416      if opus_arm_presume_aarch64_neon_intr
417        opus_conf.set('OPUS_X86_PRESUME_AARCH64_NEON_INTR', 1)
418      endif
419    else
420      message('Compiler does not support @0@ intrinsics'.format(intrin_name))
421    endif
422  elif host_cpu_family in ['x86', 'x86_64']
423    # XXX: allow external override/specification of the flags
424    x86_intrinsics = [
425      [ 'SSE', 'xmmintrin.h', '__m128', '_mm_setzero_ps()', ['-msse'] ],
426      [ 'SSE2', 'emmintrin.h', '__m128i', '_mm_setzero_si128()', ['-msse2'] ],
427      [ 'SSE4.1', 'smmintrin.h', '__m128i', '_mm_setzero_si128(); mtest = _mm_cmpeq_epi64(mtest, mtest)', ['-msse4.1'] ],
428      [ 'AVX', 'immintrin.h', '__m256', '_mm256_setzero_ps()', ['-mavx'] ],
429    ]
430
431    foreach intrin : x86_intrinsics
432      intrin_check = '''#include <@0@>
433                        int main (int argc, char ** argv) {
434                          static @1@ mtest;
435                          mtest = @2@;
436                          return *((unsigned char *) &mtest) != 0;
437                        }'''.format(intrin[1],intrin[2],intrin[3])
438      intrin_name = intrin[0]
439      # Intrinsics arguments are not available with MSVC-like compilers
440      intrin_args = cc.get_argument_syntax() == 'msvc' ? [] : intrin[4]
441      if cc.links(intrin_check, name : 'compiler supports @0@ intrinsics'.format(intrin_name))
442        may_have_intrin = true
443        presume_intrin = opus_can_presume_simd
444      elif intrin_args.length() > 0
445        presume_intrin = false
446        if cc.links(intrin_check,
447                    args : intrin_args,
448                    name : 'compiler supports @0@ intrinsics with @1@'.format(intrin_name, ' '.join(intrin_args)))
449          may_have_intrin = true
450        else
451          may_have_intrin = false
452        endif
453      endif
454      if may_have_intrin
455        intrinsics_support += [intrin_name]
456        intrin_lower_name = intrin_name.to_lower().underscorify()
457        set_variable('have_' + intrin_lower_name, true)
458        opus_conf.set('OPUS_X86_MAY_HAVE_' + intrin_name.underscorify(), 1)
459        if presume_intrin
460          opus_conf.set('OPUS_X86_PRESUME_' + intrin_name.underscorify(), 1)
461        else
462          rtcd_support += [intrin_name]
463          set_variable('opus_@0@_args'.format(intrin_lower_name), intrin_args)
464        endif
465      else
466        message('Compiler does not support @0@ intrinsics'.format(intrin_name))
467      endif
468    endforeach
469
470    if not opt_rtcd.disabled()
471      get_cpuid_by_asm = false
472      cpuid_asm_code = '''
473        #include <stdio.h>
474        int main (int argc, char ** argv) {
475                 unsigned int CPUInfo0;
476                 unsigned int CPUInfo1;
477                 unsigned int CPUInfo2;
478                 unsigned int CPUInfo3;
479                 unsigned int InfoType;
480                #if defined(__i386__) && defined(__PIC__)
481                 __asm__ __volatile__ (
482                 "xchg %%ebx, %1\n"
483                 "cpuid\n"
484                 "xchg %%ebx, %1\n":
485                 "=a" (CPUInfo0),
486                 "=r" (CPUInfo1),
487                 "=c" (CPUInfo2),
488                 "=d" (CPUInfo3) :
489                 "a" (InfoType), "c" (0)
490                );
491               #else
492                 __asm__ __volatile__ (
493                 "cpuid":
494                 "=a" (CPUInfo0),
495                 "=b" (CPUInfo1),
496                 "=c" (CPUInfo2),
497                 "=d" (CPUInfo3) :
498                 "a" (InfoType), "c" (0)
499                );
500               #endif
501          return 0;
502        }'''
503      cpuid_c_code = '''
504        #include <cpuid.h>
505        int main (int argc, char ** argv) {
506          unsigned int CPUInfo0;
507          unsigned int CPUInfo1;
508          unsigned int CPUInfo2;
509          unsigned int CPUInfo3;
510          unsigned int InfoType;
511          __get_cpuid(InfoType, &CPUInfo0, &CPUInfo1, &CPUInfo2, &CPUInfo3);
512          return 0;
513        }'''
514      cpuid_msvc_code = '''
515        #include <intrin.h>
516        int main (void) {
517          int CPUInfo, InfoType;
518          __cpuid(&CPUInfo, InfoType);
519        }'''
520      if cc.links(cpuid_asm_code, name : 'Get X86 CPU info via inline assembly')
521        opus_conf.set('CPU_INFO_BY_ASM', 1)
522      elif cc.links(cpuid_c_code, name : 'Get X86 CPU info via C method')
523        opus_conf.set('CPU_INFO_BY_C', 1)
524      elif cc.get_define('_MSC_VER') != '' and cc.links(cpuid_msvc_code)
525        message('Getting X86 CPU info via __cpuid')
526      else
527        if opt_intrinsics.enabled() and opt_rtcd.enabled()
528          error('intrinsics and rtcd options are enabled, but no Get CPU Info method detected')
529        endif
530        warning('Get CPU Info method not detected, no rtcd for intrinsics')
531      endif
532    endif # opt_rtcd
533  else
534    if opt_intrinsics.enabled()
535      error('intrinsics option enabled, but no intrinsics support for ' + host_machine.get_cpu())
536    endif
537    warning('No intrinsics support for ' + host_machine.get_cpu())
538  endif
539endif
540
541# Check whether we require intrinsics and we support intrinsics on this arch,
542# but none were detected. Can happen because of incorrect compiler flags, such
543# as missing -mfloat-abi=softfp on ARM32 softfp architectures.
544if opt_intrinsics.enabled() and intrinsics_support.length() == 0
545  error('intrinsics option was enabled, but none were detected')
546endif
547
548if opt_rtcd.disabled()
549  rtcd_support = 'disabled'
550else
551  if rtcd_support.length() > 0
552    opus_conf.set('OPUS_HAVE_RTCD', 1)
553  else
554    if intrinsics_support.length() == 0
555      rtcd_support = 'none'
556      if opt_rtcd.enabled()
557        error('rtcd option is enabled, but no support for intrinsics or assembly is available')
558      endif
559    else
560      rtcd_support = 'not needed'
561    endif
562  endif
563endif
564
565# extract source file lists from .mk files
566mk_files = ['silk_sources.mk', 'opus_headers.mk', 'opus_sources.mk', 'silk_headers.mk', 'celt_sources.mk', 'celt_headers.mk']
567lines = run_command('meson/read-sources-list.py', mk_files, check: true).stdout().strip().split('\n')
568sources = {}
569foreach l : lines
570  a = l.split(' = ')
571  var_name = a[0]
572  file_list = a[1].split()
573  sources += {var_name: files(file_list)}
574endforeach
575
576subdir('include')
577subdir('silk')
578subdir('celt')
579subdir('src')
580
581configure_file(output: 'config.h', configuration: opus_conf)
582
583if not opt_tests.disabled()
584  subdir('celt/tests')
585  subdir('silk/tests')
586  subdir('tests')
587endif
588
589# pkg-config files (not using pkg module so we can use the existing .pc.in file)
590pkgconf = configuration_data()
591
592pkgconf.set('prefix', join_paths(get_option('prefix')))
593pkgconf.set('exec_prefix', '${prefix}')
594pkgconf.set('libdir', '${prefix}/@0@'.format(get_option('libdir')))
595pkgconf.set('includedir', '${prefix}/@0@'.format(get_option('includedir')))
596pkgconf.set('VERSION', opus_version)
597pkgconf.set('PC_BUILD', pc_build)
598pkgconf.set('LIBM', libm.found() ? '-lm' : '')
599
600pkg_install_dir = '@0@/pkgconfig'.format(get_option('libdir'))
601
602configure_file(input : 'opus.pc.in',
603  output : 'opus.pc',
604  configuration : pkgconf,
605  install_dir : pkg_install_dir)
606
607# The uninstalled one has hardcoded libtool + static lib stuff, skip it for now
608#configure_file(input : 'opus-uninstalled.pc.in',
609#  output : 'opus-uninstalled.pc',
610#  configuration : pkgconf,
611#  install : false)
612
613doxygen = find_program('doxygen', required: get_option('docs'))
614if doxygen.found()
615  subdir('doc')
616endif
617
618summary(
619  {
620    'C99 var arrays': opus_conf.has('VAR_ARRAYS'),
621    'C99 lrintf': opus_conf.has('HAVE_LRINTF'),
622    'Use alloca': msg_use_alloca,
623  },
624  section: 'Compiler support',
625  bool_yn: true,
626  list_sep: ', ',
627)
628
629# Parse optimization status
630foreach status : [['inline_optimization', opt_asm],
631                  ['asm_optimization', opt_asm],
632                  ['intrinsics_support', opt_intrinsics]]
633  res = status[0]
634  opt = status[1]
635  resval = get_variable(res)
636  if opt.disabled()
637    set_variable(res, 'disabled')
638  elif resval.length() == 0
639    if host_cpu_family not in ['arm', 'aarch64', 'x86', 'x86_64']
640      set_variable(res, 'No optimizations for your platform, please send patches')
641    else
642      set_variable(res, 'none')
643    endif
644  endif
645endforeach
646
647summary(
648  {
649    'Floating point support': not opt_fixed_point,
650    'Fast float approximations': opt_float_approx,
651    'Fixed point debugging': opt_fixed_point_debug,
652    'Inline assembly optimizations': inline_optimization,
653    'External assembly optimizations': asm_optimization,
654    'Intrinsics optimizations': intrinsics_support,
655    'Run-time CPU detection': rtcd_support,
656  },
657  section: 'Optimizations',
658  bool_yn: true,
659  list_sep: ', ',
660)
661summary(
662  {
663    'Custom modes': opt_custom_modes,
664    'Assertions': opt_assertions,
665    'Hardening': opt_hardening,
666    'Fuzzing': opt_fuzzing,
667    'Check ASM': opt_check_asm,
668    'API documentation': doxygen.found(),
669    'Extra programs': not extra_programs.disabled(),
670    'Tests': not opt_tests.disabled(),
671  },
672  section: 'General configuration',
673  bool_yn: true,
674  list_sep: ', ',
675)
676