test_ok2/py/misc/buildcmodule.py

88 lines
2.9 KiB
Python

"""
A utility to build a Python extension module from C, wrapping distutils.
"""
import py
# set to true for automatic re-compilation of extensions
AUTOREGEN = True
# XXX we should distutils in a subprocess, because it messes up the
# environment and who knows what else. Currently we just save
# and restore os.environ.
def make_module_from_c(cfile):
import os, sys, imp
from distutils.core import setup
from distutils.extension import Extension
debug = 0
#try:
# from distutils.log import set_threshold
# set_threshold(10000)
#except ImportError:
# print "ERROR IMPORTING"
# pass
dirpath = cfile.dirpath()
modname = cfile.purebasename
# find the expected extension of the compiled C module
for ext, mode, filetype in imp.get_suffixes():
if filetype == imp.C_EXTENSION:
break
else:
raise ImportError, "cannot find the file name suffix of C ext modules"
lib = dirpath.join(modname+ext)
# XXX argl! we need better "build"-locations alltogether!
if lib.check() and AUTOREGEN and lib.stat().mtime < cfile.stat().mtime:
try:
lib.remove()
except EnvironmentError:
pass # XXX we just use the existing version, bah
if not lib.check():
c = py.io.StdCaptureFD()
try:
try:
saved_environ = os.environ.items()
try:
lastdir = dirpath.chdir()
try:
setup(
name = "pylibmodules",
ext_modules=[
Extension(modname, [str(cfile)])
],
script_name = 'setup.py',
script_args = ['-q', 'build_ext', '--inplace']
#script_args = ['build_ext', '--inplace']
)
finally:
lastdir.chdir()
finally:
for key, value in saved_environ:
if os.environ.get(key) != value:
os.environ[key] = value
finally:
foutput, foutput = c.done()
except KeyboardInterrupt:
raise
except SystemExit, e:
raise RuntimeError("cannot compile %s: %s\n%s" % (cfile, e,
foutput.read()))
# XXX do we need to do some check on fout/ferr?
# XXX not a nice way to import a module
if debug:
print "inserting path to sys.path", dirpath
sys.path.insert(0, str(dirpath))
if debug:
print "import %(modname)s as testmodule" % locals()
exec py.code.compile("import %(modname)s as testmodule" % locals())
try:
sys.path.remove(str(dirpath))
except ValueError:
pass
return testmodule