[ci] add pip install to readthedocs.yaml
[aubio.git] / wscript
diff --git a/wscript b/wscript
index fcf8703..8ea98f3 100644 (file)
--- a/wscript
+++ b/wscript
@@ -11,6 +11,7 @@
 # For more info about waf, see http://code.google.com/p/waf/ .
 
 import sys
+import subprocess
 
 APPNAME = 'aubio'
 
@@ -45,6 +46,12 @@ def options(ctx):
             help = 'whether to compile with (--build-type=release)' \
                     ' or without (--build-type=debug)' \
                     ' compiler opimizations [default: release]')
+    ctx.add_option('--debug', action = 'store_const',
+            dest = 'build_type', const = 'debug',
+            help = 'build in debug mode (see --build-type)')
+    ctx.add_option('--nodeps', action = 'store_const',
+            dest = 'nodeps', const = 'debug',
+            help = 'build with no external dependencies')
     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')
@@ -66,9 +73,18 @@ def options(ctx):
     add_option_enable_disable(ctx, 'avcodec', default = None,
             help_str = 'compile with libavcodec (auto)',
             help_disable_str = 'disable libavcodec')
+    add_option_enable_disable(ctx, 'vorbis', default = None,
+            help_str = 'compile with libvorbis (auto)',
+            help_disable_str = 'disable libvorbis')
+    add_option_enable_disable(ctx, 'flac', default = None,
+            help_str = 'compile with libFLAC (auto)',
+            help_disable_str = 'disable libflac')
     add_option_enable_disable(ctx, 'samplerate', default = None,
             help_str = 'compile with samplerate (auto)',
             help_disable_str = 'disable samplerate')
+    add_option_enable_disable(ctx, 'rubberband', default = None,
+            help_str = 'compile with rubberband (auto)',
+            help_disable_str = 'disable rubberband')
     add_option_enable_disable(ctx, 'memcpy', default = True,
             help_str = 'use memcpy hacks (default)',
             help_disable_str = 'do not use memcpy hacks')
@@ -123,6 +139,30 @@ def configure(ctx):
     if ctx.options.target_platform:
         target_platform = ctx.options.target_platform
 
+    if ctx.options.nodeps:
+        external_deps = [
+                'sndfile',
+                'samplerate',
+                'jack',
+                'rubberband',
+                'avcodec',
+                'blas',
+                'fftw3',
+                'fftw3f',
+                'flac',
+                'vorbis',
+        ]
+        for d in external_deps:
+            if not hasattr(ctx.options, 'enable_' + d):
+                raise ctx.errors.ConfigurationError ('--enable-%s missing from options' % d)
+            if getattr(ctx.options, 'enable_' + d) == True:
+                msg = 'Option --nodeps can not be used along with --enable-%s' % d
+                raise ctx.errors.ConfigurationError (msg)
+            elif getattr(ctx.options, 'enable_' + d) is None:
+                msg = 'Option --nodeps used but automatic detection with --enable-%s' % d
+                ctx.msg('Warning', msg)
+            setattr(ctx.options, 'enable_' + d, False)
+
     from waflib import Options
 
     if target_platform=='emscripten':
@@ -139,6 +179,7 @@ def configure(ctx):
     ctx.check(header_name='stdio.h')
     ctx.check(header_name='math.h')
     ctx.check(header_name='string.h')
+    ctx.check(header_name='errno.h')
     ctx.check(header_name='limits.h')
     ctx.check(header_name='stdarg.h')
     ctx.check(header_name='getopt.h', mandatory = False)
@@ -194,13 +235,13 @@ def configure(ctx):
         ctx.env['cshlib_PATTERN'] = 'lib%s.dll'
 
     if target_platform == 'darwin' and ctx.options.enable_fat:
-        ctx.env.CFLAGS += ['-arch', 'i386', '-arch', 'x86_64']
-        ctx.env.LINKFLAGS += ['-arch', 'i386', '-arch', 'x86_64']
+        ctx.env.CFLAGS += ['-arch', 'arm64', '-arch', 'x86_64']
+        ctx.env.LINKFLAGS += ['-arch', 'arm64', '-arch', 'x86_64']
         MINSDKVER="10.4"
         ctx.env.CFLAGS += [ '-mmacosx-version-min=' + MINSDKVER ]
         ctx.env.LINKFLAGS += [ '-mmacosx-version-min=' + MINSDKVER ]
 
