4 from distutils
.msvccompiler
import MSVCCompiler
5 from distutils
.bcppcompiler
import BCPPCompiler
7 from distutils
.errors
import \
8 DistutilsExecError
, DistutilsPlatformError
, \
9 CompileError
, LibError
, LinkError
10 from distutils
.ccompiler
import \
11 CCompiler
, gen_preprocess_options
, gen_lib_options
13 #----------------------------------------------------------------------
15 class MyMSVCCompiler(MSVCCompiler
):
17 ##------------------------------------------------------------
18 ## Override the entire compile method just to add flags to the
19 ## RC command. There should be an easier way to do this from
20 ## distutils directly or in a derived class...
21 ##------------------------------------------------------------
32 (output_dir
, macros
, include_dirs
) = \
33 self
._fix
_compile
_args
(output_dir
, macros
, include_dirs
)
34 (objects
, skip_sources
) = self
._prep
_compile
(sources
, output_dir
)
36 if extra_postargs
is None:
39 pp_opts
= gen_preprocess_options (macros
, include_dirs
)
40 compile_opts
= extra_preargs
or []
41 compile_opts
.append ('/c')
43 compile_opts
.extend (self
.compile_options_debug
)
45 compile_opts
.extend (self
.compile_options
)
47 for i
in range (len (sources
)):
48 src
= sources
[i
] ; obj
= objects
[i
]
49 ext
= (os
.path
.splitext (src
))[1]
52 self
.announce ("skipping %s (%s up-to-date)" % (src
, obj
))
54 self
.mkpath (os
.path
.dirname (obj
))
56 if ext
in self
._c
_extensions
:
57 input_opt
= "/Tc" + os
.path
.abspath(src
) ### RPD
58 elif ext
in self
._cpp
_extensions
:
59 input_opt
= "/Tp" + os
.path
.abspath(src
) ### RPD
60 elif ext
in self
._rc
_extensions
:
61 # compile .RC to .RES file
63 output_opt
= "/fo" + obj
65 self
.spawn ([self
.rc
] + pp_opts
+ ### RPD changed this line
66 [output_opt
] + [input_opt
])
67 except DistutilsExecError
, msg
:
68 raise CompileError
, msg
70 elif ext
in self
._mc
_extensions
:
72 # Compile .MC to .RC file to .RES file.
73 # * '-h dir' specifies the directory for the
74 # generated include file
75 # * '-r dir' specifies the target directory of the
76 # generated RC file and the binary message resource
79 # For now (since there are no options to change this),
80 # we use the source-directory for the include file and
81 # the build directory for the RC file and message
82 # resources. This works at least for win32all.
84 h_dir
= os
.path
.dirname (src
)
85 rc_dir
= os
.path
.dirname (obj
)
87 # first compile .MC to .RC and .H file
88 self
.spawn ([self
.mc
] +
89 ['-h', h_dir
, '-r', rc_dir
] + [src
])
90 base
, _
= os
.path
.splitext (os
.path
.basename (src
))
91 rc_file
= os
.path
.join (rc_dir
, base
+ '.rc')
92 # then compile .RC to .RES file
93 self
.spawn ([self
.rc
] +
94 ["/fo" + obj
] + [rc_file
])
96 except DistutilsExecError
, msg
:
97 raise CompileError
, msg
100 # how to handle this file?
102 "Don't know how to compile %s to %s" % \
105 output_opt
= "/Fo" + obj
107 self
.spawn ([self
.cc
] + compile_opts
+ pp_opts
+
108 [input_opt
, output_opt
] +
110 except DistutilsExecError
, msg
:
111 raise CompileError
, msg
119 from distutils
.file_util
import write_file
120 class MyBCPPCompiler(BCPPCompiler
):
122 ##------------------------------------------------------------
123 ## Override the entire compile method just to add flags to the
124 ## RC command. There should be an easier way to do this from
125 ## distutils directly or in a derived class...
126 ##------------------------------------------------------------
135 extra_postargs
=None):
137 (output_dir
, macros
, include_dirs
) = \
138 self
._fix
_compile
_args
(output_dir
, macros
, include_dirs
)
139 (objects
, skip_sources
) = self
._prep
_compile
(sources
, output_dir
)
141 if extra_postargs
is None:
144 pp_opts
= gen_preprocess_options (macros
, include_dirs
)
145 compile_opts
= extra_preargs
or []
146 compile_opts
.append ('-c')
148 compile_opts
.extend (self
.compile_options_debug
)
150 compile_opts
.extend (self
.compile_options
)
152 for i
in range (len (sources
)):
153 src
= sources
[i
] ; obj
= objects
[i
]
154 ext
= (os
.path
.splitext (src
))[1]
156 if skip_sources
[src
]:
157 self
.announce ("skipping %s (%s up-to-date)" % (src
, obj
))
159 src
= os
.path
.normpath(src
)
160 obj
= os
.path
.normpath(obj
)
161 self
.mkpath(os
.path
.dirname(obj
))
164 # This is already a binary file -- skip it.
165 continue # the 'for' loop
167 # This needs to be compiled to a .res file -- do it now.
169 self
.spawn (["brcc32"] + pp_opts
+ ["-fo"] +
170 [obj
] + [src
]) ### RPD changed this lines only
171 except DistutilsExecError
, msg
:
172 raise CompileError
, msg
173 continue # the 'for' loop
175 # The next two are both for the real compiler.
176 if ext
in self
._c
_extensions
:
178 elif ext
in self
._cpp
_extensions
:
181 # Unknown file type -- no extra options. The compiler
182 # will probably fail, but let it just in case this is a
183 # file the compiler recognizes even if we don't.
186 output_opt
= "-o" + obj
188 # Compiler command line syntax is: "bcc32 [options] file(s)".
189 # Note that the source file names must appear at the end of
192 self
.spawn ([self
.cc
] + compile_opts
+ pp_opts
+
193 [input_opt
, output_opt
] +
194 extra_postargs
+ [src
])
195 except DistutilsExecError
, msg
:
196 raise CompileError
, msg
202 ####################################################################
203 # Now we need to replace cw32mt library used by default by distutils
204 # with cw32mti library as in wxWindows DLL make file
205 # Othervise we obtain Windows "Core dump" ;-).
207 # Evgeny A Cherkashin <eugeneai@icc.ru>
209 ####################################################################
218 runtime_library_dirs
=None,
225 # XXX this ignores 'build_temp'! should follow the lead of
228 (objects
, output_dir
) = self
._fix
_object
_args
(objects
, output_dir
)
229 (libraries
, library_dirs
, runtime_library_dirs
) = \
230 self
._fix
_lib
_args
(libraries
, library_dirs
, runtime_library_dirs
)
232 if runtime_library_dirs
:
233 self
.warn ("I don't know what to do with 'runtime_library_dirs': "
234 + str (runtime_library_dirs
))
236 if output_dir
is not None:
237 output_filename
= os
.path
.join (output_dir
, output_filename
)
239 if self
._need
_link
(objects
, output_filename
):
241 # Figure out linker args based on type of target.
242 if target_desc
== CCompiler
.EXECUTABLE
:
243 startup_obj
= 'c0w32'
245 ld_args
= self
.ldflags_exe_debug
[:]
247 ld_args
= self
.ldflags_exe
[:]
249 startup_obj
= 'c0d32'
251 ld_args
= self
.ldflags_shared_debug
[:]
253 ld_args
= self
.ldflags_shared
[:]
256 # Create a temporary exports file for use by the linker
257 if export_symbols
is None:
260 head
, tail
= os
.path
.split (output_filename
)
261 modname
, ext
= os
.path
.splitext (tail
)
262 temp_dir
= os
.path
.dirname(objects
[0]) # preserve tree structure
263 def_file
= os
.path
.join (temp_dir
, '%s.def' % modname
)
264 contents
= ['EXPORTS']
265 for sym
in (export_symbols
or []):
266 contents
.append(' %s=_%s' % (sym
, sym
))
267 self
.execute(write_file
, (def_file
, contents
),
268 "writing %s" % def_file
)
270 # Borland C++ has problems with '/' in paths
271 objects2
= map(os
.path
.normpath
, objects
)
272 # split objects in .obj and .res files
273 # Borland C++ needs them at different positions in the command line
274 objects
= [startup_obj
]
276 for file in objects2
:
277 (base
, ext
) = os
.path
.splitext(os
.path
.normcase(file))
279 resources
.append(file)
284 for l
in library_dirs
:
285 ld_args
.append("/L%s" % os
.path
.normpath(l
))
286 ld_args
.append("/L.") # we sometimes use relative paths
288 # list of object files
289 ld_args
.extend(objects
)
291 # XXX the command-line syntax for Borland C++ is a bit wonky;
292 # certain filenames are jammed together in one big string, but
293 # comma-delimited. This doesn't mesh too well with the
294 # Unix-centric attitude (with a DOS/Windows quoting hack) of
295 # 'spawn()', so constructing the argument list is a bit
296 # awkward. Note that doing the obvious thing and jamming all
297 # the filenames and commas into one argument would be wrong,
298 # because 'spawn()' would quote any filenames with spaces in
299 # them. Arghghh!. Apparently it works fine as coded...
301 # name of dll/exe file
302 ld_args
.extend([',',output_filename
])
303 # no map file and start libraries
306 for lib
in libraries
:
307 # see if we find it and if there is a bcpp specific lib
309 libfile
= self
.find_library_file(library_dirs
, lib
, debug
)
312 # probably a BCPP internal library -- don't warn
313 # self.warn('library %s not found.' % lib)
315 # full name which prefers bcpp_xxx.lib over xxx.lib
316 ld_args
.append(libfile
)
318 # some default libraries
319 ld_args
.append ('import32')
320 ld_args
.append ('cw32mti') ### mt->mti (as in wx2)
322 # def file for export symbols
323 ld_args
.extend([',',def_file
])
326 ld_args
.extend(resources
)
330 ld_args
[:0] = extra_preargs
332 ld_args
.extend(extra_postargs
)
334 self
.mkpath (os
.path
.dirname (output_filename
))
336 self
.spawn ([self
.linker
] + ld_args
)
337 except DistutilsExecError
, msg
:
341 self
.announce ("skipping %s (up-to-date)" % output_filename
)
347 #----------------------------------------------------------------------
348 # Hack this module and class into the distutils...
350 from distutils
import ccompiler
352 if hasattr(ccompiler
, "default_compiler"):
353 ccompiler
.default_compiler
['nt'] = 'my_msvc'
354 elif hasattr(ccompiler
, "_default_compilers"):
355 lst
= list(ccompiler
._default
_compilers
)
356 lst
.remove( ('nt', 'msvc') )
357 lst
.append( ('nt', 'my_msvc') )
358 ccompiler
._default
_compilers
= tuple(lst
)
361 ccompiler
.compiler_class
['my_msvc'] = ('my_distutils',
363 'My MSVC derived class')
366 ccompiler
.compiler_class
['my_bcpp'] = ('my_distutils',
368 'My BCPP derived class')
370 # make it look like it is part of the package...
372 sys
.modules
['distutils.my_distutils'] = my_distutils
375 #----------------------------------------------------------------------
376 # More hacking... Distutils in Python 2.1 changed the strip_dir flag
377 # passed to object_filenames to true, which causes problems for us since
378 # there are a few duplicate source/object names between some of the
379 # extensions in wxPython. This hack replaces the CCompiler._prep_compile
380 # method with this one.
382 from distutils
.dep_util
import newer_pairwise
384 def _prep_compile (self
, sources
, output_dir
):
385 """Determine the list of object files corresponding to 'sources',
386 and figure out which ones really need to be recompiled. Return a
387 list of all object files and a dictionary telling which source
388 files can be skipped.
390 # Get the list of expected output (object) files
391 objects
= self
.object_filenames (sources
,
393 output_dir
=output_dir
)
396 skip_source
= {} # rebuild everything
397 for source
in sources
:
398 skip_source
[source
] = 0
400 # Figure out which source files we have to recompile according
401 # to a simplistic check -- we just compare the source and
402 # object file, no deep dependency checking involving header
404 skip_source
= {} # rebuild everything
405 for source
in sources
: # no wait, rebuild nothing
406 skip_source
[source
] = 1
408 (n_sources
, n_objects
) = newer_pairwise (sources
, objects
)
409 for source
in n_sources
: # no really, only rebuild what's
410 skip_source
[source
] = 0 # out-of-date
412 return (objects
, skip_source
)
416 CCompiler
._prep
_compile
= _prep_compile
421 #----------------------------------------------------------------------
422 # Run SWIG the way I want it done
424 def run_swig(files
, dir, gendir
, package
, USE_SWIG
, force
, swig_args
, swig_deps
=[]):
425 from distutils
.file_util
import copy_file
426 from distutils
.dep_util
import newer
427 from distutils
.spawn
import spawn
432 basefile
= os
.path
.splitext(file)[0]
433 i_file
= os
.path
.join(dir, file)
434 py_file
= os
.path
.join(dir, gendir
, basefile
+'.py')
435 cpp_file
= os
.path
.join(dir, gendir
, basefile
+'.cpp')
437 sources
.append(cpp_file
)
440 for dep
in swig_deps
:
441 if newer(dep
, py_file
) or newer(dep
, cpp_file
):
445 if force
or newer(i_file
, py_file
) or newer(i_file
, cpp_file
):
446 # we need forward slashes here even on win32
447 cpp_file
= string
.join(string
.split(cpp_file
, '\\'), '/')
448 i_file
= string
.join(string
.split(i_file
, '\\'), '/')
450 cmd
= ['swig'] + swig_args
+ ['-I'+dir, '-c', '-o', cpp_file
, i_file
]
451 spawn(cmd
, verbose
=1)
453 # copy the generated python file to the package directory
454 copy_file(py_file
, package
, update
=not force
, verbose
=0)
461 #----------------------------------------------------------------------
462 # Update local copies of wxWindows contrib files
465 def contrib_copy_tree(src
, dest
, verbose
=0):
466 from distutils
.dir_util
import mkpath
, copy_tree
468 mkpath(dest
, verbose
=verbose
)
469 copy_tree(src
, dest
, update
=1, verbose
=verbose
)