summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArmin Rigo <arigo@tunes.org>2015-05-17 12:27:42 +0200
committerArmin Rigo <arigo@tunes.org>2015-05-17 12:27:42 +0200
commit361461d7cb12952d20a3235f5f966eda40a8b0d3 (patch)
treefb7246f14322e057fcbf74036311a9ac595e14d9
parentfcf5dcdbff8ead1f17d0646c21df3d4e366ba0f5 (diff)
downloadcffi-361461d7cb12952d20a3235f5f966eda40a8b0d3.tar.gz
Last TODO item: setuptools on out-of-line ABI-mode modules
-rw-r--r--TODO3
-rw-r--r--cffi/setuptools_ext.py55
-rw-r--r--demo/readdir_setup.py11
3 files changed, 57 insertions, 12 deletions
diff --git a/TODO b/TODO
deleted file mode 100644
index 440917e..0000000
--- a/TODO
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-* also support ABI-mode in cffi_modules
diff --git a/cffi/setuptools_ext.py b/cffi/setuptools_ext.py
index 699f4da..7d3e76e 100644
--- a/cffi/setuptools_ext.py
+++ b/cffi/setuptools_ext.py
@@ -1,3 +1,5 @@
+import os
+
try:
basestring
except NameError:
@@ -19,14 +21,9 @@ def execfile(filename, glob):
code = compile(f.read(), filename, 'exec')
exec(code, glob, glob)
+
def add_cffi_module(dist, mod_spec):
- import os
from cffi.api import FFI
- from cffi import recompiler
- from distutils.core import Extension
- from distutils.command.build_ext import build_ext
- from distutils.dir_util import mkpath
- from distutils import log
if not isinstance(mod_spec, basestring):
error("argument to 'cffi_modules=...' must be a str or a list of str,"
@@ -65,15 +62,27 @@ def add_cffi_module(dist, mod_spec):
kwds = kwds.copy()
ffi._apply_windows_unicode(kwds)
+ if source is None:
+ _add_py_module(dist, ffi, module_name)
+ else:
+ _add_c_module(dist, ffi, module_name, source, source_extension, kwds)
+
+
+def _add_c_module(dist, ffi, module_name, source, source_extension, kwds):
+ from distutils.core import Extension
+ from distutils.command.build_ext import build_ext
+ from distutils.dir_util import mkpath
+ from distutils import log
+ from cffi import recompiler
+
allsources = ['$PLACEHOLDER']
allsources.extend(kwds.get('sources', []))
ext = Extension(name=module_name, sources=allsources, **kwds)
def make_mod(tmpdir):
- file_name = module_name + source_extension
- log.info("generating cffi module %r" % file_name)
+ c_file = os.path.join(tmpdir, module_name + source_extension)
+ log.info("generating cffi module %r" % c_file)
mkpath(tmpdir)
- c_file = os.path.join(tmpdir, file_name)
updated = recompiler.make_c_source(ffi, module_name, source, c_file)
if not updated:
log.info("already up-to-date")
@@ -90,6 +99,34 @@ def add_cffi_module(dist, mod_spec):
ext.sources[0] = make_mod(self.build_temp)
base_class.run(self)
dist.cmdclass['build_ext'] = build_ext_make_mod
+ # NB. multiple runs here will create multiple 'build_ext_make_mod'
+ # classes. Even in this case the 'build_ext' command should be
+ # run once; but just in case, the logic above does nothing if
+ # called again.
+
+
+def _add_py_module(dist, ffi, module_name):
+ from distutils.dir_util import mkpath
+ from distutils.command.build_py import build_py
+ from distutils import log
+ from cffi import recompiler
+
+ def make_mod(tmpdir):
+ module_path = module_name.split('.')
+ module_path[-1] += '.py'
+ py_file = os.path.join(tmpdir, *module_path)
+ log.info("generating cffi module %r" % py_file)
+ mkpath(os.path.dirname(py_file))
+ updated = recompiler.make_py_source(ffi, module_name, py_file)
+ if not updated:
+ log.info("already up-to-date")
+
+ base_class = dist.cmdclass.get('build_py', build_py)
+ class build_py_make_mod(base_class):
+ def run(self):
+ base_class.run(self)
+ make_mod(self.build_lib)
+ dist.cmdclass['build_py'] = build_py_make_mod
def cffi_modules(dist, attr, value):
diff --git a/demo/readdir_setup.py b/demo/readdir_setup.py
new file mode 100644
index 0000000..c8abdcb
--- /dev/null
+++ b/demo/readdir_setup.py
@@ -0,0 +1,11 @@
+from setuptools import setup
+
+setup(
+ name="example",
+ version="0.1",
+ py_modules=["readdir"],
+ setup_requires=["cffi>=1.0.dev0"],
+ cffi_modules=["readdir_build.py:ffi"],
+ install_requires=["cffi>=1.0.dev0"],
+ zip_safe=False,
+)