def compile_module(space, modname, **kwds): """ Build an extension module and return the filename of the resulting native code file. modname is the name of the module, possibly including dots if it is a module inside a package. Any extra keyword arguments are passed on to ExternalCompilationInfo to build the module (so specify your source with one of those). """ modname = modname.split('.')[-1] eci = ExternalCompilationInfo( export_symbols=['init%s' % (modname,)], include_dirs=api.include_dirs, **kwds ) eci = eci.convert_sources_to_files() dirname = (udir/uniquemodulename('module')).ensure(dir=1) soname = platform.platform.compile( [], eci, outputfilename=str(dirname/modname), standalone=False) from pypy.module.imp.importing import get_so_extension pydname = soname.new(purebasename=modname, ext=get_so_extension(space)) soname.rename(pydname) return str(pydname)
def test_gcc_ask(): f = localudir.join("y.c") f.write(""" #include <stdio.h> #include <test_gcc_ask.h> int main() { printf("hello\\n"); return 0; } """) dir1 = localudir.join('test_gcc_ask_dir1').ensure(dir=1) dir2 = localudir.join('test_gcc_ask_dir2').ensure(dir=1) dir1.join('test_gcc_ask.h').write('/* hello world */\n') dir2.join('test_gcc_ask.h').write('#error boom\n') eci = ExternalCompilationInfo(include_dirs=[str(dir1)]) # remove cache path = cache_file_path([f], eci, 'try_compile_cache') if path.check(): path.remove() assert try_compile_cache([f], eci) assert try_compile_cache([f], eci) assert build_executable_cache([f], eci) == "hello\n" eci2 = ExternalCompilationInfo(include_dirs=[str(dir2)]) err = py.test.raises(CompilationError, try_compile_cache, [f], eci2) print '<<<' print err print '>>>'
def test_gcc_exec(): f = localudir.join("x.c") f.write(""" #include <stdio.h> #include <test_gcc_exec.h> int main() { printf("%d\\n", ANSWER); return 0; } """) dir1 = localudir.join('test_gcc_exec_dir1').ensure(dir=1) dir2 = localudir.join('test_gcc_exec_dir2').ensure(dir=1) dir1.join('test_gcc_exec.h').write('#define ANSWER 3\n') dir2.join('test_gcc_exec.h').write('#define ANSWER 42\n') eci = ExternalCompilationInfo(include_dirs=[str(dir1)]) # remove cache path = cache_file_path([f], eci, 'build_executable_cache') if path.check(): path.remove() res = build_executable_cache([f], eci) assert res == "3\n" assert build_executable_cache([f], eci) == "3\n" eci2 = ExternalCompilationInfo(include_dirs=[str(dir2)]) assert build_executable_cache([f], eci2) == "42\n" f.write("#error BOOM\n") err = py.test.raises(CompilationError, build_executable_cache, [f], eci2) print '<<<' print err print '>>>'
def compile_module(space, modname, **kwds): """ Build an extension module and return the filename of the resulting native code file. modname is the name of the module, possibly including dots if it is a module inside a package. Any extra keyword arguments are passed on to ExternalCompilationInfo to build the module (so specify your source with one of those). """ modname = modname.split('.')[-1] eci = ExternalCompilationInfo(export_symbols=['init%s' % (modname, )], include_dirs=api.include_dirs, **kwds) eci = eci.convert_sources_to_files() dirname = (udir / uniquemodulename('module')).ensure(dir=1) soname = platform.platform.compile([], eci, outputfilename=str(dirname / modname), standalone=False) from pypy.module.imp.importing import get_so_extension pydname = soname.new(purebasename=modname, ext=get_so_extension(space)) soname.rename(pydname) return str(pydname)
def llexternal_use_eci(compilation_info): """Return a dummy function that, if called in a RPython program, adds the given ExternalCompilationInfo to it.""" eci = ExternalCompilationInfo(post_include_bits=['#define PYPY_NO_OP()']) eci = eci.merge(compilation_info) return llexternal('PYPY_NO_OP', [], lltype.Void, compilation_info=eci, sandboxsafe=True, _nowrapper=True, _callable=lambda: None)
def compilation_info(self): if not self.db: return ExternalCompilationInfo() gct = self.db.gctransformer return ExternalCompilationInfo(pre_include_bits=[ '/* using %s */' % (gct.__class__.__name__, ), '#define MALLOC_ZERO_FILLED %d' % (gct.malloc_zero_filled, ), ])
def get_eci(self): from distutils import sysconfig python_inc = sysconfig.get_python_inc() eci = ExternalCompilationInfo( include_dirs=[python_inc], includes=["Python.h", ], ) return eci.merge(CBuilder.get_eci(self))
def __init__(self, translator, entrypoint, config, gcpolicy=None): self.translator = translator self.entrypoint = entrypoint self.entrypoint_name = self.entrypoint.func_name self.originalentrypoint = entrypoint self.config = config self.gcpolicy = gcpolicy # for tests only, e.g. rpython/memory/ if gcpolicy is not None and gcpolicy.requires_stackless: config.translation.stackless = True self.eci = ExternalCompilationInfo()
def get_eci(self): from distutils import sysconfig python_inc = sysconfig.get_python_inc() eci = ExternalCompilationInfo( include_dirs=[python_inc], includes=[ "Python.h", ], ) return eci.merge(CBuilder.get_eci(self))
def __init__(self, translator, standalone): # reset counters Node.nodename_count = {} self.eci = ExternalCompilationInfo() self.standalone = standalone self.translator = translator self.config = translator.config
def test_merge2(self): e1 = ExternalCompilationInfo(pre_include_bits=['1'], link_files=['1.c']) e2 = ExternalCompilationInfo(pre_include_bits=['2'], link_files=['1.c', '2.c']) e3 = ExternalCompilationInfo(pre_include_bits=['3'], link_files=['1.c', '2.c', '3.c']) e = e1.merge(e2) e = e.merge(e3, e3) assert e.pre_include_bits == ('1', '2', '3') assert e.link_files == ('1.c', '2.c', '3.c')
def test_convert_sources_to_c_files(self): eci = ExternalCompilationInfo( separate_module_sources = ['xxx'], separate_module_files = ['x.c'], ) cache_dir = udir.join('test_convert_sources').ensure(dir=1) neweci = eci.convert_sources_to_files(cache_dir) assert not neweci.separate_module_sources res = neweci.separate_module_files assert len(res) == 2 assert res[0] == 'x.c' assert str(res[1]).startswith(str(cache_dir)) e = ExternalCompilationInfo() assert e.convert_sources_to_files() is e
class ComplexCConfig: """ Definitions of structure types defined by zlib and based on SimpleCConfig definitions. """ _compilation_info_ = ExternalCompilationInfo( includes = includes ) z_stream = rffi_platform.Struct( 'z_stream', [('next_in', Bytefp), ('avail_in', uInt), ('total_in', uLong), ('next_out', Bytefp), ('avail_out', uInt), ('total_out', uLong), ('msg', rffi.CCHARP), ('zalloc', lltype.Ptr( lltype.FuncType([voidpf, uInt, uInt], voidpf))), ('zfree', lltype.Ptr( lltype.FuncType([voidpf, voidpf], lltype.Void))), ('opaque', voidpf), ('data_type', rffi.INT), ('adler', uLong), ('reserved', uLong) ])
def __init__(self): self.configure(CConfig) # we need an indirection via c functions to get macro calls working on llvm if hasattr(os, 'WCOREDUMP'): decl_snippet = """ %(ret_type)s pypy_macro_wrapper_%(name)s (int status); """ def_snippet = """ %(ret_type)s pypy_macro_wrapper_%(name)s (int status) { return %(name)s(status); } """ decls = [] defs = [] for name in self.w_star: data = {'ret_type': 'int', 'name': name} decls.append(decl_snippet % data) defs.append(def_snippet % data) h_source = decls + defs self.compilation_info = self.compilation_info.merge( ExternalCompilationInfo( post_include_lines = decls, separate_module_sources = ["\n".join(h_source)] ))
class CConfig: """ Definitions for platform integration. Note: this must be processed through platform.configure() to provide usable objects. For example:: CLOCK_T = platform.configure(CConfig)['CLOCK_T'] register(function, [CLOCK_T], ...) """ _compilation_info_ = ExternalCompilationInfo( includes=includes ) if not sys.platform.startswith('win'): CLOCK_T = platform.SimpleType('clock_t', rffi.INT) TMS = platform.Struct( 'struct tms', [('tms_utime', rffi.INT), ('tms_stime', rffi.INT), ('tms_cutime', rffi.INT), ('tms_cstime', rffi.INT)]) SEEK_SET = platform.DefinedConstantInteger('SEEK_SET') SEEK_CUR = platform.DefinedConstantInteger('SEEK_CUR') SEEK_END = platform.DefinedConstantInteger('SEEK_END') UTIMBUF = platform.Struct('struct '+underscore_on_windows+'utimbuf', [('actime', rffi.INT), ('modtime', rffi.INT)])
def test_from_linker_flags(self): flags = ('-L/some/lib/path -L/other/lib/path ' '-lmylib1 -lmylib2 -?1 -!2') eci = ExternalCompilationInfo.from_linker_flags(flags) assert eci.libraries == ('mylib1', 'mylib2') assert eci.library_dirs == ('/some/lib/path', '/other/lib/path') assert eci.link_extra == ('-?1', '-!2')
def configure_boehm(platform=None): if platform is None: from pypy.translator.platform import platform if sys.platform == 'win32': import platform as host_platform # just to ask for the arch. Confusion-alert! if host_platform.architecture()[0] == '32bit': library_dir = 'Release' libraries = ['gc'] includes=['gc.h'] else: library_dir = '' libraries = ['gc64_dll'] includes = ['gc.h'] else: library_dir = '' libraries = ['gc', 'dl'] includes=['gc/gc.h'] eci = ExternalCompilationInfo( platform=platform, includes=includes, libraries=libraries, ) return configure_external_library( 'gc', eci, [dict(prefix='gc-', include_dir='include', library_dir=library_dir)], symbol='GC_init')
def test_merge(self): e1 = ExternalCompilationInfo(pre_include_bits=['1'], includes=['x.h'], post_include_bits=['p1']) e2 = ExternalCompilationInfo( pre_include_bits=['2'], includes=['x.h', 'y.h'], post_include_bits=['p2'], ) e3 = ExternalCompilationInfo(pre_include_bits=['3'], includes=['y.h', 'z.h'], post_include_bits=['p1', 'p3']) e = e1.merge(e2, e3) assert e.pre_include_bits == ('1', '2', '3') assert e.includes == ('x.h', 'y.h', 'z.h') assert e.post_include_bits == ('p1', 'p2', 'p3')
def add_extra_files(eci): srcdir = py.path.local(autopath.pypydir).join('translator', 'c', 'src') files = [ srcdir / 'profiling.c', srcdir / 'debug_print.c', ] return eci.merge(ExternalCompilationInfo(separate_module_files=files))
def eci_from_header(c_header_source, include_dirs=None): if include_dirs is None: include_dirs = [] return ExternalCompilationInfo( post_include_bits=[c_header_source], include_dirs=include_dirs )
def build_main_for_shared(self, shared_library_name, entrypoint, exe_name): import time time.sleep(1) self.shared_library_name = shared_library_name # build main program eci = self.get_eci() kw = {} if self.translator.platform.cc == 'gcc': kw['libraries'] = [self.shared_library_name.purebasename[3:]] kw['library_dirs'] = [self.targetdir] else: kw['libraries'] = [self.shared_library_name.new(ext='')] eci = eci.merge(ExternalCompilationInfo( separate_module_sources=[''' int %s(int argc, char* argv[]); int main(int argc, char* argv[]) { return %s(argc, argv); } ''' % (entrypoint, entrypoint) ], **kw )) eci = eci.convert_sources_to_files( cache_dir=self.targetdir) return self.translator.platform.compile( [], eci, outputfilename=exe_name)
def test_pass_around_t_object(self): from pypy.rpython.annlowlevel import base_ptr_lltype T = base_ptr_lltype() class X(object): _TYPE = T x = 10 def callback(x): return x.x c_source = py.code.Source(""" long eating_callback(void *arg, long(*call)(void*)) { return call(arg); } """) eci = ExternalCompilationInfo(separate_module_sources=[c_source], export_symbols=['eating_callback']) args = [T, rffi.CCallback([T], rffi.LONG)] eating_callback = rffi.llexternal('eating_callback', args, rffi.LONG, compilation_info=eci) res = eating_callback(X(), callback) assert res == 10
def test_frexp(self): if sys.platform != 'win32': eci = ExternalCompilationInfo(includes=['math.h'], libraries=['m']) else: eci = ExternalCompilationInfo(includes=['math.h']) A = lltype.FixedSizeArray(rffi.INT, 1) frexp = rffi.llexternal('frexp', [rffi.DOUBLE, lltype.Ptr(A)], rffi.DOUBLE, compilation_info=eci) p = lltype.malloc(A, flavor='raw') res = frexp(2.5, p) assert res == 0.625 assert p[0] == 2 lltype.free(p, flavor='raw') assert not ALLOCATED # detects memory leaks in the test
def define_callback_simple(cls): c_source = py.code.Source(""" int mystuff(int(*cb)(int, int)) { return cb(40, 2) + cb(3, 4); } """) eci = ExternalCompilationInfo(separate_module_sources=[c_source]) S = lltype.GcStruct('S', ('x', lltype.Signed)) CALLBACK = lltype.FuncType([lltype.Signed, lltype.Signed], lltype.Signed) z = rffi.llexternal('mystuff', [lltype.Ptr(CALLBACK)], lltype.Signed, compilation_info=eci) def mycallback(a, b): gc.collect() return a + b def f(): p = lltype.malloc(S) p.x = 100 result = z(mycallback) return result * p.x return f
def cmds_objects(self, base, standalone): use_gcc = self.genllvm.config.translation.llvm_via_c if use_gcc: self.cmds.append("llc %s.bc -march=c -f -o %s.c" % (base, base)) self.cmds.append("gcc %s.c -c -O3 -fomit-frame-pointer" % base) else: model = '' if not standalone: model = ' -relocation-model=pic' self.cmds.append("llc %s %s.bc -f -o %s.s" % (model, base, base)) self.cmds.append("as %s.s -o %s.o" % (base, base)) include_opts = get_incdirs(self.genllvm.eci) # compile separate files # XXX rxe: why do we want to run a c compiler, when we run llvm # compiler - these seems a step backwards IMHO ????? libraries = set() for filename in self.genllvm.eci.separate_module_files: assert filename.endswith(".c") objname = filename[:-2] + ".o" libraries.add(objname) self.cmds.append("gcc %s -c %s -O3 -o %s" % (filename, include_opts, objname)) attrs = self.genllvm.eci._copy_attributes() attrs['libraries'] = tuple(libraries) + attrs['libraries'] self.genllvm.eci = ExternalCompilationInfo(**attrs)
def build_winerror_to_errno(): """Build a dictionary mapping windows error numbers to POSIX errno. The function returns the dict, and the default value for codes not in the dict.""" # Prior to Visual Studio 8, the MSVCRT dll doesn't export the # _dosmaperr() function, which is available only when compiled # against the static CRT library. from pypy.translator.platform import platform, Windows static_platform = Windows() if static_platform.name == 'msvc': static_platform.cflags = ['/MT'] # static CRT static_platform.version = 0 # no manifest cfile = udir.join('dosmaperr.c') cfile.write(r''' #include <errno.h> int main() { int i; for(i=1; i < 65000; i++) { _dosmaperr(i); if (errno == EINVAL) continue; printf("%d\t%d\n", i, errno); } return 0; }''') exename = static_platform.compile( [cfile], ExternalCompilationInfo(), outputfilename = "dosmaperr", standalone=True) output = os.popen(str(exename)) errors = dict(map(int, line.split()) for line in output) return errors, errno.EINVAL
def get_rsdl_compilation_info(): if sys.platform == 'darwin': eci = ExternalCompilationInfo( includes = ['SDL.h'], include_dirs = ['/Library/Frameworks/SDL.framework/Headers'], link_files = [ str(py.magic.autopath().dirpath().join('macosx-sdl-main/SDLMain.m')), ], frameworks = ['SDL', 'Cocoa'] ) else: eci = ExternalCompilationInfo( includes=['SDL.h'], ) eci = eci.merge(ExternalCompilationInfo.from_config_tool('sdl-config')) return eci
def test_string_reverse(self): c_source = py.code.Source(""" #include <string.h> #include <Python.h> #include <src/mem.h> char *f(char* arg) { char *ret; /* lltype.free uses OP_RAW_FREE, we must allocate * with the matching function */ OP_RAW_MALLOC(strlen(arg) + 1, ret, char*) strcpy(ret, arg); return ret; } """) eci = ExternalCompilationInfo(separate_module_sources=[c_source], post_include_bits=['char *f(char*);']) z = llexternal('f', [CCHARP], CCHARP, compilation_info=eci) def f(): s = str2charp("xxx") l_res = z(s) res = charp2str(l_res) lltype.free(l_res, flavor='raw') free_charp(s) return len(res) xf = self.compile(f, [], backendopt=False) assert xf(expected_extra_mallocs=-1) == 3
def define_callback_simple(cls): import gc from pypy.rpython.lltypesystem import lltype, rffi from pypy.rpython.annlowlevel import llhelper from pypy.translator.tool.cbuild import ExternalCompilationInfo c_source = py.code.Source(""" int mystuff(int(*cb)(int, int)) { return cb(40, 2) + cb(3, 4); } """) eci = ExternalCompilationInfo(separate_module_sources=[c_source]) S = lltype.GcStruct('S', ('x', lltype.Signed)) CALLBACK = lltype.FuncType([lltype.Signed, lltype.Signed], lltype.Signed) z = rffi.llexternal('mystuff', [lltype.Ptr(CALLBACK)], lltype.Signed, compilation_info=eci) def mycallback(a, b): gc.collect() return a + b def f(): p = lltype.malloc(S) p.x = 100 result = z(mycallback) return result * p.x return f
def test_prebuilt_constant(self): py.test.skip("Think how to do it sane") h_source = py.code.Source(""" int x = 3; char** z = NULL; #endif """) h_include = udir.join('constants.h') h_include.write(h_source) eci = ExternalCompilationInfo( includes=['stdio.h', str(h_include.basename)], include_dirs=[str(udir)]) get_x, set_x = CExternVariable(lltype.Signed, 'x', eci) get_z, set_z = CExternVariable(CCHARPP, 'z', eci) def f(): one = get_x() set_x(13) return one + get_x() def g(): l = liststr2charpp(["a", "b", "c"]) try: set_z(l) return charp2str(get_z()[2]) finally: free_charpp(l) fn = self.compile(f, []) assert fn() == 16 gn = self.compile(g, []) assert gn() == "c"
def eating_callback(self): h_source = py.code.Source(""" #ifndef _CALLBACK_H #define _CALLBACK_H extern long eating_callback(long arg, long(*call)(long)); #endif /* _CALLBACK_H */ """) h_include = udir.join('callback.h') h_include.write(h_source) c_source = py.code.Source(""" long eating_callback(long arg, long(*call)(long)) { long res = call(arg); if (res == -1) return -1; return res; } """) eci = ExternalCompilationInfo(includes=['callback.h'], include_dirs=[str(udir)], separate_module_sources=[c_source], export_symbols=['eating_callback']) args = [LONG, CCallback([LONG], LONG)] eating_callback = llexternal('eating_callback', args, LONG, compilation_info=eci) return eating_callback
def generate_macro_wrapper(name, macro, functype, eci): """Wraps a function-like macro inside a real function, and expose it with llexternal.""" # Generate the function call from pypy.translator.c.database import LowLevelDatabase from pypy.translator.c.support import cdecl wrapper_name = 'pypy_macro_wrapper_%s' % (name,) argnames = ['arg%d' % (i,) for i in range(len(functype.ARGS))] db = LowLevelDatabase() implementationtypename = db.gettype(functype, argnames=argnames) if functype.RESULT is lltype.Void: pattern = '%s { %s(%s); }' else: pattern = '%s { return %s(%s); }' source = pattern % ( cdecl(implementationtypename, wrapper_name), macro, ', '.join(argnames)) # Now stuff this source into a "companion" eci that will be used # by ll2ctypes. We replace eci._with_ctypes, so that only one # shared library is actually compiled (when ll2ctypes calls the # first function) ctypes_eci = eci.merge(ExternalCompilationInfo( separate_module_sources=[source], export_symbols=[wrapper_name], )) if hasattr(eci, '_with_ctypes'): ctypes_eci = eci._with_ctypes.merge(ctypes_eci) eci._with_ctypes = ctypes_eci func = llexternal(wrapper_name, functype.ARGS, functype.RESULT, compilation_info=eci, _nowrapper=True) # _nowrapper=True returns a pointer which is not hashable return lambda *args: func(*args)
def return_char(self, signed): ctype_pref = ["un", ""][signed] rffi_type = [UCHAR, SIGNEDCHAR][signed] h_source = py.code.Source(""" %ssigned char returnchar(void) { return 42; } """ % (ctype_pref, )) h_file = udir.join("opaque2%s.h" % (ctype_pref, )) h_file.write(h_source) from pypy.rpython.tool import rffi_platform eci = ExternalCompilationInfo(includes=[h_file.basename], include_dirs=[str(udir)]) ll_returnchar = llexternal('returnchar', [], rffi_type, compilation_info=eci) def f(): result = ll_returnchar() return result f1 = self.compile(f, []) assert f1() == chr(42)
def test_stringstar(self): c_source = """ #include <string.h> int f(char *args[]) { char **p = args; int l = 0; while (*p) { l += strlen(*p); p++; } return (l); } """ eci = ExternalCompilationInfo(separate_module_sources=[c_source]) z = llexternal('f', [CCHARPP], Signed, compilation_info=eci) def f(): l = ["xxx", "x", "xxxx"] ss = liststr2charpp(l) result = z(ss) free_charpp(ss) return result xf = self.compile(f, [], backendopt=False) assert xf() == 8
def test_make_shared_lib(self): eci = ExternalCompilationInfo( separate_module_sources = [''' int get() { return 42; }'''] ) neweci = eci.compile_shared_lib() assert len(neweci.libraries) == 1 try: import ctypes except ImportError: py.test.skip("Need ctypes for that test") assert ctypes.CDLL(neweci.libraries[0]).get() == 42 assert not neweci.separate_module_sources assert not neweci.separate_module_files
def test_merge2(self): e1 = ExternalCompilationInfo( pre_include_bits = ['1'], link_files = ['1.c'] ) e2 = ExternalCompilationInfo( pre_include_bits = ['2'], link_files = ['1.c', '2.c'] ) e3 = ExternalCompilationInfo( pre_include_bits = ['3'], link_files = ['1.c', '2.c', '3.c'] ) e = e1.merge(e2) e = e.merge(e3, e3) assert e.pre_include_bits == ('1', '2', '3') assert e.link_files == ('1.c', '2.c', '3.c')
def test_platforms(self): from pypy.translator.platform import Platform class Maemo(Platform): def __init__(self, cc=None): self.cc = cc eci = ExternalCompilationInfo(platform=Maemo()) eci2 = ExternalCompilationInfo() assert eci != eci2 assert hash(eci) != hash(eci2) assert repr(eci) != repr(eci2) py.test.raises(Exception, eci2.merge, eci) assert eci.merge(eci).platform == Maemo() assert (ExternalCompilationInfo(platform=Maemo(cc='xxx')) != ExternalCompilationInfo(platform=Maemo(cc='yyy'))) assert (repr(ExternalCompilationInfo(platform=Maemo(cc='xxx'))) != repr(ExternalCompilationInfo(platform=Maemo(cc='yyy'))))
def test_from_compiler_flags(self): flags = ('-I/some/include/path -I/other/include/path ' '-DMACRO1 -D_MACRO2=baz -?1 -!2') eci = ExternalCompilationInfo.from_compiler_flags(flags) assert eci.pre_include_bits == ('#define MACRO1 1', '#define _MACRO2 baz') assert eci.includes == () assert eci.include_dirs == ('/some/include/path', '/other/include/path') assert eci.compile_extra == ('-?1', '-!2')
def test_merge(self): e1 = ExternalCompilationInfo( pre_include_bits = ['1'], includes = ['x.h'], post_include_bits = ['p1'] ) e2 = ExternalCompilationInfo( pre_include_bits = ['2'], includes = ['x.h', 'y.h'], post_include_bits = ['p2'], ) e3 = ExternalCompilationInfo( pre_include_bits = ['3'], includes = ['y.h', 'z.h'], post_include_bits = ['p1', 'p3'] ) e = e1.merge(e2, e3) assert e.pre_include_bits == ('1', '2', '3') assert e.includes == ('x.h', 'y.h', 'z.h') assert e.post_include_bits == ('p1', 'p2', 'p3')
class CBuilder(object): c_source_filename = None _compiled = False modulename = None def __init__(self, translator, entrypoint, config, gcpolicy=None): self.translator = translator self.entrypoint = entrypoint self.entrypoint_name = self.entrypoint.func_name self.originalentrypoint = entrypoint self.config = config self.gcpolicy = gcpolicy # for tests only, e.g. rpython/memory/ if gcpolicy is not None and gcpolicy.requires_stackless: config.translation.stackless = True self.eci = ExternalCompilationInfo() def build_database(self): translator = self.translator gcpolicyclass = self.get_gcpolicyclass() if self.config.translation.gcrootfinder == "asmgcc": if not self.standalone: raise NotImplementedError("--gcrootfinder=asmgcc requires standalone") if self.config.translation.stackless: if not self.standalone: raise Exception("stackless: only for stand-alone builds") from pypy.translator.stackless.transform import StacklessTransformer stacklesstransformer = StacklessTransformer( translator, self.originalentrypoint, stackless_gc=gcpolicyclass.requires_stackless) self.entrypoint = stacklesstransformer.slp_entry_point else: stacklesstransformer = None db = LowLevelDatabase(translator, standalone=self.standalone, gcpolicyclass=gcpolicyclass, stacklesstransformer=stacklesstransformer, thread_enabled=self.config.translation.thread, sandbox=self.config.translation.sandbox) self.db = db # give the gc a chance to register interest in the start-up functions it # need (we call this for its side-effects of db.get()) list(db.gcpolicy.gc_startup_code()) # build entrypoint and eventually other things to expose pf = self.getentrypointptr() pfname = db.get(pf) self.c_entrypoint_name = pfname db.complete() self.collect_compilation_info(db) return db have___thread = None def collect_compilation_info(self, db): # we need a concrete gcpolicy to do this self.eci = self.eci.merge(ExternalCompilationInfo( libraries=db.gcpolicy.gc_libraries())) all = [] for node in self.db.globalcontainers(): eci = getattr(node, 'compilation_info', None) if eci: all.append(eci) self.eci = self.eci.merge(*all) def get_gcpolicyclass(self): if self.gcpolicy is None: name = self.config.translation.gctransformer if self.config.translation.gcrootfinder == "stackless": name = "%s+stacklessgc" % (name,) elif self.config.translation.gcrootfinder == "llvmgc": name = "%s+llvmgcroot" % (name,) elif self.config.translation.gcrootfinder == "asmgcc": name = "%s+asmgcroot" % (name,) return gc.name_to_gcpolicy[name] return self.gcpolicy # use generate_source(defines=DEBUG_DEFINES) to force the #definition # of the macros that enable debugging assertions DEBUG_DEFINES = {'RPY_ASSERT': 1, 'RPY_LL_ASSERT': 1} def generate_source(self, db=None, defines={}): assert self.c_source_filename is None translator = self.translator if db is None: db = self.build_database() pf = self.getentrypointptr() pfname = db.get(pf) if self.modulename is None: self.modulename = uniquemodulename('testing') modulename = self.modulename targetdir = udir.ensure(modulename, dir=1) self.targetdir = targetdir defines = defines.copy() if self.config.translation.countmallocs: defines['COUNT_OP_MALLOCS'] = 1 if self.config.translation.sandbox: defines['RPY_SANDBOXED'] = 1 if CBuilder.have___thread is None: CBuilder.have___thread = check_under_under_thread() if not self.standalone: assert not self.config.translation.instrument cfile, extra = gen_source(db, modulename, targetdir, self.eci, defines = defines) else: if self.config.translation.instrument: defines['INSTRUMENT'] = 1 if CBuilder.have___thread: if not self.config.translation.no__thread: defines['USE___THREAD'] = 1 # explicitely include python.h and exceptions.h # XXX for now, we always include Python.h from distutils import sysconfig python_inc = sysconfig.get_python_inc() pypy_include_dir = autopath.this_dir self.eci = self.eci.merge(ExternalCompilationInfo( include_dirs=[python_inc, pypy_include_dir], )) cfile, extra = gen_source_standalone(db, modulename, targetdir, self.eci, entrypointname = pfname, defines = defines) self.c_source_filename = py.path.local(cfile) self.extrafiles = extra if self.standalone: self.gen_makefile(targetdir) return cfile def generate_graphs_for_llinterp(self, db=None): # prepare the graphs as when the source is generated, but without # actually generating the source. if db is None: db = self.build_database() graphs = db.all_graphs() db.gctransformer.prepare_inline_helpers(graphs) for node in db.containerlist: if isinstance(node, FuncNode): for funcgen in node.funcgens: funcgen.patch_graph(copy_graph=False) return db
def test_from_config_tool(self): sdlconfig = py.path.local.sysfind('sdl-config') if not sdlconfig: py.test.skip("sdl-config not installed") eci = ExternalCompilationInfo.from_config_tool('sdl-config') assert 'SDL' in eci.libraries
log(cmdline) err = os.system(cmdline) if err: raise Exception("gcc command failed") do("g++ -g -c '%s' -o '%s' `%s --cppflags`" % (cname, o1name, llvm_config)) do("g++ -g -c '%s' -o '%s' `%s --cppflags`" % (cppname, o2name, llvm_config)) do("g++ -g -shared '%s' '%s' -o '%s'" % (o1name, o2name, libname) + " `%s --cflags --ldflags --libs jit engine`" % llvm_config) ctypes_compilation_info = ExternalCompilationInfo( library_dirs = [dirname], libraries = ['pypy_cache_llvm'], ) compilation_info = ExternalCompilationInfo.from_linker_flags( os.popen("%s --ldflags --libs jit engine" % llvm_config, 'r').read()) compilation_info = compilation_info.merge(ExternalCompilationInfo( link_extra = [o1name, o2name], use_cpp_linker = True, )) compilation_info._with_ctypes = ctypes_compilation_info _teardown = None def set_teardown_function(fn): global _teardown _teardown = fn def teardown_now():
def configure_external_library(name, eci, configurations, symbol=None, _cache={}): """try to find the external library. On Unix, this simply tests and returns the given eci. On Windows, various configurations may be tried to compile the given eci object. These configurations are a list of dicts, containing: - prefix: if an absolute path, will prefix each include and library directories. If a relative path, the external directory is searched for directories which names start with the prefix. The last one in alphabetical order chosen, and becomes the prefix. - include_dir: prefix + include_dir is added to the include directories - library_dir: prefix + library_dir is added to the library directories """ if sys.platform != 'win32': configurations = [] key = (name, eci) try: return _cache[key] except KeyError: last_error = None # Always try the default configuration if {} not in configurations: configurations.append({}) for configuration in configurations: prefix = configuration.get('prefix', '') include_dir = configuration.get('include_dir', '') library_dir = configuration.get('library_dir', '') if prefix and not os.path.isabs(prefix): import glob entries = glob.glob(str(PYPY_EXTERNAL_DIR.join(prefix + '*'))) if entries: # Get last version prefix = sorted(entries)[-1] else: continue include_dir = os.path.join(prefix, include_dir) library_dir = os.path.join(prefix, library_dir) eci_lib = ExternalCompilationInfo( include_dirs=include_dir and [include_dir] or [], library_dirs=library_dir and [library_dir] or [], ) eci_lib = eci_lib.merge(eci) # verify that this eci can be compiled try: verify_eci(eci_lib) except CompilationError, e: last_error = e else: _cache[key] = eci_lib return eci_lib # Nothing found if last_error: raise last_error else: raise CompilationError("Library %s is not installed" % (name,))
import sys from pypy.rpython.lltypesystem import lltype, rffi from pypy.rpython.tool import rffi_platform as platform from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.rlib.rsdl import RSDL if sys.platform == 'darwin': eci = ExternalCompilationInfo( includes = ['SDL_mixer.h'], frameworks = ['SDL_mixer'], include_dirs = ['/Library/Frameworks/SDL_Mixer.framework/Headers'] ) else: eci = ExternalCompilationInfo( includes=['SDL_mixer.h'], libraries=['SDL_mixer'], ) eci = eci.merge(RSDL.eci) eci = eci.merge(eci) eci = eci.merge(eci) ChunkPtr = lltype.Ptr(lltype.ForwardReference()) class CConfig: _compilation_info_ = eci Chunk = platform.Struct('Mix_Chunk', [('allocated', rffi.INT), ('abuf', RSDL.Uint8P), ('alen', RSDL.Uint32),
import py from pypy.tool.autopath import pypydir from pypy.rpython.lltypesystem import lltype, llmemory, rffi from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.rpython.tool import rffi_platform import sys cdir = py.path.local(pypydir) / 'translator' / 'c' eci = ExternalCompilationInfo( include_dirs = [cdir], includes = ['src/stacklet/stacklet.h'], separate_module_sources = ['#include "src/stacklet/stacklet.c"\n'], ) if sys.platform == 'win32': eci.separate_module_files += (cdir / "src/stacklet/switch_x86_msvc.asm", ) eci.export_symbols += ( 'stacklet_newthread', 'stacklet_deletethread', 'stacklet_new', 'stacklet_switch', 'stacklet_destroy', '_stacklet_translate_pointer', ) rffi_platform.verify_eci(eci.convert_sources_to_files()) def llexternal(name, args, result, **kwds): return rffi.llexternal(name, args, result, compilation_info=eci, _nowrapper=True, **kwds)