meson.build 23 KB

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