summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Ward <gward@python.net>2000-01-09 22:47:53 (GMT)
committerGreg Ward <gward@python.net>2000-01-09 22:47:53 (GMT)
commitc9f3187be20631a2bbbce9d9d582beda148a2025 (patch)
treec4bcc6c39d6a8597b07dfeaef0516c6490eeb71d
parent5baf1c211133ac98c04dc308b6a441ecd53b6c06 (diff)
downloadcpython-c9f3187be20631a2bbbce9d9d582beda148a2025.zip
cpython-c9f3187be20631a2bbbce9d9d582beda148a2025.tar.gz
cpython-c9f3187be20631a2bbbce9d9d582beda148a2025.tar.bz2
Abstracted '_fix_link_args()' out of 'link_shared_object()'.
Added 'link_static_lib()' method, and 'archiver' and 'archiver_options' class attributes to support it. Added 'link_executable()' method, and 'ld_exec' instance attribute to support it. 'newer_group()' is now able to handle missing files, so we don't have to kludge it by catching OSError when calling it. 'object_filenames()' and 'shared_object_filename()' now take 'keep_dir' flag parameters. 'library_filename()' and 'shared_library_filename()' now respect a directory component in the library name. Various comment updates/deletions.
-rw-r--r--Lib/distutils/unixccompiler.py170
1 files changed, 133 insertions, 37 deletions
diff --git a/Lib/distutils/unixccompiler.py b/Lib/distutils/unixccompiler.py
index edff4f0..fb58269 100644
--- a/Lib/distutils/unixccompiler.py
+++ b/Lib/distutils/unixccompiler.py
@@ -59,7 +59,14 @@ class UnixCCompiler (CCompiler):
_exe_ext = ''
_shared_lib_ext = SO
_static_lib_ext = '.a'
-
+
+ # Command to create a static library: seems to be pretty consistent
+ # across the major Unices. Might have to move down into the
+ # constructor if we need platform-specific guesswork.
+ archiver = "ar"
+ archiver_options = "-cr"
+
+
def __init__ (self,
verbose=0,
dry_run=0,
@@ -87,6 +94,8 @@ class UnixCCompiler (CCompiler):
(self.ld_shared, self.ldflags_shared) = \
_split_command (LDSHARED)
+ self.ld_exec = self.cc
+
def compile (self,
sources,
@@ -122,7 +131,7 @@ class UnixCCompiler (CCompiler):
# don't have to recompile. (Simplistic check -- we just compare the
# source and object file, no deep dependency checking involving
# header files. Hmmm.)
- objects = self.object_filenames (sources, output_dir)
+ objects = self.object_filenames (sources, output_dir=output_dir)
if not self.force:
skipped = newer_pairwise (sources, objects)
for skipped_pair in skipped:
@@ -161,13 +170,70 @@ class UnixCCompiler (CCompiler):
# return *all* of them, including those that weren't recompiled on
# this call!
return self.object_filenames (orig_sources, output_dir)
-
- # XXX punting on 'link_static_lib()' for now -- it might be better for
- # CCompiler to mandate just 'link_binary()' or some such to build a new
- # Python binary; it would then take care of linking in everything
- # needed for the new Python without messing with an intermediate static
- # library.
+
+ def _fix_link_args (self, output_dir, libraries, library_dirs):
+ """Fixes up the arguments supplied to the 'link_*' methods:
+ if output_dir is None, use self.output_dir; ensure that
+ libraries and library_dirs are both lists (could be None or
+ tuples on input -- both are converted to lists). Return
+ a tuple of the three input arguments."""
+
+ if output_dir is None:
+ output_dir = self.output_dir
+ if libraries is None:
+ libraries = []
+ if library_dirs is None:
+ library_dirs = []
+
+ if type (libraries) not in (ListType, TupleType):
+ raise TypeError, \
+ "'libraries' (if supplied) must be a list of strings"
+ if type (library_dirs) not in (ListType, TupleType):
+ raise TypeError, \
+ "'library_dirs' (if supplied) must be a list of strings"
+ libraries = list (libraries)
+ library_dirs = list (library_dirs)
+
+ return (output_dir, libraries, library_dirs)
+
+
+ def link_static_lib (self,
+ objects,
+ output_libname,
+ output_dir=None):
+
+ if type (objects) not in (ListType, TupleType):
+ raise TypeError, \
+ "'objects' must be a list or tuple of strings"
+ objects = list (objects)
+
+ if output_dir is None:
+ output_dir = self.output_dir
+
+ output_filename = self.library_filename (output_libname)
+ if output_dir is not None:
+ output_filename = os.path.join (output_dir, output_filename)
+
+ # Check timestamps: if any of the object files are newer than
+ # the library file, *or* if "force" is true, then we'll
+ # recreate the library.
+ if not self.force:
+ if self.dry_run:
+ newer = newer_group (objects, output_filename, missing='newer')
+ else:
+ newer = newer_group (objects, output_filename)
+
+ if self.force or newer:
+ self.spawn ([self.archiver,
+ self.archiver_options,
+ output_filename] +
+ objects)
+ else:
+ self.announce ("skipping %s (up-to-date)" % output_filename)
+
+ # link_static_lib ()
+
def link_shared_lib (self,
objects,
@@ -198,21 +264,8 @@ class UnixCCompiler (CCompiler):
extra_preargs=None,
extra_postargs=None):
- if output_dir is None:
- output_dir = self.output_dir
- if libraries is None:
- libraries = []
- if library_dirs is None:
- library_dirs = []
-
- if type (libraries) not in (ListType, TupleType):
- raise TypeError, \
- "'libraries' (if supplied) must be a list of strings"
- if type (library_dirs) not in (ListType, TupleType):
- raise TypeError, \
- "'library_dirs' (if supplied) must be a list of strings"
- libraries = list (libraries)
- library_dirs = list (library_dirs)
+ (output_dir, libraries, library_dirs) = \
+ self._fix_link_args (output_dir, libraries, library_dirs)
lib_opts = gen_lib_options (self,
self.library_dirs + library_dirs,
@@ -223,16 +276,12 @@ class UnixCCompiler (CCompiler):
# If any of the input object files are newer than the output shared
# object, relink. Again, this is a simplistic dependency check:
# doesn't look at any of the libraries we might be linking with.
- # Note that we have to dance around errors comparing timestamps if
- # we're in dry-run mode (yuck).
+
if not self.force:
- try:
+ if self.dry_run:
+ newer = newer_group (objects, output_filename, missing='newer')
+ else:
newer = newer_group (objects, output_filename)
- except OSError:
- if self.dry_run:
- newer = 1
- else:
- raise
if self.force or newer:
ld_args = self.ldflags_shared + objects + \
@@ -248,31 +297,78 @@ class UnixCCompiler (CCompiler):
# link_shared_object ()
+ def link_executable (self,
+ objects,
+ output_progname,
+ output_dir=None,
+ libraries=None,
+ library_dirs=None,
+ extra_preargs=None,
+ extra_postargs=None):
+
+ (output_dir, libraries, library_dirs) = \
+ self._fix_link_args (output_dir, libraries, library_dirs)
+
+ lib_opts = gen_lib_options (self,
+ self.library_dirs + library_dirs,
+ self.libraries + libraries)
+ output_filename = output_progname # Unix-ism!
+ if output_dir is not None:
+ output_filename = os.path.join (output_dir, output_filename)
+
+ # Same ol' simplistic-but-still-useful dependency check.
+ if not self.force:
+ if self.dry_run:
+ newer = newer_group (objects, output_filename, missing='newer')
+ else:
+ newer = newer_group (objects, output_filename)
+
+ if self.force or newer:
+ ld_args = objects + lib_opts + ['-o', output_filename]
+ if extra_preargs:
+ ld_args[:0] = extra_preargs
+ if extra_postargs:
+ ld_args.extend (extra_postargs)
+ self.spawn ([self.ld_exec] + ld_args)
+ else:
+ self.announce ("skipping %s (up-to-date)" % output_filename)
+
+ # link_executable ()
+
+
# -- Filename-mangling (etc.) methods ------------------------------
- def object_filenames (self, source_filenames, output_dir=None):
+ def object_filenames (self, source_filenames,
+ keep_dir=0, output_dir=None):
outnames = []
for inname in source_filenames:
outname = re.sub (r'\.(c|C|cc|cxx|cpp)$', self._obj_ext, inname)
- outname = os.path.basename (outname)
+ if not keep_dir:
+ outname = os.path.basename (outname)
if output_dir is not None:
outname = os.path.join (output_dir, outname)
outnames.append (outname)
return outnames
- def shared_object_filename (self, source_filename, output_dir=None):
+ def shared_object_filename (self, source_filename,
+ keep_dir=0, output_dir=None):
outname = re.sub (r'\.(c|C|cc|cxx|cpp)$', self._shared_lib_ext)
- outname = os.path.basename (outname)
+ if not keep_dir:
+ outname = os.path.basename (outname)
if output_dir is not None:
outname = os.path.join (output_dir, outname)
return outname
def library_filename (self, libname):
- return "lib%s%s" % (libname, self._static_lib_ext)
+ (dirname, basename) = os.path.split (libname)
+ return os.path.join (dirname,
+ "lib%s%s" % (basename, self._static_lib_ext))
def shared_library_filename (self, libname):
- return "lib%s%s" % (libname, self._shared_lib_ext)
+ (dirname, basename) = os.path.split (libname)
+ return os.path.join (dirname,
+ "lib%s%s" % (basename, self._shared_lib_ext))
def library_dir_option (self, dir):