Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(4)

Side by Side Diff: Lib/distutils/cygwinccompiler.py

Issue 3871: cross and native build of python for mingw32 with distutils
Patch Set: Created 7 years, 2 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « Lib/distutils/command/install.py ('k') | Lib/distutils/sysconfig.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 """distutils.cygwinccompiler 1 """distutils.cygwinccompiler
2 2
3 Provides the CygwinCCompiler class, a subclass of UnixCCompiler that 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 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 5 the Mingw32CCompiler class which handles the mingw32 port of GCC (same as
6 cygwin in no-cygwin mode). 6 cygwin in no-cygwin mode).
7 """ 7 """
8 8
9 # problems: 9 # problems:
10 # 10 #
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
56 from distutils.file_util import write_file 56 from distutils.file_util import write_file
57 from distutils.errors import DistutilsExecError, CompileError, UnknownFileError 57 from distutils.errors import DistutilsExecError, CompileError, UnknownFileError
58 from distutils import log 58 from distutils import log
59 from distutils.version import LooseVersion 59 from distutils.version import LooseVersion
60 from distutils.spawn import find_executable 60 from distutils.spawn import find_executable
61 61
62 def get_msvcr(): 62 def get_msvcr():
63 """Include the appropriate MSVC runtime library if Python was built 63 """Include the appropriate MSVC runtime library if Python was built
64 with MSVC 7.0 or later. 64 with MSVC 7.0 or later.
65 """ 65 """
66 # FIXME: next code is from issue870382
67 # MS C-runtime libraries never support backward compatibility.
68 # Linking to a different library without to specify correct runtime
69 # version for the headers will link renamed functions to msvcrt.
70 # See issue3308: this piece of code is python problem even
71 # with correct w32api headers.
72 # Issue: for MSVC compiler we can get the version and from version
73 # to determine mcvcrt as code below. But what about if python is
74 # build with GCC compiler?
75 # Output of sys.version is information for python build on first
76 # line, on the next line is information for the compiler and the
77 # output lack information for the C-runtime.
66 msc_pos = sys.version.find('MSC v.') 78 msc_pos = sys.version.find('MSC v.')
67 if msc_pos != -1: 79 if msc_pos != -1:
68 msc_ver = sys.version[msc_pos+6:msc_pos+10] 80 msc_ver = sys.version[msc_pos+6:msc_pos+10]
69 if msc_ver == '1300': 81 if msc_ver == '1300':
70 # MSVC 7.0 82 # MSVC 7.0
71 return ['msvcr70'] 83 return ['msvcr70']
72 elif msc_ver == '1310': 84 elif msc_ver == '1310':
73 # MSVC 7.1 85 # MSVC 7.1
74 return ['msvcr71'] 86 return ['msvcr71']
75 elif msc_ver == '1400': 87 elif msc_ver == '1400':
76 # VS2005 / MSVC 8.0 88 # VS2005 / MSVC 8.0
77 return ['msvcr80'] 89 return ['msvcr80']
78 elif msc_ver == '1500': 90 elif msc_ver == '1500':
79 # VS2008 / MSVC 9.0 91 # VS2008 / MSVC 9.0
80 return ['msvcr90'] 92 return ['msvcr90']
81 elif msc_ver == '1600': 93 elif msc_ver == '1600':
82 # VS2010 / MSVC 10.0 94 # VS2010 / MSVC 10.0
83 return ['msvcr100'] 95 return ['msvcr100']
84 else: 96 else:
85 raise ValueError("Unknown MS Compiler version %s " % msc_ver) 97 raise ValueError("Unknown MS Compiler version %s " % msc_ver)
98 else:
99 return []
86 100
87 101
88 class CygwinCCompiler(UnixCCompiler): 102 class CygwinCCompiler(UnixCCompiler):
89 """ Handles the Cygwin port of the GNU C compiler to Windows. 103 """ Handles the Cygwin port of the GNU C compiler to Windows.
90 """ 104 """
105
91 compiler_type = 'cygwin' 106 compiler_type = 'cygwin'
92 obj_extension = ".o" 107 obj_extension = ".o"
93 static_lib_extension = ".a" 108 static_lib_extension = ".a"
94 shared_lib_extension = ".dll" 109 shared_lib_extension = ".dll"
110 # FIXME: dylib_... = ".dll.a" is not enought for binutils
111 # loader on win32 platform !!!
112 dylib_lib_extension = ".dll.a"
95 static_lib_format = "lib%s%s" 113 static_lib_format = "lib%s%s"
96 shared_lib_format = "%s%s" 114 shared_lib_format = "%s%s"
97 exe_extension = ".exe" 115 exe_extension = ".exe"
98 116
99 def __init__(self, verbose=0, dry_run=0, force=0): 117 def __init__(self, verbose=0, dry_run=0, force=0):
100
101 UnixCCompiler.__init__(self, verbose, dry_run, force) 118 UnixCCompiler.__init__(self, verbose, dry_run, force)
102 119
103 status, details = check_config_h() 120 status, details = check_config_h()
104 self.debug_print("Python's GCC status: %s (details: %s)" % 121 self.debug_print("Python's GCC status: %s (details: %s)" %
105 (status, details)) 122 (status, details))
106 if status is not CONFIG_H_OK: 123 if status is not CONFIG_H_OK:
107 self.warn( 124 self.warn(
108 "Python's pyconfig.h doesn't seem to support your compiler. " 125 "Python's pyconfig.h doesn't seem to support your compiler. "
109 "Reason: %s. " 126 "Reason: %s. "
110 "Compiling may fail because of undefined preprocessor macros." 127 "Compiling may fail because of undefined preprocessor macros."
111 % details) 128 % details)
112 129
130 # Next line of code is problem for cross-compiled enviroment:
131 # NOTE: GCC cross-compiler is prefixed by the <hostarch>-<hostos>-
132 # and by default binaries are installed in same directory
133 # as native compiler.
113 self.gcc_version, self.ld_version, self.dllwrap_version = \ 134 self.gcc_version, self.ld_version, self.dllwrap_version = \
114 get_versions() 135 get_versions()
115 self.debug_print(self.compiler_type + ": gcc %s, ld %s, dllwrap %s\n" % 136 self.debug_print(self.compiler_type + ": gcc %s, ld %s, dllwrap %s\n" %
116 (self.gcc_version, 137 (self.gcc_version,
117 self.ld_version, 138 self.ld_version,
118 self.dllwrap_version) ) 139 self.dllwrap_version) )
119 140
120 # ld_version >= "2.10.90" and < "2.13" should also be able to use 141 # ld_version >= "2.10.90" and < "2.13" should also be able to use
121 # gcc -mdll instead of dllwrap 142 # gcc -mdll instead of dllwrap
122 # Older dllwraps had own version numbers, newer ones use the 143 # Older dllwraps had own version numbers, newer ones use the
123 # same as the rest of binutils ( also ld ) 144 # same as the rest of binutils ( also ld )
124 # dllwrap 2.10.90 is buggy 145 # dllwrap 2.10.90 is buggy
125 if self.ld_version >= "2.10.90": 146 if self.ld_version >= "2.10.90":
126 self.linker_dll = "gcc" 147 self.linker_dll = "gcc"
127 else: 148 else:
128 self.linker_dll = "dllwrap" 149 self.linker_dll = "dllwrap"
129 150
130 # ld_version >= "2.13" support -shared so use it instead of 151 # ld_version >= "2.13" support -shared so use it instead of
131 # -mdll -static 152 # -mdll -static
132 if self.ld_version >= "2.13": 153 if self.ld_version >= "2.13":
133 shared_option = "-shared" 154 shared_option = "-shared"
134 else: 155 else:
135 shared_option = "-mdll -static" 156 shared_option = "-mdll -static"
136 157
158 # FIXME:
159 # Hard-code may override unix-compiler settings and isn't
160 # possible to use Makefile variables to pass correct flags !
137 # Hard-code GCC because that's what this is all about. 161 # Hard-code GCC because that's what this is all about.
138 # XXX optimization, warnings etc. should be customizable. 162 # XXX optimization, warnings etc. should be customizable.
139 self.set_executables(compiler='gcc -mcygwin -O -Wall', 163 self.set_executables(compiler='gcc -mcygwin -O -Wall',
140 compiler_so='gcc -mcygwin -mdll -O -Wall', 164 compiler_so='gcc -mcygwin -mdll -O -Wall',
141 compiler_cxx='g++ -mcygwin -O -Wall', 165 compiler_cxx='g++ -mcygwin -O -Wall',
142 linker_exe='gcc -mcygwin', 166 linker_exe='gcc -mcygwin',
143 linker_so=('%s -mcygwin %s' % 167 linker_so=('%s -mcygwin %s' %
144 (self.linker_dll, shared_option))) 168 (self.linker_dll, shared_option)))
145 169
146 # cygwin and mingw32 need different sets of libraries 170 # cygwin and mingw32 need different sets of libraries
147 if self.gcc_version == "2.91.57": 171 if self.gcc_version == "2.91.57":
148 # cygwin shouldn't need msvcrt, but without the dlls will crash 172 # cygwin shouldn't need msvcrt, but without the dlls will crash
149 # (gcc version 2.91.57) -- perhaps something about initialization 173 # (gcc version 2.91.57) -- perhaps something about initialization
150 self.dll_libraries=["msvcrt"] 174 self.dll_libraries=["msvcrt"]
151 self.warn( 175 self.warn(
152 "Consider upgrading to a newer version of gcc") 176 "Consider upgrading to a newer version of gcc")
153 else: 177 else:
154 # Include the appropriate MSVC runtime library if Python was built 178 # Include the appropriate MSVC runtime library if Python was built
155 # with MSVC 7.0 or later. 179 # with MSVC 7.0 or later.
156 self.dll_libraries = get_msvcr() 180 self.dll_libraries = get_msvcr()
157 181
158 def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts): 182 def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
159 """Compiles the source by spawning GCC and windres if needed.""" 183 """Compiles the source by spawning GCC and windres if needed."""
184
185 tmp_arg=[]
186
187 for arg in cc_args:
188 if arg not in ["-I.", "-I/mingw/include"]:
189 tmp_arg.append(arg)
190
191 cc_args=tmp_arg
192
160 if ext == '.rc' or ext == '.res': 193 if ext == '.rc' or ext == '.res':
161 # gcc needs '.res' and '.rc' compiled to object files !!! 194 # gcc needs '.res' and '.rc' compiled to object files !!!
162 try: 195 try:
163 self.spawn(["windres", "-i", src, "-o", obj]) 196 self.spawn(["windres", "-i", src, "-o", obj])
164 except DistutilsExecError as msg: 197 except DistutilsExecError as msg:
165 raise CompileError(msg) 198 raise CompileError(msg)
166 else: # for other files use the C-compiler 199 else: # for other files use the C-compiler
167 try: 200 try:
168 self.spawn(self.compiler_so + cc_args + [src, '-o', obj] + 201 self.spawn(self.compiler_so + cc_args + [src, '-o', obj] +
169 extra_postargs) 202 extra_postargs)
170 except DistutilsExecError as msg: 203 except DistutilsExecError as msg:
171 raise CompileError(msg) 204 raise CompileError(msg)
172 205
173 def link(self, target_desc, objects, output_filename, output_dir=None, 206 def link(self, target_desc, objects, output_filename, output_dir=None,
174 libraries=None, library_dirs=None, runtime_library_dirs=None, 207 libraries=None, library_dirs=None, runtime_library_dirs=None,
175 export_symbols=None, debug=0, extra_preargs=None, 208 export_symbols=None, debug=0, extra_preargs=None,
176 extra_postargs=None, build_temp=None, target_lang=None): 209 extra_postargs=None, build_temp=None, target_lang=None):
177 """Link the objects.""" 210 """Link the objects."""
211
178 # use separate copies, so we can modify the lists 212 # use separate copies, so we can modify the lists
179 extra_preargs = copy.copy(extra_preargs or []) 213 extra_preargs = copy.copy(extra_preargs or [])
180 libraries = copy.copy(libraries or []) 214 libraries = copy.copy(libraries or [])
181 objects = copy.copy(objects or []) 215 objects = copy.copy(objects or [])
182 216
183 # Additional libraries 217 # Additional libraries
184 libraries.extend(self.dll_libraries) 218 libraries.extend(self.dll_libraries)
185 219
186 # handle export symbols by creating a def-file 220 # handle export symbols by creating a def-file
187 # with executables this only works with gcc/ld as linker 221 # with executables this only works with gcc/ld as linker
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
247 target_lang) 281 target_lang)
248 282
249 # -- Miscellaneous methods ----------------------------------------- 283 # -- Miscellaneous methods -----------------------------------------
250 284
251 def object_filenames(self, source_filenames, strip_dir=0, output_dir=''): 285 def object_filenames(self, source_filenames, strip_dir=0, output_dir=''):
252 """Adds supports for rc and res files.""" 286 """Adds supports for rc and res files."""
253 if output_dir is None: 287 if output_dir is None:
254 output_dir = '' 288 output_dir = ''
255 obj_names = [] 289 obj_names = []
256 for src_name in source_filenames: 290 for src_name in source_filenames:
257 # use normcase to make sure '.rc' is really '.rc' and not '.RC' 291 # FIXME: "bogus checks for suffix" - as example the commented
258 base, ext = os.path.splitext(os.path.normcase(src_name)) 292 # by #BOGUS# code break valid assembler suffix ".S" !
293 #BOGUS## use normcase to make sure '.rc' is really '.rc' and not '.R C'
294 #BOGUS#base, ext = os.path.splitext(os.path.normcase(src_name))
295 base, ext = os.path.splitext (src_name)
296 ext_normcase = os.path.normcase(ext)
297 if ext_normcase in ['.rc','.res']:
298 ext = ext_normcase
259 if ext not in (self.src_extensions + ['.rc','.res']): 299 if ext not in (self.src_extensions + ['.rc','.res']):
260 raise UnknownFileError("unknown file type '%s' (from '%s')" % \ 300 raise UnknownFileError("unknown file type '%s' (from '%s')" % \
261 (ext, src_name)) 301 (ext, src_name))
302 base = os.path.splitdrive(base)[1] # Chop off the drive
303 base = base[os.path.isabs(base):] # If abs, chop off leading /
262 if strip_dir: 304 if strip_dir:
263 base = os.path.basename (base) 305 base = os.path.basename (base)
264 if ext in ('.res', '.rc'): 306 if ext in ('.res', '.rc'):
265 # these need to be compiled to object files 307 # these need to be compiled to object files
266 obj_names.append (os.path.join(output_dir, 308 obj_names.append (os.path.join(output_dir,
267 base + ext + self.obj_extension)) 309 base + ext + self.obj_extension))
268 else: 310 else:
269 obj_names.append (os.path.join(output_dir, 311 obj_names.append (os.path.join(output_dir,
270 base + self.obj_extension)) 312 base + self.obj_extension))
271 return obj_names 313 return obj_names
272 314
273 # the same as cygwin plus some additional parameters 315 # the same as cygwin plus some additional parameters
274 class Mingw32CCompiler(CygwinCCompiler): 316 class Mingw32CCompiler(CygwinCCompiler):
275 """ Handles the Mingw32 port of the GNU C compiler to Windows. 317 """ Handles the Mingw32 port of the GNU C compiler to Windows.
276 """ 318 """
277 compiler_type = 'mingw32' 319 compiler_type = 'mingw32'
278 320
279 def __init__(self, verbose=0, dry_run=0, force=0): 321 def __init__(self, verbose=0, dry_run=0, force=0):
280
281 CygwinCCompiler.__init__ (self, verbose, dry_run, force) 322 CygwinCCompiler.__init__ (self, verbose, dry_run, force)
282 323
324 compiler_options = '-mno-cygwin -O -Wall'
325
283 # ld_version >= "2.13" support -shared so use it instead of 326 # ld_version >= "2.13" support -shared so use it instead of
284 # -mdll -static 327 # -mdll -static
285 if self.ld_version >= "2.13": 328 if self.ld_version >= "4.7":
329 shared_option = "-pthread -share -W1"
330 elif self.ld_version >= "2.13":
286 shared_option = "-shared" 331 shared_option = "-shared"
287 else: 332 else:
288 shared_option = "-mdll -static" 333 shared_option = "-mdll -static"
289 334
290 # A real mingw32 doesn't need to specify a different entry point, 335 # A real mingw32 doesn't need to specify a different entry point,
291 # but cygwin 2.91.57 in no-cygwin-mode needs it. 336 # but cygwin 2.91.57 in no-cygwin-mode needs it.
292 if self.gcc_version <= "2.91.57": 337 if self.gcc_version >= "4.7":
338 entry_point = ''
339 compiler_options = '-pthread -c -Wno-unused-result -mms-bitfields -f wrapv -O3 -Wall -Wstrict-prototypes'
340 elif self.gcc_version <= "2.91.57":
293 entry_point = '--entry _DllMain@12' 341 entry_point = '--entry _DllMain@12'
294 else: 342 else:
295 entry_point = '' 343 entry_point = ''
296 344
297 self.set_executables(compiler='gcc -mno-cygwin -O -Wall', 345 self.set_executables(compiler='gcc %s' % compiler_options,
298 compiler_so='gcc -mno-cygwin -mdll -O -Wall', 346 compiler_so='gcc %s' % compiler_options,
299 compiler_cxx='g++ -mno-cygwin -O -Wall', 347 compiler_cxx='g++ -O2 -Wall',
300 linker_exe='gcc -mno-cygwin', 348 linker_exe='gcc %s' % compiler_options,
301 linker_so='%s -mno-cygwin %s %s' 349 linker_so='%s %s %s'
302 % (self.linker_dll, shared_option, 350 % (self.linker_dll, shared_option,
303 entry_point)) 351 entry_point))
352
304 # Maybe we should also append -mthreads, but then the finished 353 # Maybe we should also append -mthreads, but then the finished
305 # dlls need another dll (mingwm10.dll see Mingw32 docs) 354 # dlls need another dll (mingwm10.dll see Mingw32 docs)
306 # (-mthreads: Support thread-safe exception handling on `Mingw32') 355 # (-mthreads: Support thread-safe exception handling on `Mingw32')
307 356
308 # no additional libraries needed 357 # no additional libraries needed
309 self.dll_libraries=[] 358 self.dll_libraries=[]
310 359
311 # Include the appropriate MSVC runtime library if Python was built 360 # Include the appropriate MSVC runtime library if Python was built
312 # with MSVC 7.0 or later. 361 # with MSVC 7.0 or later.
313 self.dll_libraries = get_msvcr() 362 self.dll_libraries = get_msvcr()
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
386 # so we need to decode our bytes 435 # so we need to decode our bytes
387 return LooseVersion(result.group(1).decode()) 436 return LooseVersion(result.group(1).decode())
388 437
389 def get_versions(): 438 def get_versions():
390 """ Try to find out the versions of gcc, ld and dllwrap. 439 """ Try to find out the versions of gcc, ld and dllwrap.
391 440
392 If not possible it returns None for it. 441 If not possible it returns None for it.
393 """ 442 """
394 commands = ['gcc -dumpversion', 'ld -v', 'dllwrap --version'] 443 commands = ['gcc -dumpversion', 'ld -v', 'dllwrap --version']
395 return tuple([_find_exe_version(cmd) for cmd in commands]) 444 return tuple([_find_exe_version(cmd) for cmd in commands])
OLDNEW
« no previous file with comments | « Lib/distutils/command/install.py ('k') | Lib/distutils/sysconfig.py » ('j') | no next file with comments »

RSS Feeds Recent Issues | This issue
This is Rietveld 894c83f36cb7+