Author: mattip <matti.pi...@gmail.com> Branch: Changeset: r78277:53ae94237bb3 Date: 2015-06-23 23:19 +0300 http://bitbucket.org/pypy/pypy/changeset/53ae94237bb3/
Log: merge run-create_cffi_imports, which builds cffi import libraries as part of translation diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -16,3 +16,9 @@ .. branch: disable-unroll-for-short-loops The JIT no longer performs loop unrolling if the loop compiles to too much code. + +.. branch: run-create_cffi_imports + +Build cffi import libraries as part of translation by monkey-patching an +aditional task into translation + diff --git a/pypy/goal/targetpypystandalone.py b/pypy/goal/targetpypystandalone.py --- a/pypy/goal/targetpypystandalone.py +++ b/pypy/goal/targetpypystandalone.py @@ -1,6 +1,6 @@ import py -import os, sys +import os, sys, subprocess import pypy from pypy.interpreter import gateway @@ -298,6 +298,44 @@ wrapstr = 'space.wrap(%r)' % (options) pypy.module.sys.Module.interpleveldefs['pypy_translation_info'] = wrapstr + # HACKHACKHACK + # ugly hack to modify target goal from compile_c to build_cffi_imports + # this should probably get cleaned up and merged with driver.create_exe + from rpython.translator.driver import taskdef + import types + + class Options(object): + pass + + + def mkexename(name): + if sys.platform == 'win32': + name = name.new(ext='exe') + return name + + @taskdef(['compile_c'], "Create cffi bindings for modules") + def task_build_cffi_imports(self): + from pypy.tool.build_cffi_imports import create_cffi_import_libraries + ''' Use cffi to compile cffi interfaces to modules''' + exename = mkexename(driver.compute_exe_name()) + basedir = exename + while not basedir.join('include').exists(): + _basedir = basedir.dirpath() + if _basedir == basedir: + raise ValueError('interpreter %s not inside pypy repo', + str(exename)) + basedir = _basedir + modules = self.config.objspace.usemodules.getpaths() + options = Options() + # XXX possibly adapt options using modules + failures = create_cffi_import_libraries(exename, options, basedir) + # if failures, they were already printed + print >> sys.stderr, str(exename),'successfully built, but errors while building the above modules will be ignored' + driver.task_build_cffi_imports = types.MethodType(task_build_cffi_imports, driver) + driver.tasks['build_cffi_imports'] = driver.task_build_cffi_imports, ['compile_c'] + driver.default_goal = 'build_cffi_imports' + # HACKHACKHACK end + return self.get_entry_point(config) def jitpolicy(self, driver): diff --git a/pypy/tool/build_cffi_imports.py b/pypy/tool/build_cffi_imports.py new file mode 100644 --- /dev/null +++ b/pypy/tool/build_cffi_imports.py @@ -0,0 +1,75 @@ +import sys, shutil +from rpython.tool.runsubprocess import run_subprocess + +class MissingDependenciesError(Exception): + pass + + +cffi_build_scripts = { + "sqlite3": "_sqlite3_build.py", + "audioop": "_audioop_build.py", + "tk": "_tkinter/tklib_build.py", + "curses": "_curses_build.py" if sys.platform != "win32" else None, + "syslog": "_syslog_build.py" if sys.platform != "win32" else None, + "gdbm": "_gdbm_build.py" if sys.platform != "win32" else None, + "pwdgrp": "_pwdgrp_build.py" if sys.platform != "win32" else None, + "xx": None, # for testing: 'None' should be completely ignored + } + +def create_cffi_import_libraries(pypy_c, options, basedir): + shutil.rmtree(str(basedir.join('lib_pypy', '__pycache__')), + ignore_errors=True) + failures = [] + for key, module in sorted(cffi_build_scripts.items()): + if module is None or getattr(options, 'no_' + key, False): + continue + if module.endswith('.py'): + args = [module] + cwd = str(basedir.join('lib_pypy')) + else: + args = ['-c', 'import ' + module] + cwd = None + print >> sys.stderr, '*', ' '.join(args) + try: + status, stdout, stderr = run_subprocess(str(pypy_c), args, cwd=cwd) + if status != 0: + print >> sys.stderr, stdout, stderr + failures.append((key, module)) + except: + import traceback;traceback.print_exc() + failures.append((key, module)) + return failures + +if __name__ == '__main__': + import py, os + if '__pypy__' not in sys.builtin_module_names: + print 'Call with a pypy interpreter' + sys.exit(-1) + + class Options(object): + pass + + exename = py.path.local(sys.executable) + basedir = exename + while not basedir.join('include').exists(): + _basedir = basedir.dirpath() + if _basedir == basedir: + raise ValueError('interpreter %s not inside pypy repo', + str(exename)) + basedir = _basedir + options = Options() + print >> sys.stderr, "There should be no failures here" + failures = create_cffi_import_libraries(exename, options, basedir) + if len(failures) > 0: + print 'failed to build', [f[1] for f in failures] + assert False + + # monkey patch a failure, just to test + print >> sys.stderr, 'This line should be followed by a traceback' + for k in cffi_build_scripts: + setattr(options, 'no_' + k, True) + must_fail = '_missing_build_script.py' + assert not os.path.exists(str(basedir.join('lib_pypy').join(must_fail))) + cffi_build_scripts['should_fail'] = must_fail + failures = create_cffi_import_libraries(exename, options, basedir) + assert len(failures) == 1 diff --git a/pypy/tool/release/package.py b/pypy/tool/release/package.py --- a/pypy/tool/release/package.py +++ b/pypy/tool/release/package.py @@ -26,6 +26,9 @@ STDLIB_VER = "2.7" +from pypy.tool.build_cffi_imports import (create_cffi_import_libraries, + MissingDependenciesError, cffi_build_scripts) + def ignore_patterns(*patterns): """Function that can be used as copytree() ignore parameter. @@ -41,48 +44,12 @@ class PyPyCNotFound(Exception): pass -class MissingDependenciesError(Exception): - pass - def fix_permissions(dirname): if sys.platform != 'win32': os.system("chmod -R a+rX %s" % dirname) os.system("chmod -R g-w %s" % dirname) -cffi_build_scripts = { - "sqlite3": "_sqlite3_build.py", - "audioop": "_audioop_build.py", - "tk": "_tkinter/tklib_build.py", - "curses": "_curses_build.py" if sys.platform != "win32" else None, - "syslog": "_syslog_build.py" if sys.platform != "win32" else None, - "gdbm": "_gdbm_build.py" if sys.platform != "win32" else None, - "pwdgrp": "_pwdgrp_build.py" if sys.platform != "win32" else None, - "xx": None, # for testing: 'None' should be completely ignored - } - -def create_cffi_import_libraries(pypy_c, options, basedir): - shutil.rmtree(str(basedir.join('lib_pypy', '__pycache__')), - ignore_errors=True) - for key, module in sorted(cffi_build_scripts.items()): - if module is None or getattr(options, 'no_' + key): - continue - if module.endswith('.py'): - args = [str(pypy_c), module] - cwd = str(basedir.join('lib_pypy')) - else: - args = [str(pypy_c), '-c', 'import ' + module] - cwd = None - print >> sys.stderr, '*', ' '.join(args) - try: - subprocess.check_call(args, cwd=cwd) - except subprocess.CalledProcessError: - print >>sys.stderr, """!!!!!!!!!!\nBuilding {0} bindings failed. -You can either install development headers package, -add the --without-{0} option to skip packaging this -binary CFFI extension, or say --without-cffi.""".format(key) - raise MissingDependenciesError(module) - def pypy_runs(pypy_c, quiet=False): kwds = {} if quiet: @@ -114,9 +81,13 @@ if not _fake and not pypy_runs(pypy_c): raise OSError("Running %r failed!" % (str(pypy_c),)) if not options.no_cffi: - try: - create_cffi_import_libraries(pypy_c, options, basedir) - except MissingDependenciesError: + failures = create_cffi_import_libraries(pypy_c, options, basedir) + for key, module in failures: + print >>sys.stderr, """!!!!!!!!!!\nBuilding {0} bindings failed. + You can either install development headers package, + add the --without-{0} option to skip packaging this + binary CFFI extension, or say --without-cffi.""".format(key) + if len(failures) > 0: return 1, None if sys.platform == 'win32' and not rename_pypy_c.lower().endswith('.exe'): _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit