diff options
author | Greg Ward <gward@python.net> | 2000-01-09 22:47:53 (GMT) |
---|---|---|
committer | Greg Ward <gward@python.net> | 2000-01-09 22:47:53 (GMT) |
commit | c9f3187be20631a2bbbce9d9d582beda148a2025 (patch) | |
tree | c4bcc6c39d6a8597b07dfeaef0516c6490eeb71d | |
parent | 5baf1c211133ac98c04dc308b6a441ecd53b6c06 (diff) | |
download | cpython-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.py | 170 |
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): |