PyXR

c:\python24\lib \ distutils \ emxccompiler.py



0001 """distutils.emxccompiler
0002 
0003 Provides the EMXCCompiler class, a subclass of UnixCCompiler that
0004 handles the EMX port of the GNU C compiler to OS/2.
0005 """
0006 
0007 # issues:
0008 #
0009 # * OS/2 insists that DLLs can have names no longer than 8 characters
0010 #   We put export_symbols in a def-file, as though the DLL can have
0011 #   an arbitrary length name, but truncate the output filename.
0012 #
0013 # * only use OMF objects and use LINK386 as the linker (-Zomf)
0014 #
0015 # * always build for multithreading (-Zmt) as the accompanying OS/2 port
0016 #   of Python is only distributed with threads enabled.
0017 #
0018 # tested configurations:
0019 #
0020 # * EMX gcc 2.81/EMX 0.9d fix03
0021 
0022 __revision__ = "$Id: emxccompiler.py,v 1.11 2003/12/02 12:17:59 aimacintyre Exp $"
0023 
0024 import os,sys,copy
0025 from distutils.ccompiler import gen_preprocess_options, gen_lib_options
0026 from distutils.unixccompiler import UnixCCompiler
0027 from distutils.file_util import write_file
0028 from distutils.errors import DistutilsExecError, CompileError, UnknownFileError
0029 from distutils import log
0030 
0031 class EMXCCompiler (UnixCCompiler):
0032 
0033     compiler_type = 'emx'
0034     obj_extension = ".obj"
0035     static_lib_extension = ".lib"
0036     shared_lib_extension = ".dll"
0037     static_lib_format = "%s%s"
0038     shared_lib_format = "%s%s"
0039     res_extension = ".res"      # compiled resource file
0040     exe_extension = ".exe"
0041 
0042     def __init__ (self,
0043                   verbose=0,
0044                   dry_run=0,
0045                   force=0):
0046 
0047         UnixCCompiler.__init__ (self, verbose, dry_run, force)
0048 
0049         (status, details) = check_config_h()
0050         self.debug_print("Python's GCC status: %s (details: %s)" %
0051                          (status, details))
0052         if status is not CONFIG_H_OK:
0053             self.warn(
0054                 "Python's pyconfig.h doesn't seem to support your compiler.  " +
0055                 ("Reason: %s." % details) +
0056                 "Compiling may fail because of undefined preprocessor macros.")
0057 
0058         (self.gcc_version, self.ld_version) = \
0059             get_versions()
0060         self.debug_print(self.compiler_type + ": gcc %s, ld %s\n" %
0061                          (self.gcc_version,
0062                           self.ld_version) )
0063 
0064         # Hard-code GCC because that's what this is all about.
0065         # XXX optimization, warnings etc. should be customizable.
0066         self.set_executables(compiler='gcc -Zomf -Zmt -O3 -fomit-frame-pointer -mprobe -Wall',
0067                              compiler_so='gcc -Zomf -Zmt -O3 -fomit-frame-pointer -mprobe -Wall',
0068                              linker_exe='gcc -Zomf -Zmt -Zcrtdll',
0069                              linker_so='gcc -Zomf -Zmt -Zcrtdll -Zdll')
0070 
0071         # want the gcc library statically linked (so that we don't have
0072         # to distribute a version dependent on the compiler we have)
0073         self.dll_libraries=["gcc"]
0074 
0075     # __init__ ()
0076 
0077     def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
0078         if ext == '.rc':
0079             # gcc requires '.rc' compiled to binary ('.res') files !!!
0080             try:
0081                 self.spawn(["rc", "-r", src])
0082             except DistutilsExecError, msg:
0083                 raise CompileError, msg
0084         else: # for other files use the C-compiler
0085             try:
0086                 self.spawn(self.compiler_so + cc_args + [src, '-o', obj] +
0087                            extra_postargs)
0088             except DistutilsExecError, msg:
0089                 raise CompileError, msg
0090 
0091     def link (self,
0092               target_desc,
0093               objects,
0094               output_filename,
0095               output_dir=None,
0096               libraries=None,
0097               library_dirs=None,
0098               runtime_library_dirs=None,
0099               export_symbols=None,
0100               debug=0,
0101               extra_preargs=None,
0102               extra_postargs=None,
0103               build_temp=None,
0104               target_lang=None):
0105 
0106         # use separate copies, so we can modify the lists
0107         extra_preargs = copy.copy(extra_preargs or [])
0108         libraries = copy.copy(libraries or [])
0109         objects = copy.copy(objects or [])
0110 
0111         # Additional libraries
0112         libraries.extend(self.dll_libraries)
0113 
0114         # handle export symbols by creating a def-file
0115         # with executables this only works with gcc/ld as linker
0116         if ((export_symbols is not None) and
0117             (target_desc != self.EXECUTABLE)):
0118             # (The linker doesn't do anything if output is up-to-date.
0119             # So it would probably better to check if we really need this,
0120             # but for this we had to insert some unchanged parts of
0121             # UnixCCompiler, and this is not what we want.)
0122 
0123             # we want to put some files in the same directory as the
0124             # object files are, build_temp doesn't help much
0125             # where are the object files
0126             temp_dir = os.path.dirname(objects[0])
0127             # name of dll to give the helper files the same base name
0128             (dll_name, dll_extension) = os.path.splitext(
0129                 os.path.basename(output_filename))
0130 
0131             # generate the filenames for these files
0132             def_file = os.path.join(temp_dir, dll_name + ".def")
0133 
0134             # Generate .def file
0135             contents = [
0136                 "LIBRARY %s INITINSTANCE TERMINSTANCE" % \
0137                 os.path.splitext(os.path.basename(output_filename))[0],
0138                 "DATA MULTIPLE NONSHARED",
0139                 "EXPORTS"]
0140             for sym in export_symbols:
0141                 contents.append('  "%s"' % sym)
0142             self.execute(write_file, (def_file, contents),
0143                          "writing %s" % def_file)
0144 
0145             # next add options for def-file and to creating import libraries
0146             # for gcc/ld the def-file is specified as any other object files
0147             objects.append(def_file)
0148 
0149         #end: if ((export_symbols is not None) and
0150         #        (target_desc != self.EXECUTABLE or self.linker_dll == "gcc")):
0151 
0152         # who wants symbols and a many times larger output file
0153         # should explicitly switch the debug mode on
0154         # otherwise we let dllwrap/ld strip the output file
0155         # (On my machine: 10KB < stripped_file < ??100KB
0156         #   unstripped_file = stripped_file + XXX KB
0157         #  ( XXX=254 for a typical python extension))
0158         if not debug:
0159             extra_preargs.append("-s")
0160 
0161         UnixCCompiler.link(self,
0162                            target_desc,
0163                            objects,
0164                            output_filename,
0165                            output_dir,
0166                            libraries,
0167                            library_dirs,
0168                            runtime_library_dirs,
0169                            None, # export_symbols, we do this in our def-file
0170                            debug,
0171                            extra_preargs,
0172                            extra_postargs,
0173                            build_temp,
0174                            target_lang)
0175 
0176     # link ()
0177 
0178     # -- Miscellaneous methods -----------------------------------------
0179 
0180     # override the object_filenames method from CCompiler to
0181     # support rc and res-files
0182     def object_filenames (self,
0183                           source_filenames,
0184                           strip_dir=0,
0185                           output_dir=''):
0186         if output_dir is None: output_dir = ''
0187         obj_names = []
0188         for src_name in source_filenames:
0189             # use normcase to make sure '.rc' is really '.rc' and not '.RC'
0190             (base, ext) = os.path.splitext (os.path.normcase(src_name))
0191             if ext not in (self.src_extensions + ['.rc']):
0192                 raise UnknownFileError, \
0193                       "unknown file type '%s' (from '%s')" % \
0194                       (ext, src_name)
0195             if strip_dir:
0196                 base = os.path.basename (base)
0197             if ext == '.rc':
0198                 # these need to be compiled to object files
0199                 obj_names.append (os.path.join (output_dir,
0200                                             base + self.res_extension))
0201             else:
0202                 obj_names.append (os.path.join (output_dir,
0203                                             base + self.obj_extension))
0204         return obj_names
0205 
0206     # object_filenames ()
0207 
0208     # override the find_library_file method from UnixCCompiler
0209     # to deal with file naming/searching differences
0210     def find_library_file(self, dirs, lib, debug=0):
0211         shortlib = '%s.lib' % lib
0212         longlib = 'lib%s.lib' % lib    # this form very rare
0213 
0214         # get EMX's default library directory search path
0215         try:
0216             emx_dirs = os.environ['LIBRARY_PATH'].split(';')
0217         except KeyError:
0218             emx_dirs = []
0219 
0220         for dir in dirs + emx_dirs:
0221             shortlibp = os.path.join(dir, shortlib)
0222             longlibp = os.path.join(dir, longlib)
0223             if os.path.exists(shortlibp):
0224                 return shortlibp
0225             elif os.path.exists(longlibp):
0226                 return longlibp
0227 
0228         # Oops, didn't find it in *any* of 'dirs'
0229         return None
0230 
0231 # class EMXCCompiler
0232 
0233 
0234 # Because these compilers aren't configured in Python's pyconfig.h file by
0235 # default, we should at least warn the user if he is using a unmodified
0236 # version.
0237 
0238 CONFIG_H_OK = "ok"
0239 CONFIG_H_NOTOK = "not ok"
0240 CONFIG_H_UNCERTAIN = "uncertain"
0241 
0242 def check_config_h():
0243 
0244     """Check if the current Python installation (specifically, pyconfig.h)
0245     appears amenable to building extensions with GCC.  Returns a tuple
0246     (status, details), where 'status' is one of the following constants:
0247       CONFIG_H_OK
0248         all is well, go ahead and compile
0249       CONFIG_H_NOTOK
0250         doesn't look good
0251       CONFIG_H_UNCERTAIN
0252         not sure -- unable to read pyconfig.h
0253     'details' is a human-readable string explaining the situation.
0254 
0255     Note there are two ways to conclude "OK": either 'sys.version' contains
0256     the string "GCC" (implying that this Python was built with GCC), or the
0257     installed "pyconfig.h" contains the string "__GNUC__".
0258     """
0259 
0260     # XXX since this function also checks sys.version, it's not strictly a
0261     # "pyconfig.h" check -- should probably be renamed...
0262 
0263     from distutils import sysconfig
0264     import string
0265     # if sys.version contains GCC then python was compiled with
0266     # GCC, and the pyconfig.h file should be OK
0267     if string.find(sys.version,"GCC") >= 0:
0268         return (CONFIG_H_OK, "sys.version mentions 'GCC'")
0269 
0270     fn = sysconfig.get_config_h_filename()
0271     try:
0272         # It would probably better to read single lines to search.
0273         # But we do this only once, and it is fast enough
0274         f = open(fn)
0275         s = f.read()
0276         f.close()
0277 
0278     except IOError, exc:
0279         # if we can't read this file, we cannot say it is wrong
0280         # the compiler will complain later about this file as missing
0281         return (CONFIG_H_UNCERTAIN,
0282                 "couldn't read '%s': %s" % (fn, exc.strerror))
0283 
0284     else:
0285         # "pyconfig.h" contains an "#ifdef __GNUC__" or something similar
0286         if string.find(s,"__GNUC__") >= 0:
0287             return (CONFIG_H_OK, "'%s' mentions '__GNUC__'" % fn)
0288         else:
0289             return (CONFIG_H_NOTOK, "'%s' does not mention '__GNUC__'" % fn)
0290 
0291 
0292 def get_versions():
0293     """ Try to find out the versions of gcc and ld.
0294         If not possible it returns None for it.
0295     """
0296     from distutils.version import StrictVersion
0297     from distutils.spawn import find_executable
0298     import re
0299 
0300     gcc_exe = find_executable('gcc')
0301     if gcc_exe:
0302         out = os.popen(gcc_exe + ' -dumpversion','r')
0303         out_string = out.read()
0304         out.close()
0305         result = re.search('(\d+\.\d+\.\d+)',out_string)
0306         if result:
0307             gcc_version = StrictVersion(result.group(1))
0308         else:
0309             gcc_version = None
0310     else:
0311         gcc_version = None
0312     # EMX ld has no way of reporting version number, and we use GCC
0313     # anyway - so we can link OMF DLLs
0314     ld_version = None
0315     return (gcc_version, ld_version)
0316 

Generated by PyXR 0.9.4
SourceForge.net Logo