]>
Commit | Line | Data |
---|---|---|
c368d904 RD |
1 | |
2 | import sys, os, string | |
3 | ||
4 | from distutils.msvccompiler import MSVCCompiler | |
5 | ||
6 | from distutils.errors import \ | |
7 | DistutilsExecError, DistutilsPlatformError, \ | |
8 | CompileError, LibError, LinkError | |
9 | from distutils.ccompiler import \ | |
10 | CCompiler, gen_preprocess_options, gen_lib_options | |
11 | ||
12 | #---------------------------------------------------------------------- | |
13 | ||
14 | class MyMSVCCompiler(MSVCCompiler): | |
15 | ||
16 | ##------------------------------------------------------------ | |
17 | ## Override the entire compile method just to add flags to the | |
18 | ## RC command. There should be an easier way to do this from | |
19 | ## distutils directly or in a derived class... | |
20 | ##------------------------------------------------------------ | |
21 | ||
22 | def compile (self, | |
23 | sources, | |
24 | output_dir=None, | |
25 | macros=None, | |
26 | include_dirs=None, | |
27 | debug=0, | |
28 | extra_preargs=None, | |
29 | extra_postargs=None): | |
30 | ||
31 | (output_dir, macros, include_dirs) = \ | |
32 | self._fix_compile_args (output_dir, macros, include_dirs) | |
33 | (objects, skip_sources) = self._prep_compile (sources, output_dir) | |
34 | ||
35 | if extra_postargs is None: | |
36 | extra_postargs = [] | |
37 | ||
38 | pp_opts = gen_preprocess_options (macros, include_dirs) | |
39 | compile_opts = extra_preargs or [] | |
40 | compile_opts.append ('/c') | |
41 | if debug: | |
42 | compile_opts.extend (self.compile_options_debug) | |
43 | else: | |
44 | compile_opts.extend (self.compile_options) | |
45 | ||
46 | for i in range (len (sources)): | |
47 | src = sources[i] ; obj = objects[i] | |
48 | ext = (os.path.splitext (src))[1] | |
49 | ||
50 | if skip_sources[src]: | |
51 | self.announce ("skipping %s (%s up-to-date)" % (src, obj)) | |
52 | else: | |
53 | self.mkpath (os.path.dirname (obj)) | |
54 | ||
55 | if ext in self._c_extensions: | |
56 | input_opt = "/Tc" + src | |
57 | elif ext in self._cpp_extensions: | |
58 | input_opt = "/Tp" + src | |
59 | elif ext in self._rc_extensions: | |
60 | # compile .RC to .RES file | |
61 | input_opt = src | |
62 | output_opt = "/fo" + obj | |
63 | try: | |
64 | self.spawn ([self.rc] + pp_opts + ### RPD changed this line only | |
65 | [output_opt] + [input_opt]) | |
66 | except DistutilsExecError, msg: | |
67 | raise CompileError, msg | |
68 | continue | |
69 | elif ext in self._mc_extensions: | |
70 | ||
71 | # Compile .MC to .RC file to .RES file. | |
72 | # * '-h dir' specifies the directory for the | |
73 | # generated include file | |
74 | # * '-r dir' specifies the target directory of the | |
75 | # generated RC file and the binary message resource | |
76 | # it includes | |
77 | # | |
78 | # For now (since there are no options to change this), | |
79 | # we use the source-directory for the include file and | |
80 | # the build directory for the RC file and message | |
81 | # resources. This works at least for win32all. | |
82 | ||
83 | h_dir = os.path.dirname (src) | |
84 | rc_dir = os.path.dirname (obj) | |
85 | try: | |
86 | # first compile .MC to .RC and .H file | |
87 | self.spawn ([self.mc] + | |
88 | ['-h', h_dir, '-r', rc_dir] + [src]) | |
89 | base, _ = os.path.splitext (os.path.basename (src)) | |
90 | rc_file = os.path.join (rc_dir, base + '.rc') | |
91 | # then compile .RC to .RES file | |
92 | self.spawn ([self.rc] + | |
93 | ["/fo" + obj] + [rc_file]) | |
94 | ||
95 | except DistutilsExecError, msg: | |
96 | raise CompileError, msg | |
97 | continue | |
98 | else: | |
99 | # how to handle this file? | |
100 | raise CompileError ( | |
101 | "Don't know how to compile %s to %s" % \ | |
102 | (src, obj)) | |
103 | ||
104 | output_opt = "/Fo" + obj | |
105 | try: | |
106 | self.spawn ([self.cc] + compile_opts + pp_opts + | |
107 | [input_opt, output_opt] + | |
108 | extra_postargs) | |
109 | except DistutilsExecError, msg: | |
110 | raise CompileError, msg | |
111 | ||
112 | return objects | |
113 | ||
114 | # compile () | |
115 | ||
116 | ||
117 | ||
118 | ##------------------------------------------------------------ | |
119 | ## Now override the link() method to change where the import | |
120 | ## library is placed. Hopefully distutils will be updated | |
121 | ## someday to make this configurable... | |
122 | ##------------------------------------------------------------ | |
123 | ||
124 | def link (self, | |
125 | target_desc, | |
126 | objects, | |
127 | output_filename, | |
128 | output_dir=None, | |
129 | libraries=None, | |
130 | library_dirs=None, | |
131 | runtime_library_dirs=None, | |
132 | export_symbols=None, | |
133 | debug=0, | |
134 | extra_preargs=None, | |
135 | extra_postargs=None, | |
136 | build_temp=None): | |
137 | ||
138 | (objects, output_dir) = self._fix_object_args (objects, output_dir) | |
139 | (libraries, library_dirs, runtime_library_dirs) = \ | |
140 | self._fix_lib_args (libraries, library_dirs, runtime_library_dirs) | |
141 | ||
142 | if runtime_library_dirs: | |
143 | self.warn ("I don't know what to do with 'runtime_library_dirs': " | |
144 | + str (runtime_library_dirs)) | |
145 | ||
146 | lib_opts = gen_lib_options (self, | |
147 | library_dirs, runtime_library_dirs, | |
148 | libraries) | |
149 | if output_dir is not None: | |
150 | output_filename = os.path.join (output_dir, output_filename) | |
151 | ||
152 | if self._need_link (objects, output_filename): | |
153 | ||
154 | if target_desc == CCompiler.EXECUTABLE: | |
155 | if debug: | |
156 | ldflags = self.ldflags_shared_debug[1:] | |
157 | else: | |
158 | ldflags = self.ldflags_shared[1:] | |
159 | else: | |
160 | if debug: | |
161 | ldflags = self.ldflags_shared_debug | |
162 | else: | |
163 | ldflags = self.ldflags_shared | |
164 | ||
165 | export_opts = [] | |
166 | for sym in (export_symbols or []): | |
167 | export_opts.append("/EXPORT:" + sym) | |
168 | ||
169 | ld_args = (ldflags + lib_opts + export_opts + | |
170 | objects + ['/OUT:' + output_filename]) | |
171 | ||
172 | # The MSVC linker generates .lib and .exp files, which cannot be | |
173 | # suppressed by any linker switches. The .lib files may even be | |
174 | # needed! Make sure they are generated in the temporary build | |
175 | # directory. Since they have different names for debug and release | |
176 | # builds, they can go into the same directory. | |
177 | if export_symbols is not None: | |
178 | (dll_name, dll_ext) = os.path.splitext( | |
179 | os.path.basename(output_filename)) | |
180 | ||
181 | ## The old code | |
182 | ##implib_file = os.path.join( | |
183 | ## os.path.dirname(objects[0]), | |
184 | ## self.library_filename(dll_name)) | |
185 | ||
186 | ## The new | |
187 | implib_file = os.path.join('build', 'ilib', | |
188 | self.library_filename(dll_name)) | |
189 | self.mkpath(os.path.dirname(implib_file)) | |
190 | ||
191 | ld_args.append ('/IMPLIB:' + implib_file) | |
192 | ||
193 | if extra_preargs: | |
194 | ld_args[:0] = extra_preargs | |
195 | if extra_postargs: | |
196 | ld_args.extend(extra_postargs) | |
197 | ||
198 | self.mkpath (os.path.dirname (output_filename)) | |
199 | try: | |
200 | self.spawn ([self.linker] + ld_args) | |
201 | except DistutilsExecError, msg: | |
202 | raise LinkError, msg | |
203 | ||
204 | else: | |
205 | self.announce ("skipping %s (up-to-date)" % output_filename) | |
206 | ||
207 | # link () | |
208 | ||
209 | ||
210 | ||
211 | #---------------------------------------------------------------------- | |
212 | # Hack this module and class into the distutils... | |
213 | ||
214 | from distutils import ccompiler | |
215 | ||
216 | ccompiler.default_compiler['nt'] = 'my_msvc' | |
217 | ccompiler.compiler_class['my_msvc'] = ('my_distutils', | |
218 | 'MyMSVCCompiler', | |
219 | 'My MSVC derived class') | |
220 | ||
221 | ||
222 | # make it look like it is part of the package... | |
223 | import my_distutils | |
224 | sys.modules['distutils.my_distutils'] = my_distutils | |
225 | ||
226 | ||
227 | ||
228 | ||
229 | #---------------------------------------------------------------------- | |
230 | # Run SWIG the way I want it done | |
231 | ||
232 | def run_swig(files, dir, gendir, package, USE_SWIG, force, swig_args, swig_deps=[]): | |
233 | from distutils.file_util import copy_file | |
234 | from distutils.dep_util import newer | |
235 | from distutils.spawn import spawn | |
236 | ||
237 | sources = [] | |
238 | ||
239 | for file in files: | |
240 | basefile = os.path.splitext(file)[0] | |
241 | i_file = os.path.join(dir, file) | |
242 | py_file = os.path.join(dir, gendir, basefile+'.py') | |
243 | cpp_file = os.path.join(dir, gendir, basefile+'.cpp') | |
244 | ||
245 | sources.append(cpp_file) | |
246 | ||
247 | if USE_SWIG: | |
248 | for dep in swig_deps: | |
249 | if newer(dep, py_file) or newer(dep, cpp_file): | |
250 | force = 1 | |
251 | break | |
252 | ||
253 | if force or newer(i_file, py_file) or newer(i_file, cpp_file): | |
254 | # we need forward slashes here even on win32 | |
255 | cpp_file = string.join(string.split(cpp_file, '\\'), '/') | |
256 | i_file = string.join(string.split(i_file, '\\'), '/') | |
257 | ||
258 | cmd = ['swig'] + swig_args + ['-I'+dir, '-c', '-o', cpp_file, i_file] | |
259 | spawn(cmd, verbose=1) | |
260 | ||
261 | # copy the generated python file to the package directory | |
262 | copy_file(py_file, package, update=not force, verbose=0) | |
263 | ||
264 | ||
265 | return sources | |
266 | ||
267 | ||
268 | ||
269 | #---------------------------------------------------------------------- | |
270 | # Update local copies of wxWindows contrib files | |
271 | ||
272 | ||
273 | def contrib_copy_tree(src, dest, verbose=0): | |
274 | from distutils.dir_util import mkpath, copy_tree | |
275 | ||
276 | mkpath(dest, verbose=verbose) | |
277 | copy_tree(src, dest, update=1, verbose=verbose) | |
278 |