1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
|
import py, os, sys
from rpython.translator.platform import Platform, log, CompilationError
from rpython.translator.tool import stdoutcapture
def log_spawned_cmd(spawn):
def spawn_and_log(cmd, *args, **kwds):
log.execute(' '.join(cmd))
return spawn(cmd, *args, **kwds)
return spawn_and_log
CFLAGS = ['-O3']
if os.name != 'nt':
so_ext = 'so'
else:
so_ext = 'dll'
class DistutilsPlatform(Platform):
""" This is a generic distutils platform. I hope it'll go away at some
point soon completely
"""
name = "distutils"
so_ext = so_ext
def __init__(self, cc=None):
self.cc = cc
if self.name == "distutils":
self.name = sys.platform
def _ensure_correct_math(self):
if self.name != 'win32':
return # so far
from distutils import sysconfig
gcv = sysconfig.get_config_vars()
opt = gcv.get('OPT') # not always existent
if opt and '/Op' not in opt:
opt += '/Op'
gcv['OPT'] = opt
def compile(self, cfilenames, eci, outputfilename=None, standalone=True):
self._ensure_correct_math()
self.cfilenames = cfilenames
if standalone:
ext = ''
else:
ext = so_ext
self.standalone = standalone
self.libraries = list(eci.libraries)
self.include_dirs = list(eci.include_dirs)
self.library_dirs = list(eci.library_dirs)
self.compile_extra = list(eci.compile_extra)
self.link_extra = list(eci.link_extra)
self.frameworks = list(eci.frameworks)
if not self.name in ('win32', 'darwin', 'cygwin'): # xxx
if 'm' not in self.libraries:
self.libraries.append('m')
self.compile_extra += CFLAGS + ['-fomit-frame-pointer']
if 'pthread' not in self.libraries:
self.libraries.append('pthread')
if self.name != 'sunos5':
self.compile_extra += ['-pthread']
self.link_extra += ['-pthread']
else:
self.compile_extra += ['-pthreads']
self.link_extra += ['-lpthread']
if self.name == 'win32':
self.link_extra += ['/DEBUG'] # generate .pdb file
if self.name == 'darwin':
# support Fink & Darwinports
for s in ('/sw/', '/opt/local/'):
if s + 'include' not in self.include_dirs and \
os.path.exists(s + 'include'):
self.include_dirs.append(s + 'include')
if s + 'lib' not in self.library_dirs and \
os.path.exists(s + 'lib'):
self.library_dirs.append(s + 'lib')
self.compile_extra += CFLAGS + ['-fomit-frame-pointer']
for framework in self.frameworks:
self.link_extra += ['-framework', framework]
if outputfilename is None:
self.outputfilename = py.path.local(cfilenames[0]).new(ext=ext)
else:
self.outputfilename = py.path.local(outputfilename)
self.eci = eci
import distutils.errors
basename = self.outputfilename.new(ext='')
data = ''
try:
saved_environ = os.environ.copy()
c = stdoutcapture.Capture(mixed_out_err=True)
try:
self._build()
finally:
# workaround for a distutils bugs where some env vars can
# become longer and longer every time it is used
for key, value in saved_environ.items():
if os.environ.get(key) != value:
os.environ[key] = value
foutput, foutput = c.done()
data = foutput.read()
if data:
fdump = basename.new(ext='errors').open("wb")
fdump.write(data)
fdump.close()
except (distutils.errors.CompileError,
distutils.errors.LinkError):
raise CompilationError('', data)
except:
print >>sys.stderr, data
raise
return self.outputfilename
def _build(self):
from distutils.ccompiler import new_compiler
from distutils import sysconfig
compiler = new_compiler(force=1)
if self.cc is not None:
for c in '''compiler compiler_so compiler_cxx
linker_exe linker_so'''.split():
compiler.executables[c][0] = self.cc
if not self.standalone:
sysconfig.customize_compiler(compiler) # XXX
compiler.spawn = log_spawned_cmd(compiler.spawn)
objects = []
for cfile in self.cfilenames:
cfile = py.path.local(cfile)
compile_extra = self.compile_extra[:]
old = cfile.dirpath().chdir()
try:
res = compiler.compile([cfile.basename],
include_dirs=self.eci.include_dirs,
extra_preargs=compile_extra)
assert len(res) == 1
cobjfile = py.path.local(res[0])
assert cobjfile.check()
objects.append(str(cobjfile))
finally:
old.chdir()
if self.standalone:
cmd = compiler.link_executable
else:
cmd = compiler.link_shared_object
cmd(objects, str(self.outputfilename),
libraries=self.eci.libraries,
extra_preargs=self.link_extra,
library_dirs=self.eci.library_dirs)
def _include_dirs_for_libffi(self):
return ['/usr/include/libffi']
def _library_dirs_for_libffi(self):
return ['/usr/lib/libffi']
|