Changes in / [ddea34b:a1cce65]


Ignore:
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • python/lib/gen_external.py

    rddea34b ra1cce65  
    11import distutils.ccompiler
    2 import sys
    3 import os
    4 import subprocess
    5 import glob
     2import sys, os, subprocess, glob
    63
    74header = os.path.join('src', 'aubio.h')
     
    129"""
    1310
    14 default_skip_objects = [
    15     # already in ext/
    16     'fft',
    17     'pvoc',
    18     'filter',
    19     'filterbank',
    20     # AUBIO_UNSTABLE
    21     'hist',
    22     'parameter',
    23     'scale',
    24     'beattracking',
    25     'resampler',
    26     'peakpicker',
    27     'pitchfcomb',
    28     'pitchmcomb',
    29     'pitchschmitt',
    30     'pitchspecacf',
    31     'pitchyin',
    32     'pitchyinfft',
    33     'sink',
    34     'sink_apple_audio',
    35     'sink_sndfile',
    36     'sink_wavwrite',
    37     #'mfcc',
    38     'source',
    39     'source_apple_audio',
    40     'source_sndfile',
    41     'source_avcodec',
    42     'source_wavread',
    43     #'sampler',
    44     'audio_unit',
    45     'spectral_whitening',
    46 ]
    47 
     11skip_objects = [
     12  # already in ext/
     13  'fft',
     14  'pvoc',
     15  'filter',
     16  'filterbank',
     17  # AUBIO_UNSTABLE
     18  'hist',
     19  'parameter',
     20  'scale',
     21  'beattracking',
     22  'resampler',
     23  'peakpicker',
     24  'pitchfcomb',
     25  'pitchmcomb',
     26  'pitchschmitt',
     27  'pitchspecacf',
     28  'pitchyin',
     29  'pitchyinfft',
     30  'sink',
     31  'sink_apple_audio',
     32  'sink_sndfile',
     33  'sink_wavwrite',
     34  #'mfcc',
     35  'source',
     36  'source_apple_audio',
     37  'source_sndfile',
     38  'source_avcodec',
     39  'source_wavread',
     40  #'sampler',
     41  'audio_unit',
     42  'spectral_whitening',
     43  ]
    4844
    4945def get_preprocessor():
     
    6460
    6561    cpp_cmd = None
    66     if hasattr(compiler, 'preprocessor'):  # for unixccompiler
     62    if hasattr(compiler, 'preprocessor'): # for unixccompiler
    6763        cpp_cmd = compiler.preprocessor
    68     elif hasattr(compiler, 'compiler'):  # for ccompiler
     64    elif hasattr(compiler, 'compiler'): # for ccompiler
    6965        cpp_cmd = compiler.compiler.split()
    7066        cpp_cmd += ['-E']
    71     elif hasattr(compiler, 'cc'):  # for msvccompiler
     67    elif hasattr(compiler, 'cc'): # for msvccompiler
    7268        cpp_cmd = compiler.cc.split()
    7369        cpp_cmd += ['-E']
     
    7773        cpp_cmd = os.environ.get('CC', 'cc').split()
    7874        cpp_cmd += ['-E']
    79     cpp_cmd += ['-x', 'c']  # force C language (emcc defaults to c++)
     75
    8076    return cpp_cmd
    8177
    82 
    83 def get_c_declarations(header=header, usedouble=False):
    84     ''' return a dense and preprocessed  string of all c declarations implied by aubio.h
    85     '''
     78def get_cpp_objects(header=header, usedouble=False):
    8679    cpp_cmd = get_preprocessor()
    8780
     
    9992    print("Running command: {:s}".format(" ".join(cpp_cmd)))
    10093    proc = subprocess.Popen(cpp_cmd,
    101                             stderr=subprocess.PIPE,
    102                             stdout=subprocess.PIPE)
     94            stderr=subprocess.PIPE,
     95            stdout=subprocess.PIPE)
    10396    assert proc, 'Proc was none'
    10497    cpp_output = proc.stdout.read()
     
    107100        raise Exception("preprocessor output is empty:\n%s" % err_output)
    108101    elif err_output:
    109         print("Warning: preprocessor produced warnings:\n%s" % err_output)
     102        print ("Warning: preprocessor produced warnings:\n%s" % err_output)
    110103    if not isinstance(cpp_output, list):
    111104        cpp_output = [l.strip() for l in cpp_output.decode('utf8').split('\n')]
     
    116109    i = 1
    117110    while 1:
    118         if i >= len(cpp_output):
    119             break
    120         if ('{' in cpp_output[i - 1]) and (not '}' in cpp_output[i - 1]) or (not ';' in cpp_output[i - 1]):
    121             cpp_output[i] = cpp_output[i - 1] + ' ' + cpp_output[i]
    122             cpp_output.pop(i - 1)
    123         elif ('}' in cpp_output[i]):
    124             cpp_output[i] = cpp_output[i - 1] + ' ' + cpp_output[i]
    125             cpp_output.pop(i - 1)
     111        if i >= len(cpp_output): break
     112        if cpp_output[i-1].endswith(',') or cpp_output[i-1].endswith('{') or cpp_output[i].startswith('}'):
     113            cpp_output[i] = cpp_output[i-1] + ' ' + cpp_output[i]
     114            cpp_output.pop(i-1)
    126115        else:
    127116            i += 1
    128117
    129     # clean pointer notations
    130     tmp = []
    131     for l in cpp_output:
    132         tmp += [l.replace(' *', ' * ')]
    133     cpp_output = tmp
    134 
    135     return cpp_output
    136 
    137 
    138 def get_cpp_objects_from_c_declarations(c_declarations, skip_objects=None):
    139     if skip_objects == None:
    140         skip_objects = default_skip_objects
    141     typedefs = filter(lambda y: y.startswith('typedef struct _aubio'), c_declarations)
     118    typedefs = filter(lambda y: y.startswith ('typedef struct _aubio'), cpp_output)
     119
    142120    cpp_objects = [a.split()[3][:-1] for a in typedefs]
    143     cpp_objects_filtered = filter(lambda y: not y[6:-2] in skip_objects, cpp_objects)
    144     return cpp_objects_filtered
    145 
    146 
    147 def get_all_func_names_from_lib(lib, depth=0):
    148     ''' return flat string of all function used in lib
    149     '''
    150     res = []
    151     indent = " " * depth
    152     for k, v in lib.items():
    153         if isinstance(v, dict):
    154             res += get_all_func_names_from_lib(v, depth + 1)
    155         elif isinstance(v, list):
    156             for elem in v:
    157                 e = elem.split('(')
    158                 if len(e) < 2:
    159                     continue  # not a function
    160                 fname_part = e[0].strip().split(' ')
    161                 fname = fname_part[-1]
    162                 if fname:
    163                     res += [fname]
    164                 else:
    165                     raise NameError('gen_lib : weird function: ' + str(e))
    166 
    167     return res
    168 
    169 
    170 def generate_lib_from_c_declarations(cpp_objects, c_declarations):
    171     ''' returns a lib from given cpp_object names
    172 
    173     a lib is a dict grouping functions by family (onset,pitch...)
    174         each eement is itself a dict of functions grouped by puposes as :
    175         struct, new, del, do, get, set and other
    176     '''
     121
     122    return cpp_output, cpp_objects
     123
     124
     125def analyze_cpp_output(cpp_objects, cpp_output):
    177126    lib = {}
    178127
    179128    for o in cpp_objects:
    180         shortname = o
    181         if o[:6] == 'aubio_':
    182             shortname = o[6:-2]  # without aubio_ prefix and _t suffix
    183 
     129        if o[:6] != 'aubio_':
     130            continue
     131        shortname = o[6:-2]
     132        if shortname in skip_objects:
     133            continue
    184134        lib[shortname] = {'struct': [], 'new': [], 'del': [], 'do': [], 'get': [], 'set': [], 'other': []}
    185135        lib[shortname]['longname'] = o
    186136        lib[shortname]['shortname'] = shortname
    187 
    188         fullshortname = o[:-2]  # name without _t suffix
    189 
    190         for fn in c_declarations:
    191             func_name = fn.split('(')[0].strip().split(' ')[-1]
    192             if func_name.startswith(fullshortname + '_') or func_name.endswith(fullshortname):
    193                 # print "found", shortname, "in", fn
     137        for fn in cpp_output:
     138            if o[:-1] in fn:
     139                #print "found", o[:-1], "in", fn
    194140                if 'typedef struct ' in fn:
    195141                    lib[shortname]['struct'].append(fn)
     
    205151                    lib[shortname]['set'].append(fn)
    206152                else:
    207                     # print "no idea what to do about", fn
     153                    #print "no idea what to do about", fn
    208154                    lib[shortname]['other'].append(fn)
    209155    return lib
    210156
    211 
    212 def print_c_declarations_results(lib, c_declarations):
    213     for fn in c_declarations:
     157def print_cpp_output_results(lib, cpp_output):
     158    for fn in cpp_output:
    214159        found = 0
    215160        for o in lib:
     
    218163                    found = 1
    219164        if found == 0:
    220             print("missing", fn)
     165            print ("missing", fn)
    221166
    222167    for o in lib:
    223168        for family in lib[o]:
    224169            if type(lib[o][family]) == str:
    225                 print("{:15s} {:10s} {:s}".format(o, family, lib[o][family]))
     170                print ( "{:15s} {:10s} {:s}".format(o, family, lib[o][family] ) )
    226171            elif len(lib[o][family]) == 1:
    227                 print("{:15s} {:10s} {:s}".format(o, family, lib[o][family][0]))
     172                print ( "{:15s} {:10s} {:s}".format(o, family, lib[o][family][0] ) )
    228173            else:
    229                 print("{:15s} {:10s} {:s}".format(o, family, lib[o][family]))
     174                print ( "{:15s} {:10s} {:s}".format(o, family, lib[o][family] ) )
    230175
    231176
    232177def generate_external(header=header, output_path=output_path, usedouble=False, overwrite=True):
    233     if not os.path.isdir(output_path):
    234         os.mkdir(output_path)
    235     elif not overwrite:
    236         return sorted(glob.glob(os.path.join(output_path, '*.c')))
    237 
    238     c_declarations = get_c_declarations(header, usedouble=usedouble)
    239     cpp_objects = get_cpp_objects_from_c_declarations(c_declarations)
    240 
    241     lib = generate_lib_from_c_declarations(cpp_objects, c_declarations)
    242     # print_c_declarations_results(lib, c_declarations)
     178    if not os.path.isdir(output_path): os.mkdir(output_path)
     179    elif not overwrite: return sorted(glob.glob(os.path.join(output_path, '*.c')))
     180
     181    cpp_output, cpp_objects = get_cpp_objects(header, usedouble=usedouble)
     182
     183    lib = analyze_cpp_output(cpp_objects, cpp_output)
     184    # print_cpp_output_results(lib, cpp_output)
    243185
    244186    sources_list = []
     
    249191    for o in lib:
    250192        out = source_header
    251         mapped = MappedObject(lib[o], usedouble=usedouble)
     193        mapped = MappedObject(lib[o], usedouble = usedouble)
    252194        out += mapped.gen_code()
    253195        output_file = os.path.join(output_path, 'gen-%s.c' % o)
    254196        with open(output_file, 'w') as f:
    255197            f.write(out)
    256             print("wrote %s" % output_file)
     198            print ("wrote %s" % output_file )
    257199            sources_list.append(output_file)
    258200
     
    266208  return ({pycheck_types});
    267209}}
    268 """.format(pycheck_types=check_types)
     210""".format(pycheck_types = check_types)
    269211
    270212    add_types = "".join(["""
    271213  Py_INCREF (&Py_{name}Type);
    272   PyModule_AddObject(m, "{name}", (PyObject *) & Py_{name}Type);""".format(name=o) for o in lib])
     214  PyModule_AddObject(m, "{name}", (PyObject *) & Py_{name}Type);""".format(name = o) for o in lib])
    273215    out += """
    274216
     
    277219{add_types}
    278220}}
    279 """.format(add_types=add_types)
     221""".format(add_types = add_types)
    280222
    281223    output_file = os.path.join(output_path, 'aubio-generated.c')
    282224    with open(output_file, 'w') as f:
    283225        f.write(out)
    284         print("wrote %s" % output_file)
     226        print ("wrote %s" % output_file )
    285227        sources_list.append(output_file)
    286228
     
    300242int generated_objects ( void );
    301243void add_generated_objects( PyObject *m );
    302 """.format(objlist=objlist)
     244""".format(objlist = objlist)
    303245
    304246    output_file = os.path.join(output_path, 'aubio-generated.h')
    305247    with open(output_file, 'w') as f:
    306248        f.write(out)
    307         print("wrote %s" % output_file)
     249        print ("wrote %s" % output_file )
    308250        # no need to add header to list of sources
    309251
     
    311253
    312254if __name__ == '__main__':
    313     if len(sys.argv) > 1:
    314         header = sys.argv[1]
    315     if len(sys.argv) > 2:
    316         output_path = sys.argv[2]
     255    if len(sys.argv) > 1: header = sys.argv[1]
     256    if len(sys.argv) > 2: output_path = sys.argv[2]
    317257    generate_external(header, output_path)
  • src/wscript_build

    rddea34b ra1cce65  
    2727    build_features = ['cstlib', 'cshlib']
    2828elif ctx.env['DEST_OS'] in ['emscripten']:
    29     build_features = ['cstlib','cshlib']
     29    build_features = ['cstlib']
    3030elif '--static' in ctx.env['LDFLAGS'] or '--static' in ctx.env['LINKFLAGS']:
    3131    # static in cflags, ...
  • wscript

    rddea34b ra1cce65  
    108108    ctx.load('gnu_dirs')
    109109
    110     target_platform = sys.platform
    111     if ctx.options.target_platform:
    112         target_platform = ctx.options.target_platform
    113 
    114 
    115     if target_platform=='emscripten':
    116         # need to force spaces between flag -o and path
    117         # inspired from :
    118         # https://github.com/waf-project/waf/blob/master/waflib/extras/c_emscripten.py (#1885)
    119         # (OSX /emscripten 1.37.9)
    120         ctx.env.CC_TGT_F            = ['-c', '-o', '']
    121         ctx.env.CCLNK_TGT_F         = ['-o', '']
    122110    # check for common headers
    123111    ctx.check(header_name='stdlib.h')
     
    130118    ctx.check(header_name='unistd.h', mandatory = False)
    131119
     120    target_platform = sys.platform
     121    if ctx.options.target_platform:
     122        target_platform = ctx.options.target_platform
    132123    ctx.env['DEST_OS'] = target_platform
    133124
     
    142133            ctx.env.prepend_value('CFLAGS', ['-O0'])
    143134        else:
    144             if target_platform == 'emscripten':
    145                 # -Oz for small js file generation
    146                 ctx.env.prepend_value('CFLAGS', ['-Oz'])
    147             else:
    148                 # default to -O2 in release mode
    149                 ctx.env.prepend_value('CFLAGS', ['-O2'])
     135            # default to -O2 in release mode
     136            ctx.env.prepend_value('CFLAGS', ['-O2'])
    150137        # enable debug symbols and configure warnings
    151138        ctx.env.prepend_value('CFLAGS', ['-g', '-Wall', '-Wextra'])
     
    229216        import os.path
    230217        ctx.env.CFLAGS += [ '-I' + os.path.join(os.environ['EMSCRIPTEN'], 'system', 'include') ]
    231        
    232         if ctx.options.build_type == "debug":
    233             ctx.env.cshlib_PATTERN = '%s.js'
    234             ctx.env.LINKFLAGS += ['-s','ASSERTIONS=2']
    235             ctx.env.LINKFLAGS += ['-s','SAFE_HEAP=1']
    236             ctx.env.LINKFLAGS += ['-s','ALIASING_FUNCTION_POINTERS=0']
    237             ctx.env.LINKFLAGS += ['-O0']
    238         else:
    239             ctx.env.LINKFLAGS += ['-Oz']
    240             ctx.env.cshlib_PATTERN = '%s.min.js'
    241 
    242         # doesnt ship file system support in lib
    243         ctx.env.LINKFLAGS_cshlib += ['-s', 'NO_FILESYSTEM=1']
    244         # put memory file inside generated js files for easier portability
    245         ctx.env.LINKFLAGS += ['--memory-init-file', '0']
     218        ctx.env.CFLAGS += ['-Oz']
    246219        ctx.env.cprogram_PATTERN = "%s.js"
    247         ctx.env.cstlib_PATTERN = '%s.a'
    248 
    249         # tell emscripten functions we want to expose
    250         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
    251         c_decls = get_c_declarations(usedouble=False)  # emscripten can't use double
    252         objects = get_cpp_objects_from_c_declarations(c_decls)
    253         # ensure that aubio structs are exported
    254         objects += ['fvec_t', 'cvec_t', 'fmat_t']
    255         lib = generate_lib_from_c_declarations(objects, c_decls)
    256         exported_funcnames = get_all_func_names_from_lib(lib)
    257         c_mangled_names = ['_' + s for s in exported_funcnames]
    258         ctx.env.LINKFLAGS_cshlib += ['-s', 'EXPORTED_FUNCTIONS=%s' % c_mangled_names]
    259 
    260     if (ctx.options.enable_atlas != True):
    261         ctx.options.enable_atlas = False
     220        if (ctx.options.enable_atlas != True):
     221            ctx.options.enable_atlas = False
    262222
    263223    # check support for C99 __VA_ARGS__ macros
Note: See TracChangeset for help on using the changeset viewer.