symbian-qemu-0.9.1-12/python-win32-2.6.1/lib/distutils/emxccompiler.py
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 """distutils.emxccompiler
       
     2 
       
     3 Provides the EMXCCompiler class, a subclass of UnixCCompiler that
       
     4 handles the EMX port of the GNU C compiler to OS/2.
       
     5 """
       
     6 
       
     7 # issues:
       
     8 #
       
     9 # * OS/2 insists that DLLs can have names no longer than 8 characters
       
    10 #   We put export_symbols in a def-file, as though the DLL can have
       
    11 #   an arbitrary length name, but truncate the output filename.
       
    12 #
       
    13 # * only use OMF objects and use LINK386 as the linker (-Zomf)
       
    14 #
       
    15 # * always build for multithreading (-Zmt) as the accompanying OS/2 port
       
    16 #   of Python is only distributed with threads enabled.
       
    17 #
       
    18 # tested configurations:
       
    19 #
       
    20 # * EMX gcc 2.81/EMX 0.9d fix03
       
    21 
       
    22 __revision__ = "$Id: emxccompiler.py 34786 2003-12-02 12:17:59Z aimacintyre $"
       
    23 
       
    24 import os,sys,copy
       
    25 from distutils.ccompiler import gen_preprocess_options, gen_lib_options
       
    26 from distutils.unixccompiler import UnixCCompiler
       
    27 from distutils.file_util import write_file
       
    28 from distutils.errors import DistutilsExecError, CompileError, UnknownFileError
       
    29 from distutils import log
       
    30 
       
    31 class EMXCCompiler (UnixCCompiler):
       
    32 
       
    33     compiler_type = 'emx'
       
    34     obj_extension = ".obj"
       
    35     static_lib_extension = ".lib"
       
    36     shared_lib_extension = ".dll"
       
    37     static_lib_format = "%s%s"
       
    38     shared_lib_format = "%s%s"
       
    39     res_extension = ".res"      # compiled resource file
       
    40     exe_extension = ".exe"
       
    41 
       
    42     def __init__ (self,
       
    43                   verbose=0,
       
    44                   dry_run=0,
       
    45                   force=0):
       
    46 
       
    47         UnixCCompiler.__init__ (self, verbose, dry_run, force)
       
    48 
       
    49         (status, details) = check_config_h()
       
    50         self.debug_print("Python's GCC status: %s (details: %s)" %
       
    51                          (status, details))
       
    52         if status is not CONFIG_H_OK:
       
    53             self.warn(
       
    54                 "Python's pyconfig.h doesn't seem to support your compiler.  " +
       
    55                 ("Reason: %s." % details) +
       
    56                 "Compiling may fail because of undefined preprocessor macros.")
       
    57 
       
    58         (self.gcc_version, self.ld_version) = \
       
    59             get_versions()
       
    60         self.debug_print(self.compiler_type + ": gcc %s, ld %s\n" %
       
    61                          (self.gcc_version,
       
    62                           self.ld_version) )
       
    63 
       
    64         # Hard-code GCC because that's what this is all about.
       
    65         # XXX optimization, warnings etc. should be customizable.
       
    66         self.set_executables(compiler='gcc -Zomf -Zmt -O3 -fomit-frame-pointer -mprobe -Wall',
       
    67                              compiler_so='gcc -Zomf -Zmt -O3 -fomit-frame-pointer -mprobe -Wall',
       
    68                              linker_exe='gcc -Zomf -Zmt -Zcrtdll',
       
    69                              linker_so='gcc -Zomf -Zmt -Zcrtdll -Zdll')
       
    70 
       
    71         # want the gcc library statically linked (so that we don't have
       
    72         # to distribute a version dependent on the compiler we have)
       
    73         self.dll_libraries=["gcc"]
       
    74 
       
    75     # __init__ ()
       
    76 
       
    77     def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
       
    78         if ext == '.rc':
       
    79             # gcc requires '.rc' compiled to binary ('.res') files !!!
       
    80             try:
       
    81                 self.spawn(["rc", "-r", src])
       
    82             except DistutilsExecError, msg:
       
    83                 raise CompileError, msg
       
    84         else: # for other files use the C-compiler
       
    85             try:
       
    86                 self.spawn(self.compiler_so + cc_args + [src, '-o', obj] +
       
    87                            extra_postargs)
       
    88             except DistutilsExecError, msg:
       
    89                 raise CompileError, msg
       
    90 
       
    91     def link (self,
       
    92               target_desc,
       
    93               objects,
       
    94               output_filename,
       
    95               output_dir=None,
       
    96               libraries=None,
       
    97               library_dirs=None,
       
    98               runtime_library_dirs=None,
       
    99               export_symbols=None,
       
   100               debug=0,
       
   101               extra_preargs=None,
       
   102               extra_postargs=None,
       
   103               build_temp=None,
       
   104               target_lang=None):
       
   105 
       
   106         # use separate copies, so we can modify the lists
       
   107         extra_preargs = copy.copy(extra_preargs or [])
       
   108         libraries = copy.copy(libraries or [])
       
   109         objects = copy.copy(objects or [])
       
   110 
       
   111         # Additional libraries
       
   112         libraries.extend(self.dll_libraries)
       
   113 
       
   114         # handle export symbols by creating a def-file
       
   115         # with executables this only works with gcc/ld as linker
       
   116         if ((export_symbols is not None) and
       
   117             (target_desc != self.EXECUTABLE)):
       
   118             # (The linker doesn't do anything if output is up-to-date.
       
   119             # So it would probably better to check if we really need this,
       
   120             # but for this we had to insert some unchanged parts of
       
   121             # UnixCCompiler, and this is not what we want.)
       
   122 
       
   123             # we want to put some files in the same directory as the
       
   124             # object files are, build_temp doesn't help much
       
   125             # where are the object files
       
   126             temp_dir = os.path.dirname(objects[0])
       
   127             # name of dll to give the helper files the same base name
       
   128             (dll_name, dll_extension) = os.path.splitext(
       
   129                 os.path.basename(output_filename))
       
   130 
       
   131             # generate the filenames for these files
       
   132             def_file = os.path.join(temp_dir, dll_name + ".def")
       
   133 
       
   134             # Generate .def file
       
   135             contents = [
       
   136                 "LIBRARY %s INITINSTANCE TERMINSTANCE" % \
       
   137                 os.path.splitext(os.path.basename(output_filename))[0],
       
   138                 "DATA MULTIPLE NONSHARED",
       
   139                 "EXPORTS"]
       
   140             for sym in export_symbols:
       
   141                 contents.append('  "%s"' % sym)
       
   142             self.execute(write_file, (def_file, contents),
       
   143                          "writing %s" % def_file)
       
   144 
       
   145             # next add options for def-file and to creating import libraries
       
   146             # for gcc/ld the def-file is specified as any other object files
       
   147             objects.append(def_file)
       
   148 
       
   149         #end: if ((export_symbols is not None) and
       
   150         #        (target_desc != self.EXECUTABLE or self.linker_dll == "gcc")):
       
   151 
       
   152         # who wants symbols and a many times larger output file
       
   153         # should explicitly switch the debug mode on
       
   154         # otherwise we let dllwrap/ld strip the output file
       
   155         # (On my machine: 10KB < stripped_file < ??100KB
       
   156         #   unstripped_file = stripped_file + XXX KB
       
   157         #  ( XXX=254 for a typical python extension))
       
   158         if not debug:
       
   159             extra_preargs.append("-s")
       
   160 
       
   161         UnixCCompiler.link(self,
       
   162                            target_desc,
       
   163                            objects,
       
   164                            output_filename,
       
   165                            output_dir,
       
   166                            libraries,
       
   167                            library_dirs,
       
   168                            runtime_library_dirs,
       
   169                            None, # export_symbols, we do this in our def-file
       
   170                            debug,
       
   171                            extra_preargs,
       
   172                            extra_postargs,
       
   173                            build_temp,
       
   174                            target_lang)
       
   175 
       
   176     # link ()
       
   177 
       
   178     # -- Miscellaneous methods -----------------------------------------
       
   179 
       
   180     # override the object_filenames method from CCompiler to
       
   181     # support rc and res-files
       
   182     def object_filenames (self,
       
   183                           source_filenames,
       
   184                           strip_dir=0,
       
   185                           output_dir=''):
       
   186         if output_dir is None: output_dir = ''
       
   187         obj_names = []
       
   188         for src_name in source_filenames:
       
   189             # use normcase to make sure '.rc' is really '.rc' and not '.RC'
       
   190             (base, ext) = os.path.splitext (os.path.normcase(src_name))
       
   191             if ext not in (self.src_extensions + ['.rc']):
       
   192                 raise UnknownFileError, \
       
   193                       "unknown file type '%s' (from '%s')" % \
       
   194                       (ext, src_name)
       
   195             if strip_dir:
       
   196                 base = os.path.basename (base)
       
   197             if ext == '.rc':
       
   198                 # these need to be compiled to object files
       
   199                 obj_names.append (os.path.join (output_dir,
       
   200                                             base + self.res_extension))
       
   201             else:
       
   202                 obj_names.append (os.path.join (output_dir,
       
   203                                             base + self.obj_extension))
       
   204         return obj_names
       
   205 
       
   206     # object_filenames ()
       
   207 
       
   208     # override the find_library_file method from UnixCCompiler
       
   209     # to deal with file naming/searching differences
       
   210     def find_library_file(self, dirs, lib, debug=0):
       
   211         shortlib = '%s.lib' % lib
       
   212         longlib = 'lib%s.lib' % lib    # this form very rare
       
   213 
       
   214         # get EMX's default library directory search path
       
   215         try:
       
   216             emx_dirs = os.environ['LIBRARY_PATH'].split(';')
       
   217         except KeyError:
       
   218             emx_dirs = []
       
   219 
       
   220         for dir in dirs + emx_dirs:
       
   221             shortlibp = os.path.join(dir, shortlib)
       
   222             longlibp = os.path.join(dir, longlib)
       
   223             if os.path.exists(shortlibp):
       
   224                 return shortlibp
       
   225             elif os.path.exists(longlibp):
       
   226                 return longlibp
       
   227 
       
   228         # Oops, didn't find it in *any* of 'dirs'
       
   229         return None
       
   230 
       
   231 # class EMXCCompiler
       
   232 
       
   233 
       
   234 # Because these compilers aren't configured in Python's pyconfig.h file by
       
   235 # default, we should at least warn the user if he is using a unmodified
       
   236 # version.
       
   237 
       
   238 CONFIG_H_OK = "ok"
       
   239 CONFIG_H_NOTOK = "not ok"
       
   240 CONFIG_H_UNCERTAIN = "uncertain"
       
   241 
       
   242 def check_config_h():
       
   243 
       
   244     """Check if the current Python installation (specifically, pyconfig.h)
       
   245     appears amenable to building extensions with GCC.  Returns a tuple
       
   246     (status, details), where 'status' is one of the following constants:
       
   247       CONFIG_H_OK
       
   248         all is well, go ahead and compile
       
   249       CONFIG_H_NOTOK
       
   250         doesn't look good
       
   251       CONFIG_H_UNCERTAIN
       
   252         not sure -- unable to read pyconfig.h
       
   253     'details' is a human-readable string explaining the situation.
       
   254 
       
   255     Note there are two ways to conclude "OK": either 'sys.version' contains
       
   256     the string "GCC" (implying that this Python was built with GCC), or the
       
   257     installed "pyconfig.h" contains the string "__GNUC__".
       
   258     """
       
   259 
       
   260     # XXX since this function also checks sys.version, it's not strictly a
       
   261     # "pyconfig.h" check -- should probably be renamed...
       
   262 
       
   263     from distutils import sysconfig
       
   264     import string
       
   265     # if sys.version contains GCC then python was compiled with
       
   266     # GCC, and the pyconfig.h file should be OK
       
   267     if string.find(sys.version,"GCC") >= 0:
       
   268         return (CONFIG_H_OK, "sys.version mentions 'GCC'")
       
   269 
       
   270     fn = sysconfig.get_config_h_filename()
       
   271     try:
       
   272         # It would probably better to read single lines to search.
       
   273         # But we do this only once, and it is fast enough
       
   274         f = open(fn)
       
   275         s = f.read()
       
   276         f.close()
       
   277 
       
   278     except IOError, exc:
       
   279         # if we can't read this file, we cannot say it is wrong
       
   280         # the compiler will complain later about this file as missing
       
   281         return (CONFIG_H_UNCERTAIN,
       
   282                 "couldn't read '%s': %s" % (fn, exc.strerror))
       
   283 
       
   284     else:
       
   285         # "pyconfig.h" contains an "#ifdef __GNUC__" or something similar
       
   286         if string.find(s,"__GNUC__") >= 0:
       
   287             return (CONFIG_H_OK, "'%s' mentions '__GNUC__'" % fn)
       
   288         else:
       
   289             return (CONFIG_H_NOTOK, "'%s' does not mention '__GNUC__'" % fn)
       
   290 
       
   291 
       
   292 def get_versions():
       
   293     """ Try to find out the versions of gcc and ld.
       
   294         If not possible it returns None for it.
       
   295     """
       
   296     from distutils.version import StrictVersion
       
   297     from distutils.spawn import find_executable
       
   298     import re
       
   299 
       
   300     gcc_exe = find_executable('gcc')
       
   301     if gcc_exe:
       
   302         out = os.popen(gcc_exe + ' -dumpversion','r')
       
   303         out_string = out.read()
       
   304         out.close()
       
   305         result = re.search('(\d+\.\d+\.\d+)',out_string)
       
   306         if result:
       
   307             gcc_version = StrictVersion(result.group(1))
       
   308         else:
       
   309             gcc_version = None
       
   310     else:
       
   311         gcc_version = None
       
   312     # EMX ld has no way of reporting version number, and we use GCC
       
   313     # anyway - so we can link OMF DLLs
       
   314     ld_version = None
       
   315     return (gcc_version, ld_version)