mirror of https://github.com/python/cpython
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.
This commit is contained in:
parent
5baf1c2111
commit
c9f3187be2
|
@ -60,6 +60,13 @@ class UnixCCompiler (CCompiler):
|
||||||
_shared_lib_ext = SO
|
_shared_lib_ext = SO
|
||||||
_static_lib_ext = '.a'
|
_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,
|
def __init__ (self,
|
||||||
verbose=0,
|
verbose=0,
|
||||||
dry_run=0,
|
dry_run=0,
|
||||||
|
@ -87,6 +94,8 @@ class UnixCCompiler (CCompiler):
|
||||||
(self.ld_shared, self.ldflags_shared) = \
|
(self.ld_shared, self.ldflags_shared) = \
|
||||||
_split_command (LDSHARED)
|
_split_command (LDSHARED)
|
||||||
|
|
||||||
|
self.ld_exec = self.cc
|
||||||
|
|
||||||
|
|
||||||
def compile (self,
|
def compile (self,
|
||||||
sources,
|
sources,
|
||||||
|
@ -122,7 +131,7 @@ class UnixCCompiler (CCompiler):
|
||||||
# don't have to recompile. (Simplistic check -- we just compare the
|
# don't have to recompile. (Simplistic check -- we just compare the
|
||||||
# source and object file, no deep dependency checking involving
|
# source and object file, no deep dependency checking involving
|
||||||
# header files. Hmmm.)
|
# header files. Hmmm.)
|
||||||
objects = self.object_filenames (sources, output_dir)
|
objects = self.object_filenames (sources, output_dir=output_dir)
|
||||||
if not self.force:
|
if not self.force:
|
||||||
skipped = newer_pairwise (sources, objects)
|
skipped = newer_pairwise (sources, objects)
|
||||||
for skipped_pair in skipped:
|
for skipped_pair in skipped:
|
||||||
|
@ -163,11 +172,68 @@ class UnixCCompiler (CCompiler):
|
||||||
return self.object_filenames (orig_sources, output_dir)
|
return self.object_filenames (orig_sources, output_dir)
|
||||||
|
|
||||||
|
|
||||||
# XXX punting on 'link_static_lib()' for now -- it might be better for
|
def _fix_link_args (self, output_dir, libraries, library_dirs):
|
||||||
# CCompiler to mandate just 'link_binary()' or some such to build a new
|
"""Fixes up the arguments supplied to the 'link_*' methods:
|
||||||
# Python binary; it would then take care of linking in everything
|
if output_dir is None, use self.output_dir; ensure that
|
||||||
# needed for the new Python without messing with an intermediate static
|
libraries and library_dirs are both lists (could be None or
|
||||||
# library.
|
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,
|
def link_shared_lib (self,
|
||||||
objects,
|
objects,
|
||||||
|
@ -198,21 +264,8 @@ class UnixCCompiler (CCompiler):
|
||||||
extra_preargs=None,
|
extra_preargs=None,
|
||||||
extra_postargs=None):
|
extra_postargs=None):
|
||||||
|
|
||||||
if output_dir is None:
|
(output_dir, libraries, library_dirs) = \
|
||||||
output_dir = self.output_dir
|
self._fix_link_args (output_dir, libraries, library_dirs)
|
||||||
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)
|
|
||||||
|
|
||||||
lib_opts = gen_lib_options (self,
|
lib_opts = gen_lib_options (self,
|
||||||
self.library_dirs + library_dirs,
|
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
|
# If any of the input object files are newer than the output shared
|
||||||
# object, relink. Again, this is a simplistic dependency check:
|
# object, relink. Again, this is a simplistic dependency check:
|
||||||
# doesn't look at any of the libraries we might be linking with.
|
# 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:
|
if not self.force:
|
||||||
try:
|
if self.dry_run:
|
||||||
|
newer = newer_group (objects, output_filename, missing='newer')
|
||||||
|
else:
|
||||||
newer = newer_group (objects, output_filename)
|
newer = newer_group (objects, output_filename)
|
||||||
except OSError:
|
|
||||||
if self.dry_run:
|
|
||||||
newer = 1
|
|
||||||
else:
|
|
||||||
raise
|
|
||||||
|
|
||||||
if self.force or newer:
|
if self.force or newer:
|
||||||
ld_args = self.ldflags_shared + objects + \
|
ld_args = self.ldflags_shared + objects + \
|
||||||
|
@ -248,31 +297,78 @@ class UnixCCompiler (CCompiler):
|
||||||
# link_shared_object ()
|
# 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 ------------------------------
|
# -- 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 = []
|
outnames = []
|
||||||
for inname in source_filenames:
|
for inname in source_filenames:
|
||||||
outname = re.sub (r'\.(c|C|cc|cxx|cpp)$', self._obj_ext, inname)
|
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:
|
if output_dir is not None:
|
||||||
outname = os.path.join (output_dir, outname)
|
outname = os.path.join (output_dir, outname)
|
||||||
outnames.append (outname)
|
outnames.append (outname)
|
||||||
return outnames
|
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 = 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:
|
if output_dir is not None:
|
||||||
outname = os.path.join (output_dir, outname)
|
outname = os.path.join (output_dir, outname)
|
||||||
return outname
|
return outname
|
||||||
|
|
||||||
|
|
||||||
def library_filename (self, libname):
|
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):
|
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):
|
def library_dir_option (self, dir):
|
||||||
|
|
Loading…
Reference in New Issue