88 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			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
 |