[io] [osx] switch to floating point AudioBufferList
[aubio.git] / wscript
diff --git a/wscript b/wscript
index d1ab97c..0690a36 100644 (file)
--- a/wscript
+++ b/wscript
@@ -42,14 +42,18 @@ def options(ctx):
             default = "release",
             choices = ('debug', 'release'),
             dest = 'build_type',
-            help = 'whether to compile with (--build-type=release) or without (--build-type=debug) '\
-              ' compiler opimizations [default: release]')
+            help = 'whether to compile with (--build-type=release)' \
+                    ' or without (--build-type=debug)' \
+                    ' compiler opimizations [default: release]')
     add_option_enable_disable(ctx, 'fftw3f', default = False,
             help_str = 'compile with fftw3f instead of ooura (recommended)',
             help_disable_str = 'do not compile with fftw3f')
     add_option_enable_disable(ctx, 'fftw3', default = False,
             help_str = 'compile with fftw3 instead of ooura',
             help_disable_str = 'do not compile with fftw3')
+    add_option_enable_disable(ctx, 'intelipp', default = False,
+            help_str = 'use Intel IPP libraries (auto)',
+            help_disable_str = 'do not use Intel IPP libraries')
     add_option_enable_disable(ctx, 'complex', default = False,
             help_str ='compile with C99 complex',
             help_disable_str = 'do not use C99 complex (default)' )
@@ -80,9 +84,12 @@ def options(ctx):
     add_option_enable_disable(ctx, 'apple-audio', default = None,
             help_str = 'use CoreFoundation (darwin only) (auto)',
             help_disable_str = 'do not use CoreFoundation framework')
+    add_option_enable_disable(ctx, 'blas', default = False,
+            help_str = 'use BLAS acceleration library (no)',
+            help_disable_str = 'do not use BLAS library')
     add_option_enable_disable(ctx, 'atlas', default = False,
-            help_str = 'use Atlas library (no)',
-            help_disable_str = 'do not use Atlas library')
+            help_str = 'use ATLAS acceleration library (no)',
+            help_disable_str = 'do not use ATLAS library')
     add_option_enable_disable(ctx, 'wavread', default = True,
             help_str = 'compile with source_wavread (default)',
             help_disable_str = 'do not compile source_wavread')
@@ -94,31 +101,39 @@ def options(ctx):
             help_str = 'build documentation (auto)',
             help_disable_str = 'do not build documentation')
 
+    add_option_enable_disable(ctx, 'tests', default = True,
+            help_str = 'build tests (true)',
+            help_disable_str = 'do not build or run tests')
+
+    add_option_enable_disable(ctx, 'examples', default = True,
+            help_str = 'build examples (true)',
+            help_disable_str = 'do not build examples')
+
     ctx.add_option('--with-target-platform', type='string',
-            help='set target platform for cross-compilation', dest='target_platform')
+            help='set target platform for cross-compilation',
+            dest='target_platform')
 
     ctx.load('compiler_c')
     ctx.load('waf_unit_test')
     ctx.load('gnu_dirs')
+    ctx.load('waf_gensyms', tooldir='.')
 
 def configure(ctx):
-    from waflib import Options
-    ctx.load('compiler_c')
-    ctx.load('waf_unit_test')
-    ctx.load('gnu_dirs')
-
     target_platform = sys.platform
     if ctx.options.target_platform:
         target_platform = ctx.options.target_platform
 
+    from waflib import Options
 
     if target_platform=='emscripten':
-        # need to force spaces between flag -o and path 
-        # inspired from :
-        # https://github.com/waf-project/waf/blob/master/waflib/extras/c_emscripten.py (#1885)
-        # (OSX /emscripten 1.37.9)
-        ctx.env.CC_TGT_F            = ['-c', '-o', '']
-        ctx.env.CCLNK_TGT_F         = ['-o', '']
+        ctx.load('c_emscripten')
+    else:
+        ctx.load('compiler_c')
+
+    ctx.load('waf_unit_test')
+    ctx.load('gnu_dirs')
+    ctx.load('waf_gensyms', tooldir='.')
+
     # check for common headers
     ctx.check(header_name='stdlib.h')
     ctx.check(header_name='stdio.h')
@@ -151,10 +166,17 @@ def configure(ctx):
         ctx.env.prepend_value('CFLAGS', ['-g', '-Wall', '-Wextra'])
     else:
         # enable debug symbols
