=== modified file 'Lib/distutils/command/build_ext.py' --- Lib/distutils/command/build_ext.py 2010-01-29 11:46:31 +0000 +++ Lib/distutils/command/build_ext.py 2010-07-07 18:21:04 +0000 @@ -515,7 +515,7 @@ "a list of source filenames" % ext.name) sources = list(sources) - ext_path = self.get_ext_fullpath(ext.name) + ext_path = self.get_ext_fullpath(ext.name, ext) depends = sources + ext.depends if not (self.force or newer_group(depends, ext_path, 'newer')): log.debug("skipping '%s' extension (up-to-date)", ext.name) @@ -669,7 +669,7 @@ # -- Name generators ----------------------------------------------- # (extension names, filenames, whatever) - def get_ext_fullpath(self, ext_name): + def get_ext_fullpath(self, ext_name, ext=None): """Returns the path of the filename for a given extension. The file is located in `build_lib` or directly in the package @@ -677,7 +677,7 @@ """ fullname = self.get_ext_fullname(ext_name) modpath = fullname.split('.') - filename = self.get_ext_filename(modpath[-1]) + filename = self.get_ext_filename(modpath[-1], ext) if not self.inplace: # no further work needed @@ -705,7 +705,7 @@ else: return self.package + '.' + ext_name - def get_ext_filename(self, ext_name): + def get_ext_filename(self, ext_name, ext=None): r"""Convert the name of an extension (eg. "foo.bar") into the name of the file from which it will be loaded (eg. "foo/bar.so", or "foo\bar.pyd"). @@ -717,6 +717,17 @@ ext_path[len(ext_path) - 1] = ext_path[len(ext_path) - 1][:8] # extensions in debug_mode are named 'module_d.pyd' under windows so_ext = _sysconfig.get_config_var('SO') + if ext is not None and ext.so_abi_tag is not None: + tag, sep, file_ext = so_ext.rpartition('.') + # The ABI tag could be the empty string, in which case there is no + # tag, just the .so extension. Otherwise, we can replace the + # ABI tag hard coded in the Makefile with the one requested in the + # Extension instance. + if ext.so_abi_tag == '': + so_ext = sep + file_ext + else: + so_ext = sep + so_abi_tag + sep + file_ext + if os.name == 'nt' and self.debug: return os.path.join(*ext_path) + '_d' + so_ext return os.path.join(*ext_path) + so_ext === modified file 'Lib/distutils/extension.py' --- Lib/distutils/extension.py 2010-01-29 11:41:03 +0000 +++ Lib/distutils/extension.py 2010-07-07 18:21:04 +0000 @@ -125,6 +125,9 @@ self.language = language self.optional = optional + # Optional shared library ABI tag. + self.so_abi_tag = kw.pop('so_abi_tag', None) + # If there are unknown keyword options, warn about them if len(kw) > 0: options = [repr(option) for option in kw] === modified file 'Lib/distutils/tests/test_build_ext.py' --- Lib/distutils/tests/test_build_ext.py 2010-04-02 21:38:52 +0000 +++ Lib/distutils/tests/test_build_ext.py 2010-07-07 18:21:04 +0000 @@ -330,8 +330,8 @@ finally: os.chdir(old_wd) self.assertTrue(os.path.exists(so_file)) - self.assertEquals(os.path.splitext(so_file)[-1], - sysconfig.get_config_var('SO')) + so_ext = sysconfig.get_config_var('SO') + self.assertTrue(so_file.endswith(so_ext)) so_dir = os.path.dirname(so_file) self.assertEquals(so_dir, other_tmp_dir) @@ -339,8 +339,7 @@ cmd.run() so_file = cmd.get_outputs()[0] self.assertTrue(os.path.exists(so_file)) - self.assertEquals(os.path.splitext(so_file)[-1], - sysconfig.get_config_var('SO')) + self.assertTrue(so_file.endswith(so_ext)) so_dir = os.path.dirname(so_file) self.assertEquals(so_dir, cmd.build_lib) === modified file 'Makefile.pre.in' --- Makefile.pre.in 2010-06-27 19:40:18 +0000 +++ Makefile.pre.in 2010-07-07 18:21:04 +0000 @@ -35,6 +35,7 @@ AR= @AR@ RANLIB= @RANLIB@ SVNVERSION= @SVNVERSION@ +SOABI= @SOABI@ GNULD= @GNULD@ @@ -554,6 +555,11 @@ Modules/python.o: $(srcdir)/Modules/python.c $(MAINCC) -c $(PY_CFLAGS) -o $@ $(srcdir)/Modules/python.c +Python/dynload_shlib.o: $(srcdir)/Python/dynload_shlib.c Makefile + $(CC) -c $(PY_CFLAGS) \ + $(SOABI) \ + -o $@ $(srcdir)/Python/dynload_shlib.c + $(IO_OBJS): $(IO_H) $(GRAMMAR_H) $(GRAMMAR_C): $(PGEN) $(GRAMMAR_INPUT) === modified file 'Python/dynload_shlib.c' --- Python/dynload_shlib.c 2010-05-09 14:52:27 +0000 +++ Python/dynload_shlib.c 2010-07-07 18:21:04 +0000 @@ -30,6 +30,11 @@ #define LEAD_UNDERSCORE "" #endif +/* The .so extension module ABI tag, supplied by the Makefile via + Makefile.pre.in and configure. This is used to discriminate between + incompatible .so files so that extensions for different Python builds can + live in the same directory. E.g. foomodule.cpython-32.so +*/ const struct filedescr _PyImport_DynLoadFiletab[] = { #ifdef __CYGWIN__ @@ -48,9 +53,13 @@ #else {".so", "rb", C_EXTENSION}, {"module.so", "rb", C_EXTENSION}, -#endif -#endif -#endif +#ifdef SOABI + {"." SOABI ".so", "rb", C_EXTENSION}, + {"module." SOABI ".so", "rb", C_EXTENSION}, +#endif /* SOABI */ +#endif /* __VMS */ +#endif /* defined(PYOS_OS2) && defined(PYCC_GCC) */ +#endif /* __CYGWIN__ */ {0, 0} }; === modified file 'configure' --- configure 2010-06-27 22:34:03 +0000 +++ configure 2010-07-07 18:21:04 +0000 @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in Revision: 82090 . +# From configure.in Revision. # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.65 for python 3.2. # @@ -679,6 +679,7 @@ ARCH_RUN_32BIT UNIVERSALSDK CONFIG_ARGS +SOABI SOVERSION VERSION target_alias @@ -722,6 +723,7 @@ ac_subst_files='' ac_user_opts=' enable_option_checking +with_so_abi_tag enable_universalsdk with_universal_archs with_framework_name @@ -1386,6 +1388,8 @@ Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-so-abi-tag=TAG specify a tag to uniquely identify .so file ABI + compliance; e.g. foo..so --with-universal-archs=ARCH select architectures for universal build ("32-bit", "64-bit", "3-way", "intel" or "all") @@ -1929,11 +1933,11 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default + enum { N = $2 / 2 - 1 }; int main () { -static int test_array [1 - 2 * !(enum { N = $2 / 2 - 1 }; - 0 < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1))]; +static int test_array [1 - 2 * !(0 < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1))]; test_array [0] = 0 ; @@ -1944,11 +1948,11 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default + enum { N = $2 / 2 - 1 }; int main () { -static int test_array [1 - 2 * !(enum { N = $2 / 2 - 1 }; - ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1) +static int test_array [1 - 2 * !(($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1) < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 2))]; test_array [0] = 0 @@ -2696,9 +2700,29 @@ VERSION=3.2 +# Version number or Python's own shared library file. SOVERSION=1.0 +# ABI version string for Python extension modules. This appears between the +# periods in shared library file names, e.g. foo..so. Use the empty +# string to specify no value. + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-so-abi-tag" >&5 +$as_echo_n "checking for --with-so-abi-tag... " >&6; } + +# Check whether --with-so-abi-tag was given. +if test "${with_so_abi_tag+set}" = set; then : + withval=$with_so_abi_tag; + SOABI=$withval +else + + SOABI= +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $SOABI" >&5 +$as_echo "$SOABI" >&6; } + # The later defininition of _XOPEN_SOURCE disables certain features # on Linux, so we need _GNU_SOURCE to re-enable them (makedev, tm_zone). @@ -7425,6 +7449,16 @@ esac ;; CYGWIN*) SO=.dll;; + Linux*) + if test -z "$SOABI" + then + SO=.so + SOABI=-USOABI + else + SO=.${SOABI}.so + SOABI="-DSOABI=\\\"$SOABI\\\"" + fi + ;; *) SO=.so;; esac else === modified file 'configure.in' --- configure.in 2010-06-19 18:58:37 +0000 +++ configure.in 2010-07-07 18:21:04 +0000 @@ -52,9 +52,23 @@ AC_SUBST(VERSION) VERSION=PYTHON_VERSION +# Version number or Python's own shared library file. AC_SUBST(SOVERSION) SOVERSION=1.0 +# ABI version string for Python extension modules. This appears between the +# periods in shared library file names, e.g. foo..so. Use the empty +# string to specify no value. +AC_SUBST(SOABI) +AC_MSG_CHECKING(for --with-so-abi-tag) +AC_ARG_WITH(so-abi-tag, + AS_HELP_STRING([--with-so-abi-tag=TAG], + [specify a tag to uniquely identify .so file ABI compliance; e.g. foo..so]), +[ + SOABI=$withval], [ + SOABI= ]) +AC_MSG_RESULT($SOABI) + # The later defininition of _XOPEN_SOURCE disables certain features # on Linux, so we need _GNU_SOURCE to re-enable them (makedev, tm_zone). AC_DEFINE(_GNU_SOURCE, 1, [Define on Linux to activate all library features]) @@ -1656,6 +1670,16 @@ esac ;; CYGWIN*) SO=.dll;; + Linux*) + if test -z "$SOABI" + then + SO=.so + SOABI=-USOABI + else + SO=.${SOABI}.so + SOABI="-DSOABI=\\\"$SOABI\\\"" + fi + ;; *) SO=.so;; esac else