-    if target_platform in [ 'darwin', 'ios', 'iosimulator']:
+    if target_platform in [ 'darwin', 'ios', 'iosimulator' ]:
         if (ctx.options.enable_apple_audio != False):
             ctx.env.FRAMEWORK += ['CoreFoundation', 'AudioToolbox']
             ctx.define('HAVE_SOURCE_APPLE_AUDIO', 1)
@@ -217,16 +258,28 @@ def configure(ctx):
             ctx.msg('Checking for Accelerate framework', 'no (disabled)',
                     color = 'YELLOW')
 
-    if target_platform in [ 'ios', 'iosimulator' ]:
+    if target_platform in [ 'ios', 'iosimulator', 'watchos', 'watchsimulator' ]:
         MINSDKVER="6.1"
+        xcodeslct_output = subprocess.check_output (['xcode-select', '--print-path'])
+        XCODEPATH = xcodeslct_output.decode(sys.stdout.encoding).strip()
+        if target_platform == 'ios':
+            SDKNAME = "iPhoneOS"
+        elif target_platform == 'iosimulator':
+            SDKNAME = "iPhoneSimulator"
+        elif target_platform == 'watchos':
+            SDKNAME = "WatchOS"
+        elif target_platform == 'watchsimulator':
+            SDKNAME = "WatchSimulator"
+        else:
+            raise ctx.errors.ConfigurationError ("Error: unknown target platform '"
+                + target_platform + "'")
+        DEVROOT = "%(XCODEPATH)s/Platforms/%(SDKNAME)s.platform/Developer" % locals()
+        SDKROOT = "%(DEVROOT)s/SDKs/%(SDKNAME)s.sdk" % locals()
         ctx.env.CFLAGS += ['-std=c99']
-        if (ctx.options.enable_apple_audio != False):
+        if ctx.options.enable_apple_audio != False and target_platform.startswith ('ios'):
             ctx.define('HAVE_AUDIO_UNIT', 1)
             #ctx.env.FRAMEWORK += ['CoreFoundation', 'AudioToolbox']
         if target_platform == 'ios':
-            DEVROOT = "/Applications/Xcode.app/Contents"
-            DEVROOT += "/Developer/Platforms/iPhoneOS.platform/Developer"
-            SDKROOT = "%(DEVROOT)s/SDKs/iPhoneOS.sdk" % locals()
             ctx.env.CFLAGS += [ '-fembed-bitcode' ]
             ctx.env.CFLAGS += [ '-arch', 'arm64' ]
             ctx.env.CFLAGS += [ '-arch', 'armv7' ]
@@ -236,16 +289,27 @@ def configure(ctx):
             ctx.env.LINKFLAGS += ['-arch', 'armv7s']
             ctx.env.CFLAGS += [ '-miphoneos-version-min=' + MINSDKVER ]
             ctx.env.LINKFLAGS += [ '-miphoneos-version-min=' + MINSDKVER ]
-        else:
-            DEVROOT = "/Applications/Xcode.app/Contents"
-            DEVROOT += "/Developer/Platforms/iPhoneSimulator.platform/Developer"
-            SDKROOT = "%(DEVROOT)s/SDKs/iPhoneSimulator.sdk" % locals()
-            ctx.env.CFLAGS += [ '-arch', 'i386' ]
+        elif target_platform == 'iosimulator':
             ctx.env.CFLAGS += [ '-arch', 'x86_64' ]
-            ctx.env.LINKFLAGS += ['-arch', 'i386']
+            ctx.env.CFLAGS += [ '-arch', 'arm64' ]
             ctx.env.LINKFLAGS += ['-arch', 'x86_64']
+            ctx.env.LINKFLAGS += ['-arch', 'arm64']
             ctx.env.CFLAGS += [ '-mios-simulator-version-min=' + MINSDKVER ]
             ctx.env.LINKFLAGS += [ '-mios-simulator-version-min=' + MINSDKVER ]
+        elif target_platform == 'watchos':
+            ctx.env.CFLAGS += [ '-arch', 'armv7' ]
+            ctx.env.CFLAGS += [ '-arch', 'armv7s' ]
+            ctx.env.LINKFLAGS += ['-arch', 'armv7']
+            ctx.env.LINKFLAGS += ['-arch', 'armv7s']
+            ctx.env.CFLAGS += [ '-mwatchos-version-min=' + MINSDKVER ]
+            ctx.env.LINKFLAGS += [ '-mwatchos-version-min=' + MINSDKVER ]
+        elif target_platform == 'watchsimulator':
+            ctx.env.CFLAGS += [ '-arch', 'x86_64' ]
+            ctx.env.CFLAGS += [ '-arch', 'arm64' ]
+            ctx.env.LINKFLAGS += ['-arch', 'x86_64']
+            ctx.env.LINKFLAGS += ['-arch', 'arm64']
+            ctx.env.CFLAGS += [ '-mwatchsimulator-version-min=' + MINSDKVER ]
+            ctx.env.LINKFLAGS += [ '-mwatchsimulator-version-min=' + MINSDKVER ]
         ctx.env.CFLAGS += [ '-isysroot' , SDKROOT]
         ctx.env.LINKFLAGS += [ '-isysroot' , SDKROOT]
 
