mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	 5e71744000
			
		
	
	
		5e71744000
		
	
	
	
	
		
			
			Added 'verbose' and 'dry_run' parameters to constructor. Changed 'compile()', 'link_*()' to default lists arguments to None rather than empty list. Added implementations of the filename-mangling methods mandated by the CCompiler interface.
		
			
				
	
	
		
			230 lines
		
	
	
	
		
			8.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			230 lines
		
	
	
	
		
			8.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| """distutils.unixccompiler
 | |
| 
 | |
| Contains the UnixCCompiler class, a subclass of CCompiler that handles
 | |
| the "typical" Unix-style command-line C compiler:
 | |
|   * macros defined with -Dname[=value]
 | |
|   * macros undefined with -Uname
 | |
|   * include search directories specified with -Idir
 | |
|   * libraries specified with -lllib
 | |
|   * library search directories specified with -Ldir
 | |
|   * compile handled by 'cc' (or similar) executable with -c option:
 | |
|     compiles .c to .o
 | |
|   * link static library handled by 'ar' command (possibly with 'ranlib')
 | |
|   * link shared library handled by 'cc -shared'
 | |
| """
 | |
| 
 | |
| # created 1999/07/05, Greg Ward
 | |
| 
 | |
| __rcsid__ = "$Id$"
 | |
| 
 | |
| import string, re
 | |
| from types import *
 | |
| from sysconfig import \
 | |
|      CC, CCSHARED, CFLAGS, OPT, LDSHARED, LDFLAGS, RANLIB, AR, SO
 | |
| from ccompiler import CCompiler
 | |
| 
 | |
| 
 | |
| # XXX Things not currently handled:
 | |
| #   * optimization/debug/warning flags; we just use whatever's in Python's
 | |
| #     Makefile and live with it.  Is this adequate?  If not, we might
 | |
| #     have to have a bunch of subclasses GNUCCompiler, SGICCompiler,
 | |
| #     SunCCompiler, and I suspect down that road lies madness.
 | |
| #   * even if we don't know a warning flag from an optimization flag,
 | |
| #     we need some way for outsiders to feed preprocessor/compiler/linker
 | |
| #     flags in to us -- eg. a sysadmin might want to mandate certain flags
 | |
| #     via a site config file, or a user might want to set something for
 | |
| #     compiling this module distribution only via the setup.py command
 | |
| #     line, whatever.  As long as these options come from something on the
 | |
| #     current system, they can be as system-dependent as they like, and we
 | |
| #     should just happily stuff them into the preprocessor/compiler/linker
 | |
| #     options and carry on.
 | |
| 
 | |
| 
 | |
| class UnixCCompiler (CCompiler):
 | |
| 
 | |
|     # XXX perhaps there should really be *three* kinds of include
 | |
|     # directories: those built in to the preprocessor, those from Python's
 | |
|     # Makefiles, and those supplied to {add,set}_include_dirs().  Currently
 | |
|     # we make no distinction between the latter two at this point; it's all
 | |
|     # up to the client class to select the include directories to use above
 | |
|     # and beyond the compiler's defaults.  That is, both the Python include
 | |
|     # directories and any module- or package-specific include directories
 | |
|     # are specified via {add,set}_include_dirs(), and there's no way to
 | |
|     # distinguish them.  This might be a bug.
 | |
|     
 | |
|     def __init__ (self,
 | |
|                   verbose=0,
 | |
|                   dry_run=0):
 | |
| 
 | |
|         CCompiler.__init__ (self, verbose, dry_run)
 | |
| 
 | |
|         self.preprocess_options = None
 | |
|         self.compile_options = None
 | |
| 
 | |
|         # Munge CC and OPT together in case there are flags stuck in CC.
 | |
|         # Note that using these variables from sysconfig immediately makes
 | |
|         # this module specific to building Python extensions and
 | |
|         # inappropriate as a general-purpose C compiler front-end.  So sue
 | |
|         # me.  Note also that we use OPT rather than CFLAGS, because CFLAGS
 | |
|         # is the flags used to compile Python itself -- not only are there
 | |
|         # -I options in there, they are the *wrong* -I options.  We'll
 | |
|         # leave selection of include directories up to the class using
 | |
|         # UnixCCompiler!
 | |
| 
 | |
|         (self.cc, self.ccflags) = \
 | |
|             _split_command (CC + ' ' + OPT)
 | |
|         self.ccflags_shared = string.split (CCSHARED)
 | |
| 
 | |
|         (self.ld_shared, self.ldflags_shared) = \
 | |
|             _split_command (LDSHARED)
 | |
| 
 | |
| 
 | |
|     def compile (self,
 | |
|                  sources,
 | |
|                  macros=None,
 | |
|                  includes=None):
 | |
| 
 | |
|         if macros is None:
 | |
|             macros = []
 | |
|         if includes is None:
 | |
|             includes = []
 | |
| 
 | |
|         if type (macros) is not ListType:
 | |
|             raise TypeError, \
 | |
|                   "'macros' (if supplied) must be a list of tuples"
 | |
|         if type (includes) is not ListType:
 | |
|             raise TypeError, \
 | |
|                   "'includes' (if supplied) must be a list of strings"
 | |
| 
 | |
|         pp_opts = _gen_preprocess_options (self.macros + macros,
 | |
|                                            self.include_dirs + includes)
 | |
