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.
This commit is contained in:
Mathieu Virbel 2013-01-05 12:17:52 +01:00
parent d539c90474
commit 92f38fe2d7
6 changed files with 94 additions and 4 deletions

1
.gitignore vendored
View file

@ -4,6 +4,7 @@ Python-*
freetype-*
build/*
src/SDL/Xcode-iPhoneOS/SDL/build/
src/SDL/Xcode-iOS/SDL/build/
tmp/*
kivy/*
libtremor/*

View file

@ -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 file

@ -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 file

@ -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

41
tools/cythonize.py Executable file
View file

@ -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 file

@ -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);
}