[Python-checkins] r41927 - in sandbox/trunk/setuptools: setuptools/__init__.py setuptools/command/build_ext.py setuptools/dist.py setuptools/extension.py tests tests/shlib_test tests/shlib_test/hello.c tests/shlib_test/hello.pyx tests/shlib_test/hellolib.c tests/shlib_test/setup.py tests/shlib_test/test_hello.py
phillip.eby
python-checkins at python.org
Fri Jan 6 00:14:27 CET 2006
Author: phillip.eby
Date: Fri Jan 6 00:14:21 2006
New Revision: 41927
Added:
sandbox/trunk/setuptools/tests/
sandbox/trunk/setuptools/tests/shlib_test/
sandbox/trunk/setuptools/tests/shlib_test/hello.c (contents, props changed)
sandbox/trunk/setuptools/tests/shlib_test/hello.pyx (contents, props changed)
sandbox/trunk/setuptools/tests/shlib_test/hellolib.c (contents, props changed)
sandbox/trunk/setuptools/tests/shlib_test/setup.py (contents, props changed)
sandbox/trunk/setuptools/tests/shlib_test/test_hello.py (contents, props changed)
Modified:
sandbox/trunk/setuptools/setuptools/__init__.py
sandbox/trunk/setuptools/setuptools/command/build_ext.py
sandbox/trunk/setuptools/setuptools/dist.py
sandbox/trunk/setuptools/setuptools/extension.py
Log:
First draft of shared library build support. See tests/shlib_test
for a trivial example. This has only been tested on Windows with
a MinGW compiler, and the Mac OS support isn't finished. Testing
w/other platforms+compilers would be helpful.
Modified: sandbox/trunk/setuptools/setuptools/__init__.py
==============================================================================
--- sandbox/trunk/setuptools/setuptools/__init__.py (original)
+++ sandbox/trunk/setuptools/setuptools/__init__.py Fri Jan 6 00:14:21 2006
@@ -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
Modified: sandbox/trunk/setuptools/setuptools/command/build_ext.py
==============================================================================
--- sandbox/trunk/setuptools/setuptools/command/build_ext.py (original)
+++ sandbox/trunk/setuptools/setuptools/command/build_ext.py Fri Jan 6 00:14:21 2006
@@ -7,9 +7,11 @@
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 @@
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 @@
# 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)
+
+
+
+
Modified: sandbox/trunk/setuptools/setuptools/dist.py
==============================================================================
--- sandbox/trunk/setuptools/setuptools/dist.py (original)
+++ sandbox/trunk/setuptools/setuptools/dist.py Fri Jan 6 00:14:21 2006
@@ -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 @@
+
+
def assert_string_list(dist, attr, value):
"""Verify that value is a string list or None"""
try:
Modified: sandbox/trunk/setuptools/setuptools/extension.py
==============================================================================
--- sandbox/trunk/setuptools/setuptools/extension.py (original)
+++ sandbox/trunk/setuptools/setuptools/extension.py Fri Jan 6 00:14:21 2006
@@ -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 @@
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
Added: sandbox/trunk/setuptools/tests/shlib_test/hello.c
==============================================================================
--- (empty file)
+++ sandbox/trunk/setuptools/tests/shlib_test/hello.c Fri Jan 6 00:14:21 2006
@@ -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);
+}
Added: sandbox/trunk/setuptools/tests/shlib_test/hello.pyx
==============================================================================
--- (empty file)
+++ sandbox/trunk/setuptools/tests/shlib_test/hello.pyx Fri Jan 6 00:14:21 2006
@@ -0,0 +1,4 @@
+cdef extern char *get_hello_msg()
+
+def hello():
+ return get_hello_msg()
Added: sandbox/trunk/setuptools/tests/shlib_test/hellolib.c
==============================================================================
--- (empty file)
+++ sandbox/trunk/setuptools/tests/shlib_test/hellolib.c Fri Jan 6 00:14:21 2006
@@ -0,0 +1,3 @@
+extern char* get_hello_msg() {
+ return "Hello, world!";
+}
Added: sandbox/trunk/setuptools/tests/shlib_test/setup.py
==============================================================================
--- (empty file)
+++ sandbox/trunk/setuptools/tests/shlib_test/setup.py Fri Jan 6 00:14:21 2006
@@ -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",
+)
Added: sandbox/trunk/setuptools/tests/shlib_test/test_hello.py
==============================================================================
--- (empty file)
+++ sandbox/trunk/setuptools/tests/shlib_test/test_hello.py Fri Jan 6 00:14:21 2006
@@ -0,0 +1,7 @@
+from unittest import TestCase
+
+class HelloWorldTest(TestCase):
+ def testHelloMsg(self):
+ from hello import hello
+ self.assertEqual(hello(), "Hello, world!")
+
More information about the Python-checkins
mailing list