-        ctx.env.CFLAGS += ['/Z7', '/FS']
+        ctx.env.CFLAGS += ['/Z7']
+        # /FS flag available in msvc >= 12 (2013)
+        if 'MSVC_VERSION' in ctx.env and ctx.env.MSVC_VERSION >= 12:
+            ctx.env.CFLAGS += ['/FS']
         ctx.env.LINKFLAGS += ['/DEBUG', '/INCREMENTAL:NO']
         # configure warnings
         ctx.env.CFLAGS += ['/W4', '/D_CRT_SECURE_NO_WARNINGS']
+        # ignore "possible loss of data" warnings
+        ctx.env.CFLAGS += ['/wd4305', '/wd4244', '/wd4245', '/wd4267']
+        # ignore "unreferenced formal parameter" warnings
+        ctx.env.CFLAGS += ['/wd4100']
         # set optimization level and runtime libs
         if (ctx.options.build_type == "release"):
             ctx.env.CFLAGS += ['/Ox']
@@ -185,13 +207,15 @@ def configure(ctx):
             ctx.define('HAVE_SINK_APPLE_AUDIO', 1)
             ctx.msg('Checking for AudioToolbox.framework', 'yes')
         else:
-            ctx.msg('Checking for AudioToolbox.framework', 'no (disabled)', color = 'YELLOW')
+            ctx.msg('Checking for AudioToolbox.framework', 'no (disabled)',
+                    color = 'YELLOW')
         if (ctx.options.enable_accelerate != False):
             ctx.define('HAVE_ACCELERATE', 1)
             ctx.env.FRAMEWORK += ['Accelerate']
             ctx.msg('Checking for Accelerate framework', 'yes')
         else:
-            ctx.msg('Checking for Accelerate framework', 'no (disabled)', color = 'YELLOW')
+            ctx.msg('Checking for Accelerate framework', 'no (disabled)',
+                    color = 'YELLOW')
 
     if target_platform in [ 'ios', 'iosimulator' ]:
         MINSDKVER="6.1"
@@ -226,33 +250,38 @@ def configure(ctx):
         ctx.env.LINKFLAGS += [ '-isysroot' , SDKROOT]
 
     if target_platform == 'emscripten':
-        import os.path
-        ctx.env.CFLAGS += [ '-I' + os.path.join(os.environ['EMSCRIPTEN'], 'system', 'include') ]
-        
         if ctx.options.build_type == "debug":
             ctx.env.cshlib_PATTERN = '%s.js'
-            ctx.env.LINKFLAGS_cshlib += ['-s','ASSERTIONS=2']
-            ctx.env.LINKFLAGS_cshlib += ['-s','SAFE_HEAP=1']
-            ctx.env.LINKFLAGS_cshlib += ['-s','ALIASING_FUNCTION_POINTERS=0']
+            ctx.env.LINKFLAGS += ['-s','ASSERTIONS=2']
+            ctx.env.LINKFLAGS += ['-s','SAFE_HEAP=1']
+            ctx.env.LINKFLAGS += ['-s','ALIASING_FUNCTION_POINTERS=0']
+            ctx.env.LINKFLAGS += ['-O0']
         else:
             ctx.env.LINKFLAGS += ['-Oz']
             ctx.env.cshlib_PATTERN = '%s.min.js'
-        
-         # import exposed function names
-        from python.lib.gen_external import get_c_declarations,get_cpp_objects_from_c_declarations,get_all_func_names_from_lib,generate_lib_from_c_declarations
-        c_decls = get_c_declarations(usedouble=False) #emscripten can't use double
-        objects = get_cpp_objects_from_c_declarations(c_decls)
-        objects+=['fvec']
-        lib =  generate_lib_from_c_declarations(objects,c_decls)
-        exported_funcnames = get_all_func_names_from_lib(lib)
-        c_mangled_names = ['_'+s for s in exported_funcnames]
-        ctx.env.LINKFLAGS_cshlib += ['-s','EXPORTED_FUNCTIONS=%s'%c_mangled_names]
-        # put memory file inside generated js files
-        ctx.env.LINKFLAGS_cshlib+=['--memory-init-file','0']
+
+        # doesnt ship file system support in lib
+        ctx.env.LINKFLAGS_cshlib += ['-s', 'NO_FILESYSTEM=1']
+        # put memory file inside generated js files for easier portability
+        ctx.env.LINKFLAGS += ['--memory-init-file', '0']
         ctx.env.cprogram_PATTERN = "%s.js"
         ctx.env.cstlib_PATTERN = '%s.a'
