Commit c2b542b6 authored by Tim-Philipp Müller's avatar Tim-Philipp Müller Committed by Nirbheek Chauhan
Browse files

Add support for Meson build system

Tested on:
 - Linux/x86* with gcc
 - Android armv7 arm64 x86 x86_64 with clang
 - Windows x86 x86_64 with Visual Studio 2017
 - Windows x86 x86_64 with MinGW
 - macOS x86_64 with clang
 - iOS arm64 x86_64 with clang

Co-authored by: Nirbheek Chauhan <nirbheek@centricular.com>

!13
parent 034c1b61
Pipeline #2229 passed with stage
in 4 minutes and 46 seconds
......@@ -19,7 +19,7 @@ autoconf:
script:
- ./autogen.sh
- ./configure
- make
- make -j4
- make distcheck
cache:
paths:
......@@ -40,3 +40,21 @@ cmake:
- cmake -S . -B build -G "Ninja" -DCMAKE_BUILD_TYPE=Release -DOPUS_BUILD_TESTING=ON -DOPUS_BUILD_PROGRAMS=ON
- cmake --build build
- cd build && ctest --output-on-failure
meson:
stage: build
before_script:
- apt-get update &&
apt-get install -y python3-pip ninja-build doxygen
- export XDG_CACHE_HOME=$PWD/pip-cache
- pip3 install --user meson
script:
- export PATH=$PATH:$HOME/.local/bin
- mkdir builddir
- meson setup --werror -Dtests=enabled -Ddocs=enabled -Dbuildtype=release builddir
- meson compile -C builddir
- meson test -C builddir
#- meson dist --no-tests -C builddir
cache:
paths:
- 'pip-cache/*'
......@@ -224,6 +224,18 @@ EXTRA_DIST = opus.pc.in \
cmake/OpusSources.cmake \
cmake/config.h.cmake.in \
cmake/vla.c \
meson/get-version.py \
meson/read-sources-list.py \
meson.build \
meson_options.txt \
include/meson.build \
celt/meson.build \
celt/tests/meson.build \
silk/meson.build \
silk/tests/meson.build \
src/meson.build \
tests/meson.build \
doc/meson.build \
tests/run_vectors.sh \
celt/arm/arm2gnu.pl \
celt/arm/celt_pitch_xcorr_arm.s \
......
celt_sources = sources['CELT_SOURCES']
celt_sse_sources = sources['CELT_SOURCES_SSE']
celt_sse2_sources = sources['CELT_SOURCES_SSE2']
celt_sse4_1_sources = sources['CELT_SOURCES_SSE4_1']
celt_neon_intr_sources = sources['CELT_SOURCES_ARM_NEON_INTR']
celt_static_libs = []
foreach intr_name : ['sse', 'sse2', 'sse4_1', 'neon_intr']
have_intr = get_variable('have_' + intr_name)
if not have_intr
continue
endif
intr_sources = get_variable('celt_@0@_sources'.format(intr_name))
intr_args = get_variable('opus_@0@_args'.format(intr_name), [])
celt_static_libs += static_library('celt_' + intr_name, intr_sources,
c_args: intr_args,
include_directories: opus_includes,
install: false)
endforeach
have_arm_intrinsics_or_asm = have_arm_ne10
if (intrinsics_support.length() + asm_optimization.length() + inline_optimization.length()) > 0
have_arm_intrinsics_or_asm = true
endif
if host_cpu_family in ['arm', 'aarch64'] and have_arm_intrinsics_or_asm
celt_sources += sources['CELT_SOURCES_ARM']
if have_arm_ne10
celt_sources += sources['CELT_SOURCES_ARM_NE10']
endif
if opus_arm_external_asm
arm2gnu = [find_program('arm/arm2gnu.pl')] + arm2gnu_args
celt_sources_arm_asm = configure_file(input: 'arm/celt_pitch_xcorr_arm.s',
output: '@BASENAME@-gnu.S',
command: arm2gnu + ['@INPUT@'],
capture: true)
celt_arm_armopts_s = configure_file(input: 'arm/armopts.s.in',
output: 'arm/armopts.s',
configuration: opus_conf)
celt_static_libs += static_library('celt-armasm',
celt_arm_armopts_s, celt_sources_arm_asm,
install: false)
endif
endif
celt_c_args = []
if host_system == 'windows'
celt_c_args += ['-DDLL_EXPORT']
endif
celt_lib = static_library('opus-celt',
celt_sources,
c_args: celt_c_args,
include_directories: opus_includes,
link_whole: celt_static_libs,
dependencies: libm,
install: false)
tests = [
'test_unit_types',
'test_unit_mathops',
'test_unit_entropy',
'test_unit_laplace',
'test_unit_dft',
'test_unit_mdct',
'test_unit_rotation',
'test_unit_cwrs32',
]
foreach test_name : tests
exe = executable(test_name, '@0@.c'.format(test_name),
include_directories : opus_includes,
link_with : [celt_lib, celt_static_libs],
dependencies : libm,
install : false)
test(test_name, exe)
endforeach
......@@ -335,3 +335,6 @@ PREDEFINED = OPUS_EXPORT= \
# configure time.
#
HAVE_DOT = @HAVE_DOT@
# move docs to the correct place
OUTPUT_DIRECTORY = @top_builddir@/doc
top_srcdir = meson.source_root()
top_builddir = meson.build_root()
have_dot = find_program('dot', required: false).found()
doxyfile_conf = configuration_data()
doxyfile_conf.set('VERSION', opus_version)
doxyfile_conf.set('HAVE_DOT', have_dot)
doxyfile_conf.set('top_srcdir', top_srcdir)
doxyfile_conf.set('top_builddir', top_builddir)
doxyfile = configure_file(input: 'Doxyfile.in',
output: 'Doxyfile',
configuration: doxyfile_conf,
install: false)
docdir = join_paths(get_option('datadir'), get_option('docdir'))
doc_inputs = [
'customdoxygen.css',
'footer.html',
'header.html',
'opus_logo.svg',
top_srcdir + '/include/opus.h',
top_srcdir + '/include/opus_multistream.h',
top_srcdir + '/include/opus_defines.h',
top_srcdir + '/include/opus_types.h',
top_srcdir + '/include/opus_custom.h',
]
custom_target('doc',
input: [ doxyfile ] + doc_inputs,
output: [ 'html' ],
command: [ doxygen, doxyfile ],
install_dir: docdir,
install: true)
opus_headers = [
'opus.h',
'opus_multistream.h',
'opus_projection.h',
'opus_types.h',
'opus_defines.h',
]
if opt_custom_modes
opus_headers += ['opus_custom.h']
endif
install_headers(opus_headers, subdir: 'opus')
This diff is collapsed.
#!/usr/bin/env python3
#
# Opus get-version.py
#
# Extracts versions for build:
# - Opus package version based on 'git describe' or $srcroot/package_version
# - libtool version based on configure.ac
# - macos lib version based on configure.ac
#
# Usage:
# get-version.py [--package-version | --libtool-version | --darwin-version]
import argparse
import subprocess
import os
import sys
import shutil
if __name__ == '__main__':
arg_parser = argparse.ArgumentParser(description='Extract Opus package version or libtool version')
group = arg_parser.add_mutually_exclusive_group(required=True)
group.add_argument('--libtool-version', action='store_true')
group.add_argument('--package-version', action='store_true')
group.add_argument('--darwin-version', action='store_true')
args = arg_parser.parse_args()
srcroot = os.path.normpath(os.path.join(os.path.dirname(__file__), '..'))
# package version
if args.package_version:
package_version = None
# check if git checkout
git_dir = os.path.join(srcroot, '.git')
is_git = os.path.isdir(git_dir)
have_git = shutil.which('git') is not None
if is_git and have_git:
git_cmd = subprocess.run(['git', '--git-dir=' + git_dir, 'describe', 'HEAD'], stdout=subprocess.PIPE)
if git_cmd.returncode:
print('ERROR: Could not extract package version via `git describe` in', srcroot, file=sys.stderr)
sys.exit(-1)
package_version = git_cmd.stdout.decode('ascii').strip().lstrip('v')
else:
with open(os.path.join(srcroot, 'package_version'), 'r') as f:
for line in f:
if line.startswith('PACKAGE_VERSION="'):
package_version = line[17:].strip().lstrip('v').rstrip('"')
if package_version:
break
if not package_version:
print('ERROR: Could not extract package version from package_version file in', srcroot, file=sys.stderr)
sys.exit(-1)
print(package_version)
sys.exit(0)
# libtool version + darwin version
elif args.libtool_version or args.darwin_version:
opus_lt_cur = None
opus_lt_rev = None
opus_lt_age = None
with open(os.path.join(srcroot, 'configure.ac'), 'r') as f:
for line in f:
if line.strip().startswith('OPUS_LT_CURRENT='):
opus_lt_cur = line[16:].strip()
elif line.strip().startswith('OPUS_LT_REVISION='):
opus_lt_rev = line[17:].strip()
elif line.strip().startswith('OPUS_LT_AGE='):
opus_lt_age = line[12:].strip()
if opus_lt_cur and opus_lt_rev and opus_lt_age:
opus_lt_cur = int(opus_lt_cur)
opus_lt_rev = int(opus_lt_rev)
opus_lt_age = int(opus_lt_age)
if args.libtool_version:
print('{}.{}.{}'.format(opus_lt_cur - opus_lt_age, opus_lt_age, opus_lt_rev))
elif args.darwin_version:
print('{}.{}.{}'.format(opus_lt_cur + 1, 0, 0))
sys.exit(0)
else:
print('ERROR: Could not extract libtool version from configure.ac file in', srcroot, file=sys.stderr)
sys.exit(-1)
else:
sys.exit(-1)
#!/usr/bin/env python3
#
# opus/read-sources-list.py
#
# Parses .mk files and extracts list of source files.
# Prints one line per source file list, with filenames space-separated.
import sys
if len(sys.argv) < 2:
sys.exit('Usage: {} sources_foo.mk [sources_bar.mk...]'.format(sys.argv[0]))
for input_fn in sys.argv[1:]:
with open(input_fn, 'r', encoding='utf8') as f:
text = f.read()
text = text.replace('\\\n', '')
# Remove empty lines
lines = [line for line in text.split('\n') if line.strip()]
# Print SOURCES_XYZ = file1.c file2.c
for line in lines:
values = line.strip().split('=', maxsplit=2)
if len(values) != 2:
raise RuntimeError('Unable to parse line "{}" from file "{}"'.format(line, input_fn))
var, files = values
sources_list = [f for f in files.split(' ') if f]
print(var.strip(), '=', ' '.join(sources_list))
# Optimizations
option('fixed-point', type : 'boolean', value : false, description : 'Compile without floating point (for machines without a fast enough FPU')
option('fixed-point-debug', type : 'boolean', value : false, description : 'Debug fixed-point implementation')
option('float-api', type : 'boolean', value : true, description : 'Compile with or without the floating point API (for machines with no float library')
option('float-approx', type : 'boolean', value : false, description : 'Enable fast approximations for floating point (not supported on all platforms)')
option('rtcd', type : 'feature', value : 'auto', description : 'Run-time CPU capabilities detection')
option('asm', type : 'feature', value : 'auto', description : 'Assembly optimizations for ARM (fixed-point)')
option('intrinsics', type : 'feature', value : 'auto', description : 'Intrinsics optimizations for ARM NEON or x86')
option('custom-modes', type : 'boolean', value : false, description : 'Enable non-Opus modes, e.g. 44.1 kHz & 2^n frames')
option('extra-programs', type : 'feature', value : 'auto', description : 'Extra programs (demo and tests)')
option('assertions', type : 'boolean', value : false, description : 'Additional software error checking')
option('hardening', type : 'boolean', value : true, description : 'Run-time checks that are cheap and safe for use in production')
option('fuzzing', type : 'boolean', value : false, description : 'Causes the encoder to make random decisions')
option('check-asm', type : 'boolean', value : false, description : 'Run bit-exactness checks between optimized and c implementations')
# common feature options
option('tests', type : 'feature', value : 'auto', description : 'Build tests')
option('docs', type: 'feature', value: 'auto', description: 'Build API documentation')
# other options
option('docdir', type: 'string', value: 'doc/opus', description: 'Directory to install documentation into (default: DATADIR/doc/opus')
silk_sources = sources['SILK_SOURCES']
silk_sources_sse4_1 = sources['SILK_SOURCES_SSE4_1']
silk_sources_neon_intr = sources['SILK_SOURCES_ARM_NEON_INTR']
silk_sources_fixed_neon_intr = sources['SILK_SOURCES_FIXED_ARM_NEON_INTR']
silk_sources_fixed = sources['SILK_SOURCES_FIXED']
silk_sources_fixed_sse4_1 = sources['SILK_SOURCES_FIXED_SSE4_1']
silk_sources_float = sources['SILK_SOURCES_FLOAT']
if opt_fixed_point
silk_sources += silk_sources_fixed
else
silk_sources += silk_sources_float
endif
silk_includes = [opus_includes, include_directories('float', 'fixed')]
silk_static_libs = []
foreach intr_name : ['sse4_1', 'neon_intr']
have_intr = get_variable('have_' + intr_name)
if not have_intr
continue
endif
intr_sources = get_variable('silk_sources_' + intr_name)
if opt_fixed_point
intr_sources += get_variable('silk_sources_fixed_' + intr_name)
endif
intr_args = get_variable('opus_@0@_args'.format(intr_name), [])
silk_static_libs += static_library('silk_' + intr_name, intr_sources,
c_args: intr_args,
include_directories: silk_includes,
install: false)
endforeach
silk_c_args = []
if host_machine.system() == 'windows'
silk_c_args += ['-DDLL_EXPORT']
endif
silk_lib = static_library('opus-silk',
silk_sources,
c_args: silk_c_args,
include_directories: silk_includes,
link_whole: silk_static_libs,
dependencies: libm,
install: false)
exe = executable('test_unit_LPC_inv_pred_gain',
'test_unit_LPC_inv_pred_gain.c', '../LPC_inv_pred_gain.c',
include_directories: opus_includes,
link_with: [celt_lib, celt_static_libs, silk_lib, silk_static_libs],
dependencies: libm,
install: false)
test(test_name, exe)
opus_sources = sources['OPUS_SOURCES']
opus_sources_float = sources['OPUS_SOURCES_FLOAT']
if not disable_float_api
opus_sources += opus_sources_float
endif
opus_lib_c_args = []
if host_machine.system() == 'windows'
opus_lib_c_args += ['-DDLL_EXPORT']
endif
opus_lib = library('opus',
opus_sources,
version: libversion,
darwin_versions: macosversion,
c_args: opus_lib_c_args,
include_directories: opus_includes,
link_with: [celt_lib, silk_lib],
dependencies: libm,
install: true)
opus_dep = declare_dependency(link_with: opus_lib,
include_directories: opus_public_includes)
# Extra uninstalled Opus programs
if not extra_programs.disabled()
foreach prog : ['opus_compare', 'opus_demo', 'repacketizer_demo']
executable(prog, '@0@.c'.format(prog),
include_directories: opus_includes,
link_with: opus_lib,
dependencies: libm,
install: false)
endforeach
if opt_custom_modes
executable('opus_custom_demo', '../celt/opus_custom_demo.c',
include_directories: opus_includes,
link_with: opus_lib,
dependencies: libm,
install: false)
endif
endif
# Tests that link to libopus
opus_tests = [
['test_opus_api'],
['test_opus_decode', [], 60],
['test_opus_encode', 'opus_encode_regressions.c', 120],
['test_opus_padding'],
['test_opus_projection'],
]
foreach t : opus_tests
test_name = t.get(0)
extra_srcs = t.get(1, [])
test_kwargs = {}
if t.length() > 2
test_kwargs += {'timeout': t[2]}
endif
exe_kwargs = {}
# This test uses private symbols
if test_name == 'test_opus_projection'
exe_kwargs = {
'link_with': [celt_lib, silk_lib],
'objects': opus_lib.extract_all_objects(),
}
endif
exe = executable(test_name, '@0@.c'.format(test_name), extra_srcs,
include_directories: opus_includes,
dependencies: [libm, opus_dep],
install: false,
kwargs: exe_kwargs)
test(test_name, exe, kwargs: test_kwargs)
endforeach
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment