home *** CD-ROM | disk | FTP | other *** search
/ Freelog 125 / Freelog_MarsAvril2015_No125.iso / Bureautique / LibreOffice / LibreOffice_4.3.5_Win_x86.msi / cygwinccompiler.py < prev    next >
Text File  |  2014-12-12  |  17KB  |  406 lines

  1. """distutils.cygwinccompiler
  2.  
  3. Provides the CygwinCCompiler class, a subclass of UnixCCompiler that
  4. handles the Cygwin port of the GNU C compiler to Windows.  It also contains
  5. the Mingw32CCompiler class which handles the mingw32 port of GCC (same as
  6. cygwin in no-cygwin mode).
  7. """
  8.  
  9. # problems:
  10. #
  11. # * if you use a msvc compiled python version (1.5.2)
  12. #   1. you have to insert a __GNUC__ section in its config.h
  13. #   2. you have to generate a import library for its dll
  14. #      - create a def-file for python??.dll
  15. #      - create a import library using
  16. #             dlltool --dllname python15.dll --def python15.def \
  17. #                       --output-lib libpython15.a
  18. #
  19. #   see also http://starship.python.net/crew/kernr/mingw32/Notes.html
  20. #
  21. # * We put export_symbols in a def-file, and don't use
  22. #   --export-all-symbols because it doesn't worked reliable in some
  23. #   tested configurations. And because other windows compilers also
  24. #   need their symbols specified this no serious problem.
  25. #
  26. # tested configurations:
  27. #
  28. # * cygwin gcc 2.91.57/ld 2.9.4/dllwrap 0.2.4 works
  29. #   (after patching python's config.h and for C++ some other include files)
  30. #   see also http://starship.python.net/crew/kernr/mingw32/Notes.html
  31. # * mingw32 gcc 2.95.2/ld 2.9.4/dllwrap 0.2.4 works
  32. #   (ld doesn't support -shared, so we use dllwrap)
  33. # * cygwin gcc 2.95.2/ld 2.10.90/dllwrap 2.10.90 works now
  34. #   - its dllwrap doesn't work, there is a bug in binutils 2.10.90
  35. #     see also http://sources.redhat.com/ml/cygwin/2000-06/msg01274.html
  36. #   - using gcc -mdll instead dllwrap doesn't work without -static because
  37. #     it tries to link against dlls instead their import libraries. (If
  38. #     it finds the dll first.)
  39. #     By specifying -static we force ld to link against the import libraries,
  40. #     this is windows standard and there are normally not the necessary symbols
  41. #     in the dlls.
  42. #   *** only the version of June 2000 shows these problems
  43. # * cygwin gcc 3.2/ld 2.13.90 works
  44. #   (ld supports -shared)
  45. # * mingw gcc 3.2/ld 2.13 works
  46. #   (ld supports -shared)
  47.  
  48. import os
  49. import sys
  50. import copy
  51. from subprocess import Popen, PIPE, check_output
  52. import re
  53.  
  54. from distutils.ccompiler import gen_preprocess_options, gen_lib_options
  55. from distutils.unixccompiler import UnixCCompiler
  56. from distutils.file_util import write_file
  57. from distutils.errors import DistutilsExecError, CompileError, UnknownFileError
  58. from distutils import log
  59. from distutils.version import LooseVersion
  60. from distutils.spawn import find_executable
  61.  
  62. def get_msvcr():
  63.     """Include the appropriate MSVC runtime library if Python was built
  64.     with MSVC 7.0 or later.
  65.     """
  66.     msc_pos = sys.version.find('MSC v.')
  67.     if msc_pos != -1:
  68.         msc_ver = sys.version[msc_pos+6:msc_pos+10]
  69.         if msc_ver == '1300':
  70.             # MSVC 7.0
  71.             return ['msvcr70']
  72.         elif msc_ver == '1310':
  73.             # MSVC 7.1
  74.             return ['msvcr71']
  75.         elif msc_ver == '1400':
  76.             # VS2005 / MSVC 8.0
  77.             return ['msvcr80']
  78.         elif msc_ver == '1500':
  79.             # VS2008 / MSVC 9.0
  80.             return ['msvcr90']
  81.         elif msc_ver == '1600':
  82.             # VS2010 / MSVC 10.0
  83.             return ['msvcr100']
  84.         else:
  85.             raise ValueError("Unknown MS Compiler version %s " % msc_ver)
  86.  
  87.  
  88. class CygwinCCompiler(UnixCCompiler):
  89.     """ Handles the Cygwin port of the GNU C compiler to Windows.
  90.     """
  91.     compiler_type = 'cygwin'
  92.     obj_extension = ".o"
  93.     static_lib_extension = ".a"
  94.     shared_lib_extension = ".dll"
  95.     static_lib_format = "lib%s%s"
  96.     shared_lib_format = "%s%s"
  97.     exe_extension = ".exe"
  98.  
  99.     def __init__(self, verbose=0, dry_run=0, force=0):
  100.  
  101.         UnixCCompiler.__init__(self, verbose, dry_run, force)
  102.  
  103.         status, details = check_config_h()
  104.         self.debug_print("Python's GCC status: %s (details: %s)" %
  105.                          (status, details))
  106.         if status is not CONFIG_H_OK:
  107.             self.warn(
  108.                 "Python's pyconfig.h doesn't seem to support your compiler. "
  109.                 "Reason: %s. "
  110.                 "Compiling may fail because of undefined preprocessor macros."
  111.                 % details)
  112.  
  113.         self.gcc_version, self.ld_version, self.dllwrap_version = \
  114.             get_versions()
  115.         self.debug_print(self.compiler_type + ": gcc %s, ld %s, dllwrap %s\n" %
  116.                          (self.gcc_version,
  117.                           self.ld_version,
  118.                           self.dllwrap_version) )
  119.  
  120.         # ld_version >= "2.10.90" and < "2.13" should also be able to use
  121.         # gcc -mdll instead of dllwrap
  122.         # Older dllwraps had own version numbers, newer ones use the
  123.         # same as the rest of binutils ( also ld )
  124.         # dllwrap 2.10.90 is buggy
  125.         if self.ld_version >= "2.10.90":
  126.             self.linker_dll = "gcc"
  127.         else:
  128.             self.linker_dll = "dllwrap"
  129.  
  130.         # ld_version >= "2.13" support -shared so use it instead of
  131.         # -mdll -static
  132.         if self.ld_version >= "2.13":
  133.             shared_option = "-shared"
  134.         else:
  135.             shared_option = "-mdll -static"
  136.  
  137.         # Hard-code GCC because that's what this is all about.
  138.         # XXX optimization, warnings etc. should be customizable.
  139.         self.set_executables(compiler='gcc -mcygwin -O -Wall',
  140.                              compiler_so='gcc -mcygwin -mdll -O -Wall',
  141.                              compiler_cxx='g++ -mcygwin -O -Wall',
  142.                              linker_exe='gcc -mcygwin',
  143.                              linker_so=('%s -mcygwin %s' %
  144.                                         (self.linker_dll, shared_option)))
  145.  
  146.         # cygwin and mingw32 need different sets of libraries
  147.         if self.gcc_version == "2.91.57":
  148.             # cygwin shouldn't need msvcrt, but without the dlls will crash
  149.             # (gcc version 2.91.57) -- perhaps something about initialization
  150.             self.dll_libraries=["msvcrt"]
  151.             self.warn(
  152.                 "Consider upgrading to a newer version of gcc")
  153.         else:
  154.             # Include the appropriate MSVC runtime library if Python was built
  155.             # with MSVC 7.0 or later.
  156.             self.dll_libraries = get_msvcr()
  157.  
  158.     def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
  159.         """Compiles the source by spawning GCC and windres if needed."""
  160.         if ext == '.rc' or ext == '.res':
  161.             # gcc needs '.res' and '.rc' compiled to object files !!!
  162.             try:
  163.                 self.spawn(["windres", "-i", src, "-o", obj])
  164.             except DistutilsExecError as msg:
  165.                 raise CompileError(msg)
  166.         else: # for other files use the C-compiler
  167.             try:
  168.                 self.spawn(self.compiler_so + cc_args + [src, '-o', obj] +
  169.                            extra_postargs)
  170.             except DistutilsExecError as msg:
  171.                 raise CompileError(msg)
  172.  
  173.     def link(self, target_desc, objects, output_filename, output_dir=None,
  174.              libraries=None, library_dirs=None, runtime_library_dirs=None,
  175.              export_symbols=None, debug=0, extra_preargs=None,
  176.              extra_postargs=None, build_temp=None, target_lang=None):
  177.         """Link the objects."""
  178.         # use separate copies, so we can modify the lists
  179.         extra_preargs = copy.copy(extra_preargs or [])
  180.         libraries = copy.copy(libraries or [])
  181.         objects = copy.copy(objects or [])
  182.  
  183.         # Additional libraries
  184.         libraries.extend(self.dll_libraries)
  185.  
  186.         # handle export symbols by creating a def-file
  187.         # with executables this only works with gcc/ld as linker
  188.         if ((export_symbols is not None) and
  189.             (target_desc != self.EXECUTABLE or self.linker_dll == "gcc")):
  190.             # (The linker doesn't do anything if output is up-to-date.
  191.             # So it would probably better to check if we really need this,
  192.             # but for this we had to insert some unchanged parts of
  193.             # UnixCCompiler, and this is not what we want.)
  194.  
  195.             # we want to put some files in the same directory as the
  196.             # object files are, build_temp doesn't help much
  197.             # where are the object files
  198.             temp_dir = os.path.dirname(objects[0])
  199.             # name of dll to give the helper files the same base name
  200.             (dll_name, dll_extension) = os.path.splitext(
  201.                 os.path.basename(output_filename))
  202.  
  203.             # generate the filenames for these files
  204.             def_file = os.path.join(temp_dir, dll_name + ".def")
  205.             lib_file = os.path.join(temp_dir, 'lib' + dll_name + ".a")
  206.  
  207.             # Generate .def file
  208.             contents = [
  209.                 "LIBRARY %s" % os.path.basename(output_filename),
  210.                 "EXPORTS"]
  211.             for sym in export_symbols:
  212.                 contents.append(sym)
  213.             self.execute(write_file, (def_file, contents),
  214.                          "writing %s" % def_file)
  215.  
  216.             # next add options for def-file and to creating import libraries
  217.  
  218.             # dllwrap uses different options than gcc/ld
  219.             if self.linker_dll == "dllwrap":
  220.                 extra_preargs.extend(["--output-lib", lib_file])
  221.                 # for dllwrap we have to use a special option
  222.                 extra_preargs.extend(["--def", def_file])
  223.             # we use gcc/ld here and can be sure ld is >= 2.9.10
  224.             else:
  225.                 # doesn't work: bfd_close build\...\libfoo.a: Invalid operation
  226.                 #extra_preargs.extend(["-Wl,--out-implib,%s" % lib_file])
  227.                 # for gcc/ld the def-file is specified as any object files
  228.                 objects.append(def_file)
  229.  
  230.         #end: if ((export_symbols is not None) and
  231.         #        (target_desc != self.EXECUTABLE or self.linker_dll == "gcc")):
  232.  
  233.         # who wants symbols and a many times larger output file
  234.         # should explicitly switch the debug mode on
  235.         # otherwise we let dllwrap/ld strip the output file
  236.         # (On my machine: 10KB < stripped_file < ??100KB
  237.         #   unstripped_file = stripped_file + XXX KB
  238.         #  ( XXX=254 for a typical python extension))
  239.         if not debug:
  240.             extra_preargs.append("-s")
  241.  
  242.         UnixCCompiler.link(self, target_desc, objects, output_filename,
  243.                            output_dir, libraries, library_dirs,
  244.                            runtime_library_dirs,
  245.                            None, # export_symbols, we do this in our def-file
  246.                            debug, extra_preargs, extra_postargs, build_temp,
  247.                            target_lang)
  248.  
  249.     # -- Miscellaneous methods -----------------------------------------
  250.  
  251.     def object_filenames(self, source_filenames, strip_dir=0, output_dir=''):
  252.         """Adds supports for rc and res files."""
  253.         if output_dir is None:
  254.             output_dir = ''
  255.         obj_names = []
  256.         for src_name in source_filenames:
  257.             # use normcase to make sure '.rc' is really '.rc' and not '.RC'
  258.             base, ext = os.path.splitext(os.path.normcase(src_name))
  259.             if ext not in (self.src_extensions + ['.rc','.res']):
  260.                 raise UnknownFileError("unknown file type '%s' (from '%s')" % \
  261.                       (ext, src_name))
  262.             if strip_dir:
  263.                 base = os.path.basename (base)
  264.             if ext in ('.res', '.rc'):
  265.                 # these need to be compiled to object files
  266.                 obj_names.append (os.path.join(output_dir,
  267.                                               base + ext + self.obj_extension))
  268.             else:
  269.                 obj_names.append (os.path.join(output_dir,
  270.                                                base + self.obj_extension))
  271.         return obj_names
  272.  
  273. # the same as cygwin plus some additional parameters
  274. class Mingw32CCompiler(CygwinCCompiler):
  275.     """ Handles the Mingw32 port of the GNU C compiler to Windows.
  276.     """
  277.     compiler_type = 'mingw32'
  278.  
  279.     def __init__(self, verbose=0, dry_run=0, force=0):
  280.  
  281.         CygwinCCompiler.__init__ (self, verbose, dry_run, force)
  282.  
  283.         # ld_version >= "2.13" support -shared so use it instead of
  284.         # -mdll -static
  285.         if self.ld_version >= "2.13":
  286.             shared_option = "-shared"
  287.         else:
  288.             shared_option = "-mdll -static"
  289.  
  290.         # A real mingw32 doesn't need to specify a different entry point,
  291.         # but cygwin 2.91.57 in no-cygwin-mode needs it.
  292.         if self.gcc_version <= "2.91.57":
  293.             entry_point = '--entry _DllMain@12'
  294.         else:
  295.             entry_point = ''
  296.  
  297.         if self.gcc_version < '4' or is_cygwingcc():
  298.             no_cygwin = ' -mno-cygwin'
  299.         else:
  300.             no_cygwin = ''
  301.  
  302.         self.set_executables(compiler='gcc%s -O -Wall' % no_cygwin,
  303.                              compiler_so='gcc%s -mdll -O -Wall' % no_cygwin,
  304.                              compiler_cxx='g++%s -O -Wall' % no_cygwin,
  305.                              linker_exe='gcc%s' % no_cygwin,
  306.                              linker_so='%s%s %s %s'
  307.                                     % (self.linker_dll, no_cygwin,
  308.                                        shared_option, entry_point))
  309.         # Maybe we should also append -mthreads, but then the finished
  310.         # dlls need another dll (mingwm10.dll see Mingw32 docs)
  311.         # (-mthreads: Support thread-safe exception handling on `Mingw32')
  312.  
  313.         # no additional libraries needed
  314.         self.dll_libraries=[]
  315.  
  316.         # Include the appropriate MSVC runtime library if Python was built
  317.         # with MSVC 7.0 or later.
  318.         self.dll_libraries = get_msvcr()
  319.  
  320. # Because these compilers aren't configured in Python's pyconfig.h file by
  321. # default, we should at least warn the user if he is using a unmodified
  322. # version.
  323.  
  324. CONFIG_H_OK = "ok"
  325. CONFIG_H_NOTOK = "not ok"
  326. CONFIG_H_UNCERTAIN = "uncertain"
  327.  
  328. def check_config_h():
  329.     """Check if the current Python installation appears amenable to building
  330.     extensions with GCC.
  331.  
  332.     Returns a tuple (status, details), where 'status' is one of the following
  333.     constants:
  334.  
  335.     - CONFIG_H_OK: all is well, go ahead and compile
  336.     - CONFIG_H_NOTOK: doesn't look good
  337.     - CONFIG_H_UNCERTAIN: not sure -- unable to read pyconfig.h
  338.  
  339.     'details' is a human-readable string explaining the situation.
  340.  
  341.     Note there are two ways to conclude "OK": either 'sys.version' contains
  342.     the string "GCC" (implying that this Python was built with GCC), or the
  343.     installed "pyconfig.h" contains the string "__GNUC__".
  344.     """
  345.  
  346.     # XXX since this function also checks sys.version, it's not strictly a
  347.     # "pyconfig.h" check -- should probably be renamed...
  348.  
  349.     from distutils import sysconfig
  350.  
  351.     # if sys.version contains GCC then python was compiled with GCC, and the
  352.     # pyconfig.h file should be OK
  353.     if "GCC" in sys.version:
  354.         return CONFIG_H_OK, "sys.version mentions 'GCC'"
  355.  
  356.     # let's see if __GNUC__ is mentioned in python.h
  357.     fn = sysconfig.get_config_h_filename()
  358.     try:
  359.         config_h = open(fn)
  360.         try:
  361.             if "__GNUC__" in config_h.read():
  362.                 return CONFIG_H_OK, "'%s' mentions '__GNUC__'" % fn
  363.             else:
  364.                 return CONFIG_H_NOTOK, "'%s' does not mention '__GNUC__'" % fn
  365.         finally:
  366.             config_h.close()
  367.     except IOError as exc:
  368.         return (CONFIG_H_UNCERTAIN,
  369.                 "couldn't read '%s': %s" % (fn, exc.strerror))
  370.  
  371. RE_VERSION = re.compile(b'(\d+\.\d+(\.\d+)*)')
  372.  
  373. def _find_exe_version(cmd):
  374.     """Find the version of an executable by running `cmd` in the shell.
  375.  
  376.     If the command is not found, or the output does not match
  377.     `RE_VERSION`, returns None.
  378.     """
  379.     executable = cmd.split()[0]
  380.     if find_executable(executable) is None:
  381.         return None
  382.     out = Popen(cmd, shell=True, stdout=PIPE).stdout
  383.     try:
  384.         out_string = out.read()
  385.     finally:
  386.         out.close()
  387.     result = RE_VERSION.search(out_string)
  388.     if result is None:
  389.         return None
  390.     # LooseVersion works with strings
  391.     # so we need to decode our bytes
  392.     return LooseVersion(result.group(1).decode())
  393.  
  394. def get_versions():
  395.     """ Try to find out the versions of gcc, ld and dllwrap.
  396.  
  397.     If not possible it returns None for it.
  398.     """
  399.     commands = ['gcc -dumpversion', 'ld -v', 'dllwrap --version']
  400.     return tuple([_find_exe_version(cmd) for cmd in commands])
  401.  
  402. def is_cygwingcc():
  403.     '''Try to determine if the gcc that would be used is from cygwin.'''
  404.     out_string = check_output(['gcc', '-dumpmachine'])
  405.     return out_string.strip().endswith(b'cygwin')
  406.