-        if (ctx.options.enable_atlas != True):
-            ctx.options.enable_atlas = False
+
+        # tell emscripten functions we want to expose
+        from python.lib.gen_external import get_c_declarations, \
+                get_cpp_objects_from_c_declarations, \
+                get_all_func_names_from_lib, \
+                generate_lib_from_c_declarations
+        # emscripten can't use double
+        c_decls = get_c_declarations(usedouble=False)
+        objects = list(get_cpp_objects_from_c_declarations(c_decls))
+        # ensure that aubio structs are exported
+        objects += ['fvec_t', 'cvec_t', 'fmat_t']
+        lib = generate_lib_from_c_declarations(objects, c_decls)
+        exported_funcnames = get_all_func_names_from_lib(lib)
+        c_mangled_names = ['_' + s for s in exported_funcnames]
+        ctx.env.LINKFLAGS_cshlib += ['-s',
+                'EXPORTED_FUNCTIONS=%s' % c_mangled_names]
 
     # check support for C99 __VA_ARGS__ macros
     check_c99_varargs = '''
@@ -280,6 +309,22 @@ def configure(ctx):
     else:
         ctx.msg('Checking if complex.h is enabled', 'no')
 
+    # check for Intel IPP
+    if (ctx.options.enable_intelipp != False):
+        has_ipp_headers = ctx.check(header_name=['ippcore.h', 'ippvm.h',
+            'ipps.h'], mandatory = False)
+        has_ipp_libs = ctx.check(lib=['ippcore', 'ippvm', 'ipps'],
+                uselib_store='INTEL_IPP', mandatory = False)
+        if (has_ipp_headers and has_ipp_libs):
+            ctx.msg('Checking if Intel IPP is available', 'yes')
+            ctx.define('HAVE_INTEL_IPP', 1)
+            if ctx.env.CC_NAME == 'msvc':
+                # force linking multi-threaded static IPP libraries on Windows
+                # with msvc
+                ctx.define('_IPP_SEQUENTIAL_STATIC', 1)
+        else:
+            ctx.msg('Checking if Intel IPP is available', 'no')
+
     # check for fftw3
     if (ctx.options.enable_fftw3 != False or ctx.options.enable_fftw3f != False):
         # one of fftwf or fftw3f
@@ -303,13 +348,15 @@ def configure(ctx):
                         mandatory = ctx.options.enable_fftw3)
         ctx.define('HAVE_FFTW3', 1)
 
-    # fftw not enabled, use vDSP or ooura
+    # fftw not enabled, use vDSP, intelIPP or ooura
     if 'HAVE_FFTW3F' in ctx.env.define_key:
         ctx.msg('Checking for FFT implementation', 'fftw3f')
     elif 'HAVE_FFTW3' in ctx.env.define_key:
         ctx.msg('Checking for FFT implementation', 'fftw3')
     elif 'HAVE_ACCELERATE' in ctx.env.define_key:
         ctx.msg('Checking for FFT implementation', 'vDSP')
+    elif 'HAVE_INTEL_IPP' in ctx.env.define_key:
+        ctx.msg('Checking for FFT implementation', 'Intel IPP')
     else:
         ctx.msg('Checking for FFT implementation', 'ooura')
 
@@ -322,11 +369,12 @@ def configure(ctx):
     # check for libsamplerate
     if (ctx.options.enable_double):
         if (ctx.options.enable_samplerate):
-            ctx.fatal("Could not compile aubio in double precision mode with libsamplerate")
+            ctx.fatal("Could not compile aubio in double precision mode' \
+                    ' with libsamplerate")
         else:
             ctx.options.enable_samplerate = False
-            ctx.msg('Checking if using samplerate', 'no (disabled in double precision mode)',
-                    color = 'YELLOW')
+            ctx.msg('Checking if using samplerate',
+                    'no (disabled in double precision mode)', color = 'YELLOW')
     if (ctx.options.enable_samplerate != False):
         ctx.check_cfg(package = 'samplerate',
                 args = '--cflags --libs samplerate >= 0.0.15',
@@ -369,7 +417,8 @@ def configure(ctx):
             ctx.msg(msg_check, 'not found (missing avformat)', color = 'YELLOW')
         elif 'HAVE_AVUTIL' not in ctx.env:
             ctx.msg(msg_check, 'not found (missing avutil)', color = 'YELLOW')
-        elif 'HAVE_SWRESAMPLE' not in ctx.env and 'HAVE_AVRESAMPLE' not in ctx.env:
+        elif 'HAVE_SWRESAMPLE' not in ctx.env \
+                and 'HAVE_AVRESAMPLE' not in ctx.env:
             resample_missing = 'not found (avresample or swresample required)'
             ctx.msg(msg_check, resample_missing, color = 'YELLOW')
         else:
@@ -382,16 +431,29 @@ def configure(ctx):
 
     if (ctx.options.enable_wavread != False):
         ctx.define('HAVE_WAVREAD', 1)
-    ctx.msg('Checking if using source_wavread', ctx.options.enable_wavread and 'yes' or 'no')
+    ctx.msg('Checking if using source_wavread',
+            ctx.options.enable_wavread and 'yes' or 'no')
     if (ctx.options.enable_wavwrite!= False):
         ctx.define('HAVE_WAVWRITE', 1)
-    ctx.msg('Checking if using sink_wavwrite', ctx.options.enable_wavwrite and 'yes' or 'no')
+    ctx.msg('Checking if using sink_wavwrite',
+            ctx.options.enable_wavwrite and 'yes' or 'no')
 
-    # use ATLAS
-    if (ctx.options.enable_atlas != False):
-        ctx.check(header_name = 'atlas/cblas.h', mandatory = ctx.options.enable_atlas)
-        #ctx.check(lib = 'lapack', uselib_store = 'LAPACK', mandatory = ctx.options.enable_atlas)
-        ctx.check(lib = 'cblas', uselib_store = 'BLAS', mandatory = ctx.options.enable_atlas)
+    # use BLAS/ATLAS
+    if (ctx.options.enable_blas != False):
+        ctx.check_cfg(package = 'blas',
+                args = '--cflags --libs',
+                uselib_store='BLAS', mandatory = ctx.options.enable_blas)
+        if 'LIB_BLAS' in ctx.env:
+            blas_header = None
+            if ctx.env['LIBPATH_BLAS']:
+                if 'atlas' in ctx.env['LIBPATH_BLAS'][0]:
+                    blas_header = 'atlas/cblas.h'
+                elif 'openblas' in ctx.env['LIBPATH_BLAS'][0]:
+                    blas_header = 'openblas/cblas.h'
+            else:
+                blas_header = 'cblas.h'
+            ctx.check(header_name = blas_header, mandatory =
+                    ctx.options.enable_atlas)
 
     # use memcpy hacks
     if (ctx.options.enable_memcpy == True):
@@ -440,8 +502,12 @@ def build(bld):
 
     # add sub directories
     if bld.env['DEST_OS'] not in ['ios', 'iosimulator', 'android']:
-        bld.recurse('examples')
-        bld.recurse('tests')
+        if bld.env['DEST_OS']=='emscripten' and not bld.options.testcmd:
+            bld.options.testcmd = 'node %s'
+        if bld.options.enable_examples:
+            bld.recurse('examples')
+        if bld.options.enable_tests:
+            bld.recurse('tests')
 
     # pkg-config template
     bld( source = 'aubio.pc.in' )
@@ -451,6 +517,10 @@ def build(bld):
     doxygen(bld)
     sphinx(bld)
 
+    from waflib.Tools import waf_unit_test
+    bld.add_post_fun(waf_unit_test.summary)
+    bld.add_post_fun(waf_unit_test.set_exit_code)
+
 def txt2man(bld):
     # build manpages from txt files using txt2man
     if bld.env['TXT2MAN']:
@@ -476,30 +546,45 @@ def doxygen(bld):
     # build documentation from source files using doxygen
     if bld.env['DOXYGEN']:
         bld.env.VERSION = VERSION
-        rule = '( cat ${SRC} && echo PROJECT_NUMBER=${VERSION}; )'
+        rule = '( cat ${SRC[0]} && echo PROJECT_NUMBER=${VERSION}'
+        rule += ' && echo OUTPUT_DIRECTORY=%s && echo HTML_OUTPUT=%s )'
         rule += ' | doxygen - > /dev/null'
+        rule %= (os.path.abspath(out), 'api')
         bld( name = 'doxygen', rule = rule,
-                source = 'doc/web.cfg',
-                target = '../doc/web/html/index.html',
-                cwd = 'doc')
-        bld.install_files( '${DATAROOTDIR}' + '/doc/libaubio-doc',
-                bld.path.ant_glob('doc/web/html/**'),
-                cwd = bld.path.find_dir ('doc/web'),
-                relative_trick = True)
+                source = ['doc/web.cfg']
+                    + bld.path.find_dir('src').ant_glob('**/*.h'),
+                target = bld.path.find_or_declare('api/index.html'),
+                cwd = bld.path.find_dir('doc'))
+        # evaluate nodes lazily to prevent build directory traversal warnings
+        bld.install_files('${DATAROOTDIR}/doc/libaubio-doc/api',
+                bld.path.find_or_declare('api').ant_glob('**/*',
+                    generator=True), cwd=bld.path.find_or_declare('api'),
+                relative_trick=True)
 
 def sphinx(bld):
     # build documentation from source files using sphinx-build
-    # note: build in ../doc/_build/html, otherwise waf wont install unsigned files
-    if bld.env['SPHINX']:
+    try:
+        import aubio
+        has_aubio = True
+    except ImportError:
+        from waflib import Logs
+        Logs.pprint('YELLOW', "Sphinx manual: install aubio first")
+        has_aubio = False
+    if bld.env['SPHINX'] and has_aubio:
         bld.env.VERSION = VERSION
-        bld( name = 'sphinx',
-                rule = '${SPHINX} -b html -D release=${VERSION} -D version=${VERSION} -a -q `dirname ${SRC}` `dirname ${TGT}`',
-                source = 'doc/conf.py',
-                target = '../doc/_build/html/index.html')
-        bld.install_files( '${DATAROOTDIR}' + '/doc/libaubio-doc/sphinx',
-                bld.path.ant_glob('doc/_build/html/**'),
-                cwd = bld.path.find_dir('doc/_build/html'),
-                relative_trick = True)
+        rule = '${SPHINX} -b html -D release=${VERSION}' \
+                ' -D version=${VERSION} -W -a -q' \
+                ' -d %s ' % os.path.join(os.path.abspath(out), 'doctrees')
+        rule += ' . %s' % os.path.join(os.path.abspath(out), 'manual')
+        bld( name = 'sphinx', rule = rule,
+                cwd = bld.path.find_dir('doc'),
+                source = bld.path.find_dir('doc').ant_glob('*.rst'),
+                target = bld.path.find_or_declare('manual/index.html'))
+        # evaluate nodes lazily to prevent build directory traversal warnings
+        bld.install_files('${DATAROOTDIR}/doc/libaubio-doc/manual',
+                bld.path.find_or_declare('manual').ant_glob('**/*',
+                    generator=True), cwd=bld.path.find_or_declare('manual'),
+                relative_trick=True)
 
 # register the previous rules as build rules
 from waflib.Build import BuildContext
@@ -523,13 +608,16 @@ class build_doxygen(BuildContext):
 def shutdown(bld):
     from waflib import Logs
     if bld.options.target_platform in ['ios', 'iosimulator']:
-        msg ='building for %s, contact the author for a commercial license' % bld.options.target_platform
+        msg ='building for %s, contact the author for a commercial license' \
+                % bld.options.target_platform
         Logs.pprint('RED', msg)
         msg ='   Paul Brossier <piem@aubio.org>'
         Logs.pprint('RED', msg)
 
 def dist(ctx):
-    ctx.excl  = ' **/.waf* **/*~ **/*.pyc **/*.swp **/*.swo **/*.swn **/.lock-w* **/.git*'
+    ctx.excl  = ' **/.waf*'
+    ctx.excl += ' **/.git*'
+    ctx.excl += ' **/*~ **/*.pyc **/*.swp **/*.swo **/*.swn **/.lock-w*'
     ctx.excl += ' **/build/*'
     ctx.excl += ' doc/_build'
     ctx.excl += ' python/demos_*'
@@ -537,6 +625,9 @@ def dist(ctx):
     ctx.excl += ' **/python/ext/config.h'
     ctx.excl += ' **/python/lib/aubio/_aubio.so'
     ctx.excl += ' **.egg-info'
+    ctx.excl += ' **/.eggs'
+    ctx.excl += ' **/.pytest_cache'
+    ctx.excl += ' **/.cache'
     ctx.excl += ' **/**.zip **/**.tar.bz2'
     ctx.excl += ' **.tar.bz2'
     ctx.excl += ' **/doc/full/* **/doc/web/*'
@@ -544,6 +635,7 @@ def dist(ctx):
     ctx.excl += ' **/python/*.db'
     ctx.excl += ' **/python.old/*'
     ctx.excl += ' **/python/*/*.old'
+    ctx.excl += ' **/python/lib/aubio/*.so'
     ctx.excl += ' **/python/tests/sounds'
     ctx.excl += ' **/**.asc'
     ctx.excl += ' **/dist*'
@@ -551,3 +643,6 @@ def dist(ctx):
     ctx.excl += ' **/.travis.yml'
     ctx.excl += ' **/.landscape.yml'
     ctx.excl += ' **/.appveyor.yml'
+    ctx.excl += ' **/.circleci/*'
+    ctx.excl += ' **/azure-pipelines.yml'
+    ctx.excl += ' **/.coverage*'