The setup script now attempts to build the _aubio extension as follows: - if src/aubio.h is found, use it to generate python/gen/ files - if build/src/ is found, use it to link python-aubio against libaubio - otherwise: - add all libaubio source (src/*) to the python module sources - look for optional dependencies using pkg-config - set flags accordingly - otherwise, look for aubio headers and libraries using pkg-config This should help building the python module in a virtualenv (#2), on windows (#55), and allow installing aubio directly with pip.
Showing the changes to python (1 of 2 files). Show all
Unified · Split
| @@ -1,6 +1,114 @@ | ||
| 1 | +""" A collection of function used from setup.py distutils script """ | |
| 2 | +# | |
| 3 | +import sys, os, glob, subprocess | |
| 1 | 4 | import distutils, distutils.command.clean, distutils.dir_util |
| 2 | 5 | from .gen_external import generate_external, header, output_path |
| 3 | 6 | |
| 7 | +# inspired from https://gist.github.com/abergmeier/9488990 | |
| 8 | +def add_packages(packages, ext=None, **kw): | |
| 9 | + """ use pkg-config to search which of 'packages' are installed """ | |
| 10 | + flag_map = { | |
| 11 | + '-I': 'include_dirs', | |
| 12 | + '-L': 'library_dirs', | |
| 13 | + '-l': 'libraries'} | |
| 14 | + | |
| 15 | + # if a setuptools extension is passed, fill it with pkg-config results | |
| 16 | + if ext: | |
| 17 | + kw = {'include_dirs': ext.include_dirs, | |
| 18 | + 'extra_link_args': ext.extra_link_args, | |
| 19 | + 'library_dirs': ext.library_dirs, | |
| 20 | + 'libraries': ext.libraries, | |
| 21 | + } | |
| 22 | + | |
| 23 | + for package in packages: | |
| 24 | + try: | |
| 25 | + cmd = ['pkg-config', '--libs', '--cflags', package] | |
| 26 | + tokens = subprocess.check_output(cmd) | |
| 27 | + except subprocess.CalledProcessError: | |
| 28 | + print("{:s} could not be found".format(package)) | |
| 29 | + continue | |
| 30 | + tokens = tokens.decode('utf8').split() | |
| 31 | + for token in tokens: | |
| 32 | + key = token[:2] | |
| 33 | + try: | |
| 34 | + arg = flag_map[key] | |
| 35 | + value = token[2:] | |
| 36 | + except KeyError: | |
| 37 | + arg = 'extra_link_args' | |
| 38 | + value = token | |
| 39 | + kw.setdefault(arg, []).append(value) | |
| 40 | + for key, value in iter(kw.items()): # remove duplicated | |
| 41 | + kw[key] = list(set(value)) | |
| 42 | + return kw | |
| 43 | + | |
| 44 | +def add_local_aubio_header(ext): | |
| 45 | + """ use local "src/aubio.h", not <aubio/aubio.h>""" | |
| 46 | + ext.define_macros += [('USE_LOCAL_AUBIO', 1)] | |
| 47 | + ext.include_dirs += ['src'] # aubio.h | |
| 48 | + | |
| 49 | +def add_local_aubio_lib(ext): | |
| 50 | + """ add locally built libaubio from build/src """ | |
| 51 | + print("Info: using locally built libaubio") | |
| 52 | + ext.library_dirs += [os.path.join('build', 'src')] | |
| 53 | + ext.libraries += ['aubio'] | |
| 54 | + | |
| 55 | +def add_local_aubio_sources(ext): | |
| 56 | + """ build aubio inside python module instead of linking against libaubio """ | |
| 57 | + print("Warning: libaubio was not built with waf, adding src/") | |
| 58 | + # create an empty header, macros will be passed on the command line | |
| 59 | + fake_config_header = os.path.join('python', 'ext', 'config.h') | |
| 60 | + distutils.file_util.write_file(fake_config_header, "") | |
| 61 | + aubio_sources = glob.glob(os.path.join('src', '**.c')) | |
| 62 | + aubio_sources += glob.glob(os.path.join('src', '*', '**.c')) | |
| 63 | + ext.sources += aubio_sources | |
| 64 | + # define macros (waf puts them in build/src/config.h) | |
| 65 | + for define_macro in ['HAVE_STDLIB_H', 'HAVE_STDIO_H', | |
| 66 | + 'HAVE_MATH_H', 'HAVE_STRING_H', | |
| 67 | + 'HAVE_LIMITS_H', 'HAVE_MEMCPY_HACKS']: | |
| 68 | + ext.define_macros += [(define_macro, 1)] | |
| 69 | + | |
| 70 | + # loof for additional packages | |
| 71 | + print("Info: looking for *optional* additional packages") | |
| 72 | + packages = ['libavcodec', 'libavformat', 'libavutil', 'libavresample', | |
| 73 | + 'jack', | |
| 74 | + 'sndfile', 'samplerate', | |
| 75 | + #'fftw3f', | |
| 76 | + ] | |
| 77 | + add_packages(packages, ext=ext) | |
| 78 | + if 'avcodec' in ext.libraries \ | |
| 79 | + and 'avformat' in ext.libraries \ | |
| 80 | + and 'avutil' in ext.libraries \ | |
| 81 | + and 'avresample' in ext.libraries: | |
| 82 | + ext.define_macros += [('HAVE_LIBAV', 1)] | |
| 83 | + if 'jack' in ext.libraries: | |
| 84 | + ext.define_macros += [('HAVE_JACK', 1)] | |
| 85 | + if 'sndfile' in ext.libraries: | |
| 86 | + ext.define_macros += [('HAVE_SNDFILE', 1)] | |
| 87 | + if 'samplerate' in ext.libraries: | |
| 88 | + ext.define_macros += [('HAVE_SAMPLERATE', 1)] | |
| 89 | + if 'fftw3f' in ext.libraries: | |
| 90 | + ext.define_macros += [('HAVE_FFTW3F', 1)] | |
| 91 | + ext.define_macros += [('HAVE_FFTW3', 1)] | |
| 92 | + | |
| 93 | + # add accelerate on darwin | |
| 94 | + if sys.platform.startswith('darwin'): | |
| 95 | + ext.extra_link_args += ['-framework', 'accelerate'] | |
| 96 | + ext.define_macros += [('HAVE_ACCELERATE', 1)] | |
| 97 | + | |
| 98 | + ext.define_macros += [('HAVE_WAVWRITE', 1)] | |
| 99 | + ext.define_macros += [('HAVE_WAVREAD', 1)] | |
| 100 | + # TODO: | |
| 101 | + # add cblas | |
| 102 | + if 0: | |
| 103 | + ext.libraries += ['cblas'] | |
| 104 | + ext.define_macros += [('HAVE_ATLAS_CBLAS_H', 1)] | |
| 105 | + | |
| 106 | +def add_system_aubio(ext): | |
| 107 | + # use pkg-config to find aubio's location | |
| 108 | + add_packages(['aubio'], ext) | |
| 109 | + if 'aubio' not in ext.libraries: | |
| 110 | + print("Error: libaubio not found") | |
| 111 | + | |
| 4 | 112 | class CleanGenerated(distutils.command.clean.clean): |
| 5 | 113 | def run(self): |
| 6 | 114 | distutils.dir_util.remove_tree(output_path) |
| @@ -24,4 +132,4 @@ class GenerateCommand(distutils.cmd.Command): · 17 unmodified lines | ||
| 24 | 132 | |
| 25 | 133 | def run(self): |
| 26 | 134 | self.announce( 'Generating code', level=distutils.log.INFO) |
| 27 | − generated_object_files = generate_external(header, output_path, usedouble = self.enable_double) | |
| 135 | + generated_object_files = generate_external(header, output_path, usedouble=self.enable_double) | |