blob: 2ac2678e7390c6d07319712843a87bc4df24512d [file] [log] [blame]
Greg Ward7c6395a2000-06-21 03:33:03 +00001"""distutils.cygwinccompiler
2
Greg Wardf34506a2000-06-29 22:57:55 +00003Provides the CygwinCCompiler class, a subclass of UnixCCompiler that
4handles the Cygwin port of the GNU C compiler to Windows. It also contains
5the Mingw32CCompiler class which handles the mingw32 port of GCC (same as
6cygwin in no-cygwin mode).
Greg Ward7c6395a2000-06-21 03:33:03 +00007"""
8
Greg Wardbf5c7092000-08-02 01:31:56 +00009# 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 use 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 .....
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
Greg Ward7c6395a2000-06-21 03:33:03 +000043# created 2000/05/05, Rene Liebscher
44
45__revision__ = "$Id$"
46
Greg Wardb1dceae2000-08-13 00:43:56 +000047import os,sys,copy
Greg Ward7c6395a2000-06-21 03:33:03 +000048from distutils.unixccompiler import UnixCCompiler
Greg Wardbf5c7092000-08-02 01:31:56 +000049from distutils.file_util import write_file
Greg Ward7c6395a2000-06-21 03:33:03 +000050
Greg Ward7c6395a2000-06-21 03:33:03 +000051class CygwinCCompiler (UnixCCompiler):
52
53 compiler_type = 'cygwin'
Greg Wardb1dceae2000-08-13 00:43:56 +000054 obj_extension = ".o"
55 static_lib_extension = ".a"
56 shared_lib_extension = ".dll"
57 static_lib_format = "lib%s%s"
58 shared_lib_format = "%s%s"
59 exe_extension = ".exe"
Greg Ward7c6395a2000-06-21 03:33:03 +000060
61 def __init__ (self,
62 verbose=0,
63 dry_run=0,
64 force=0):
65
66 UnixCCompiler.__init__ (self, verbose, dry_run, force)
67
Greg Warde8e9d112000-08-13 01:18:55 +000068 (status, details) = check_config_h()
69 self.debug_print("Python's GCC status: %s (details: %s)" %
70 (status, details))
71 if status is not CONFIG_H_OK:
Greg Wardbf5c7092000-08-02 01:31:56 +000072 self.warn(
Greg Warde8e9d112000-08-13 01:18:55 +000073 "Python's config.h doesn't seem to support your compiler. " +
74 ("Reason: %s." % details) +
Greg Wardbf5c7092000-08-02 01:31:56 +000075 "Compiling may fail because of undefined preprocessor macros.")
76
77 (self.gcc_version, self.ld_version, self.dllwrap_version) = \
78 get_versions()
Greg Wardb1dceae2000-08-13 00:43:56 +000079 self.debug_print(self.compiler_type + ": gcc %s, ld %s, dllwrap %s\n" %
Greg Wardbf5c7092000-08-02 01:31:56 +000080 (self.gcc_version,
81 self.ld_version,
82 self.dllwrap_version) )
83
84 # ld_version >= "2.10.90" should also be able to use
85 # gcc -mdll instead of dllwrap
86 # Older dllwraps had own version numbers, newer ones use the
87 # same as the rest of binutils ( also ld )
88 # dllwrap 2.10.90 is buggy
89 if self.ld_version >= "2.10.90":
90 self.linker = "gcc"
91 else:
92 self.linker = "dllwrap"
93
Greg Wardf34506a2000-06-29 22:57:55 +000094 # Hard-code GCC because that's what this is all about.
95 # XXX optimization, warnings etc. should be customizable.
Greg Wardbf5c7092000-08-02 01:31:56 +000096 self.set_executables(compiler='gcc -mcygwin -O -Wall',
97 compiler_so='gcc -mcygwin -mdll -O -Wall',
98 linker_exe='gcc -mcygwin',
99 linker_so=('%s -mcygwin -mdll -static' %
100 self.linker))
Greg Ward7c6395a2000-06-21 03:33:03 +0000101
Greg Wardf34506a2000-06-29 22:57:55 +0000102 # cygwin and mingw32 need different sets of libraries
Greg Wardbf5c7092000-08-02 01:31:56 +0000103 if self.gcc_version == "2.91.57":
104 # cygwin shouldn't need msvcrt, but without the dlls will crash
105 # (gcc version 2.91.57) -- perhaps something about initialization
106 self.dll_libraries=["msvcrt"]
107 self.warn(
108 "Consider upgrading to a newer version of gcc")
109 else:
110 self.dll_libraries=[]
Greg Ward7c6395a2000-06-21 03:33:03 +0000111
112 # __init__ ()
113
114 def link_shared_object (self,
115 objects,
116 output_filename,
117 output_dir=None,
118 libraries=None,
119 library_dirs=None,
120 runtime_library_dirs=None,
121 export_symbols=None,
Greg Wardf34506a2000-06-29 22:57:55 +0000122 debug=0,
Greg Ward7c6395a2000-06-21 03:33:03 +0000123 extra_preargs=None,
Greg Wardf34506a2000-06-29 22:57:55 +0000124 extra_postargs=None,
125 build_temp=None):
Greg Ward7c6395a2000-06-21 03:33:03 +0000126
Greg Wardb1dceae2000-08-13 00:43:56 +0000127 # use separate copies, so we can modify the lists
128 extra_preargs = copy.copy(extra_preargs or [])
129 libraries = copy.copy(libraries or [])
Greg Ward7c6395a2000-06-21 03:33:03 +0000130
Greg Wardbf5c7092000-08-02 01:31:56 +0000131 # Additional libraries
Greg Wardf34506a2000-06-29 22:57:55 +0000132 libraries.extend(self.dll_libraries)
Greg Ward7c6395a2000-06-21 03:33:03 +0000133
Greg Wardbf5c7092000-08-02 01:31:56 +0000134 # we want to put some files in the same directory as the
135 # object files are, build_temp doesn't help much
136
137 # where are the object files
138 temp_dir = os.path.dirname(objects[0])
139
140 # name of dll to give the helper files (def, lib, exp) the same name
141 (dll_name, dll_extension) = os.path.splitext(
142 os.path.basename(output_filename))
143
144 # generate the filenames for these files
145 def_file = None # this will be done later, if necessary
146 exp_file = os.path.join(temp_dir, dll_name + ".exp")
147 lib_file = os.path.join(temp_dir, 'lib' + dll_name + ".a")
148
149 #extra_preargs.append("--verbose")
150 if self.linker == "dllwrap":
151 extra_preargs.extend([#"--output-exp",exp_file,
152 "--output-lib",lib_file,
153 ])
Greg Wardf34506a2000-06-29 22:57:55 +0000154 else:
Greg Wardbf5c7092000-08-02 01:31:56 +0000155 # doesn't work: bfd_close build\...\libfoo.a: Invalid operation
156 extra_preargs.extend([#"-Wl,--out-implib,%s" % lib_file,
157 ])
158
159 # check what we got in export_symbols
160 if export_symbols is not None:
161 # Make .def file
162 # (It would probably better to check if we really need this,
163 # but for this we had to insert some unchanged parts of
164 # UnixCCompiler, and this is not what we want.)
165 def_file = os.path.join(temp_dir, dll_name + ".def")
166 contents = [
167 "LIBRARY %s" % os.path.basename(output_filename),
168 "EXPORTS"]
Greg Ward7c6395a2000-06-21 03:33:03 +0000169 for sym in export_symbols:
Greg Wardbf5c7092000-08-02 01:31:56 +0000170 contents.append(sym)
171 self.execute(write_file, (def_file, contents),
172 "writing %s" % def_file)
173
174 if def_file:
175 if self.linker == "dllwrap":
176 # for dllwrap we have to use a special option
177 extra_preargs.append("--def")
178 # for gcc/ld it is specified as any other object file
179 extra_preargs.append(def_file)
180
Greg Wardf34506a2000-06-29 22:57:55 +0000181 # who wants symbols and a many times larger output file
Greg Ward612eb9f2000-07-27 02:13:20 +0000182 # should explicitly switch the debug mode on
Greg Wardbf5c7092000-08-02 01:31:56 +0000183 # otherwise we let dllwrap/ld strip the output file
Greg Wardf34506a2000-06-29 22:57:55 +0000184 # (On my machine unstripped_file = stripped_file + 254KB
Greg Ward7c6395a2000-06-21 03:33:03 +0000185 # 10KB < stripped_file < ??100KB )
186 if not debug:
Greg Wardbf5c7092000-08-02 01:31:56 +0000187 extra_preargs.append("-s")
Greg Wardf34506a2000-06-29 22:57:55 +0000188
189 UnixCCompiler.link_shared_object(self,
Greg Ward7c6395a2000-06-21 03:33:03 +0000190 objects,
191 output_filename,
192 output_dir,
193 libraries,
194 library_dirs,
195 runtime_library_dirs,
Greg Wardbf5c7092000-08-02 01:31:56 +0000196 None, # export_symbols, we do this in our def-file
Greg Ward7c6395a2000-06-21 03:33:03 +0000197 debug,
198 extra_preargs,
Greg Wardf34506a2000-06-29 22:57:55 +0000199 extra_postargs,
200 build_temp)
Greg Ward7c6395a2000-06-21 03:33:03 +0000201
202 # link_shared_object ()
203
204# class CygwinCCompiler
205
Greg Wardf34506a2000-06-29 22:57:55 +0000206
Greg Ward7c6395a2000-06-21 03:33:03 +0000207# the same as cygwin plus some additional parameters
208class Mingw32CCompiler (CygwinCCompiler):
209
210 compiler_type = 'mingw32'
211
212 def __init__ (self,
213 verbose=0,
214 dry_run=0,
215 force=0):
216
217 CygwinCCompiler.__init__ (self, verbose, dry_run, force)
Greg Wardbf5c7092000-08-02 01:31:56 +0000218
219 # A real mingw32 doesn't need to specify a different entry point,
220 # but cygwin 2.91.57 in no-cygwin-mode needs it.
221 if self.gcc_version <= "2.91.57":
222 entry_point = '--entry _DllMain@12'
223 else:
224 entry_point = ''
Greg Ward7c6395a2000-06-21 03:33:03 +0000225
Greg Wardf34506a2000-06-29 22:57:55 +0000226 self.set_executables(compiler='gcc -mno-cygwin -O -Wall',
Greg Wardbf5c7092000-08-02 01:31:56 +0000227 compiler_so='gcc -mno-cygwin -mdll -O -Wall',
Greg Wardf34506a2000-06-29 22:57:55 +0000228 linker_exe='gcc -mno-cygwin',
Greg Wardbf5c7092000-08-02 01:31:56 +0000229 linker_so='%s -mno-cygwin -mdll -static %s'
230 % (self.linker, entry_point))
231 # Maybe we should also append -mthreads, but then the finished
232 # dlls need another dll (mingwm10.dll see Mingw32 docs)
233 # (-mthreads: Support thread-safe exception handling on `Mingw32')
234
235 # no additional libraries needed
236 self.dll_libraries=[]
237
Greg Ward7c6395a2000-06-21 03:33:03 +0000238 # __init__ ()
Greg Wardbf5c7092000-08-02 01:31:56 +0000239
Greg Ward7c6395a2000-06-21 03:33:03 +0000240# class Mingw32CCompiler
Greg Wardbf5c7092000-08-02 01:31:56 +0000241
242# Because these compilers aren't configured in Python's config.h file by
243# default, we should at least warn the user if he is using a unmodified
244# version.
245
Greg Warde8e9d112000-08-13 01:18:55 +0000246CONFIG_H_OK = "ok"
247CONFIG_H_NOTOK = "not ok"
248CONFIG_H_UNCERTAIN = "uncertain"
249
Greg Wardbf5c7092000-08-02 01:31:56 +0000250def check_config_h():
Greg Warde8e9d112000-08-13 01:18:55 +0000251
252 """Check if the current Python installation (specifically, config.h)
253 appears amenable to building extensions with GCC. Returns a tuple
254 (status, details), where 'status' is one of the following constants:
255 CONFIG_H_OK
256 all is well, go ahead and compile
257 CONFIG_H_NOTOK
258 doesn't look good
259 CONFIG_H_UNCERTAIN
260 not sure -- unable to read config.h
261 'details' is a human-readable string explaining the situation.
262
263 Note there are two ways to conclude "OK": either 'sys.version' contains
264 the string "GCC" (implying that this Python was built with GCC), or the
265 installed "config.h" contains the string "__GNUC__".
Greg Wardbf5c7092000-08-02 01:31:56 +0000266 """
Greg Warde8e9d112000-08-13 01:18:55 +0000267
268 # XXX since this function also checks sys.version, it's not strictly a
269 # "config.h" check -- should probably be renamed...
Greg Wardbf5c7092000-08-02 01:31:56 +0000270
271 from distutils import sysconfig
272 import string,sys
273 # if sys.version contains GCC then python was compiled with
274 # GCC, and the config.h file should be OK
Greg Warde8e9d112000-08-13 01:18:55 +0000275 if string.find(sys.version,"GCC") >= 0:
276 return (CONFIG_H_OK, "sys.version mentions 'GCC'")
Greg Wardbf5c7092000-08-02 01:31:56 +0000277
Greg Warde8e9d112000-08-13 01:18:55 +0000278 fn = sysconfig.get_config_h_filename()
Greg Wardbf5c7092000-08-02 01:31:56 +0000279 try:
280 # It would probably better to read single lines to search.
281 # But we do this only once, and it is fast enough
Greg Warde8e9d112000-08-13 01:18:55 +0000282 f = open(fn)
283 s = f.read()
Greg Wardbf5c7092000-08-02 01:31:56 +0000284 f.close()
285
Greg Warde8e9d112000-08-13 01:18:55 +0000286 except IOError, exc:
Greg Wardbf5c7092000-08-02 01:31:56 +0000287 # if we can't read this file, we cannot say it is wrong
288 # the compiler will complain later about this file as missing
Greg Warde8e9d112000-08-13 01:18:55 +0000289 return (CONFIG_H_UNCERTAIN,
290 "couldn't read '%s': %s" % (fn, exc.strerror))
291
292 else:
293 # "config.h" contains an "#ifdef __GNUC__" or something similar
294 if string.find(s,"__GNUC__") >= 0:
295 return (CONFIG_H_OK, "'%s' mentions '__GNUC__'" % fn)
296 else:
297 return (CONFIG_H_NOTOK, "'%s' does not mention '__GNUC__'" % fn)
298
299
Greg Wardbf5c7092000-08-02 01:31:56 +0000300
301def get_versions():
302 """ Try to find out the versions of gcc, ld and dllwrap.
303 If not possible it returns None for it.
304 """
305 from distutils.version import StrictVersion
306 from distutils.spawn import find_executable
307 import re
308
309 gcc_exe = find_executable('gcc')
310 if gcc_exe:
311 out = os.popen(gcc_exe + ' -dumpversion','r')
312 out_string = out.read()
313 out.close()
314 result = re.search('(\d+\.\d+\.\d+)',out_string)
315 if result:
316 gcc_version = StrictVersion(result.group(1))
317 else:
318 gcc_version = None
319 else:
320 gcc_version = None
321 ld_exe = find_executable('ld')
322 if ld_exe:
323 out = os.popen(ld_exe + ' -v','r')
324 out_string = out.read()
325 out.close()
326 result = re.search('(\d+\.\d+\.\d+)',out_string)
327 if result:
328 ld_version = StrictVersion(result.group(1))
329 else:
330 ld_version = None
331 else:
332 ld_version = None
333 dllwrap_exe = find_executable('dllwrap')
334 if dllwrap_exe:
335 out = os.popen(dllwrap_exe + ' --version','r')
336 out_string = out.read()
337 out.close()
338 result = re.search(' (\d+\.\d+\.\d+)',out_string)
339 if result:
340 dllwrap_version = StrictVersion(result.group(1))
341 else:
342 dllwrap_version = None
343 else:
344 dllwrap_version = None
345 return (gcc_version, ld_version, dllwrap_version)
346