@@ -380,6 +444,12 @@ def configure(ctx):
                 args = '--cflags --libs samplerate >= 0.0.15',
                 mandatory = ctx.options.enable_samplerate)
 
+    # check for librubberband
+    if (ctx.options.enable_rubberband != False):
+        ctx.check_cfg(package = 'rubberband', atleast_version = '1.3',
+                args = '--cflags --libs',
+                mandatory = ctx.options.enable_rubberband)
+
     # check for jack
     if (ctx.options.enable_jack != False):
         ctx.check_cfg(package = 'jack',
@@ -404,11 +474,6 @@ def configure(ctx):
                 args = '--cflags --libs libswresample >= 1.2.0',
                 uselib_store = 'SWRESAMPLE',
                 mandatory = False)
-        if 'HAVE_SWRESAMPLE' not in ctx.env:
-            ctx.check_cfg(package = 'libavresample',
-                    args = '--cflags --libs libavresample >= 1.0.1',
-                    uselib_store = 'AVRESAMPLE',
-                    mandatory = False)
 
         msg_check = 'Checking for all libav libraries'
         if 'HAVE_AVCODEC' not in ctx.env:
@@ -417,18 +482,27 @@ 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:
-            resample_missing = 'not found (avresample or swresample required)'
+        elif 'HAVE_SWRESAMPLE' not in ctx.env :
+            resample_missing = 'not found (missing swresample)'
             ctx.msg(msg_check, resample_missing, color = 'YELLOW')
         else:
             ctx.msg(msg_check, 'yes')
-            if 'HAVE_SWRESAMPLE' in ctx.env:
-                ctx.define('HAVE_SWRESAMPLE', 1)
-            elif 'HAVE_AVRESAMPLE' in ctx.env:
-                ctx.define('HAVE_AVRESAMPLE', 1)
             ctx.define('HAVE_LIBAV', 1)
 
+    # check for vorbisenc
+    if (ctx.options.enable_vorbis != False):
+        ctx.check_cfg(package = 'vorbisenc vorbis ogg',
+                args = '--cflags --libs',
+                uselib_store = 'VORBISENC',
+                mandatory = ctx.options.enable_vorbis)
+
+    # check for flac
+    if (ctx.options.enable_flac != False):
+        ctx.check_cfg(package = 'flac',
+                args = '--cflags --libs',
+                uselib_store = 'FLAC',
+                mandatory = ctx.options.enable_flac)
+
     if (ctx.options.enable_wavread != False):
         ctx.define('HAVE_WAVREAD', 1)
     ctx.msg('Checking if using source_wavread',
@@ -501,7 +575,7 @@ def build(bld):
     bld.recurse('src')
 
     # add sub directories
-    if bld.env['DEST_OS'] not in ['ios', 'iosimulator', 'android']:
+    if bld.env['DEST_OS'] not in ['ios', 'iosimulator', 'watchos', 'watchsimulator', 'android']:
         if bld.env['DEST_OS']=='emscripten' and not bld.options.testcmd:
             bld.options.testcmd = 'node %s'
         if bld.options.enable_examples:
@@ -546,32 +620,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']:
+    # build documentation from source files using sphinx-build
+    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
@@ -616,7 +703,7 @@ def dist(ctx):
     ctx.excl += ' **/.pytest_cache'
     ctx.excl += ' **/.cache'
     ctx.excl += ' **/**.zip **/**.tar.bz2'
-    ctx.excl += ' **.tar.bz2'
+    ctx.excl += ' **.tar.bz2**'
     ctx.excl += ' **/doc/full/* **/doc/web/*'
     ctx.excl += ' **/doc/full.cfg'
     ctx.excl += ' **/python/*.db'
@@ -628,7 +715,6 @@ def dist(ctx):
     ctx.excl += ' **/dist*'
     ctx.excl += ' **/.DS_Store'
     ctx.excl += ' **/.travis.yml'
-    ctx.excl += ' **/.landscape.yml'
     ctx.excl += ' **/.appveyor.yml'
     ctx.excl += ' **/.circleci/*'
     ctx.excl += ' **/azure-pipelines.yml'