Permalink
Browse files

fix builtin module conflict

Now all the cythonized modules are rewrite with a mangled name of
package + module name. This avoid symbol conflict if you have the same
module.so as another library (for example, audiostream.sources.thread
and python thread.so was in conflict).

Then, a custom builtin importer is loaded before the application start,
and when you will want to import audiostream.sources.thread, if will
import builtin audiostream_sources_thread.

kivy/ios/lxml/audiostream recipes are impacted. A full rebuild is
needed.
  • Loading branch information...
tito committed Jan 5, 2013
1 parent d539c90 commit 92f38fe2d7ecf222a25a90465a53a086389b559d
Showing with 94 additions and 4 deletions.
  1. +1 −0 .gitignore
  2. +2 −2 tools/build-ios.sh
  3. +21 −1 tools/build-kivy.sh
  4. +1 −1 tools/build-lxml.sh
  5. +41 −0 tools/cythonize.py
  6. +28 −0 tools/templates/main.m
View
@@ -4,6 +4,7 @@ Python-*
freetype-*
build/*
src/SDL/Xcode-iPhoneOS/SDL/build/
+src/SDL/Xcode-iOS/SDL/build/
tmp/*
kivy/*
libtremor/*
View
@@ -13,10 +13,10 @@ export LDSHARED="$KIVYIOSROOT/tools/liblink"
try pushd $KIVYIOSROOT/src/ios
HOSTPYTHON=$TMPROOT/Python-$PYTHON_VERSION/hostpython
-try cython *.pyx
+try $KIVYIOSROOT/tools/cythonize.py *.pyx
try $HOSTPYTHON setup.py build_ext
try $HOSTPYTHON setup.py install -O2 --root iosbuild
-try find iosbuild | grep -E '*\.(py|pyc|so\.o|so\.a|so\.libs)$$' | xargs rm
+try find iosbuild | grep -E '.*\.(py|pyc|so\.o|so\.a|so\.libs)$$' | xargs rm
try rm -rdf "$BUILDROOT/python/lib/python2.7/site-packages/ios*"
try cp iosbuild/usr/local/lib/python2.7/site-packages/ios.so "$BUILDROOT/python/lib/python2.7/site-packages"
popd
View
@@ -21,7 +21,27 @@ OLD_CFLAGS="$CFLAGS"
OLD_LDSHARED="$LDSHARED"
export LDSHARED="$KIVYIOSROOT/tools/liblink"
export CFLAGS="$ARM_CFLAGS"
-try make ios
+
+ln -s $KIVYIOSROOT/Python-$PYTHON_VERSION/python
+ln -s $KIVYIOSROOT/Python-$PYTHON_VERSION/python.exe
+
+rm -rdf iosbuild/
+try mkdir iosbuild
+
+echo "First build ========================================"
+HOSTPYTHON=$TMPROOT/Python-$PYTHON_VERSION/hostpython
+$HOSTPYTHON setup.py build_ext -g
+echo "cythoning =========================================="
+find . -name *.pyx -exec $KIVYIOSROOT/tools/cythonize.py {} \;
+echo "Second build ======================================="
+$HOSTPYTHON setup.py build_ext -g
+$HOSTPYTHON setup.py install -O2 --root iosbuild
+# Strip away the large stuff
+find iosbuild/ | grep -E '.*\.(py|pyc|so\.o|so\.a|so\.libs)$$' | xargs rm
+rm -rdf "$BUILDROOT/python/lib/python2.7/site-packages/kivy"
+# Copy to python for iOS installation
+cp -R "iosbuild/usr/local/lib/python2.7/site-packages/kivy" "$BUILDROOT/python/lib/python2.7/site-packages"
+
export LDSHARED="$OLD_LDSHARED"
export CFLAGS="$OLD_CFLAGS"
popd
View
@@ -100,7 +100,7 @@ pushd $TMPROOT/lxml-$LXML_VERSION
HOSTPYTHON=$TMPROOT/Python-$PYTHON_VERSION/hostpython
XML2_CONFIG=$PREFIX/bin/xml2-config
XSLT_CONFIG=$PREFIX/bin/xslt-config
-find . -name *.pyx -exec cython -t {} \;
+find . -name *.pyx -exec $KIVYIOSROOT/tools/cythonize.py -t {} \;
try $HOSTPYTHON setup.py build_ext
try $HOSTPYTHON setup.py install -O2 --root iosbuild
View
@@ -0,0 +1,41 @@
+#!/usr/bin/env python
+
+import sys
+import subprocess
+
+def do(fn):
+ print 'cythonize:', fn
+ parts = fn.split('/')
+ assert(parts[-1].endswith('.pyx'))
+ if parts[0] == '.':
+ parts.pop(0)
+ modname = parts[-1][:-4]
+ package = '_'.join(parts[:-1])
+
+ # cythonize
+ subprocess.Popen(['cython', fn]).communicate()
+
+ if not package:
+ print 'no need to rewrite', fn
+ else:
+ # get the .c, and change the initXXX
+ fn_c = fn[:-3] + 'c'
+ with open(fn_c) as fd:
+ data = fd.read()
+ pat1 = 'init{}(void)'.format(modname)
+ sub1 = 'init{}_{}(void)'.format(package, modname)
+ pat2 = 'PyInit_{}(void)'.format(modname)
+ sub2 = 'PyInit{}_{}(void)'.format(package, modname)
+ pat3 = 'Pyx_NAMESTR("{}")'.format(modname)
+ sub3 = 'Pyx_NAMESTR("{}_{}")'.format(package, modname)
+ data = data.replace(pat1, sub1)
+ data = data.replace(pat2, sub2)
+ data = data.replace(pat3, sub3)
+
+ print 'rewrite', fn_c
+ with open(fn_c, 'w') as fd:
+ fd.write(data)
+
+if __name__ == '__main__':
+ for fn in sys.argv[1:]:
+ do(fn)
View
@@ -50,6 +50,9 @@ int main(int argc, char *argv[]) {
// If other modules are using thread, we need to initialize them before.
PyEval_InitThreads();
+ // Add an importer for builtin modules
+ load_custom_builtin_importer();
+
// Search and start main.py
const char * prog = [
[[NSBundle mainBundle] pathForResource:@"YourApp/main" ofType:@"pyo"] cStringUsingEncoding:
@@ -94,3 +97,28 @@ void export_orientation() {
//NSLog(@"Available orientation: %@", result);
}
+void load_custom_builtin_importer() {
+ static const char *custom_builtin_importer = \
+ "import sys, imp\n" \
+ "from os.path import exists, join\n" \
+ "class CustomBuiltinImporter(object):\n" \
+ " def find_module(self, fullname, mpath=None):\n" \
+ " if '.' not in fullname:\n" \
+ " return\n" \
+ " if mpath is None:\n" \
+ " return\n" \
+ " part = fullname.rsplit('.')[-1]\n" \
+ " fn = join(mpath[0], '{}.so'.format(part))\n" \
+ " if exists(fn):\n" \
+ " return self\n" \
+ " return\n" \
+ " def load_module(self, fullname):\n" \
+ " f = fullname.replace('.', '_')\n" \
+ " mod = sys.modules.get(f)\n" \
+ " if mod is None:\n" \
+ " mod = imp.load_dynamic(f, f)\n" \
+ " return mod\n" \
+ " return mod\n" \
+ "sys.meta_path.append(RewriteImporter())";
+ PyRun_SimpleString(custom_builtin_importer);
+}

0 comments on commit 92f38fe

Please sign in to comment.