diff options
-rw-r--r-- | setuptools/__init__.py | 3 | ||||
-rw-r--r-- | setuptools/command/build_ext.py | 98 | ||||
-rw-r--r-- | setuptools/dist.py | 4 | ||||
-rw-r--r-- | setuptools/extension.py | 33 | ||||
-rwxr-xr-x | tests/shlib_test/hello.c | 168 | ||||
-rwxr-xr-x | tests/shlib_test/hello.pyx | 4 | ||||
-rwxr-xr-x | tests/shlib_test/hellolib.c | 3 | ||||
-rwxr-xr-x | tests/shlib_test/setup.py | 10 | ||||
-rwxr-xr-x | tests/shlib_test/test_hello.py | 7 |
9 files changed, 301 insertions, 29 deletions
diff --git a/setuptools/__init__.py b/setuptools/__init__.py index d545f2a5..4c14fe3a 100644 --- a/setuptools/__init__.py +++ b/setuptools/__init__.py @@ -1,8 +1,7 @@ - """Extensions to the 'distutils' for large or complex distributions""" +from setuptools.extension import Extension, SharedLibrary from setuptools.dist import Distribution, Feature, _get_unpatched import distutils.core, setuptools.command -from setuptools.extension import Extension from setuptools.depends import Require from distutils.core import Command as _Command from distutils.util import convert_path diff --git a/setuptools/command/build_ext.py b/setuptools/command/build_ext.py index 3678ac3e..b2095796 100644 --- a/setuptools/command/build_ext.py +++ b/setuptools/command/build_ext.py @@ -7,9 +7,11 @@ except ImportError: import os, sys from distutils.file_util import copy_file +from setuptools.extension import SharedLibrary +from distutils.ccompiler import new_compiler +from distutils.sysconfig import customize_compiler -class build_ext(_build_ext): - +class build_ext(_build_ext): def run(self): """Build extensions in build directory, then copy if --inplace""" old_inplace, self.inplace = self.inplace, 0 @@ -21,15 +23,13 @@ class build_ext(_build_ext): def copy_extensions_to_source(self): build_py = self.get_finalized_command('build_py') for ext in self.extensions or (): - fullname = ext.name + fullname = self.get_ext_fullname(ext.name) + filename = self.get_ext_filename(fullname) modpath = fullname.split('.') package = '.'.join(modpath[:-1]) - base = modpath[-1] package_dir = build_py.get_package_dir(package) - dest_filename = os.path.join(package_dir, - self.get_ext_filename(base)) - src_filename = os.path.join(self.build_lib, - self.get_ext_filename(fullname)) + dest_filename = os.path.join(package_dir,os.path.basename(filename)) + src_filename = os.path.join(self.build_lib,filename) # Always copy, even if source is older than destination, to ensure # that the right extensions for the current Python/platform are @@ -47,6 +47,88 @@ class build_ext(_build_ext): # Then do any actual SWIG stuff on the remainder return _du_build_ext.swig_sources(self, sources, *otherargs) + def get_ext_filename(self, fullname): + filename = _build_ext.get_ext_filename(self,fullname) + for ext in self.shlibs: + if self.get_ext_fullname(ext.name)==fullname: + fn, ext = os.path.splitext(filename) + fn = self.shlib_compiler.library_filename(fn,'shared') + print "shlib",fn + return fn + return filename + + def initialize_options(self): + _build_ext.initialize_options(self) + self.shlib_compiler = None + self.shlibs = [] + + def finalize_options(self): + _build_ext.finalize_options(self) + self.shlibs = [ext for ext in self.extensions or () + if isinstance(ext,SharedLibrary)] + if self.shlibs: + self.setup_shlib_compiler() + self.library_dirs.append(self.build_lib) + + def build_extension(self, ext): + _compiler = self.compiler + try: + if isinstance(ext,SharedLibrary): + self.compiler = self.shlib_compiler + _build_ext.build_extension(self,ext) + finally: + self.compiler = _compiler + + + def setup_shlib_compiler(self): + compiler = self.shlib_compiler = new_compiler( + compiler=self.compiler, dry_run=self.dry_run, force=self.force + ) + customize_compiler(compiler) + if sys.platform == "darwin": + # XXX need to fix up compiler_so:ccshared + linker_so:ldshared too + compiler.shared_lib_extension = ".dylib" + + if self.include_dirs is not None: + compiler.set_include_dirs(self.include_dirs) + if self.define is not None: + # 'define' option is a list of (name,value) tuples + for (name,value) in self.define: + compiler.define_macro(name, value) + if self.undef is not None: + for macro in self.undef: + compiler.undefine_macro(macro) + if self.libraries is not None: + compiler.set_libraries(self.libraries) + if self.library_dirs is not None: + compiler.set_library_dirs(self.library_dirs) + if self.rpath is not None: + compiler.set_runtime_library_dirs(self.rpath) + if self.link_objects is not None: + compiler.set_link_objects(self.link_objects) + + # hack so distutils' build_extension() builds a shared lib instead + # + def link_shared_object(self, objects, output_libname, output_dir=None, + libraries=None, library_dirs=None, runtime_library_dirs=None, + export_symbols=None, debug=0, extra_preargs=None, + extra_postargs=None, build_temp=None, target_lang=None + ): self.link( + self.SHARED_LIBRARY, objects, output_libname, + output_dir, libraries, library_dirs, runtime_library_dirs, + export_symbols, debug, extra_preargs, extra_postargs, + build_temp, target_lang + ) + compiler.link_shared_object = link_shared_object.__get__(compiler) + + def get_export_symbols(self, ext): + if isinstance(ext,SharedLibrary): + return ext.export_symbols + return _build_ext.get_export_symbols(self,ext) + + + + diff --git a/setuptools/dist.py b/setuptools/dist.py index fb7df8ce..4a0ae146 100644 --- a/setuptools/dist.py +++ b/setuptools/dist.py @@ -1,9 +1,7 @@ __all__ = ['Distribution', 'Feature'] from distutils.core import Distribution as _Distribution -from distutils.core import Extension from setuptools.depends import Require -from setuptools.command.build_ext import build_ext from setuptools.command.install import install from setuptools.command.sdist import sdist from setuptools.command.install_lib import install_lib @@ -39,6 +37,8 @@ sequence = tuple, list + + def assert_string_list(dist, attr, value): """Verify that value is a string list or None""" try: diff --git a/setuptools/extension.py b/setuptools/extension.py index 37b62576..33b870f0 100644 --- a/setuptools/extension.py +++ b/setuptools/extension.py @@ -1,19 +1,20 @@ from distutils.core import Extension as _Extension +from dist import _get_unpatched +_Extension = _get_unpatched(_Extension) try: from Pyrex.Distutils.build_ext import build_ext - except ImportError: + have_pyrex = False +else: + have_pyrex = True - # Pyrex isn't around, so fix up the sources - - from dist import _get_unpatched - _Extension = _get_unpatched(_Extension) - - class Extension(_Extension): - """Extension that uses '.c' files in place of '.pyx' files""" +class Extension(_Extension): + """Extension that uses '.c' files in place of '.pyx' files""" + if not have_pyrex: + # convert .pyx extensions to .c def __init__(self,*args,**kw): _Extension.__init__(self,*args,**kw) sources = [] @@ -24,14 +25,12 @@ except ImportError: sources.append(s) self.sources = sources - import sys, distutils.core, distutils.extension - distutils.core.Extension = Extension - distutils.extension.Extension = Extension - if 'distutils.command.build_ext' in sys.modules: - sys.modules['distutils.command.build_ext'].Extension = Extension - -else: +class SharedLibrary(Extension): + """Just like a regular Extension, but built as a shared library instead""" - # Pyrex is here, just use regular extension type - Extension = _Extension +import sys, distutils.core, distutils.extension +distutils.core.Extension = Extension +distutils.extension.Extension = Extension +if 'distutils.command.build_ext' in sys.modules: + sys.modules['distutils.command.build_ext'].Extension = Extension diff --git a/tests/shlib_test/hello.c b/tests/shlib_test/hello.c new file mode 100755 index 00000000..9998372c --- /dev/null +++ b/tests/shlib_test/hello.c @@ -0,0 +1,168 @@ +/* Generated by Pyrex 0.9.3 on Thu Jan 05 17:47:12 2006 */ + +#include "Python.h" +#include "structmember.h" +#ifndef PY_LONG_LONG + #define PY_LONG_LONG LONG_LONG +#endif + + +typedef struct {PyObject **p; char *s;} __Pyx_InternTabEntry; /*proto*/ +typedef struct {PyObject **p; char *s; long n;} __Pyx_StringTabEntry; /*proto*/ +static PyObject *__Pyx_UnpackItem(PyObject *, int); /*proto*/ +static int __Pyx_EndUnpack(PyObject *, int); /*proto*/ +static int __Pyx_PrintItem(PyObject *); /*proto*/ +static int __Pyx_PrintNewline(void); /*proto*/ +static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); /*proto*/ +static void __Pyx_ReRaise(void); /*proto*/ +static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/ +static PyObject *__Pyx_GetExcValue(void); /*proto*/ +static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed, char *name); /*proto*/ +static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/ +static int __Pyx_GetStarArgs(PyObject **args, PyObject **kwds, char *kwd_list[], int nargs, PyObject **args2, PyObject **kwds2); /*proto*/ +static void __Pyx_WriteUnraisable(char *name); /*proto*/ +static void __Pyx_AddTraceback(char *funcname); /*proto*/ +static PyTypeObject *__Pyx_ImportType(char *module_name, char *class_name, long size); /*proto*/ +static int __Pyx_SetVtable(PyObject *dict, void *vtable); /*proto*/ +static int __Pyx_GetVtable(PyObject *dict, void *vtabptr); /*proto*/ +static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, char *modname); /*proto*/ +static int __Pyx_InternStrings(__Pyx_InternTabEntry *t); /*proto*/ +static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/ +static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/ + +static PyObject *__pyx_m; +static PyObject *__pyx_b; +static int __pyx_lineno; +static char *__pyx_filename; +staticforward char **__pyx_f; + +/* Declarations from hello */ + +char (*(get_hello_msg(void))); /*proto*/ + +/* Implementation of hello */ + +static PyObject *__pyx_n_hello; + +static PyObject *__pyx_f_5hello_hello(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static PyObject *__pyx_f_5hello_hello(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_r; + PyObject *__pyx_1 = 0; + static char *__pyx_argnames[] = {0}; + if (!PyArg_ParseTupleAndKeywords(__pyx_args, __pyx_kwds, "", __pyx_argnames)) return 0; + + /* "C:\cygwin\home\pje\setuptools\tests\shlib_test\hello.pyx":4 */ + __pyx_1 = PyString_FromString(get_hello_msg()); if (!__pyx_1) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 4; goto __pyx_L1;} + __pyx_r = __pyx_1; + __pyx_1 = 0; + goto __pyx_L0; + + __pyx_r = Py_None; Py_INCREF(__pyx_r); + goto __pyx_L0; + __pyx_L1:; + Py_XDECREF(__pyx_1); + __Pyx_AddTraceback("hello.hello"); + __pyx_r = 0; + __pyx_L0:; + return __pyx_r; +} + +static __Pyx_InternTabEntry __pyx_intern_tab[] = { + {&__pyx_n_hello, "hello"}, + {0, 0} +}; + +static struct PyMethodDef __pyx_methods[] = { + {"hello", (PyCFunction)__pyx_f_5hello_hello, METH_VARARGS|METH_KEYWORDS, 0}, + {0, 0, 0, 0} +}; + +DL_EXPORT(void) inithello(void); /*proto*/ +DL_EXPORT(void) inithello(void) { + __pyx_m = Py_InitModule4("hello", __pyx_methods, 0, 0, PYTHON_API_VERSION); + if (!__pyx_m) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; goto __pyx_L1;}; + __pyx_b = PyImport_AddModule("__builtin__"); + if (!__pyx_b) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; goto __pyx_L1;}; + if (PyObject_SetAttrString(__pyx_m, "__builtins__", __pyx_b) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; goto __pyx_L1;}; + if (__Pyx_InternStrings(__pyx_intern_tab) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; goto __pyx_L1;}; + + /* "C:\cygwin\home\pje\setuptools\tests\shlib_test\hello.pyx":3 */ + return; + __pyx_L1:; + __Pyx_AddTraceback("hello"); +} + +static char *__pyx_filenames[] = { + "hello.pyx", +}; +statichere char **__pyx_f = __pyx_filenames; + +/* Runtime support code */ + +static int __Pyx_InternStrings(__Pyx_InternTabEntry *t) { + while (t->p) { + *t->p = PyString_InternFromString(t->s); + if (!*t->p) + return -1; + ++t; + } + return 0; +} + +#include "compile.h" +#include "frameobject.h" +#include "traceback.h" + +static void __Pyx_AddTraceback(char *funcname) { + PyObject *py_srcfile = 0; + PyObject *py_funcname = 0; + PyObject *py_globals = 0; + PyObject *empty_tuple = 0; + PyObject *empty_string = 0; + PyCodeObject *py_code = 0; + PyFrameObject *py_frame = 0; + + py_srcfile = PyString_FromString(__pyx_filename); + if (!py_srcfile) goto bad; + py_funcname = PyString_FromString(funcname); + if (!py_funcname) goto bad; + py_globals = PyModule_GetDict(__pyx_m); + if (!py_globals) goto bad; + empty_tuple = PyTuple_New(0); + if (!empty_tuple) goto bad; + empty_string = PyString_FromString(""); + if (!empty_string) goto bad; + py_code = PyCode_New( + 0, /*int argcount,*/ + 0, /*int nlocals,*/ + 0, /*int stacksize,*/ + 0, /*int flags,*/ + empty_string, /*PyObject *code,*/ + empty_tuple, /*PyObject *consts,*/ + empty_tuple, /*PyObject *names,*/ + empty_tuple, /*PyObject *varnames,*/ + empty_tuple, /*PyObject *freevars,*/ + empty_tuple, /*PyObject *cellvars,*/ + py_srcfile, /*PyObject *filename,*/ + py_funcname, /*PyObject *name,*/ + __pyx_lineno, /*int firstlineno,*/ + empty_string /*PyObject *lnotab*/ + ); + if (!py_code) goto bad; + py_frame = PyFrame_New( + PyThreadState_Get(), /*PyThreadState *tstate,*/ + py_code, /*PyCodeObject *code,*/ + py_globals, /*PyObject *globals,*/ + 0 /*PyObject *locals*/ + ); + if (!py_frame) goto bad; + py_frame->f_lineno = __pyx_lineno; + PyTraceBack_Here(py_frame); +bad: + Py_XDECREF(py_srcfile); + Py_XDECREF(py_funcname); + Py_XDECREF(empty_tuple); + Py_XDECREF(empty_string); + Py_XDECREF(py_code); + Py_XDECREF(py_frame); +} diff --git a/tests/shlib_test/hello.pyx b/tests/shlib_test/hello.pyx new file mode 100755 index 00000000..58ce6919 --- /dev/null +++ b/tests/shlib_test/hello.pyx @@ -0,0 +1,4 @@ +cdef extern char *get_hello_msg() + +def hello(): + return get_hello_msg() diff --git a/tests/shlib_test/hellolib.c b/tests/shlib_test/hellolib.c new file mode 100755 index 00000000..88d65cee --- /dev/null +++ b/tests/shlib_test/hellolib.c @@ -0,0 +1,3 @@ +extern char* get_hello_msg() { + return "Hello, world!"; +} diff --git a/tests/shlib_test/setup.py b/tests/shlib_test/setup.py new file mode 100755 index 00000000..122de77c --- /dev/null +++ b/tests/shlib_test/setup.py @@ -0,0 +1,10 @@ +from setuptools import setup, Extension, SharedLibrary + +setup( + name="shlib_test", + ext_modules = [ + SharedLibrary("hellolib", ["hellolib.c"]), + Extension("hello", ["hello.pyx"], libraries=["hellolib"]) + ], + test_suite="test_hello.HelloWorldTest", +) diff --git a/tests/shlib_test/test_hello.py b/tests/shlib_test/test_hello.py new file mode 100755 index 00000000..6da02e31 --- /dev/null +++ b/tests/shlib_test/test_hello.py @@ -0,0 +1,7 @@ +from unittest import TestCase + +class HelloWorldTest(TestCase): + def testHelloMsg(self): + from hello import hello + self.assertEqual(hello(), "Hello, world!") + |