1 """distutils.cygwinccompiler
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).
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
19 # see also http://starship.python.net/crew/kernr/mingw32/Notes.html
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.
26 # tested configurations:
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
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)
54 from warnings
import warn
56 from distutils
.unixccompiler
import UnixCCompiler
57 from distutils
.file_util
import write_file
58 from distutils
.errors
import DistutilsExecError
, CompileError
, UnknownFileError
59 from distutils
.util
import get_compiler_versions
62 """Include the appropriate MSVC runtime library if Python was built
63 with MSVC 7.0 or later.
65 msc_pos
= sys
.version
.find('MSC v.')
67 msc_ver
= sys
.version
[msc_pos
+6:msc_pos
+10]
71 elif msc_ver
== '1310':
74 elif msc_ver
== '1400':
77 elif msc_ver
== '1500':
81 raise ValueError("Unknown MS Compiler version %s " % msc_ver
)
84 class CygwinCCompiler(UnixCCompiler
):
85 """ Handles the Cygwin port of the GNU C compiler to Windows.
87 compiler_type
= 'cygwin'
89 static_lib_extension
= ".a"
90 shared_lib_extension
= ".dll"
91 static_lib_format
= "lib%s%s"
92 shared_lib_format
= "%s%s"
93 exe_extension
= ".exe"
95 def __init__(self
, verbose
=0, dry_run
=0, force
=0):
97 UnixCCompiler
.__init
__(self
, verbose
, dry_run
, force
)
99 status
, details
= check_config_h()
100 self
.debug_print("Python's GCC status: %s (details: %s)" %
102 if status
is not CONFIG_H_OK
:
104 "Python's pyconfig.h doesn't seem to support your compiler. "
106 "Compiling may fail because of undefined preprocessor macros."
109 self
.gcc_version
, self
.ld_version
, self
.dllwrap_version
= \
110 get_compiler_versions()
111 self
.debug_print(self
.compiler_type
+ ": gcc %s, ld %s, dllwrap %s\n" %
114 self
.dllwrap_version
) )
116 # ld_version >= "2.10.90" and < "2.13" should also be able to use
117 # gcc -mdll instead of dllwrap
118 # Older dllwraps had own version numbers, newer ones use the
119 # same as the rest of binutils ( also ld )
120 # dllwrap 2.10.90 is buggy
121 if self
.ld_version
>= "2.10.90":
122 self
.linker_dll
= "gcc"
124 self
.linker_dll
= "dllwrap"
126 # ld_version >= "2.13" support -shared so use it instead of
128 if self
.ld_version
>= "2.13":
129 shared_option
= "-shared"
131 shared_option
= "-mdll -static"
133 # Hard-code GCC because that's what this is all about.
134 # XXX optimization, warnings etc. should be customizable.
135 self
.set_executables(compiler
='gcc -mcygwin -O -Wall',
136 compiler_so
='gcc -mcygwin -mdll -O -Wall',
137 compiler_cxx
='g++ -mcygwin -O -Wall',
138 linker_exe
='gcc -mcygwin',
139 linker_so
=('%s -mcygwin %s' %
140 (self
.linker_dll
, shared_option
)))
142 # cygwin and mingw32 need different sets of libraries
143 if self
.gcc_version
== "2.91.57":
144 # cygwin shouldn't need msvcrt, but without the dlls will crash
145 # (gcc version 2.91.57) -- perhaps something about initialization
146 self
.dll_libraries
=["msvcrt"]
148 "Consider upgrading to a newer version of gcc")
150 # Include the appropriate MSVC runtime library if Python was built
151 # with MSVC 7.0 or later.
152 self
.dll_libraries
= get_msvcr()
154 def _compile(self
, obj
, src
, ext
, cc_args
, extra_postargs
, pp_opts
):
155 """Compiles the source by spawing GCC and windres if needed."""
156 if ext
== '.rc' or ext
== '.res':
157 # gcc needs '.res' and '.rc' compiled to object files !!!
159 self
.spawn(["windres", "-i", src
, "-o", obj
])
160 except DistutilsExecError
, msg
:
161 raise CompileError
, msg
162 else: # for other files use the C-compiler
164 self
.spawn(self
.compiler_so
+ cc_args
+ [src
, '-o', obj
] +
166 except DistutilsExecError
, msg
:
167 raise CompileError
, msg
169 def link(self
, target_desc
, objects
, output_filename
, output_dir
=None,
170 libraries
=None, library_dirs
=None, runtime_library_dirs
=None,
171 export_symbols
=None, debug
=0, extra_preargs
=None,
172 extra_postargs
=None, build_temp
=None, target_lang
=None):
173 """Link the objects."""
174 # use separate copies, so we can modify the lists
175 extra_preargs
= copy
.copy(extra_preargs
or [])
176 libraries
= copy
.copy(libraries
or [])
177 objects
= copy
.copy(objects
or [])
179 # Additional libraries
180 libraries
.extend(self
.dll_libraries
)
182 # handle export symbols by creating a def-file
183 # with executables this only works with gcc/ld as linker
184 if ((export_symbols
is not None) and
185 (target_desc
!= self
.EXECUTABLE
or self
.linker_dll
== "gcc")):
186 # (The linker doesn't do anything if output is up-to-date.
187 # So it would probably better to check if we really need this,
188 # but for this we had to insert some unchanged parts of
189 # UnixCCompiler, and this is not what we want.)
191 # we want to put some files in the same directory as the
192 # object files are, build_temp doesn't help much
193 # where are the object files
194 temp_dir
= os
.path
.dirname(objects
[0])
195 # name of dll to give the helper files the same base name
196 (dll_name
, dll_extension
) = os
.path
.splitext(
197 os
.path
.basename(output_filename
))
199 # generate the filenames for these files
200 def_file
= os
.path
.join(temp_dir
, dll_name
+ ".def")
201 lib_file
= os
.path
.join(temp_dir
, 'lib' + dll_name
+ ".a")
205 "LIBRARY %s" % os
.path
.basename(output_filename
),
207 for sym
in export_symbols
:
209 self
.execute(write_file
, (def_file
, contents
),
210 "writing %s" % def_file
)
212 # next add options for def-file and to creating import libraries
214 # dllwrap uses different options than gcc/ld
215 if self
.linker_dll
== "dllwrap":
216 extra_preargs
.extend(["--output-lib", lib_file
])
217 # for dllwrap we have to use a special option
218 extra_preargs
.extend(["--def", def_file
])
219 # we use gcc/ld here and can be sure ld is >= 2.9.10
221 # doesn't work: bfd_close build\...\libfoo.a: Invalid operation
222 #extra_preargs.extend(["-Wl,--out-implib,%s" % lib_file])
223 # for gcc/ld the def-file is specified as any object files
224 objects
.append(def_file
)
226 #end: if ((export_symbols is not None) and
227 # (target_desc != self.EXECUTABLE or self.linker_dll == "gcc")):
229 # who wants symbols and a many times larger output file
230 # should explicitly switch the debug mode on
231 # otherwise we let dllwrap/ld strip the output file
232 # (On my machine: 10KB < stripped_file < ??100KB
233 # unstripped_file = stripped_file + XXX KB
234 # ( XXX=254 for a typical python extension))
236 extra_preargs
.append("-s")
238 UnixCCompiler
.link(self
, target_desc
, objects
, output_filename
,
239 output_dir
, libraries
, library_dirs
,
240 runtime_library_dirs
,
241 None, # export_symbols, we do this in our def-file
242 debug
, extra_preargs
, extra_postargs
, build_temp
,
245 # -- Miscellaneous methods -----------------------------------------
247 def object_filenames(self
, source_filenames
, strip_dir
=0, output_dir
=''):
248 """Adds supports for rc and res files."""
249 if output_dir
is None:
252 for src_name
in source_filenames
:
253 # use normcase to make sure '.rc' is really '.rc' and not '.RC'
254 base
, ext
= os
.path
.splitext(os
.path
.normcase(src_name
))
255 if ext
not in (self
.src_extensions
+ ['.rc','.res']):
256 raise UnknownFileError
, \
257 "unknown file type '%s' (from '%s')" % (ext
, src_name
)
259 base
= os
.path
.basename (base
)
260 if ext
in ('.res', '.rc'):
261 # these need to be compiled to object files
262 obj_names
.append (os
.path
.join(output_dir
,
263 base
+ ext
+ self
.obj_extension
))
265 obj_names
.append (os
.path
.join(output_dir
,
266 base
+ self
.obj_extension
))
269 # the same as cygwin plus some additional parameters
270 class Mingw32CCompiler(CygwinCCompiler
):
271 """ Handles the Mingw32 port of the GNU C compiler to Windows.
273 compiler_type
= 'mingw32'
275 def __init__(self
, verbose
=0, dry_run
=0, force
=0):
277 CygwinCCompiler
.__init
__ (self
, verbose
, dry_run
, force
)
279 # ld_version >= "2.13" support -shared so use it instead of
281 if self
.ld_version
>= "2.13":
282 shared_option
= "-shared"
284 shared_option
= "-mdll -static"
286 # A real mingw32 doesn't need to specify a different entry point,
287 # but cygwin 2.91.57 in no-cygwin-mode needs it.
288 if self
.gcc_version
<= "2.91.57":
289 entry_point
= '--entry _DllMain@12'
293 self
.set_executables(compiler
='gcc -mno-cygwin -O -Wall',
294 compiler_so
='gcc -mno-cygwin -mdll -O -Wall',
295 compiler_cxx
='g++ -mno-cygwin -O -Wall',
296 linker_exe
='gcc -mno-cygwin',
297 linker_so
='%s -mno-cygwin %s %s'
298 % (self
.linker_dll
, shared_option
,
300 # Maybe we should also append -mthreads, but then the finished
301 # dlls need another dll (mingwm10.dll see Mingw32 docs)
302 # (-mthreads: Support thread-safe exception handling on `Mingw32')
304 # no additional libraries needed
305 self
.dll_libraries
=[]
307 # Include the appropriate MSVC runtime library if Python was built
308 # with MSVC 7.0 or later.
309 self
.dll_libraries
= get_msvcr()
311 # Because these compilers aren't configured in Python's pyconfig.h file by
312 # default, we should at least warn the user if he is using a unmodified
316 CONFIG_H_NOTOK
= "not ok"
317 CONFIG_H_UNCERTAIN
= "uncertain"
319 def check_config_h():
320 """Check if the current Python installation appears amenable to building
323 Returns a tuple (status, details), where 'status' is one of the following
326 - CONFIG_H_OK: all is well, go ahead and compile
327 - CONFIG_H_NOTOK: doesn't look good
328 - CONFIG_H_UNCERTAIN: not sure -- unable to read pyconfig.h
330 'details' is a human-readable string explaining the situation.
332 Note there are two ways to conclude "OK": either 'sys.version' contains
333 the string "GCC" (implying that this Python was built with GCC), or the
334 installed "pyconfig.h" contains the string "__GNUC__".
337 # XXX since this function also checks sys.version, it's not strictly a
338 # "pyconfig.h" check -- should probably be renamed...
340 from distutils
import sysconfig
342 # if sys.version contains GCC then python was compiled with GCC, and the
343 # pyconfig.h file should be OK
344 if "GCC" in sys
.version
:
345 return CONFIG_H_OK
, "sys.version mentions 'GCC'"
347 # let's see if __GNUC__ is mentioned in python.h
348 fn
= sysconfig
.get_config_h_filename()
350 with
open(fn
) as config_h
:
351 if "__GNUC__" in config_h
.read():
352 return CONFIG_H_OK
, "'%s' mentions '__GNUC__'" % fn
354 return CONFIG_H_NOTOK
, "'%s' does not mention '__GNUC__'" % fn
356 return (CONFIG_H_UNCERTAIN
,
357 "couldn't read '%s': %s" % (fn
, exc
.strerror
))
359 class _Deprecated_SRE_Pattern(object):
360 def __init__(self
, pattern
):
361 self
.pattern
= pattern
363 def __getattr__(self
, name
):
364 if name
in ('findall', 'finditer', 'match', 'scanner', 'search',
365 'split', 'sub', 'subn'):
366 warn("'distutils.cygwinccompiler.RE_VERSION' is deprecated "
367 "and will be removed in the next version", DeprecationWarning)
368 return getattr(self
.pattern
, name
)
370 RE_VERSION
= _Deprecated_SRE_Pattern(re
.compile('(\d+\.\d+(\.\d+)*)'))
373 """ Try to find out the versions of gcc, ld and dllwrap.
375 If not possible it returns None for it.
377 warn("'distutils.cygwinccompiler.get_versions' is deprecated "
378 "use 'distutils.util.get_compiler_versions' instead",
381 return get_compiler_versions()