PyXR

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



0001 """distutils.cygwinccompiler
0002 
0003 Provides the CygwinCCompiler class, a subclass of UnixCCompiler that
0004 handles the Cygwin port of the GNU C compiler to Windows.  It also contains
0005 the Mingw32CCompiler class which handles the mingw32 port of GCC (same as
0006 cygwin in no-cygwin mode).
0007 """
0008 
0009 # problems:
0010 #
0011 # * if you use a msvc compiled python version (1.5.2)
0012 #   1. you have to insert a __GNUC__ section in its config.h
0013 #   2. you have to generate a import library for its dll
0014 #      - create a def-file for python??.dll
0015 #      - create a import library using
0016 #             dlltool --dllname python15.dll --def python15.def \
0017 #                       --output-lib libpython15.a
0018 #
0019 #   see also http://starship.python.net/crew/kernr/mingw32/Notes.html
0020 #
0021 # * We put export_symbols in a def-file, and don't use
0022 #   --export-all-symbols because it doesn't worked reliable in some
0023 #   tested configurations. And because other windows compilers also
0024 #   need their symbols specified this no serious problem.
0025 #
0026 # tested configurations:
0027 #
0028 # * cygwin gcc 2.91.57/ld 2.9.4/dllwrap 0.2.4 works
0029 #   (after patching python's config.h and for C++ some other include files)
0030 #   see also http://starship.python.net/crew/kernr/mingw32/Notes.html
0031 # * mingw32 gcc 2.95.2/ld 2.9.4/dllwrap 0.2.4 works
0032 #   (ld doesn't support -shared, so we use dllwrap)
0033 # * cygwin gcc 2.95.2/ld 2.10.90/dllwrap 2.10.90 works now
0034 #   - its dllwrap doesn't work, there is a bug in binutils 2.10.90
0035 #     see also http://sources.redhat.com/ml/cygwin/2000-06/msg01274.html
0036 #   - using gcc -mdll instead dllwrap doesn't work without -static because
0037 #     it tries to link against dlls instead their import libraries. (If
0038 #     it finds the dll first.)
0039 #     By specifying -static we force ld to link against the import libraries,
0040 #     this is windows standard and there are normally not the necessary symbols
0041 #     in the dlls.
0042 #   *** only the version of June 2000 shows these problems
0043 # * cygwin gcc 3.2/ld 2.13.90 works
0044 #   (ld supports -shared)
0045 # * mingw gcc 3.2/ld 2.13 works
0046 #   (ld supports -shared)
0047 
0048 # This module should be kept compatible with Python 1.5.2.
0049 
0050 __revision__ = "$Id: cygwinccompiler.py,v 1.28 2004/08/04 02:36:18 tim_one Exp $"
0051 
0052 import os,sys,copy
0053 from distutils.ccompiler import gen_preprocess_options, gen_lib_options
0054 from distutils.unixccompiler import UnixCCompiler
0055 from distutils.file_util import write_file
0056 from distutils.errors import DistutilsExecError, CompileError, UnknownFileError
0057 from distutils import log
0058 
0059 class CygwinCCompiler (UnixCCompiler):
0060 
0061     compiler_type = 'cygwin'
0062     obj_extension = ".o"
0063     static_lib_extension = ".a"
0064     shared_lib_extension = ".dll"
0065     static_lib_format = "lib%s%s"
0066     shared_lib_format = "%s%s"
0067     exe_extension = ".exe"
0068 
0069     def __init__ (self, verbose=0, dry_run=0, force=0):
0070 
0071         UnixCCompiler.__init__ (self, verbose, dry_run, force)
0072 
0073         (status, details) = check_config_h()
0074         self.debug_print("Python's GCC status: %s (details: %s)" %
0075                          (status, details))
0076         if status is not CONFIG_H_OK:
0077             self.warn(
0078                 "Python's pyconfig.h doesn't seem to support your compiler. "
0079                 "Reason: %s. "
0080                 "Compiling may fail because of undefined preprocessor macros."
0081                 % details)
0082 
0083         self.gcc_version, self.ld_version, self.dllwrap_version = \
0084             get_versions()
0085         self.debug_print(self.compiler_type + ": gcc %s, ld %s, dllwrap %s\n" %
0086                          (self.gcc_version,
0087                           self.ld_version,
0088                           self.dllwrap_version) )
0089 
0090         # ld_version >= "2.10.90" and < "2.13" should also be able to use
0091         # gcc -mdll instead of dllwrap
0092         # Older dllwraps had own version numbers, newer ones use the
0093         # same as the rest of binutils ( also ld )
0094         # dllwrap 2.10.90 is buggy
0095         if self.ld_version >= "2.10.90":
0096             self.linker_dll = "gcc"
0097         else:
0098             self.linker_dll = "dllwrap"
0099 
0100         # ld_version >= "2.13" support -shared so use it instead of
0101         # -mdll -static
0102         if self.ld_version >= "2.13":
0103             shared_option = "-shared"
0104         else:
0105             shared_option = "-mdll -static"
0106 
0107         # Hard-code GCC because that's what this is all about.
0108         # XXX optimization, warnings etc. should be customizable.
0109         self.set_executables(compiler='gcc -mcygwin -O -Wall',
0110                              compiler_so='gcc -mcygwin -mdll -O -Wall',
0111                              compiler_cxx='g++ -mcygwin -O -Wall',
0112                              linker_exe='gcc -mcygwin',
0113                              linker_so=('%s -mcygwin %s' %
0114                                         (self.linker_dll, shared_option)))
0115 
0116         # cygwin and mingw32 need different sets of libraries
0117         if self.gcc_version == "2.91.57":
0118             # cygwin shouldn't need msvcrt, but without the dlls will crash
0119             # (gcc version 2.91.57) -- perhaps something about initialization
0120             self.dll_libraries=["msvcrt"]
0121             self.warn(
0122                 "Consider upgrading to a newer version of gcc")
0123         else:
0124             self.dll_libraries=[]
0125             # Include the appropriate MSVC runtime library if Python was built
0126             # with MSVC 7.0 or 7.1.
0127             msc_pos = sys.version.find('MSC v.')
0128             if msc_pos != -1:
0129                 msc_ver = sys.version[msc_pos+6:msc_pos+10]
0130                 if msc_ver == '1300':
0131                     # MSVC 7.0
0132                     self.dll_libraries = ['msvcr70']
0133                 elif msc_ver == '1310':
0134                     # MSVC 7.1
0135                     self.dll_libraries = ['msvcr71']
0136 
0137     # __init__ ()
0138 
0139 
0140     def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
0141         if ext == '.rc' or ext == '.res':
0142             # gcc needs '.res' and '.rc' compiled to object files !!!
0143             try:
0144                 self.spawn(["windres", "-i", src, "-o", obj])
0145             except DistutilsExecError, msg:
0146                 raise CompileError, msg
0147         else: # for other files use the C-compiler
0148             try:
0149                 self.spawn(self.compiler_so + cc_args + [src, '-o', obj] +
0150                            extra_postargs)
0151             except DistutilsExecError, msg:
0152                 raise CompileError, msg
0153 
0154     def link (self,
0155               target_desc,
0156               objects,
0157               output_filename,
0158               output_dir=None,
0159               libraries=None,
0160               library_dirs=None,
0161               runtime_library_dirs=None,
0162               export_symbols=None,
0163               debug=0,
0164               extra_preargs=None,
0165               extra_postargs=None,
0166               build_temp=None,
0167               target_lang=None):
0168 
0169         # use separate copies, so we can modify the lists
0170         extra_preargs = copy.copy(extra_preargs or [])
0171         libraries = copy.copy(libraries or [])
0172         objects = copy.copy(objects or [])
0173 
0174         # Additional libraries
0175         libraries.extend(self.dll_libraries)
0176 
0177         # handle export symbols by creating a def-file
0178         # with executables this only works with gcc/ld as linker
0179         if ((export_symbols is not None) and
0180             (target_desc != self.EXECUTABLE or self.linker_dll == "gcc")):
0181             # (The linker doesn't do anything if output is up-to-date.
0182             # So it would probably better to check if we really need this,
0183             # but for this we had to insert some unchanged parts of
0184             # UnixCCompiler, and this is not what we want.)
0185 
0186             # we want to put some files in the same directory as the
0187             # object files are, build_temp doesn't help much
0188             # where are the object files
0189             temp_dir = os.path.dirname(objects[0])
0190             # name of dll to give the helper files the same base name
0191             (dll_name, dll_extension) = os.path.splitext(
0192                 os.path.basename(output_filename))
0193 
0194             # generate the filenames for these files
0195             def_file = os.path.join(temp_dir, dll_name + ".def")
0196             lib_file = os.path.join(temp_dir, 'lib' + dll_name + ".a")
0197 
0198             # Generate .def file
0199             contents = [
0200                 "LIBRARY %s" % os.path.basename(output_filename),
0201                 "EXPORTS"]
0202             for sym in export_symbols:
0203                 contents.append(sym)
0204             self.execute(write_file, (def_file, contents),
0205                          "writing %s" % def_file)
0206 
0207             # next add options for def-file and to creating import libraries
0208 
0209             # dllwrap uses different options than gcc/ld
0210             if self.linker_dll == "dllwrap":
0211                 extra_preargs.extend(["--output-lib", lib_file])
0212                 # for dllwrap we have to use a special option
0213                 extra_preargs.extend(["--def", def_file])
0214             # we use gcc/ld here and can be sure ld is >= 2.9.10
0215             else:
0216                 # doesn't work: bfd_close build\...\libfoo.a: Invalid operation
0217                 #extra_preargs.extend(["-Wl,--out-implib,%s" % lib_file])
0218                 # for gcc/ld the def-file is specified as any object files
0219                 objects.append(def_file)
0220 
0221         #end: if ((export_symbols is not None) and
0222         #        (target_desc != self.EXECUTABLE or self.linker_dll == "gcc")):
0223 
0224         # who wants symbols and a many times larger output file
0225         # should explicitly switch the debug mode on
0226         # otherwise we let dllwrap/ld strip the output file
0227         # (On my machine: 10KB < stripped_file < ??100KB
0228         #   unstripped_file = stripped_file + XXX KB
0229         #  ( XXX=254 for a typical python extension))
0230         if not debug:
0231             extra_preargs.append("-s")
0232 
0233         UnixCCompiler.link(self,
0234                            target_desc,
0235                            objects,
0236                            output_filename,
0237                            output_dir,
0238                            libraries,
0239                            library_dirs,
0240                            runtime_library_dirs,
0241                            None, # export_symbols, we do this in our def-file
0242                            debug,
0243                            extra_preargs,
0244                            extra_postargs,
0245                            build_temp,
0246                            target_lang)
0247 
0248     # link ()
0249 
0250     # -- Miscellaneous methods -----------------------------------------
0251 
0252     # overwrite the one from CCompiler to support rc and res-files
0253     def object_filenames (self,
0254                           source_filenames,
0255                           strip_dir=0,
0256                           output_dir=''):
0257         if output_dir is None: output_dir = ''
0258         obj_names = []
0259         for src_name in source_filenames:
0260             # use normcase to make sure '.rc' is really '.rc' and not '.RC'
0261             (base, ext) = os.path.splitext (os.path.normcase(src_name))
0262             if ext not in (self.src_extensions + ['.rc','.res']):
0263                 raise UnknownFileError, \
0264                       "unknown file type '%s' (from '%s')" % \
0265                       (ext, src_name)
0266             if strip_dir:
0267                 base = os.path.basename (base)
0268             if ext == '.res' or ext == '.rc':
0269                 # these need to be compiled to object files
0270                 obj_names.append (os.path.join (output_dir,
0271                                             base + ext + self.obj_extension))
0272             else:
0273                 obj_names.append (os.path.join (output_dir,
0274                                             base + self.obj_extension))
0275         return obj_names
0276 
0277     # object_filenames ()
0278 
0279 # class CygwinCCompiler
0280 
0281 
0282 # the same as cygwin plus some additional parameters
0283 class Mingw32CCompiler (CygwinCCompiler):
0284 
0285     compiler_type = 'mingw32'
0286 
0287     def __init__ (self,
0288                   verbose=0,
0289                   dry_run=0,
0290                   force=0):
0291 
0292         CygwinCCompiler.__init__ (self, verbose, dry_run, force)
0293 
0294         # ld_version >= "2.13" support -shared so use it instead of
0295         # -mdll -static
0296         if self.ld_version >= "2.13":
0297             shared_option = "-shared"
0298         else:
0299             shared_option = "-mdll -static"
0300 
0301         # A real mingw32 doesn't need to specify a different entry point,
0302         # but cygwin 2.91.57 in no-cygwin-mode needs it.
0303         if self.gcc_version <= "2.91.57":
0304             entry_point = '--entry _DllMain@12'
0305         else:
0306             entry_point = ''
0307 
0308         self.set_executables(compiler='gcc -mno-cygwin -O -Wall',
0309                              compiler_so='gcc -mno-cygwin -mdll -O -Wall',
0310                              compiler_cxx='g++ -mno-cygwin -O -Wall',
0311                              linker_exe='gcc -mno-cygwin',
0312                              linker_so='%s -mno-cygwin %s %s'
0313                                         % (self.linker_dll, shared_option,
0314                                            entry_point))
0315         # Maybe we should also append -mthreads, but then the finished
0316         # dlls need another dll (mingwm10.dll see Mingw32 docs)
0317         # (-mthreads: Support thread-safe exception handling on `Mingw32')
0318 
0319         # no additional libraries needed
0320         self.dll_libraries=[]
0321 
0322         # Include the appropriate MSVC runtime library if Python was built
0323         # with MSVC 7.0 or 7.1.
0324         msc_pos = sys.version.find('MSC v.')
0325         if msc_pos != -1:
0326             msc_ver = sys.version[msc_pos+6:msc_pos+10]
0327             if msc_ver == '1300':
0328                 # MSVC 7.0
0329                 self.dll_libraries = ['msvcr70']
0330             elif msc_ver == '1310':
0331                 # MSVC 7.1
0332                 self.dll_libraries = ['msvcr71']
0333 
0334     # __init__ ()
0335 
0336 # class Mingw32CCompiler
0337 
0338 # Because these compilers aren't configured in Python's pyconfig.h file by
0339 # default, we should at least warn the user if he is using a unmodified
0340 # version.
0341 
0342 CONFIG_H_OK = "ok"
0343 CONFIG_H_NOTOK = "not ok"
0344 CONFIG_H_UNCERTAIN = "uncertain"
0345 
0346 def check_config_h():
0347 
0348     """Check if the current Python installation (specifically, pyconfig.h)
0349     appears amenable to building extensions with GCC.  Returns a tuple
0350     (status, details), where 'status' is one of the following constants:
0351       CONFIG_H_OK
0352         all is well, go ahead and compile
0353       CONFIG_H_NOTOK
0354         doesn't look good
0355       CONFIG_H_UNCERTAIN
0356         not sure -- unable to read pyconfig.h
0357     'details' is a human-readable string explaining the situation.
0358 
0359     Note there are two ways to conclude "OK": either 'sys.version' contains
0360     the string "GCC" (implying that this Python was built with GCC), or the
0361     installed "pyconfig.h" contains the string "__GNUC__".
0362     """
0363 
0364     # XXX since this function also checks sys.version, it's not strictly a
0365     # "pyconfig.h" check -- should probably be renamed...
0366 
0367     from distutils import sysconfig
0368     import string
0369     # if sys.version contains GCC then python was compiled with
0370     # GCC, and the pyconfig.h file should be OK
0371     if string.find(sys.version,"GCC") >= 0:
0372         return (CONFIG_H_OK, "sys.version mentions 'GCC'")
0373 
0374     fn = sysconfig.get_config_h_filename()
0375     try:
0376         # It would probably better to read single lines to search.
0377         # But we do this only once, and it is fast enough
0378         f = open(fn)
0379         s = f.read()
0380         f.close()
0381 
0382     except IOError, exc:
0383         # if we can't read this file, we cannot say it is wrong
0384         # the compiler will complain later about this file as missing
0385         return (CONFIG_H_UNCERTAIN,
0386                 "couldn't read '%s': %s" % (fn, exc.strerror))
0387 
0388     else:
0389         # "pyconfig.h" contains an "#ifdef __GNUC__" or something similar
0390         if string.find(s,"__GNUC__") >= 0:
0391             return (CONFIG_H_OK, "'%s' mentions '__GNUC__'" % fn)
0392         else:
0393             return (CONFIG_H_NOTOK, "'%s' does not mention '__GNUC__'" % fn)
0394 
0395 
0396 
0397 def get_versions():
0398     """ Try to find out the versions of gcc, ld and dllwrap.
0399         If not possible it returns None for it.
0400     """
0401     from distutils.version import StrictVersion
0402     from distutils.spawn import find_executable
0403     import re
0404 
0405     gcc_exe = find_executable('gcc')
0406     if gcc_exe:
0407         out = os.popen(gcc_exe + ' -dumpversion','r')
0408         out_string = out.read()
0409         out.close()
0410         result = re.search('(\d+\.\d+(\.\d+)*)',out_string)
0411         if result:
0412             gcc_version = StrictVersion(result.group(1))
0413         else:
0414             gcc_version = None
0415     else:
0416         gcc_version = None
0417     ld_exe = find_executable('ld')
0418     if ld_exe:
0419         out = os.popen(ld_exe + ' -v','r')
0420         out_string = out.read()
0421         out.close()
0422         result = re.search('(\d+\.\d+(\.\d+)*)',out_string)
0423         if result:
0424             ld_version = StrictVersion(result.group(1))
0425         else:
0426             ld_version = None
0427     else:
0428         ld_version = None
0429     dllwrap_exe = find_executable('dllwrap')
0430     if dllwrap_exe:
0431         out = os.popen(dllwrap_exe + ' --version','r')
0432         out_string = out.read()
0433         out.close()
0434         result = re.search(' (\d+\.\d+(\.\d+)*)',out_string)
0435         if result:
0436             dllwrap_version = StrictVersion(result.group(1))
0437         else:
0438             dllwrap_version = None
0439     else:
0440         dllwrap_version = None
0441     return (gcc_version, ld_version, dllwrap_version)
0442 

Generated by PyXR 0.9.4
SourceForge.net Logo