| 
 | |
|         # 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
 | |
| 
 | |
|         # this will change to 'spawn' when I have it!
 | |
|         #print string.join ([self.cc] + cc_args, ' ')
 | |
|         self.spawn ([self.cc] + cc_args)
 | |
| 
 | |
| 
 | |
|     # 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 link_shared_lib (self,
 | |
|                          objects,
 | |
|                          output_libname,
 | |
|                          libraries=None,
 | |
|                          library_dirs=None):
 | |
|         # XXX should we sanity check the library name? (eg. no
 | |
|         # slashes)
 | |
|         self.link_shared_object (objects, "lib%s%s" % (output_libname, SO))
 | |
| 
 | |
| 
 | |
|     def link_shared_object (self,
 | |
|                             objects,
 | |
|                             output_filename,
 | |
|                             libraries=None,
 | |
|                             library_dirs=None):
 | |
| 
 | |
|         if libraries is None:
 | |
|             libraries = []
 | |
|         if library_dirs is None:
 | |
|             library_dirs = []
 | |
| 
 | |
|         lib_opts = _gen_lib_options (self.libraries + libraries,
 | |
|                                      self.library_dirs + library_dirs)
 | |
|         ld_args = self.ldflags_shared + lib_opts + \
 | |
|                   objects + ['-o', output_filename]
 | |
| 
 | |
|         #print string.join ([self.ld_shared] + ld_args, ' ')
 | |
|         self.spawn ([self.ld_shared] + ld_args)
 | |
| 
 | |
| 
 | |
|     def object_filenames (self, source_filenames):
 | |
|         outnames = []
 | |
|         for inname in source_filenames:
 | |
|             outnames.append (re.sub (r'\.(c|C|cc|cxx)$', '.o', inname))
 | |
|         return outnames
 | |
| 
 | |
|     def shared_object_filename (self, source_filename):
 | |
|         return re.sub (r'\.(c|C|cc|cxx)$', SO)
 | |
| 
 | |
|     def library_filename (self, libname):
 | |
|         return "lib%s.a" % libname
 | |
| 
 | |
|     def shared_library_filename (self, libname):
 | |
|         return "lib%s.so" % libname
 | |
| 
 | |
| 
 | |
| # class UnixCCompiler
 | |
| 
 | |
| 
 | |
| def _split_command (cmd):
 | |
|     """Split a command string up into the progam to run (a string) and
 | |
|        the list of arguments; return them as (cmd, arglist)."""
 | |
|     args = string.split (cmd)
 | |
|     return (args[0], args[1:])
 | |
| 
 | |
| 
 | |
| def _gen_preprocess_options (macros, includes):
 | |
| 
 | |
|     # XXX it would be nice (mainly aesthetic, and so we don't generate
 | |
|     # stupid-looking command lines) to go over 'macros' and eliminate
 | |
|     # redundant definitions/undefinitions (ie. ensure that only the
 | |
|     # latest mention of a particular macro winds up on the command
 | |
|     # line).  I don't think it's essential, though, since most (all?)
 | |
|     # Unix C compilers only pay attention to the latest -D or -U
 | |
|     # mention of a macro on their command line.  Similar situation for
 | |
|     # 'includes'.  I'm punting on both for now.  Anyways, weeding out
 | |
|     # redundancies like this should probably be the province of
 | |
|     # CCompiler, since the data structures used are inherited from it
 | |
|     # and therefore common to all CCompiler classes.
 | |
| 
 | |
| 
 | |
|     pp_opts = []
 | |
|     for macro in macros:
 | |
|         if len (macro) == 1:        # undefine this macro
 | |
|             pp_opts.append ("-U%s" % macro[0])
 | |
|         elif len (macro) == 2:
 | |
|             if macro[1] is None:    # define with no explicit value
 | |
|                 pp_opts.append ("-D%s" % macro[0])
 | |
|             else:
 | |
|                 # XXX *don't* need to be clever about quoting the
 | |
|                 # macro value here, because we're going to avoid the
 | |
|                 # shell at all costs when we spawn the command!
 | |
|                 pp_opts.append ("-D%s=%s" % macro)
 | |
| 
 | |
|     for dir in includes:
 | |
|         pp_opts.append ("-I%s" % dir)
 | |
| 
 | |
|     return pp_opts
 | |
| 
 | |
| # _gen_preprocess_options ()
 | |
| 
 | |
| 
 | |
| def _gen_lib_options (libraries, library_dirs):
 | |
| 
 | |
|     lib_opts = []
 | |
| 
 | |
|     for dir in library_dirs:
 | |
|         lib_opts.append ("-L%s" % dir)
 | |
| 
 | |
|     # XXX it's important that we *not* remove redundant library mentions!
 | |
|     # sometimes you really do have to say "-lfoo -lbar -lfoo" in order to
 | |
|     # resolve all symbols.  I just hope we never have to say "-lfoo obj.o
 | |
|     # -lbar" to get things to work -- that's certainly a possibility, but a
 | |
|     # pretty nasty way to arrange your C code.
 | |
| 
 | |
|     for lib in libraries:
 | |
|         lib_opts.append ("-l%s" % lib)
 | |
| 
 | |
|     return lib_opts
 | |
| 
 | |
| # _gen_lib_options ()
 |