summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Ward <gward@python.net>1999-09-29 12:20:55 (GMT)
committerGreg Ward <gward@python.net>1999-09-29 12:20:55 (GMT)
commit802d6b7b4c83dde3eebf3afb7221edcba88d7937 (patch)
tree41a8f1c78812c2207ed120a5136b6c0610e704e2
parentcd1486fff14888437837298ada405b13ce965217 (diff)
downloadcpython-802d6b7b4c83dde3eebf3afb7221edcba88d7937.zip
cpython-802d6b7b4c83dde3eebf3afb7221edcba88d7937.tar.gz
cpython-802d6b7b4c83dde3eebf3afb7221edcba88d7937.tar.bz2
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).
-rw-r--r--Lib/distutils/ccompiler.py141
1 files changed, 94 insertions, 47 deletions
diff --git a/Lib/distutils/ccompiler.py b/Lib/distutils/ccompiler.py
index 2a80739..bfbb50f 100644
--- a/Lib/distutils/ccompiler.py
+++ b/Lib/distutils/ccompiler.py
@@ -7,7 +7,7 @@ for the Distutils compiler abstraction model."""
__rcsid__ = "$Id$"
-import os
+import sys, os
from types import *
from copy import copy
from distutils.errors import *
@@ -30,6 +30,15 @@ class CCompiler:
most (all?) of those attributes may be varied on a per-compilation
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:
# * client can't provide additional options for a compiler,
@@ -251,7 +260,9 @@ class CCompiler:
sources,
output_dir=None,
macros=None,
- includes=None):
+ includes=None,
+ extra_preargs=None,
+ extra_postargs=None):
"""Compile one or more C/C++ source files. 'sources' must be
a list of strings, each one the name of a C/C++ source
file. Return a list of the object filenames generated
@@ -266,7 +277,16 @@ class CCompiler:
'includes', if given, must be a list of strings, the directories
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
@@ -278,7 +298,9 @@ class CCompiler:
output_libname,
output_dir=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
file. The "bunch of stuff" consists of the list of object
files supplied as 'objects', the extra object files supplied
@@ -292,42 +314,23 @@ class CCompiler:
'library_dirs', if supplied, should be a list of additional
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
- # 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,
objects,
output_libname,
output_dir=None,
libraries=None,
library_dirs=None,
- build_info=None):
+ extra_preargs=None,
+ extra_postargs=None):
"""Link a bunch of stuff together to create a shared library
file. Has the same effect as 'link_static_lib()' except
that the filename inferred from 'output_libname' will most
@@ -335,18 +338,20 @@ class CCompiler:
almost certainly be different."""
pass
+
def link_shared_object (self,
objects,
output_filename,
output_dir=None,
libraries=None,
library_dirs=None,
- build_info=None):
+ extra_preargs=None,
+ extra_postargs=None):
"""Link a bunch of stuff together to create a shared object
file. Much like 'link_shared_lib()', except the output filename
is explicitly supplied as 'output_filename'. If 'output_dir' is
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)."""
pass
@@ -407,23 +412,65 @@ 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,
+ compiler=None,
verbose=0,
dry_run=0):
- """Generate a CCompiler instance for platform 'plat' (or the
- current platform, if 'plat' not supplied). Really instantiates
- some concrete subclass of CCompiler, of course."""
-
- if plat is None: plat = os.name
- if plat == 'posix':
- from unixccompiler import UnixCCompiler
- return UnixCCompiler (verbose, dry_run)
- elif plat == 'nt':
- from msvccompiler import MSVCCompiler
- return MSVCCompiler (verbose, dry_run)
- else:
- raise DistutilsPlatformError, \
- "don't know how to compile C/C++ code on platform %s" % plat
+
+ """Generate an instance of some CCompiler subclass for the supplied
+ platform/compiler combination. 'plat' defaults to 'os.name'
+ (eg. 'posix', 'nt'), and 'compiler' defaults to the default
+ compiler for that platform. Currently only 'posix' and 'nt'
+ are supported, and the default compilers are "traditional Unix
+ interface" (UnixCCompiler class) and Visual C++ (MSVCCompiler
+ class). Note that it's perfectly possible to ask for a Unix
+ compiler object under Windows, and a Microsoft compiler object
+ under Unix -- if you supply a value for 'compiler', 'plat'
+ is ignored."""
+
+ if plat is None:
+ 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):
@@ -477,7 +524,7 @@ def gen_preprocess_options (macros, includes):
# 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
linking with specific libraries. 'libraries' and 'library_dirs'
are, respectively, lists of library names (not filenames!) and