Kaydet (Commit) 802d6b7b authored tarafından Greg Ward's avatar Greg Ward

Added 'extra_preargs' and 'extra_postargs' parameters to most methods,

  which allowed us to get rid of the 'build_info' used in some places
  (a temporary kludge to support MSVC++ "def" files).
Deleted big comment whining about that kludge.
Added 'compiler_type' class attribute.
Overhauled 'new_compiler()': now takes 'compiler' argument along with
  'plat' (both optional with sensible defaults), and looks them both up
  in the new 'default_compiler' and 'compiler_class' dictionaries to
  figure out where to get the concrete compiler class from.
Reordered arguments to 'gen_lib_options()' to match the order in
  which the arguments are generated (ie. -L before -l).
üst cd1486ff
...@@ -7,7 +7,7 @@ for the Distutils compiler abstraction model.""" ...@@ -7,7 +7,7 @@ for the Distutils compiler abstraction model."""
__rcsid__ = "$Id$" __rcsid__ = "$Id$"
import os import sys, os
from types import * from types import *
from copy import copy from copy import copy
from distutils.errors import * from distutils.errors import *
...@@ -30,6 +30,15 @@ class CCompiler: ...@@ -30,6 +30,15 @@ class CCompiler:
most (all?) of those attributes may be varied on a per-compilation most (all?) of those attributes may be varied on a per-compilation
or per-link basis.""" or per-link basis."""
# 'compiler_type' is a class attribute that identifies this class. It
# keeps code that wants to know what kind of compiler it's dealing with
# from having to import all possible compiler classes just to do an
# 'isinstance'. In concrete CCompiler subclasses, 'compiler_type'
# should really, really be one of the keys of the 'compiler_class'
# dictionary (see below -- used by the 'new_compiler()' factory
# function) -- authors of new compiler interface classes are
# responsible for updating 'compiler_class'!
compiler_type = None
# XXX things not handled by this compiler abstraction model: # XXX things not handled by this compiler abstraction model:
# * client can't provide additional options for a compiler, # * client can't provide additional options for a compiler,
...@@ -251,7 +260,9 @@ class CCompiler: ...@@ -251,7 +260,9 @@ class CCompiler:
sources, sources,
output_dir=None, output_dir=None,
macros=None, macros=None,
includes=None): includes=None,
extra_preargs=None,
extra_postargs=None):
"""Compile one or more C/C++ source files. 'sources' must be """Compile one or more C/C++ source files. 'sources' must be
a list of strings, each one the name of a C/C++ source a list of strings, each one the name of a C/C++ source
file. Return a list of the object filenames generated file. Return a list of the object filenames generated
...@@ -266,7 +277,16 @@ class CCompiler: ...@@ -266,7 +277,16 @@ class CCompiler:
'includes', if given, must be a list of strings, the directories 'includes', if given, must be a list of strings, the directories
to add to the default include file search path for this to add to the default include file search path for this
compilation only.""" compilation only.
'extra_preargs' and 'extra_postargs' are optional lists of extra
command-line arguments that will be, respectively, prepended or
appended to the generated command line immediately before
execution. These will most likely be peculiar to the particular
platform and compiler being worked with, but are a necessary
escape hatch for those occasions when the abstract compiler
framework doesn't cut the mustard."""
pass pass
...@@ -278,7 +298,9 @@ class CCompiler: ...@@ -278,7 +298,9 @@ class CCompiler:
output_libname, output_libname,
output_dir=None, output_dir=None,
libraries=None, libraries=None,
library_dirs=None): library_dirs=None,
extra_preargs=None,
extra_postargs=None):
"""Link a bunch of stuff together to create a static library """Link a bunch of stuff together to create a static library
file. The "bunch of stuff" consists of the list of object file. The "bunch of stuff" consists of the list of object
files supplied as 'objects', the extra object files supplied files supplied as 'objects', the extra object files supplied
...@@ -292,42 +314,23 @@ class CCompiler: ...@@ -292,42 +314,23 @@ class CCompiler:
'library_dirs', if supplied, should be a list of additional 'library_dirs', if supplied, should be a list of additional
directories to search on top of the system default and those directories to search on top of the system default and those
supplied to 'add_library_dir()' and/or 'set_library_dirs()'.""" supplied to 'add_library_dir()' and/or 'set_library_dirs()'.
'extra_preargs' and 'extra_postargs' are as for 'compile()'
(except of course that they supply command-line arguments
for the particular linker being used)."""
pass pass
# XXX passing in 'build_info' here is a kludge to deal with the
# oddities of one particular compiler (Visual C++). For some reason,
# it needs to be told about ".def" files, and currently the
# 'build_info' hash allows this through a 'def_file' element. The link
# methods for VC++ look for 'def_file' and transform it into the
# appropriate command-line options. The current code is objectionable
# for a number of reasons: 1) if the link methods take 'build_info',
# why bother passing in libraries, library_dirs, etc.? 2) if the link
# methods do it, why not the compile methods? 3) build_info is part of
# the interface between setup.py and the 'build_ext' command -- it
# should stop there and not be propagated down into the compiler
# classes! and 4) I don't like elevating a platform- and
# compiler-specific oddity to "first-class" status in 'build_info' (oh
# well, at least it's not being reified in the compiler classes -- that
# would be really gross).
#
# Possible solutions:
# - just pass build_info to all the compile/link methods,
# never mind all those other parameters and screw the
# integrity of the interfaces
# - add a mechanism for passing platform-specific and/or
# compiler-specific compiler/linker options from setup.py
# straight through to the appropriate compiler class
def link_shared_lib (self, def link_shared_lib (self,
objects, objects,
output_libname, output_libname,
output_dir=None, output_dir=None,
libraries=None, libraries=None,
library_dirs=None, library_dirs=None,
build_info=None): extra_preargs=None,
extra_postargs=None):
"""Link a bunch of stuff together to create a shared library """Link a bunch of stuff together to create a shared library
file. Has the same effect as 'link_static_lib()' except file. Has the same effect as 'link_static_lib()' except
that the filename inferred from 'output_libname' will most that the filename inferred from 'output_libname' will most
...@@ -335,18 +338,20 @@ class CCompiler: ...@@ -335,18 +338,20 @@ class CCompiler:
almost certainly be different.""" almost certainly be different."""
pass pass
def link_shared_object (self, def link_shared_object (self,
objects, objects,
output_filename, output_filename,
output_dir=None, output_dir=None,
libraries=None, libraries=None,
library_dirs=None, library_dirs=None,
build_info=None): extra_preargs=None,
extra_postargs=None):
"""Link a bunch of stuff together to create a shared object """Link a bunch of stuff together to create a shared object
file. Much like 'link_shared_lib()', except the output filename file. Much like 'link_shared_lib()', except the output filename
is explicitly supplied as 'output_filename'. If 'output_dir' is is explicitly supplied as 'output_filename'. If 'output_dir' is
supplied, 'output_filename' is relative to it supplied, 'output_filename' is relative to it
(i.e. 'output_filename' can provide directoriy components if (i.e. 'output_filename' can provide directory components if
needed).""" needed)."""
pass pass
...@@ -407,23 +412,65 @@ class CCompiler: ...@@ -407,23 +412,65 @@ class CCompiler:
# class CCompiler # class CCompiler
# Map a platform ('posix', 'nt') to the default compiler type for
# that platform.
default_compiler = { 'posix': 'unix',
'nt': 'msvc',
}
# Map compiler types to (module_name, class_name) pairs -- ie. where to
# find the code that implements an interface to this compiler. (The module
# is assumed to be in the 'distutils' package.)
compiler_class = { 'unix': ('unixccompiler', 'UnixCCompiler'),
'msvc': ('msvccompiler', 'MSVCCompiler'),
}
def new_compiler (plat=None, def new_compiler (plat=None,
compiler=None,
verbose=0, verbose=0,
dry_run=0): dry_run=0):
"""Generate a CCompiler instance for platform 'plat' (or the
current platform, if 'plat' not supplied). Really instantiates """Generate an instance of some CCompiler subclass for the supplied
some concrete subclass of CCompiler, of course.""" platform/compiler combination. 'plat' defaults to 'os.name'
(eg. 'posix', 'nt'), and 'compiler' defaults to the default
if plat is None: plat = os.name compiler for that platform. Currently only 'posix' and 'nt'
if plat == 'posix': are supported, and the default compilers are "traditional Unix
from unixccompiler import UnixCCompiler interface" (UnixCCompiler class) and Visual C++ (MSVCCompiler
return UnixCCompiler (verbose, dry_run) class). Note that it's perfectly possible to ask for a Unix
elif plat == 'nt': compiler object under Windows, and a Microsoft compiler object
from msvccompiler import MSVCCompiler under Unix -- if you supply a value for 'compiler', 'plat'
return MSVCCompiler (verbose, dry_run) is ignored."""
else:
raise DistutilsPlatformError, \ if plat is None:
"don't know how to compile C/C++ code on platform %s" % plat plat = os.name
try:
if compiler is None:
compiler = default_compiler[plat]
(module_name, class_name) = compiler_class[compiler]
except KeyError:
msg = "don't know how to compile C/C++ code on platform '%s'" % plat
if compiler is not None:
msg = msg + " with '%s' compiler" % compiler
raise DistutilsPlatformError, msg
try:
module_name = "distutils." + module_name
__import__ (module_name)
module = sys.modules[module_name]
klass = vars(module)[class_name]
except ImportError:
raise DistutilsModuleError, \
"can't compile C/C++ code: unable to load module '%s'" % \
module_name
except KeyError:
raise DistutilsModuleError, \
("can't compile C/C++ code: unable to find class '%s' " +
"in module '%s'") % (class_name, module_name)
return klass (verbose, dry_run)
def gen_preprocess_options (macros, includes): def gen_preprocess_options (macros, includes):
...@@ -477,7 +524,7 @@ def gen_preprocess_options (macros, includes): ...@@ -477,7 +524,7 @@ def gen_preprocess_options (macros, includes):
# gen_preprocess_options () # gen_preprocess_options ()
def gen_lib_options (libraries, library_dirs, lib_format, dir_format): def gen_lib_options (library_dirs, libraries, dir_format, lib_format):
"""Generate linker options for searching library directories and """Generate linker options for searching library directories and
linking with specific libraries. 'libraries' and 'library_dirs' linking with specific libraries. 'libraries' and 'library_dirs'
are, respectively, lists of library names (not filenames!) and are, respectively, lists of library names (not filenames!) and
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment