Fix ctypes support on Linux.

find_library() is not the correct function to resolve the full path,
at least not on Linux.


git-svn-id: http://svn.pyinstaller.org/trunk@632 8dd32b29-ccff-0310-8a9a-9233e24343b1
This commit is contained in:
giovannibajo
2009-03-01 12:13:57 +00:00
parent d20b371de1
commit f7f2f1d674
3 changed files with 58 additions and 14 deletions
+23 -10
View File
@@ -1,22 +1,35 @@
# -*- mode: python -*-
import sys
if not sys.platform.startswith("darwin"):
raise RuntimeError("please port test15 under linux2 and win32")
import os
CTYPES_DIR = "ctypes"
TEST_LIB = os.path.join(CTYPES_DIR, "testctypes")
if sys.platform == "linux2":
TEST_LIB += ".so"
elif sys.platform == "darwin2":
TEST_LIB += ".dylib"
elif sys.platform == "win32":
TEST_LIB += ".dll"
else:
raise NotImplentedError
# If the required dylib does not reside in the current directory, the Analysis
# class machinery, based on ctypes.util.find_library, will not find it. This was
# done on purpose for this test, to show how to give Analysis class a clue.
os.environ["DYLD_LIBRARY_PATH"] = "ctypes/"
os.environ["DYLD_LIBRARY_PATH"] = CTYPES_DIR
os.environ["LD_LIBRARY_PATH"] = CTYPES_DIR
# Check for presence of testctypes shared library, build it if not present
if not os.path.exists("ctypes/testctypes.dylib"):
os.chdir("ctypes")
os.system("gcc -Wall -dynamiclib testctypes.c -o testctypes.dylib -headerpad_max_install_names")
id_dylib = os.path.abspath("testctypes.dylib")
os.system("install_name_tool -id %s testctypes.dylib" % (id_dylib,))
if not os.path.exists(TEST_LIB):
os.chdir(CTYPES_DIR)
if sys.platform == "darwin2":
os.system("gcc -Wall -dynamiclib testctypes.c -o testctypes.dylib -headerpad_max_install_names")
id_dylib = os.path.abspath("testctypes.dylib")
os.system("install_name_tool -id %s testctypes.dylib" % (id_dylib,))
elif sys.platform == "linux2":
os.system("gcc -fPIC -shared testctypes.c -o testctypes.so")
else:
raise NotImplementedError
os.chdir("..")
__testname__ = 'test15'
+9 -2
View File
@@ -1,7 +1,14 @@
#!/usr/bin/env python
import sys
from ctypes import *
def dummy(arg):
tct = CDLL("testctypes.dylib")
if sys.platform == "linux2":
tct = CDLL("testctypes.so")
elif sys.platform == "darwin":
tct = CDLL("testctypes.dylib")
elif sys.platform == "win32":
tct = CDLL("testctypes.dll")
else:
raise NotImplementedError
return tct.dummy(arg)
+26 -2
View File
@@ -539,11 +539,35 @@ class ImportTracker:
cbinaries = list(mod.binaries)
mod.binaries = []
# Executes find_library prepending ImportTracker's local paths to
# library search paths, then replaces original values.
# Try to locate the shared library on disk. This is done by
# executing ctypes.utile.find_library prepending ImportTracker's
# local paths to library search paths, then replaces original values.
old = _savePaths()
for cbin in cbinaries:
cpath = find_library(os.path.splitext(cbin)[0])
if sys.platform == "linux2":
# CAVEAT: find_library() is not the correct function. Ctype's
# documentation says that it is meant to resolve only the filename
# (as a *compiler* does) not the full path. Anyway, it works well
# enough on Windows and Mac. On Linux, we need to implement
# more code to find out the full path.
if cpath is None:
cpath = cbin
# "man ld.so" says that we should first search LD_LIBRARY_PATH
# and then the ldcache
for d in os.environ["LD_LIBRARY_PATH"].split(":"):
if os.path.isfile(d + "/" + cpath):
cpath = d + "/" + cpath
break
else:
for L in os.popen("ldconfig -p").read().splitlines():
if cpath in L:
cpath = L.split("=>", 1)[1].strip()
assert os.path.isfile(cpath)
break
else:
cpath = None
if cpath is None:
print "W: library %s required via ctypes not found" % (cbin,)
else: