def __init__(self, storage_dir=None, depdirs=(), include_paths=(), define_symbols=(), undefine_symbols=(), extra_opts=(), working_dir=None, type_mappers=()): if storage_dir is None: self.storage_dir = tempfile.mkdtemp() self.scrap_dir = True else: self.storage_dir = os.path.abspath(storage_dir) self.scrap_dir = False self.depdirs = allabs(list(depdirs)) + [self.storage_dir] self.include_paths = allabs(include_paths) self.define_symbols = define_symbols self.undefine_symbols = undefine_symbols self.extra_opts = extra_opts if working_dir is None: self.working_dir = self.storage_dir else: self.working_dir = os.path.abspath(working_dir) self.type_mappers = type_mappers self.depfile = os.path.join(self.storage_dir, 'deps.json') self.builder = Builder(dirs=self.depdirs, depsname=self.depfile, debug=True) self.libcache = {}
def __init__(self, storage_dir = None, depdirs = (), include_paths = (), define_symbols = (), undefine_symbols = (), extra_opts = (), working_dir = None, type_mappers = ()): if storage_dir is None: self.storage_dir = tempfile.mkdtemp() self.scrap_dir = True else: self.storage_dir = os.path.abspath(storage_dir) self.scrap_dir = False self.depdirs = allabs(list(depdirs))+[self.storage_dir] self.include_paths = allabs(include_paths) self.define_symbols = define_symbols self.undefine_symbols = undefine_symbols self.extra_opts = extra_opts if working_dir is None: self.working_dir = self.storage_dir else: self.working_dir = os.path.abspath(working_dir) self.type_mappers = type_mappers self.depfile = os.path.join(self.storage_dir, 'deps.json') self.builder = Builder(dirs = self.depdirs, depsname = self.depfile, debug=True) self.libcache = {}
class CtypesBuilder(object): def __init__(self, storage_dir=None, depdirs=(), include_paths=(), define_symbols=(), undefine_symbols=(), extra_opts=(), working_dir=None, type_mappers=()): if storage_dir is None: self.storage_dir = tempfile.mkdtemp() self.scrap_dir = True else: self.storage_dir = os.path.abspath(storage_dir) self.scrap_dir = False self.depdirs = allabs(list(depdirs)) + [self.storage_dir] self.include_paths = allabs(include_paths) self.define_symbols = define_symbols self.undefine_symbols = undefine_symbols self.extra_opts = extra_opts if working_dir is None: self.working_dir = self.storage_dir else: self.working_dir = os.path.abspath(working_dir) self.type_mappers = type_mappers self.depfile = os.path.join(self.storage_dir, 'deps.json') self.builder = Builder(dirs=self.depdirs, depsname=self.depfile, debug=True) self.libcache = {} def lazy_getlib(self, *args, **kwargs): return self.buildlib(*args, **kwargs) def getlib(self, *args, **kwargs): lazy = kwargs.pop('lazy', True) if lazy: return self.lazy_buildlib(*args, **kwargs) return self.buildlib(*args, **kwargs) def buildlib(self, libfile, sources=(), depdirs=(), include_paths=(), define_symbols=(), undefine_symbols=(), extra_opts=(), working_dir=None, export_dirs=(), cmd=(), force_rebuild=False, extra_mappers=()): if working_dir is None: raise Exception("Must specify working_dir.") if isinstance(sources, basestring): sources = [sources] if not export_dirs and working_dir: export_dirs = (working_dir, ) export_dirs = allabs(export_dirs) depdirs = allabs(list(depdirs) + list(self.depdirs)) include_paths = allabs(list(include_paths) + list(self.include_paths)) define_symbols = list(define_symbols) + list(self.define_symbols) undefine_symbols = list(undefine_symbols) + list(self.undefine_symbols) extra_opts = list(extra_opts) + list(self.extra_opts) type_mappers = list(extra_mappers) + list(self.type_mappers) if working_dir is None: working_dir = self.working_dir else: working_dir = os.path.abspath(working_dir) with chdir(working_dir): if force_rebuild and os.path.exists(libfile): shutil.mv(libfile, libfile + '.bkp') if cmd: return self.dumb_get(libfile, cmd, depdirs) else: return self.smart_get(libfile, sources, depdirs, include_paths, define_symbols, undefine_symbols, extra_opts, working_dir, export_dirs, type_mappers=type_mappers) lazy_buildlib = makelazy(buildlib) def smart_get(self, libfile, sources, depdirs, include_paths, define_symbols, undefine_symbols, extra_opts, working_dir, export_dirs, type_mappers=()): key = ` [ libfile, sources, depdirs, include_paths, define_symbols, undefine_symbols, extra_opts, working_dir, export_dirs ] ` cmd = ['g++', '-Wno-attributes', '-Wno-deprecated', '-shared' ] + sources + ['-o', libfile, '-fPIC'] cmd += ['-I' + inc for inc in include_paths] cmd += ['-D' + sym for sym in define_symbols] cmd += ['-U' + sym for sym in undefine_symbols] cmd += extra_opts command, deps, outputs = self.builder.run(cmd) rebuilt = (deps is not None) or (outputs is not None) retyped = False xml = self.getxml(libfile, force_rebuild=rebuilt) if xml is None: xml = parse(sources, working_directory=working_dir, include_paths=include_paths, define_symbols=define_symbols, undefine_symbols=undefine_symbols) self.savexml(libfile, xml) retyped = True return self.loadlib(key, libfile, rebuilt or retyped, xml, export_dirs, type_mappers=type_mappers) def loadlib(self, key, libfile, force_retype=False, xml=None, export_dirs=None, type_mappers=()): if force_retype or key not in self.libcache: lib = ctypes.cdll.LoadLibrary(libfile) if xml is not None and export_dirs is not None: for fn in extract_fns(xml, export_dirs=export_dirs): func = Func(xml, fn, mappers=type_mappers) if func.valid_types: func.assign(lib) else: setattr(lib, func.name, UnloadedFn(func.name, func.reason)) self.libcache[key] = lib return self.libcache[key] def dumb_get(self, libfile, command, depdirs): depdirs = list(depdirs) + self.depdirs key = ` [libfile, command, depdirs] ` cmdstr, deps, outputs = self.builder.run(command) rebuilt = (deps is not None) or (outputs is not None) return self.loadlib(key, libfile, force_retype=rebuilt) def xmlname(self, libfile): return libfile + '.typeinfo.pickle' def getxml(self, libfile, force_rebuild=False): name = self.xmlname(libfile) if os.path.exists(name) and not force_rebuild: return cPickle.load(open(name)) return None def savexml(self, libfile, funcs): cPickle.dump(funcs, open(self.xmlname(libfile), 'w')) def __del__(self): # Somehow yaml's cleanup seems to clobber shutil? # or at least, I get errors without this hack, but only if I import yaml... global shutil try: import shutil except: pass if self.scrap_dir and shutil is not None: shutil.rmtree(self.storage_dir)
class CtypesBuilder(object): def __init__(self, storage_dir = None, depdirs = (), include_paths = (), define_symbols = (), undefine_symbols = (), extra_opts = (), working_dir = None, type_mappers = ()): if storage_dir is None: self.storage_dir = tempfile.mkdtemp() self.scrap_dir = True else: self.storage_dir = os.path.abspath(storage_dir) self.scrap_dir = False self.depdirs = allabs(list(depdirs))+[self.storage_dir] self.include_paths = allabs(include_paths) self.define_symbols = define_symbols self.undefine_symbols = undefine_symbols self.extra_opts = extra_opts if working_dir is None: self.working_dir = self.storage_dir else: self.working_dir = os.path.abspath(working_dir) self.type_mappers = type_mappers self.depfile = os.path.join(self.storage_dir, 'deps.json') self.builder = Builder(dirs = self.depdirs, depsname = self.depfile, debug=True) self.libcache = {} def lazy_getlib(self, *args, **kwargs): return self.buildlib(*args, **kwargs) def getlib(self, *args, **kwargs): lazy = kwargs.pop('lazy', True) if lazy: return self.lazy_buildlib(*args, **kwargs) return self.buildlib(*args, **kwargs) def buildlib(self, libfile, sources=(), depdirs = (), include_paths = (), define_symbols = (), undefine_symbols = (), extra_opts = (), working_dir = None, export_dirs = (), cmd=(), force_rebuild=False, extra_mappers=()): if working_dir is None: raise Exception("Must specify working_dir.") if isinstance(sources, basestring): sources = [sources] if not export_dirs and working_dir: export_dirs = (working_dir,) export_dirs = allabs(export_dirs) depdirs = allabs(list(depdirs) + list(self.depdirs)) include_paths = allabs(list(include_paths) + list(self.include_paths)) define_symbols = list(define_symbols) + list(self.define_symbols) undefine_symbols = list(undefine_symbols) + list(self.undefine_symbols) extra_opts = list(extra_opts) + list(self.extra_opts) type_mappers = list(extra_mappers) + list(self.type_mappers) if working_dir is None: working_dir = self.working_dir else: working_dir = os.path.abspath(working_dir) with chdir(working_dir): if force_rebuild and os.path.exists(libfile): shutil.mv(libfile, libfile+'.bkp') if cmd: return self.dumb_get(libfile, cmd, depdirs) else: return self.smart_get(libfile, sources, depdirs, include_paths, define_symbols, undefine_symbols, extra_opts, working_dir, export_dirs, type_mappers=type_mappers) lazy_buildlib = makelazy(buildlib) def smart_get(self, libfile, sources, depdirs, include_paths, define_symbols, undefine_symbols, extra_opts, working_dir, export_dirs, type_mappers=()): key = `[libfile, sources, depdirs, include_paths, define_symbols, undefine_symbols, extra_opts, working_dir, export_dirs]` cmd = ['g++', '-Wno-attributes', '-Wno-deprecated', '-shared'] + sources + ['-o', libfile, '-fPIC'] cmd += ['-I'+inc for inc in include_paths] cmd += ['-D'+sym for sym in define_symbols] cmd += ['-U'+sym for sym in undefine_symbols] cmd += extra_opts command, deps, outputs = self.builder.run(cmd) rebuilt = (deps is not None) or (outputs is not None) retyped = False xml = self.getxml(libfile, force_rebuild=rebuilt) if xml is None: xml = parse(sources, working_directory=working_dir, include_paths = include_paths, define_symbols = define_symbols, undefine_symbols = undefine_symbols) self.savexml(libfile, xml) retyped = True return self.loadlib(key, libfile, rebuilt or retyped, xml, export_dirs, type_mappers = type_mappers) def loadlib(self, key, libfile, force_retype = False, xml = None, export_dirs = None, type_mappers=()): if force_retype or key not in self.libcache: lib = ctypes.cdll.LoadLibrary(libfile) if xml is not None and export_dirs is not None: for fn in extract_fns(xml, export_dirs = export_dirs): func = Func(xml, fn, mappers=type_mappers) if func.valid_types: func.assign(lib) else: setattr(lib, func.name, UnloadedFn(func.name, func.reason)) self.libcache[key] = lib return self.libcache[key] def dumb_get(self, libfile, command, depdirs): depdirs = list(depdirs) + self.depdirs key = `[libfile, command, depdirs]` cmdstr, deps, outputs = self.builder.run(command) rebuilt = (deps is not None) or (outputs is not None) return self.loadlib(key, libfile, force_retype = rebuilt) def xmlname(self, libfile): return libfile + '.typeinfo.pickle' def getxml(self, libfile, force_rebuild=False): name = self.xmlname(libfile) if os.path.exists(name) and not force_rebuild: return cPickle.load(open(name)) return None def savexml(self, libfile, funcs): cPickle.dump(funcs, open(self.xmlname(libfile),'w')) def __del__(self): # Somehow yaml's cleanup seems to clobber shutil? # or at least, I get errors without this hack, but only if I import yaml... global shutil try: import shutil except: pass if self.scrap_dir and shutil is not None: shutil.rmtree(self.storage_dir)