"Sage La Torra" <sagelt@gmail.com> writes:
> As of last week, David James and I think that the Ctypes Python
> Binding Branch is ready for merging, or at least a thorough review in
> preparation for merging. The branch is available at
> http://svn.collab.net/repos/svn/branches/ctypes-python-bindings/.
As a first step to reviewing, I tried to build it. Currently,
you assume everything is installed on the linker search path, but
this is frequently not the case. So, I changed autogen.py and
ctypesgen/wrap.py to take -L, -R, and --rpath options (as well as
the -Wl,-prefixed forms) to specify libdirs to search.
I also changed autogen.py to use apr-1-config --ldflags --link-ld
so that ensuring autogen.py has the right apr-1-config is all a
user needs to do if all svn stuff is in the same libdir.
[[[
* autogen.py
(option_W): Add optparse callback to parse -Wl,-prefixed linker
options (typically used as -Wl,-R/some/dir to specify RPATH).
(parser): Handle -L, -R, --rpath, and -W (using option_W) options,
storing values into options.libdirs list.
(get_apr_config): Initialize ldflags to the output of 'apr-1-config
--ldflags --libs' so we pick up any libdir options, to be passed on to
ctypesgen/wrap.py .
Pass options.libdirs on to ctypesgen/wrap.py with -R option. Handle
errors from ctypesgen/wrap.py .
* wrap.py
(load_library): Take new optional libdirs argument; if provided, if CDLL
couldn't find the library, and if the path from find_library is
relative, try loading the library from each of the libdirs.
(CtypesWrapper.begin_output): Save new optional libdirs argument in
self.libdirs for foo.
(CtypesWrapper.print_preamble): Pass self.libdirs along to load_library.
(option_W): Add optparse callback to parse -Wl,-prefixed linker
options (typically used as -Wl,-R/some/dir to specify RPATH).
(main): Handle -L, -R, --rpath, and -W (using option_W) options, storing
values into options.libdirs list.
]]]
Index: autogen.py
===================================================================
--- autogen.py (revision 26401)
+++ autogen.py (working copy)
@@ -6,6 +6,17 @@
from tempfile import mkdtemp
from glob import glob
+def option_W(option, opt, value, parser):
+ if len(value) < 4 or value[0:3] != 'l,-':
+ raise optparse.BadOptionError("not in '-Wl,<opt>' form: %s%s"
+ % (opt, value))
+ opt = value[2:]
+ if opt not in ['-L', '-R', '--rpath']:
+ raise optparse.BadOptionError("-Wl option must be -L, -R"
+ " or --rpath, not " + value[2:])
+ # Push the linker option onto the list for further parsing.
+ parser.rargs.insert(0, value)
+
parser = OptionParser()
parser.add_option("-a", "--apr-config", dest="apr_config",
help="The full path to your apr-1-config or apr-config script")
@@ -15,6 +26,12 @@
parser.add_option("", "--save-preprocessed-headers", dest="filename",
help="Save the preprocessed headers to the specified "
"FILENAME")
+parser.add_option("-W", action="callback", callback=option_W, type='str',
+ metavar="l,OPTION",
+ help="where OPTION is -L, -R, or --rpath")
+parser.add_option("-L", "-R", "--rpath", action="append", dest="libdirs",
+ metavar="LIBDIR", help="Add LIBDIR to the search path")
+parser.set_defaults(libdirs=[])
(options, args) = parser.parse_args()
@@ -48,6 +65,10 @@
apr_include_dir = run_cmd("%s --includedir" % apr_config).strip()
apr_version = run_cmd("%s --version" % apr_config).strip()
cpp = run_cmd("%s --cpp" % apr_config).strip()
+
+ fout = run_cmd("%s --ldflags --link-ld" % apr_config)
+ if fout:
+ ldflags = fout.split()
break
else:
print ferr
@@ -72,10 +93,9 @@
"to your Subversion installation using the --prefix\n"
"option.")
- ldflags = [
- "-lapr-%s" % apr_version[0],
- "-laprutil-%s" % apr_version[0],
- ]
+ # TODO: Use apu-1-config, as above:
+ # ldflags.extend(run_cmd('apu-1-config --ldflags --link-ld').split())
+ ldflags.append("-laprutil-%s" % apr_version[0])
# List the libraries in the order they should be loaded
libraries = [
@@ -124,16 +144,31 @@
os.environ["LIBRARY_PATH"] = library_path
-cmd = ("cd %s && %s %s/ctypesgen/wrap.py --cpp '%s %s' %s "
+cmd = ["cd %s && %s %s/ctypesgen/wrap.py --cpp '%s %s' %s "
"%s -o svn_all.py" % (tempdir, sys.executable, os.getcwd(),
- cpp, flags, ldflags, includes))
+ cpp, flags, ldflags, includes)]
+cmd.extend('-R ' + x for x in options.libdirs)
+cmd = ' '.join(cmd)
if options.filename:
cmd += " --save-preprocessed-headers=%s" % \
os.path.abspath(options.filename)
print cmd
-os.system(cmd)
+status = os.system(cmd)
+if os.WIFEXITED(status):
+ status = os.WEXITSTATUS(status)
+ if status != 0:
+ sys.exit(status)
+elif os.WIFSIGNALED(status):
+ sys.stderr.write("wrap.py killed with signal %d" % (os.WTERMSIG(status),))
+ sys.exit(2)
+elif os.WIFSTOPPED(status):
+ sys.stderr.write("wrap.py stopped with signal %d" % (os.WSTOPSIG(status),))
+ sys.exit(2)
+else:
+ sys.stderr.write("wrap.py exited with invalid status %d" % (status,))
+ sys.exit(2)
func_re = re.compile(r"CFUNCTYPE\(POINTER\((\w+)\)")
out = file("%s/svn_all2.py" % tempdir, "w")
Index: ctypesgen/wrap.py
===================================================================
--- ctypesgen/wrap.py (revision 35)
+++ ctypesgen/wrap.py (working copy)
@@ -14,11 +14,12 @@
from ctypesparser import *
import textwrap
-import sys, re
+import optparse, os, sys, re
+from errno import ENOENT
from ctypes import CDLL, RTLD_GLOBAL, c_byte
from ctypes.util import find_library
-def load_library(name, mode=RTLD_GLOBAL):
+def load_library(name, mode=RTLD_GLOBAL, libdirs=None):
if os.name == "nt":
return CDLL(name, mode=mode)
path = find_library(name)
@@ -26,14 +27,34 @@
# Maybe 'name' is not a library name in the linker style,
# give CDLL a last chance to find the library.
path = name
- return CDLL(path, mode=mode)
+ try:
+ return CDLL(path, mode=mode)
+ except OSError, e:
+ # XXX Sadly, ctypes raises OSError without setting errno.
+ if e.errno not in [ENOENT, None]:
+ raise
+ if os.path.isabs(path) or libdirs is None:
+ raise
+ # path is relative and the linker couldn't find it; if the
+ # user provided any libdirs, try those.
+ # XXX This isn't quite right; if the user provided libdirs, we
+ # should *only* try those; he may be specifically trying to
+ # avoid one on the system search path. But we're relying on
+ # find_library to turn e.g. 'apr-1' into 'libapr-1.so.0'
+ for libdir in set(libdirs):
+ try:
+ return CDLL(os.path.join(libdir, path), mode=mode)
+ except OSError, e:
+ if e.errno not in [ENOENT, None]:
+ raise
class CtypesWrapper(CtypesParser, CtypesTypeVisitor):
file=None
def begin_output(self, output_file, library, link_modules=(),
emit_filenames=(), all_headers=False,
include_symbols=None, exclude_symbols=None,
- save_preprocessed_headers=None):
+ save_preprocessed_headers=None,
+ libdirs=None):
self.library = library
self.file = output_file
self.all_names = []
@@ -51,6 +72,7 @@
self.exclude_symbols = re.compile(exclude_symbols)
self.preprocessor_parser.save_preprocessed_headers = \
save_preprocessed_headers
+ self.libdirs = libdirs
self.linked_symbols = {}
for name in link_modules:
@@ -180,7 +202,7 @@
}).lstrip()
self.loaded_libraries = []
for library in self.library:
- lib = load_library(library)
+ lib = load_library(library, libdirs=self.libdirs)
if lib:
self.loaded_libraries.append(lib)
print >>self.file, textwrap.dedent("""
@@ -314,11 +336,19 @@
self.all_names.append(name)
break
+def option_W(option, opt, value, parser):
+ if len(value) < 4 or value[0:3] != 'l,-':
+ raise optparse.BadOptionError("not in '-Wl,<opt>' form: %s%s"
+ % (opt, value))
+ opt = value[2:]
+ if opt not in ['-L', '-R', '--rpath']:
+ raise optparse.BadOptionError("-Wl option must be -L, -R"
+ " or --rpath, not " + value[2:])
+ # Push the linker option onto the list for further parsing.
+ parser.rargs.insert(0, value)
+
def main(*argv):
from tempfile import NamedTemporaryFile
- import optparse
- import sys
- import os.path
usage = 'usage: %prog [options] <header.h>'
op = optparse.OptionParser(usage=usage)
@@ -341,7 +371,12 @@
op.add_option('', '--save-preprocessed-headers', dest='filename',
help='Save the preprocessed headers to the specified '
'FILENAME')
-
+ op.add_option("-W", action="callback", callback=option_W, type='str',
+ metavar="l,OPTION",
+ help="where OPTION is -L, -R, or --rpath")
+ op.add_option("-L", "-R", "--rpath", action="append", dest="libdirs",
+ metavar="LIBDIR", help="Add LIBDIR to the search path")
+
(options, args) = op.parse_args(list(argv[1:]))
if len(args) < 1:
print >> sys.stderr, 'No header files specified.'
@@ -363,7 +398,8 @@
all_headers=options.all_headers,
include_symbols=options.include_symbols,
exclude_symbols=options.exclude_symbols,
- save_preprocessed_headers=options.filename
+ save_preprocessed_headers=options.filename,
+ libdirs=options.libdirs,
)
wrapper.preprocessor_parser.cpp = options.cpp
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Fri Aug 31 01:12:46 2007