[pypy-commit] pypy default: merge run-create_cffi_imports, which builds cffi import libraries as part of translation
mattip
noreply at buildbot.pypy.org
Tue Jun 23 22:21:23 CEST 2015
Author: mattip <matti.picus at 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'):
More information about the pypy-commit
mailing list