| 1 |
# DSR:2005.10.27.23.51 |
|---|
| 2 |
|
|---|
| 3 |
# XXX: |
|---|
| 4 |
# These two will have to wait until DMD can create shared libraries on Linux, |
|---|
| 5 |
# because DSR doesn't have (the non-free version of) MSVC 2003, which is |
|---|
| 6 |
# necessary to create a debug build or a UCS4 build of Python 2.4 on Windows: |
|---|
| 7 |
# - Handle distutils debug builds responsibly (make sure both -debug and -g are |
|---|
| 8 |
# passed through to DMD, even if optimizations are requested). Also make |
|---|
| 9 |
# sure that extensions built with this module work under debug builds of |
|---|
| 10 |
# Python. |
|---|
| 11 |
# - Try out a UCS4 build of Python to make sure that works. |
|---|
| 12 |
|
|---|
| 13 |
import os, os.path, sys |
|---|
| 14 |
|
|---|
| 15 |
from distutils import ccompiler as cc |
|---|
| 16 |
from distutils.ccompiler import gen_lib_options |
|---|
| 17 |
from distutils.errors import ( |
|---|
| 18 |
DistutilsExecError, DistutilsFileError, DistutilsPlatformError, |
|---|
| 19 |
CompileError, LibError, LinkError, UnknownFileError |
|---|
| 20 |
) |
|---|
| 21 |
|
|---|
| 22 |
_isPlatWin = sys.platform.lower().startswith('win') |
|---|
| 23 |
|
|---|
| 24 |
_infraDir = os.path.join(os.path.dirname(__file__), 'infrastructure') |
|---|
| 25 |
|
|---|
| 26 |
from pyd_support import make_pydmain, make_pyddef |
|---|
| 27 |
|
|---|
| 28 |
_pydFiles = [ |
|---|
| 29 |
'class_wrap.d', |
|---|
| 30 |
'ctor_wrap.d', |
|---|
| 31 |
'def.d', |
|---|
| 32 |
'dg_convert.d', |
|---|
| 33 |
'exception.d', |
|---|
| 34 |
'func_wrap.d', |
|---|
| 35 |
'iteration.d', |
|---|
| 36 |
'lib_abstract.d', |
|---|
| 37 |
'make_object.d', |
|---|
| 38 |
'make_wrapper.d', |
|---|
| 39 |
'op_wrap.d', |
|---|
| 40 |
'pyd.d', |
|---|
| 41 |
'pydobject.d', |
|---|
| 42 |
'struct_wrap.d', |
|---|
| 43 |
] |
|---|
| 44 |
|
|---|
| 45 |
_stFiles = [ |
|---|
| 46 |
'coroutine.d', |
|---|
| 47 |
'stackcontext.d', |
|---|
| 48 |
'stackthread.d', |
|---|
| 49 |
'tls.d', |
|---|
| 50 |
] |
|---|
| 51 |
|
|---|
| 52 |
_metaFiles = [ |
|---|
| 53 |
'Default.d', |
|---|
| 54 |
'Demangle.d', |
|---|
| 55 |
'Nameof.d', |
|---|
| 56 |
'Util.d', |
|---|
| 57 |
] |
|---|
| 58 |
|
|---|
| 59 |
_pyVerXDotY = '.'.join(str(v) for v in sys.version_info[:2]) # e.g., '2.4' |
|---|
| 60 |
_pyVerXY = _pyVerXDotY.replace('.', '') # e.g., '24' |
|---|
| 61 |
|
|---|
| 62 |
|
|---|
| 63 |
class DCompiler(cc.CCompiler): |
|---|
| 64 |
|
|---|
| 65 |
src_extensions = ['.d'] |
|---|
| 66 |
obj_extension = (_isPlatWin and '.obj') or '.o' |
|---|
| 67 |
static_lib_extension = (_isPlatWin and '.lib') or '.a' |
|---|
| 68 |
shared_lib_extension = (_isPlatWin and '.pyd') or '.so' |
|---|
| 69 |
static_lib_format = (_isPlatWin and '%s%s') or 'lib%s%s' |
|---|
| 70 |
shared_lib_format = '%s%s' |
|---|
| 71 |
exe_extension = (_isPlatWin and '.exe') or '' |
|---|
| 72 |
|
|---|
| 73 |
def __init__(self, *args, **kwargs): |
|---|
| 74 |
cc.CCompiler.__init__(self, *args, **kwargs) |
|---|
| 75 |
# Get DMD/GDC specific info |
|---|
| 76 |
self._initialize() |
|---|
| 77 |
# _binpath |
|---|
| 78 |
try: |
|---|
| 79 |
dBin = os.environ[self._env_var] |
|---|
| 80 |
if not os.path.isfile(dBin): |
|---|
| 81 |
self.warn("Environment variable %s provided, but file '%s' does not exist." % (self._env_var, dBin)) |
|---|
| 82 |
raise KeyError |
|---|
| 83 |
except KeyError: |
|---|
| 84 |
if _isPlatWin: |
|---|
| 85 |
# The environment variable wasn't supplied, so search the PATH. |
|---|
| 86 |
# Windows requires the full path for reasons that escape me at |
|---|
| 87 |
# the moment. |
|---|
| 88 |
dBin = _findInPath(self.compiler_type + self.exe_extension) |
|---|
| 89 |
if dBin is None: |
|---|
| 90 |
raise DistutilsFileError('You must either set the %s' |
|---|
| 91 |
' environment variable to the full path of the %s' |
|---|
| 92 |
' executable, or place the executable on the PATH.' % |
|---|
| 93 |
(self._env_var, self.compiler_type) |
|---|
| 94 |
) |
|---|
| 95 |
else: |
|---|
| 96 |
# Just run it via the PATH directly in Linux |
|---|
| 97 |
dBin = self.compiler_type |
|---|
| 98 |
self._binpath = dBin |
|---|
| 99 |
# _unicodeOpt |
|---|
| 100 |
self._unicodeOpt = self._versionOpt % ('Python_Unicode_UCS' + ((sys.maxunicode == 0xFFFF and '2') or '4')) |
|---|
| 101 |
|
|---|
| 102 |
def _initialize(self): |
|---|
| 103 |
# It is intended that this method be implemented by subclasses. |
|---|
| 104 |
raise NotImplementedError, "Cannot initialize DCompiler, use DMDDCompiler or GDCDCompiler instead." |
|---|
| 105 |
|
|---|
| 106 |
def _def_file(self, output_dir, output_filename): |
|---|
| 107 |
"""A list of options used to tell the linker how to make a dll/so. In |
|---|
| 108 |
DMD, it is the .def file. In GDC, it is |
|---|
| 109 |
['-shared', '-Wl,-soname,blah.so'] or similar.""" |
|---|
| 110 |
raise NotImplementedError, "Cannot initialize DCompiler, use DMDDCompiler or GDCDCompiler instead." |
|---|
| 111 |
|
|---|
| 112 |
def _lib_file(self, libraries): |
|---|
| 113 |
return '' |
|---|
| 114 |
|
|---|
| 115 |
def find_library_file(self, dirs, lib, debug=0): |
|---|
| 116 |
shared_f = self.library_filename(lib, lib_type='shared') |
|---|
| 117 |
static_f = self.library_filename(lib, lib_type='static') |
|---|
| 118 |
|
|---|
| 119 |
for dir in dirs: |
|---|
| 120 |
shared = os.path.join(dir, shared_f) |
|---|
| 121 |
static = os.path.join(dir, static_f) |
|---|
| 122 |
|
|---|
| 123 |
if os.path.exists(shared): |
|---|
| 124 |
return shared |
|---|
| 125 |
elif os.path.exists(static): |
|---|
| 126 |
return static |
|---|
| 127 |
|
|---|
| 128 |
return None |
|---|
| 129 |
|
|---|
| 130 |
def compile(self, sources, |
|---|
| 131 |
output_dir=None, macros=None, include_dirs=None, debug=0, |
|---|
| 132 |
extra_preargs=None, extra_postargs=None, depends=None |
|---|
| 133 |
): |
|---|
| 134 |
macros = macros or [] |
|---|
| 135 |
include_dirs = include_dirs or [] |
|---|
| 136 |
extra_preargs = extra_preargs or [] |
|---|
| 137 |
extra_postargs = extra_postargs or [] |
|---|
| 138 |
|
|---|
| 139 |
if not os.path.exists(output_dir): |
|---|
| 140 |
os.makedirs(output_dir) |
|---|
| 141 |
|
|---|
| 142 |
binpath = _qp(self._binpath) |
|---|
| 143 |
compileOpts = self._compileOpts |
|---|
| 144 |
outputOpts = self._outputOpts |
|---|
| 145 |
|
|---|
| 146 |
includePathOpts = [] |
|---|
| 147 |
|
|---|
| 148 |
# All object files will be placed in one of three directories: |
|---|
| 149 |
# infra - All of the infrastructure's object files. |
|---|
| 150 |
# project - The project's own object files. |
|---|
| 151 |
# outside - Any source files specified by the project which are not |
|---|
| 152 |
# contained in the project's own directory. |
|---|
| 153 |
orig_sources = sources |
|---|
| 154 |
sources = [] |
|---|
| 155 |
for source in orig_sources: |
|---|
| 156 |
if os.path.abspath(source).startswith(os.getcwd()): |
|---|
| 157 |
sources.append((source, 'project')) |
|---|
| 158 |
else: |
|---|
| 159 |
sources.append((source, 'outside')) |
|---|
| 160 |
|
|---|
| 161 |
# To sources, add the appropriate D header file python.d, as well as |
|---|
| 162 |
# any platform-specific boilerplate. |
|---|
| 163 |
pythonHeaderPath = os.path.join(_infraDir, 'python', 'python.d') |
|---|
| 164 |
# Add the python header's directory to the include path |
|---|
| 165 |
includePathOpts += self._includeOpts |
|---|
| 166 |
includePathOpts[-1] = includePathOpts[-1] % os.path.join(_infraDir, 'python') |
|---|
| 167 |
if not os.path.isfile(pythonHeaderPath): |
|---|
| 168 |
raise DistutilsPlatformError('Required D translation of Python' |
|---|
| 169 |
' header files "%s" is missing.' % pythonHeaderPath |
|---|
| 170 |
) |
|---|
| 171 |
sources.append((pythonHeaderPath, 'infra')) |
|---|
| 172 |
|
|---|
| 173 |
# flags = (with_pyd, with_st, with_meta, with_main) |
|---|
| 174 |
with_pyd, with_st, with_meta, with_main = [f for f, category in macros if category == 'aux'][0] |
|---|
| 175 |
# And Pyd! |
|---|
| 176 |
if with_pyd: |
|---|
| 177 |
# If we're not using StackThreads, don't use iteration.d in Pyd |
|---|
| 178 |
if not with_st or not self._st_support: |
|---|
| 179 |
_pydFiles.remove('iteration.d'); |
|---|
| 180 |
for file in _pydFiles: |
|---|
| 181 |
filePath = os.path.join(_infraDir, 'pyd', file) |
|---|
| 182 |
if not os.path.isfile(filePath): |
|---|
| 183 |
raise DistutilsPlatformError("Required Pyd source file '%s' is" |
|---|
| 184 |
" missing." % filePath |
|---|
| 185 |
) |
|---|
| 186 |
sources.append((filePath, 'infra')) |
|---|
| 187 |
# If using PydMain, parse the template file |
|---|
| 188 |
if with_main: |
|---|
| 189 |
name = [n for n, category in macros if category == 'name'][0] |
|---|
| 190 |
# Store the finished pydmain.d file alongside the object files |
|---|
| 191 |
infra_output_dir = os.path.join(output_dir, 'infra') |
|---|
| 192 |
if not os.path.exists(infra_output_dir): |
|---|
| 193 |
os.makedirs(infra_output_dir) |
|---|
| 194 |
mainFilename = os.path.join(infra_output_dir, 'pydmain.d') |
|---|
| 195 |
make_pydmain(mainFilename, name) |
|---|
| 196 |
sources.append((mainFilename, 'infra')) |
|---|
| 197 |
# And StackThreads |
|---|
| 198 |
if self._st_support and with_st: |
|---|
| 199 |
for file in _stFiles: |
|---|
| 200 |
filePath = os.path.join(_infraDir, 'st', file) |
|---|
| 201 |
if not os.path.isfile(filePath): |
|---|
| 202 |
raise DistutilsPlatformError("Required StackThreads source" |
|---|
| 203 |
" file '%s' is missing." % filePath |
|---|
| 204 |
) |
|---|
| 205 |
sources.append((filePath, 'infra')) |
|---|
| 206 |
# Add the version conditional for st |
|---|
| 207 |
macros.append(('Pyd_with_StackThreads', 'version')) |
|---|
| 208 |
# And meta |
|---|
| 209 |
if with_meta: |
|---|
| 210 |
for file in _metaFiles: |
|---|
| 211 |
filePath = os.path.join(_infraDir, 'meta', file) |
|---|
| 212 |
if not os.path.isfile(filePath): |
|---|
| 213 |
raise DistutilsPlatformError("Required meta source file" |
|---|
| 214 |
" '%s' is missing." % filePath |
|---|
| 215 |
) |
|---|
| 216 |
sources.append((filePath, 'infra')) |
|---|
| 217 |
# Add the infraDir to the include path for pyd, st, and meta. |
|---|
| 218 |
if True in (with_pyd, with_st, with_meta): |
|---|
| 219 |
includePathOpts += self._includeOpts |
|---|
| 220 |
includePathOpts[-1] = includePathOpts[-1] % os.path.join(_infraDir) |
|---|
| 221 |
|
|---|
| 222 |
# Add DLL/SO boilerplate code file. |
|---|
| 223 |
if _isPlatWin: |
|---|
| 224 |
boilerplatePath = os.path.join(_infraDir, 'd', |
|---|
| 225 |
'python_dll_windows_boilerplate.d' |
|---|
| 226 |
) |
|---|
| 227 |
else: |
|---|
| 228 |
boilerplatePath = os.path.join(_infraDir, 'd', |
|---|
| 229 |
'python_so_linux_boilerplate.d' |
|---|
| 230 |
) |
|---|
| 231 |
if not os.path.isfile(boilerplatePath): |
|---|
| 232 |
raise DistutilsFileError('Required supporting code file "%s"' |
|---|
| 233 |
' is missing.' % boilerplatePath |
|---|
| 234 |
) |
|---|
| 235 |
sources.append((boilerplatePath, 'infra')) |
|---|
| 236 |
|
|---|
| 237 |
# Extension subclass DExtension will have packed any user-supplied |
|---|
| 238 |
# version and debug flags into macros; we extract them and convert them |
|---|
| 239 |
# into the appropriate command-line args. |
|---|
| 240 |
versionFlags = [name for (name, category) in macros if category == 'version'] |
|---|
| 241 |
debugFlags = [name for (name, category) in macros if category == 'debug'] |
|---|
| 242 |
userVersionAndDebugOpts = ( |
|---|
| 243 |
[self._versionOpt % v for v in versionFlags] + |
|---|
| 244 |
[self._debugOpt % v for v in debugFlags] |
|---|
| 245 |
) |
|---|
| 246 |
|
|---|
| 247 |
# Python version option allows extension writer to take advantage of |
|---|
| 248 |
# Python/C API features available only in recent version of Python with |
|---|
| 249 |
# a version statement like: |
|---|
| 250 |
# version(Python_2_4_Or_Later) { |
|---|
| 251 |
# Py_ConvenientCallOnlyAvailableInPython24AndLater(); |
|---|
| 252 |
# } else { |
|---|
| 253 |
# // Do it the hard way... |
|---|
| 254 |
# } |
|---|
| 255 |
pythonVersionOpt = self._versionOpt % ('Python_%d_%d_Or_Later' % sys.version_info[:2]) |
|---|
| 256 |
|
|---|
| 257 |
# Optimization opts |
|---|
| 258 |
args = [a.lower() for a in sys.argv[1:]] |
|---|
| 259 |
optimize = ('-o' in args or '--optimize' in args) |
|---|
| 260 |
if debug: |
|---|
| 261 |
optimizationOpts = self._debugOptimizeOpts |
|---|
| 262 |
elif optimize: |
|---|
| 263 |
optimizationOpts = self._releaseOptimizeOpts |
|---|
| 264 |
else: |
|---|
| 265 |
optimizationOpts = self._defaultOptimizeOpts |
|---|
| 266 |
|
|---|
| 267 |
print 'sources: ', [os.path.basename(s) for s, t in sources] |
|---|
| 268 |
|
|---|
| 269 |
objFiles = [] |
|---|
| 270 |
for source, source_type in sources: |
|---|
| 271 |
outOpts = outputOpts[:] |
|---|
| 272 |
objFilename = os.path.splitext(source)[0] + self.obj_extension |
|---|
| 273 |
if source_type == 'project': |
|---|
| 274 |
objName = os.path.join(output_dir, 'project', objFilename) |
|---|
| 275 |
elif source_type == 'outside': |
|---|
| 276 |
objName = os.path.join(output_dir, 'outside', os.path.basename(objFilename)) |
|---|
| 277 |
else: # infra |
|---|
| 278 |
objName = os.path.join(output_dir, 'infra', os.path.basename(objFilename)) |
|---|
| 279 |
if not os.path.exists(os.path.dirname(objName)): |
|---|
| 280 |
os.makedirs(os.path.dirname(objName)) |
|---|
| 281 |
objFiles.append(objName) |
|---|
| 282 |
outOpts[-1] = outOpts[-1] % _qp(objName) |
|---|
| 283 |
cmdElements = ( |
|---|
| 284 |
[binpath] + extra_preargs + compileOpts + |
|---|
| 285 |
[pythonVersionOpt, self._unicodeOpt] + optimizationOpts + |
|---|
| 286 |
includePathOpts + outOpts + userVersionAndDebugOpts + |
|---|
| 287 |
[_qp(source)] + extra_postargs |
|---|
| 288 |
) |
|---|
| 289 |
cmdElements = [el for el in cmdElements if el] |
|---|
| 290 |
try: |
|---|
| 291 |
self.spawn(cmdElements) |
|---|
| 292 |
except DistutilsExecError, msg: |
|---|
| 293 |
raise CompileError(msg) |
|---|
| 294 |
return objFiles |
|---|
| 295 |
|
|---|
| 296 |
def link (self, |
|---|
| 297 |
target_desc, objects, output_filename, |
|---|
| 298 |
output_dir=None, |
|---|
| 299 |
libraries=None, library_dirs=None, runtime_library_dirs=None, |
|---|
| 300 |
export_symbols=None, debug=0, |
|---|
| 301 |
extra_preargs=None, extra_postargs=None, |
|---|
| 302 |
build_temp=None, target_lang=None |
|---|
| 303 |
): |
|---|
| 304 |
# Distutils defaults to None for "unspecified option list"; we want |
|---|
| 305 |
# empty lists in that case (this substitution is done here in the body |
|---|
| 306 |
# rather than by changing the default parameters in case distutils |
|---|
| 307 |
# passes None explicitly). |
|---|
| 308 |
libraries = libraries or [] |
|---|
| 309 |
library_dirs = library_dirs or [] |
|---|
| 310 |
runtime_library_dirs = runtime_library_dirs or [] |
|---|
| 311 |
export_symbols = export_symbols or [] |
|---|
| 312 |
extra_preargs = extra_preargs or [] |
|---|
| 313 |
extra_postargs = extra_postargs or [] |
|---|
| 314 |
|
|---|
| 315 |
binpath = self._binpath |
|---|
| 316 |
outputOpts = self._outputOpts[:] |
|---|
| 317 |
objectOpts = [_qp(fn) for fn in objects] |
|---|
| 318 |
|
|---|
| 319 |
(objects, output_dir) = self._fix_object_args (objects, output_dir) |
|---|
| 320 |
(libraries, library_dirs, runtime_library_dirs) = \ |
|---|
| 321 |
self._fix_lib_args (libraries, library_dirs, runtime_library_dirs) |
|---|
| 322 |
if runtime_library_dirs: |
|---|
| 323 |
self.warn('This CCompiler implementation does nothing with' |
|---|
| 324 |
' "runtime_library_dirs": ' + str(runtime_library_dirs) |
|---|
| 325 |
) |
|---|
| 326 |
|
|---|
| 327 |
if output_dir and os.path.basename(output_filename) == output_filename: |
|---|
| 328 |
output_filename = os.path.join(output_dir, output_filename) |
|---|
| 329 |
else: |
|---|
| 330 |
if not output_filename: |
|---|
| 331 |
raise DistutilsFileError, 'Neither output_dir nor' \ |
|---|
| 332 |
' output_filename was specified.' |
|---|
| 333 |
output_dir = os.path.dirname(output_filename) |
|---|
| 334 |
if not output_dir: |
|---|
| 335 |
raise DistutilsFileError, 'Unable to guess output_dir on the'\ |
|---|
| 336 |
' bases of output_filename "%s" alone.' % output_filename |
|---|
| 337 |
|
|---|
| 338 |
# Format the output filename option |
|---|
| 339 |
# (-offilename in DMD, -o filename in GDC) |
|---|
| 340 |
outputOpts[-1] = outputOpts[-1] % _qp(output_filename) |
|---|
| 341 |
|
|---|
| 342 |
if not os.path.exists(output_dir): |
|---|
| 343 |
os.makedirs(output_dir) |
|---|
| 344 |
|
|---|
| 345 |
if not self._need_link(objects, output_filename): |
|---|
| 346 |
print "All binary output files are up to date." |
|---|
| 347 |
return |
|---|
| 348 |
|
|---|
| 349 |
# The .def file (on Windows) or -shared and -soname (on Linux) |
|---|
| 350 |
sharedOpts = self._def_file(build_temp, output_filename) |
|---|
| 351 |
|
|---|
| 352 |
# The python .lib file, if needed |
|---|
| 353 |
pythonLibOpt = self._lib_file(libraries) |
|---|
| 354 |
if pythonLibOpt: |
|---|
| 355 |
pythonLibOpt = _qp(pythonLibOpt) |
|---|
| 356 |
|
|---|
| 357 |
if target_desc != cc.CCompiler.SHARED_OBJECT: |
|---|
| 358 |
raise LinkError('This CCompiler implementation does not know' |
|---|
| 359 |
' how to link anything except an extension module (that is, a' |
|---|
| 360 |
' shared object file).' |
|---|
| 361 |
) |
|---|
| 362 |
|
|---|
| 363 |
# Library linkage options |
|---|
| 364 |
print "library_dirs:", library_dirs |
|---|
| 365 |
print "runtime_library_dirs:", runtime_library_dirs |
|---|
| 366 |
print "libraries:", libraries |
|---|
| 367 |
libOpts = gen_lib_options(self, library_dirs, runtime_library_dirs, libraries) |
|---|
| 368 |
|
|---|
| 369 |
# Optimization opts |
|---|
| 370 |
args = [a.lower() for a in sys.argv[1:]] |
|---|
| 371 |
optimize = ('-o' in args or '--optimize' in args) |
|---|
| 372 |
if debug: |
|---|
| 373 |
optimizationOpts = self._debugOptimizeOpts |
|---|
| 374 |
elif optimize: |
|---|
| 375 |
optimizationOpts = self._releaseOptimizeOpts |
|---|
| 376 |
else: |
|---|
| 377 |
optimizationOpts = self._defaultOptimizeOpts |
|---|
| 378 |
|
|---|
| 379 |
cmdElements = ( |
|---|
| 380 |
[binpath] + extra_preargs + self._linkOpts + optimizationOpts + |
|---|
| 381 |
outputOpts + [pythonLibOpt] + objectOpts + libOpts + sharedOpts + |
|---|
| 382 |
extra_postargs |
|---|
| 383 |
) |
|---|
| 384 |
cmdElements = [el for el in cmdElements if el] |
|---|
| 385 |
|
|---|
| 386 |
try: |
|---|
| 387 |
self.spawn(cmdElements) |
|---|
| 388 |
except DistutilsExecError, msg: |
|---|
| 389 |
raise CompileError(msg) |
|---|
| 390 |
|
|---|
| 391 |
class DMDDCompiler(DCompiler): |
|---|
| 392 |
compiler_type = 'dmd' |
|---|
| 393 |
|
|---|
| 394 |
executables = { |
|---|
| 395 |
'preprocessor' : None, |
|---|
| 396 |
'compiler' : ['dmd'], |
|---|
| 397 |
'compiler_so' : ['dmd'], |
|---|
| 398 |
'linker_so' : ['dmd'], |
|---|
| 399 |
'linker_exe' : ['dmd'], |
|---|
| 400 |
} |
|---|
| 401 |
|
|---|
| 402 |
_env_var = 'DMD_BIN' |
|---|
| 403 |
|
|---|
| 404 |
def _initialize(self): |
|---|
| 405 |
# _compileOpts |
|---|
| 406 |
self._compileOpts = ['-c'] |
|---|
| 407 |
# _outputOpts |
|---|
| 408 |
self._outputOpts = ['-of%s'] |
|---|
| 409 |
# _linkOpts |
|---|
| 410 |
self._linkOpts = [] |
|---|
| 411 |
# _includeOpts |
|---|
| 412 |
self._includeOpts = ['-I%s'] |
|---|
| 413 |
# _versionOpt |
|---|
| 414 |
self._versionOpt = '-version=%s' |
|---|
| 415 |
# _debugOpt |
|---|
| 416 |
self._debugOpt = '-debug=%s' |
|---|
| 417 |
# _defaultOptimizeOpts |
|---|
| 418 |
self._defaultOptimizeOpts = ['-debug'] |
|---|
| 419 |
# _debugOptimizeOpts |
|---|
| 420 |
self._debugOptimizeOpts = self._defaultOptimizeOpts + ['-unittest', '-g'] |
|---|
| 421 |
# _releaseOptimizeOpts |
|---|
| 422 |
self._releaseOptimizeOpts = ['-version=Optimized', '-release', '-O', '-inline'] |
|---|
| 423 |
# StackThreads support |
|---|
| 424 |
self._st_support = True |
|---|
| 425 |
|
|---|
| 426 |
#def link_opts(self, |
|---|
| 427 |
|
|---|
| 428 |
def _def_file(self, output_dir, output_filename): |
|---|
| 429 |
if _isPlatWin: |
|---|
| 430 |
# Automatically create a .def file: |
|---|
| 431 |
defFilePath = os.path.join(output_dir, 'infra', 'python_dll_def.def') |
|---|
| 432 |
make_pyddef( |
|---|
| 433 |
defFilePath, |
|---|
| 434 |
os.path.basename(output_filename) |
|---|
| 435 |
) |
|---|
| 436 |
return [defFilePath] |
|---|
| 437 |
else: |
|---|
| 438 |
return [] |
|---|
| 439 |
|
|---|
| 440 |
def _lib_file(self, libraries): |
|---|
| 441 |
if _isPlatWin: |
|---|
| 442 |
# The DMD-compatible .lib file can be generated with implib.exe |
|---|
| 443 |
# (from the Digital Mars "Basic Utilities" package) using a command |
|---|
| 444 |
# series similar to the following: |
|---|
| 445 |
# cd C:\Windows\system32 |
|---|
| 446 |
# \path\to\dm\bin\implib.exe /system python24_digitalmars.lib python24.dll |
|---|
| 447 |
# |
|---|
| 448 |
# I chose not to incorporate automatic .lib generation into this |
|---|
| 449 |
# code because Python X.Y releases are fairly infrequent, so it's |
|---|
| 450 |
# more convenient to distribute a pre-extracted .lib file to the |
|---|
| 451 |
# users and spare them the need for the "Basic Utilities" package. |
|---|
| 452 |
pythonDMDLibPath = _qp(os.path.join(_infraDir, 'python', |
|---|
| 453 |
'python%s_digitalmars.lib' % _pyVerXY |
|---|
| 454 |
)) |
|---|
| 455 |
if not os.path.isfile(pythonDMDLibPath): |
|---|
| 456 |
raise DistutilsFileError('The DMD-compatible Python .lib file' |
|---|
| 457 |
' which should be located at "%s" is missing. Try' |
|---|
| 458 |
' downloading a more recent version of celeriD that' |
|---|
| 459 |
' contains a .lib file appropriate for your Python version.' |
|---|
| 460 |
% pythonDMDLibPath |
|---|
| 461 |
) |
|---|
| 462 |
pythonLibOpt = _qp(pythonDMDLibPath) |
|---|
| 463 |
|
|---|
| 464 |
# distutils will normally request that the library 'pythonXY' be |
|---|
| 465 |
# linked against. Since D requires a different .lib file from the |
|---|
| 466 |
# one used by the C compiler that built Python, and we've just |
|---|
| 467 |
# dealt with that requirement, we take the liberty of removing the |
|---|
| 468 |
# distutils-requested pythonXY.lib. |
|---|
| 469 |
if 'python' + _pyVerXY in libraries: |
|---|
| 470 |
libraries.remove('python' + _pyVerXY) |
|---|
| 471 |
return pythonLibOpt |
|---|
| 472 |
else: |
|---|
| 473 |
return '' |
|---|
| 474 |
|
|---|
| 475 |
def library_dir_option(self, dir): |
|---|
| 476 |
self.warn("Don't know how to set library search path for DMD.") |
|---|
| 477 |
#raise DistutilsPlatformError, "Don't know how to set library search path for DMD." |
|---|
| 478 |
|
|---|
| 479 |
def runtime_library_dir_option(self, dir): |
|---|
| 480 |
self.warn("Don't know how to set runtime library search path for DMD.") |
|---|
| 481 |
#raise DistutilsPlayformError, "Don't know how to set runtime library search path for DMD." |
|---|
| 482 |
|
|---|
| 483 |
def library_option(self, lib): |
|---|
| 484 |
if _isPlatWin: |
|---|
| 485 |
return self.library_filename(lib) |
|---|
| 486 |
else: |
|---|
| 487 |
return '-L-l' + lib |
|---|
| 488 |
|
|---|
| 489 |
class GDCDCompiler(DCompiler): |
|---|
| 490 |
compiler_type = 'gdc' |
|---|
| 491 |
|
|---|
| 492 |
executables = { |
|---|
| 493 |
'preprocessor' : None, |
|---|
| 494 |
'compiler' : ['gdc'], |
|---|
| 495 |
'compiler_so' : ['gdc'], |
|---|
| 496 |
'linker_so' : ['gdc'], |
|---|
| 497 |
'linker_exe' : ['gdc'], |
|---|
| 498 |
} |
|---|
| 499 |
|
|---|
| 500 |
_env_var = 'GDC_BIN' |
|---|
| 501 |
|
|---|
| 502 |
def _initialize(self): |
|---|
| 503 |
# _compileOpts |
|---|
| 504 |
self._compileOpts = ['-fPIC', '-c'] |
|---|
| 505 |
# _outputOpts |
|---|
| 506 |
self._outputOpts = ['-o', '%s'] |
|---|
| 507 |
# _linkOpts |
|---|
| 508 |
self._linkOpts = ['-fPIC', '-nostartfiles', '-shared'] |
|---|
| 509 |
# _includeOpts |
|---|
| 510 |
self._includeOpts = ['-I', '%s'] |
|---|
| 511 |
# _versionOpt |
|---|
| 512 |
self._versionOpt = '-fversion=%s' |
|---|
| 513 |
# _debugOpt |
|---|
| 514 |
self._debugOpt = '-fdebug=%s' |
|---|
| 515 |
# _defaultOptimizeOpts |
|---|
| 516 |
self._defaultOptimizeOpts = ['-fdebug'] |
|---|
| 517 |
# _debugOptimizeOpts |
|---|
| 518 |
self._debugOptimizeOpts = self._defaultOptimizeOpts + ['-g', '-funittest'] |
|---|
| 519 |
# _releaseOptimizeOpts |
|---|
| 520 |
self._releaseOptimizeOpts = ['-fversion=Optimized', '-frelease', '-O3', '-finline-functions'] |
|---|
| 521 |
# StackThreads support |
|---|
| 522 |
self._st_support = False |
|---|
| 523 |
|
|---|
| 524 |
def _def_file(self, output_dir, output_filename): |
|---|
| 525 |
return ['-Wl,-soname,' + os.path.basename(output_filename)] |
|---|
| 526 |
|
|---|
| 527 |
def library_dir_option(self, dir): |
|---|
| 528 |
return '-L' + dir |
|---|
| 529 |
|
|---|
| 530 |
def runtime_library_dir_option(self, dir): |
|---|
| 531 |
return '-Wl,-R' + dir |
|---|
| 532 |
|
|---|
| 533 |
def library_option(self, lib): |
|---|
| 534 |
return '-l' + lib |
|---|
| 535 |
|
|---|
| 536 |
# Utility functions: |
|---|
| 537 |
def _findInPath(fileName, startIn=None): |
|---|
| 538 |
# Find a file named fileName in the PATH, starting in startIn. |
|---|
| 539 |
try: |
|---|
| 540 |
path = os.environ['PATH'] |
|---|
| 541 |
except KeyError: |
|---|
| 542 |
pass |
|---|
| 543 |
else: |
|---|
| 544 |
pathDirs = path.split(os.pathsep) |
|---|
| 545 |
if startIn: |
|---|
| 546 |
if startIn in pathDirs: |
|---|
| 547 |
&nb |
|---|