blob: da0d60b0c2eae3b8202a4ebd3a392c37ba190de3 [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 Wardb1dceae2000-08-13 00:43:56 +000068 check_result = check_config_h()
69 self.debug_print("Python's GCC status: %s" % check_result)
70 if check_result[:2] <> "OK":
Greg Wardbf5c7092000-08-02 01:31:56 +000071 self.warn(
72 "Python's config.h doesn't seem to support your compiler. "
73 "Compiling may fail because of undefined preprocessor macros.")
74
75 (self.gcc_version, self.ld_version, self.dllwrap_version) = \
76 get_versions()
Greg Wardb1dceae2000-08-13 00:43:56 +000077 self.debug_print(self.compiler_type + ": gcc %s, ld %s, dllwrap %s\n" %
Greg Wardbf5c7092000-08-02 01:31:56 +000078 (self.gcc_version,
79 self.ld_version,
80 self.dllwrap_version) )
81
82 # ld_version >= "2.10.90" should also be able to use
83 # gcc -mdll instead of dllwrap
84 # Older dllwraps had own version numbers, newer ones use the
85 # same as the rest of binutils ( also ld )
86 # dllwrap 2.10.90 is buggy
87 if self.ld_version >= "2.10.90":
88 self.linker = "gcc"
89 else:
90 self.linker = "dllwrap"
91
Greg Wardf34506a2000-06-29 22:57:55 +000092 # Hard-code GCC because that's what this is all about.
93 # XXX optimization, warnings etc. should be customizable.
Greg Wardbf5c7092000-08-02 01:31:56 +000094 self.set_executables(compiler='gcc -mcygwin -O -Wall',
95 compiler_so='gcc -mcygwin -mdll -O -Wall',
96 linker_exe='gcc -mcygwin',
97 linker_so=('%s -mcygwin -mdll -static' %
98 self.linker))
Greg Ward7c6395a2000-06-21 03:33:03 +000099
Greg Wardf34506a2000-06-29 22:57:55 +0000100 # cygwin and mingw32 need different sets of libraries
Greg Wardbf5c7092000-08-02 01:31:56 +0000101 if self.gcc_version == "2.91.57":
102 # cygwin shouldn't need msvcrt, but without the dlls will crash
103 # (gcc version 2.91.57) -- perhaps something about initialization
104 self.dll_libraries=["msvcrt"]
105 self.warn(
106 "Consider upgrading to a newer version of gcc")
107 else:
108 self.dll_libraries=[]
Greg Ward7c6395a2000-06-21 03:33:03 +0000109
110 # __init__ ()
111
112 def link_shared_object (self,
113 objects,
114 output_filename,
115 output_dir=None,
116 libraries=None,
117 library_dirs=None,
118 runtime_library_dirs=None,
119 export_symbols=None,
Greg Wardf34506a2000-06-29 22:57:55 +0000120 debug=0,
Greg Ward7c6395a2000-06-21 03:33:03 +0000121 extra_preargs=None,
Greg Wardf34506a2000-06-29 22:57:55 +0000122 extra_postargs=None,
123 build_temp=None):
Greg Ward7c6395a2000-06-21 03:33:03 +0000124
Greg Wardb1dceae2000-08-13 00:43:56 +0000125 # use separate copies, so we can modify the lists
126 extra_preargs = copy.copy(extra_preargs or [])
127 libraries = copy.copy(libraries or [])
Greg Ward7c6395a2000-06-21 03:33:03 +0000128
Greg Wardbf5c7092000-08-02 01:31:56 +0000129 # Additional libraries
Greg Wardf34506a2000-06-29 22:57:55 +0000130 libraries.extend(self.dll_libraries)
Greg Ward7c6395a2000-06-21 03:33:03 +0000131
Greg Wardbf5c7092000-08-02 01:31:56 +0000132 # we want to put some files in the same directory as the
133 # object files are, build_temp doesn't help much
134
135 # where are the object files
136 temp_dir = os.path.dirname(objects[0])
137
138 # name of dll to give the helper files (def, lib, exp) the same name
139 (dll_name, dll_extension) = os.path.splitext(
140 os.path.basename(output_filename))
141
142 # generate the filenames for these files
143 def_file = None # this will be done later, if necessary
144 exp_file = os.path.join(temp_dir, dll_name + ".exp")
145 lib_file = os.path.join(temp_dir, 'lib' + dll_name + ".a")
146
147 #extra_preargs.append("--verbose")
148 if self.linker == "dllwrap":
149 extra_preargs.extend([#"--output-exp",exp_file,
150 "--output-lib",lib_file,
151 ])
Greg Wardf34506a2000-06-29 22:57:55 +0000152 else:
Greg Wardbf5c7092000-08-02 01:31:56 +0000153 # doesn't work: bfd_close build\...\libfoo.a: Invalid operation
154 extra_preargs.extend([#"-Wl,--out-implib,%s" % lib_file,
155 ])
156
157 # check what we got in export_symbols
158 if export_symbols is not None:
159 # Make .def file
160 # (It would probably better to check if we really need this,
161 # but for this we had to insert some unchanged parts of
162 # UnixCCompiler, and this is not what we want.)
163 def_file = os.path.join(temp_dir, dll_name + ".def")
164 contents = [
165 "LIBRARY %s" % os.path.basename(output_filename),
166 "EXPORTS"]
Greg Ward7c6395a2000-06-21 03:33:03 +0000167 for sym in export_symbols:
Greg Wardbf5c7092000-08-02 01:31:56 +0000168 contents.append(sym)
169 self.execute(write_file, (def_file, contents),
170 "writing %s" % def_file)
171
172 if def_file:
173 if self.linker == "dllwrap":
174 # for dllwrap we have to use a special option
175 extra_preargs.append("--def")
176 # for gcc/ld it is specified as any other object file
177 extra_preargs.append(def_file)
178
Greg Wardf34506a2000-06-29 22:57:55 +0000179 # who wants symbols and a many times larger output file
Greg Ward612eb9f2000-07-27 02:13:20 +0000180 # should explicitly switch the debug mode on
Greg Wardbf5c7092000-08-02 01:31:56 +0000181 # otherwise we let dllwrap/ld strip the output file
Greg Wardf34506a2000-06-29 22:57:55 +0000182 # (On my machine unstripped_file = stripped_file + 254KB
Greg Ward7c6395a2000-06-21 03:33:03 +0000183 # 10KB < stripped_file < ??100KB )
184 if not debug:
Greg Wardbf5c7092000-08-02 01:31:56 +0000185 extra_preargs.append("-s")
Greg Wardf34506a2000-06-29 22:57:55 +0000186
187 UnixCCompiler.link_shared_object(self,
Greg Ward7c6395a2000-06-21 03:33:03 +0000188 objects,
189 output_filename,
190 output_dir,
191 libraries,
192 library_dirs,
193 runtime_library_dirs,
Greg Wardbf5c7092000-08-02 01:31:56 +0000194 None, # export_symbols, we do this in our def-file
Greg Ward7c6395a2000-06-21 03:33:03 +0000195 debug,
196 extra_preargs,
Greg Wardf34506a2000-06-29 22:57:55 +0000197 extra_postargs,
198 build_temp)
Greg Ward7c6395a2000-06-21 03:33:03 +0000199
200 # link_shared_object ()
201
202# class CygwinCCompiler
203
Greg Wardf34506a2000-06-29 22:57:55 +0000204
Greg Ward7c6395a2000-06-21 03:33:03 +0000205# the same as cygwin plus some additional parameters
206class Mingw32CCompiler (CygwinCCompiler):
207
208 compiler_type = 'mingw32'
209
210 def __init__ (self,
211 verbose=0,
212 dry_run=0,
213 force=0):
214
215 CygwinCCompiler.__init__ (self, verbose, dry_run, force)
Greg Wardbf5c7092000-08-02 01:31:56 +0000216
217 # A real mingw32 doesn't need to specify a different entry point,
218 # but cygwin 2.91.57 in no-cygwin-mode needs it.
219 if self.gcc_version <= "2.91.57":
220 entry_point = '--entry _DllMain@12'
221 else:
222 entry_point = ''
Greg Ward7c6395a2000-06-21 03:33:03 +0000223
Greg Wardf34506a2000-06-29 22:57:55 +0000224 self.set_executables(compiler='gcc -mno-cygwin -O -Wall',
Greg Wardbf5c7092000-08-02 01:31:56 +0000225 compiler_so='gcc -mno-cygwin -mdll -O -Wall',
Greg Wardf34506a2000-06-29 22:57:55 +0000226 linker_exe='gcc -mno-cygwin',
Greg Wardbf5c7092000-08-02 01:31:56 +0000227 linker_so='%s -mno-cygwin -mdll -static %s'
228 % (self.linker, entry_point))
229 # Maybe we should also append -mthreads, but then the finished
230 # dlls need another dll (mingwm10.dll see Mingw32 docs)
231 # (-mthreads: Support thread-safe exception handling on `Mingw32')
232
233 # no additional libraries needed
234 self.dll_libraries=[]
235
Greg Ward7c6395a2000-06-21 03:33:03 +0000236 # __init__ ()
Greg Wardbf5c7092000-08-02 01:31:56 +0000237
Greg Ward7c6395a2000-06-21 03:33:03 +0000238# class Mingw32CCompiler
Greg Wardbf5c7092000-08-02 01:31:56 +0000239
240# Because these compilers aren't configured in Python's config.h file by
241# default, we should at least warn the user if he is using a unmodified
242# version.
243
244def check_config_h():
245 """Checks if the GCC compiler is mentioned in config.h. If it is not,
246 compiling probably doesn't work.
247 """
248 # return values
Greg Wardb1dceae2000-08-13 00:43:56 +0000249 # "OK, python was compiled with GCC"
250 # "OK, python's config.h mentions __GCC__"
251 # "uncertain, because we couldn't check it"
252 # "not OK, because we didn't found __GCC__ in config.h"
253 # You could check check_config_h()[:2] == "OK"
Greg Wardbf5c7092000-08-02 01:31:56 +0000254
255 from distutils import sysconfig
256 import string,sys
257 # if sys.version contains GCC then python was compiled with
258 # GCC, and the config.h file should be OK
259 if -1 == string.find(sys.version,"GCC"):
260 pass # go to the next test
261 else:
Greg Wardb1dceae2000-08-13 00:43:56 +0000262 return "OK, python was compiled with GCC"
Greg Wardbf5c7092000-08-02 01:31:56 +0000263
264 try:
265 # It would probably better to read single lines to search.
266 # But we do this only once, and it is fast enough
267 f=open(sysconfig.get_config_h_filename())
268 s=f.read()
269 f.close()
270
271 # is somewhere a #ifdef __GNUC__ or something similar
272 if -1 == string.find(s,"__GNUC__"):
Greg Wardb1dceae2000-08-13 00:43:56 +0000273 return "not OK, because we didn't found __GCC__ in config.h"
Greg Wardbf5c7092000-08-02 01:31:56 +0000274 else:
Greg Wardb1dceae2000-08-13 00:43:56 +0000275 return "OK, python's config.h mentions __GCC__"
Greg Wardbf5c7092000-08-02 01:31:56 +0000276 except IOError:
277 # if we can't read this file, we cannot say it is wrong
278 # the compiler will complain later about this file as missing
279 pass
Greg Wardb1dceae2000-08-13 00:43:56 +0000280 return "uncertain, because we couldn't check it"
Greg Wardbf5c7092000-08-02 01:31:56 +0000281
282def get_versions():
283 """ Try to find out the versions of gcc, ld and dllwrap.
284 If not possible it returns None for it.
285 """
286 from distutils.version import StrictVersion
287 from distutils.spawn import find_executable
288 import re
289
290 gcc_exe = find_executable('gcc')
291 if gcc_exe:
292 out = os.popen(gcc_exe + ' -dumpversion','r')
293 out_string = out.read()
294 out.close()
295 result = re.search('(\d+\.\d+\.\d+)',out_string)
296 if result:
297 gcc_version = StrictVersion(result.group(1))
298 else:
299 gcc_version = None
300 else:
301 gcc_version = None
302 ld_exe = find_executable('ld')
303 if ld_exe:
304 out = os.popen(ld_exe + ' -v','r')
305 out_string = out.read()
306 out.close()
307 result = re.search('(\d+\.\d+\.\d+)',out_string)
308 if result:
309 ld_version = StrictVersion(result.group(1))
310 else:
311 ld_version = None
312 else:
313 ld_version = None
314 dllwrap_exe = find_executable('dllwrap')
315 if dllwrap_exe:
316 out = os.popen(dllwrap_exe + ' --version','r')
317 out_string = out.read()
318 out.close()
319 result = re.search(' (\d+\.\d+\.\d+)',out_string)
320 if result:
321 dllwrap_version = StrictVersion(result.group(1))
322 else:
323 dllwrap_version = None
324 else:
325 dllwrap_version = None
326 return (gcc_version, ld_version, dllwrap_version)
327