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