Commit 8037cb11 authored by Greg Ward's avatar Greg Ward

Added 'output_dir' parameter to 'compile()' and 'link_shared_object().

Changed those two methods to only compile/link if necessary (according
  to simplistic timestamp checks).
Added 'output_dir' to 'object_filenames()' and 'shared_object_filename()'.
parent 3b120ab3
...@@ -17,12 +17,13 @@ the "typical" Unix-style command-line C compiler: ...@@ -17,12 +17,13 @@ the "typical" Unix-style command-line C compiler:
__rcsid__ = "$Id$" __rcsid__ = "$Id$"
import string, re import string, re, os
from types import * from types import *
from copy import copy
from sysconfig import \ from sysconfig import \
CC, CCSHARED, CFLAGS, OPT, LDSHARED, LDFLAGS, RANLIB, AR, SO CC, CCSHARED, CFLAGS, OPT, LDSHARED, LDFLAGS, RANLIB, AR, SO
from ccompiler import CCompiler, gen_preprocess_options, gen_lib_options from ccompiler import CCompiler, gen_preprocess_options, gen_lib_options
from util import move_file, newer_pairwise, newer_group
# XXX Things not currently handled: # XXX Things not currently handled:
# * optimization/debug/warning flags; we just use whatever's in Python's # * optimization/debug/warning flags; we just use whatever's in Python's
...@@ -86,9 +87,12 @@ class UnixCCompiler (CCompiler): ...@@ -86,9 +87,12 @@ class UnixCCompiler (CCompiler):
def compile (self, def compile (self,
sources, sources,
output_dir=None,
macros=None, macros=None,
includes=None): includes=None):
if output_dir is None:
output_dir = self.output_dir
if macros is None: if macros is None:
macros = [] macros = []
if includes is None: if includes is None:
...@@ -104,15 +108,48 @@ class UnixCCompiler (CCompiler): ...@@ -104,15 +108,48 @@ class UnixCCompiler (CCompiler):
pp_opts = gen_preprocess_options (self.macros + macros, pp_opts = gen_preprocess_options (self.macros + macros,
self.include_dirs + includes) self.include_dirs + includes)
# use of ccflags_shared means we're blithely assuming that we're # So we can mangle 'sources' without hurting the caller's data
# compiling for inclusion in a shared object! (will have to fix orig_sources = sources
# this when I add the ability to build a new Python) sources = copy (sources)
cc_args = ['-c'] + pp_opts + \
self.ccflags + self.ccflags_shared + \ # Get the list of expected output (object) files and drop files we
sources # 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)
skipped = newer_pairwise (sources, objects)
for skipped_pair in skipped:
self.announce ("skipping %s (%s up-to-date)" % skipped_pair)
# If anything left to compile, compile it
if sources:
# XXX use of ccflags_shared means we're blithely assuming
# that we're compiling for inclusion in a shared object!
# (will have to fix this when I add the ability to build a
# new Python)
cc_args = ['-c'] + pp_opts + \
self.ccflags + self.ccflags_shared + \
sources
self.spawn ([self.cc] + cc_args)
self.spawn ([self.cc] + cc_args) # Note that compiling multiple source files in the same go like
return self.object_filenames (sources) # we've just done drops the .o file in the current directory, which
# may not be what the caller wants (depending on the 'output_dir'
# parameter). So, if necessary, fix that now by moving the .o
# files into the desired output directory. (The alternative, of
# course, is to compile one-at-a-time with a -o option. 6 of one,
# 12/2 of the other...)
if output_dir:
for i in range (len (objects)):
src = os.path.basename (objects[i])
objects[i] = self.move_file (src, output_dir)
# Have to re-fetch list of object filenames, because we want to
# 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 # XXX punting on 'link_static_lib()' for now -- it might be better for
...@@ -124,23 +161,31 @@ class UnixCCompiler (CCompiler): ...@@ -124,23 +161,31 @@ class UnixCCompiler (CCompiler):
def link_shared_lib (self, def link_shared_lib (self,
objects, objects,
output_libname, output_libname,
output_dir=None,
libraries=None, libraries=None,
library_dirs=None, library_dirs=None,
build_info=None): build_info=None):
# XXX should we sanity check the library name? (eg. no # XXX should we sanity check the library name? (eg. no
# slashes) # slashes)
self.link_shared_object (objects, "lib%s%s" % \ self.link_shared_object (
(output_libname, self._shared_lib_ext), objects,
build_info=build_info) "lib%s%s" % (output_libname, self._shared_lib_ext),
output_dir,
libraries,
library_dirs,
build_info)
def link_shared_object (self, def link_shared_object (self,
objects, objects,
output_filename, output_filename,
output_dir=None,
libraries=None, libraries=None,
library_dirs=None, library_dirs=None,
build_info=None): build_info=None):
if output_dir is None:
output_dir = self.output_dir
if libraries is None: if libraries is None:
libraries = [] libraries = []
if library_dirs is None: if library_dirs is None:
...@@ -151,21 +196,37 @@ class UnixCCompiler (CCompiler): ...@@ -151,21 +196,37 @@ class UnixCCompiler (CCompiler):
lib_opts = gen_lib_options (self.libraries + libraries, lib_opts = gen_lib_options (self.libraries + libraries,
self.library_dirs + library_dirs, self.library_dirs + library_dirs,
"-l%s", "-L%s") "-l%s", "-L%s")
ld_args = self.ldflags_shared + lib_opts + \ if output_dir is not None:
objects + ['-o', output_filename] output_filename = os.path.join (output_dir, output_filename)
# 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.
if newer_group (objects, output_filename):
ld_args = self.ldflags_shared + lib_opts + \
objects + ['-o', output_filename]
self.spawn ([self.ld_shared] + ld_args) self.spawn ([self.ld_shared] + ld_args)
else:
self.announce ("skipping %s (up-to-date)" % output_filename)
def object_filenames (self, source_filenames): def object_filenames (self, source_filenames, output_dir=None):
outnames = [] outnames = []
for inname in source_filenames: for inname in source_filenames:
outnames.append ( re.sub (r'\.(c|C|cc|cxx|cpp)$', outname = re.sub (r'\.(c|C|cc|cxx|cpp)$', self._obj_ext, inname)
self._obj_ext, inname)) outname = os.path.basename (outname)
if output_dir is not None:
outname = os.path.join (output_dir, outname)
outnames.append (outname)
return outnames return outnames
def shared_object_filename (self, source_filename): def shared_object_filename (self, source_filename, output_dir=None):
return 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 output_dir is not None:
outname = os.path.join (output_dir, outname)
return outname
def library_filename (self, libname): def library_filename (self, libname):
return "lib%s%s" % (libname, self._static_lib_ext ) return "lib%s%s" % (libname, self._static_lib_ext )
......
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