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