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