Changes in / [ddea34b:a1cce65]
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
python/lib/gen_external.py
rddea34b ra1cce65 1 1 import distutils.ccompiler 2 import sys 3 import os 4 import subprocess 5 import glob 2 import sys, os, subprocess, glob 6 3 7 4 header = os.path.join('src', 'aubio.h') … … 12 9 """ 13 10 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 11 skip_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 ] 48 44 49 45 def get_preprocessor(): … … 64 60 65 61 cpp_cmd = None 66 if hasattr(compiler, 'preprocessor'): 62 if hasattr(compiler, 'preprocessor'): # for unixccompiler 67 63 cpp_cmd = compiler.preprocessor 68 elif hasattr(compiler, 'compiler'): 64 elif hasattr(compiler, 'compiler'): # for ccompiler 69 65 cpp_cmd = compiler.compiler.split() 70 66 cpp_cmd += ['-E'] 71 elif hasattr(compiler, 'cc'): 67 elif hasattr(compiler, 'cc'): # for msvccompiler 72 68 cpp_cmd = compiler.cc.split() 73 69 cpp_cmd += ['-E'] … … 77 73 cpp_cmd = os.environ.get('CC', 'cc').split() 78 74 cpp_cmd += ['-E'] 79 cpp_cmd += ['-x', 'c'] # force C language (emcc defaults to c++) 75 80 76 return cpp_cmd 81 77 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 ''' 78 def get_cpp_objects(header=header, usedouble=False): 86 79 cpp_cmd = get_preprocessor() 87 80 … … 99 92 print("Running command: {:s}".format(" ".join(cpp_cmd))) 100 93 proc = subprocess.Popen(cpp_cmd, 101 102 94 stderr=subprocess.PIPE, 95 stdout=subprocess.PIPE) 103 96 assert proc, 'Proc was none' 104 97 cpp_output = proc.stdout.read() … … 107 100 raise Exception("preprocessor output is empty:\n%s" % err_output) 108 101 elif err_output: 109 print ("Warning: preprocessor produced warnings:\n%s" % err_output)102 print ("Warning: preprocessor produced warnings:\n%s" % err_output) 110 103 if not isinstance(cpp_output, list): 111 104 cpp_output = [l.strip() for l in cpp_output.decode('utf8').split('\n')] … … 116 109 i = 1 117 110 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) 126 115 else: 127 116 i += 1 128 117 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 142 120 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 125 def analyze_cpp_output(cpp_objects, cpp_output): 177 126 lib = {} 178 127 179 128 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 184 134 lib[shortname] = {'struct': [], 'new': [], 'del': [], 'do': [], 'get': [], 'set': [], 'other': []} 185 135 lib[shortname]['longname'] = o 186 136 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 194 140 if 'typedef struct ' in fn: 195 141 lib[shortname]['struct'].append(fn) … … 205 151 lib[shortname]['set'].append(fn) 206 152 else: 207 # 153 #print "no idea what to do about", fn 208 154 lib[shortname]['other'].append(fn) 209 155 return lib 210 156 211 212 def print_c_declarations_results(lib, c_declarations): 213 for fn in c_declarations: 157 def print_cpp_output_results(lib, cpp_output): 158 for fn in cpp_output: 214 159 found = 0 215 160 for o in lib: … … 218 163 found = 1 219 164 if found == 0: 220 print ("missing", fn)165 print ("missing", fn) 221 166 222 167 for o in lib: 223 168 for family in lib[o]: 224 169 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] ) ) 226 171 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] ) ) 228 173 else: 229 print ("{:15s} {:10s} {:s}".format(o, family, lib[o][family]))174 print ( "{:15s} {:10s} {:s}".format(o, family, lib[o][family] ) ) 230 175 231 176 232 177 def 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) 243 185 244 186 sources_list = [] … … 249 191 for o in lib: 250 192 out = source_header 251 mapped = MappedObject(lib[o], usedouble =usedouble)193 mapped = MappedObject(lib[o], usedouble = usedouble) 252 194 out += mapped.gen_code() 253 195 output_file = os.path.join(output_path, 'gen-%s.c' % o) 254 196 with open(output_file, 'w') as f: 255 197 f.write(out) 256 print ("wrote %s" % output_file)198 print ("wrote %s" % output_file ) 257 199 sources_list.append(output_file) 258 200 … … 266 208 return ({pycheck_types}); 267 209 }} 268 """.format(pycheck_types =check_types)210 """.format(pycheck_types = check_types) 269 211 270 212 add_types = "".join([""" 271 213 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]) 273 215 out += """ 274 216 … … 277 219 {add_types} 278 220 }} 279 """.format(add_types =add_types)221 """.format(add_types = add_types) 280 222 281 223 output_file = os.path.join(output_path, 'aubio-generated.c') 282 224 with open(output_file, 'w') as f: 283 225 f.write(out) 284 print ("wrote %s" % output_file)226 print ("wrote %s" % output_file ) 285 227 sources_list.append(output_file) 286 228 … … 300 242 int generated_objects ( void ); 301 243 void add_generated_objects( PyObject *m ); 302 """.format(objlist =objlist)244 """.format(objlist = objlist) 303 245 304 246 output_file = os.path.join(output_path, 'aubio-generated.h') 305 247 with open(output_file, 'w') as f: 306 248 f.write(out) 307 print ("wrote %s" % output_file)249 print ("wrote %s" % output_file ) 308 250 # no need to add header to list of sources 309 251 … … 311 253 312 254 if __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] 317 257 generate_external(header, output_path) -
src/wscript_build
rddea34b ra1cce65 27 27 build_features = ['cstlib', 'cshlib'] 28 28 elif ctx.env['DEST_OS'] in ['emscripten']: 29 build_features = ['cstlib' ,'cshlib']29 build_features = ['cstlib'] 30 30 elif '--static' in ctx.env['LDFLAGS'] or '--static' in ctx.env['LINKFLAGS']: 31 31 # static in cflags, ... -
wscript
rddea34b ra1cce65 108 108 ctx.load('gnu_dirs') 109 109 110 target_platform = sys.platform111 if ctx.options.target_platform:112 target_platform = ctx.options.target_platform113 114 115 if target_platform=='emscripten':116 # need to force spaces between flag -o and path117 # 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', '']122 110 # check for common headers 123 111 ctx.check(header_name='stdlib.h') … … 130 118 ctx.check(header_name='unistd.h', mandatory = False) 131 119 120 target_platform = sys.platform 121 if ctx.options.target_platform: 122 target_platform = ctx.options.target_platform 132 123 ctx.env['DEST_OS'] = target_platform 133 124 … … 142 133 ctx.env.prepend_value('CFLAGS', ['-O0']) 143 134 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']) 150 137 # enable debug symbols and configure warnings 151 138 ctx.env.prepend_value('CFLAGS', ['-g', '-Wall', '-Wextra']) … … 229 216 import os.path 230 217 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'] 246 219 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 262 222 263 223 # check support for C99 __VA_ARGS__ macros
Note: See TracChangeset
for help on using the changeset viewer.