X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/185d7c3ee4c6e4a9ddaf811ae38e57d68a0fdff3..d062e17fca1a1fc0b82b269da4a7ad271075ba2b:/wxPython/my_distutils.py diff --git a/wxPython/my_distutils.py b/wxPython/my_distutils.py index 9d66065ff0..cbff3b4e99 100644 --- a/wxPython/my_distutils.py +++ b/wxPython/my_distutils.py @@ -2,6 +2,7 @@ import sys, os, string from distutils.msvccompiler import MSVCCompiler +from distutils.bcppcompiler import BCPPCompiler from distutils.errors import \ DistutilsExecError, DistutilsPlatformError, \ @@ -53,15 +54,15 @@ class MyMSVCCompiler(MSVCCompiler): self.mkpath (os.path.dirname (obj)) if ext in self._c_extensions: - input_opt = "/Tc" + os.path.abspath(src) + input_opt = "/Tc" + os.path.abspath(src) ### RPD elif ext in self._cpp_extensions: - input_opt = "/Tp" + os.path.abspath(src) + input_opt = "/Tp" + os.path.abspath(src) ### RPD elif ext in self._rc_extensions: # compile .RC to .RES file input_opt = src output_opt = "/fo" + obj try: - self.spawn ([self.rc] + pp_opts + ### RPD changed this line only + self.spawn ([self.rc] + pp_opts + ### RPD changed this line [output_opt] + [input_opt]) except DistutilsExecError, msg: raise CompileError, msg @@ -115,12 +116,98 @@ class MyMSVCCompiler(MSVCCompiler): +from distutils.file_util import write_file +class MyBCPPCompiler(BCPPCompiler): + ##------------------------------------------------------------ - ## Now override the link() method to change where the import - ## library is placed. Hopefully distutils will be updated - ## someday to make this configurable... + ## Override the entire compile method just to add flags to the + ## RC command. There should be an easier way to do this from + ## distutils directly or in a derived class... ##------------------------------------------------------------ + def compile (self, + sources, + output_dir=None, + macros=None, + include_dirs=None, + debug=0, + extra_preargs=None, + extra_postargs=None): + + (output_dir, macros, include_dirs) = \ + self._fix_compile_args (output_dir, macros, include_dirs) + (objects, skip_sources) = self._prep_compile (sources, output_dir) + + if extra_postargs is None: + extra_postargs = [] + + pp_opts = gen_preprocess_options (macros, include_dirs) + compile_opts = extra_preargs or [] + compile_opts.append ('-c') + if debug: + compile_opts.extend (self.compile_options_debug) + else: + compile_opts.extend (self.compile_options) + + for i in range (len (sources)): + src = sources[i] ; obj = objects[i] + ext = (os.path.splitext (src))[1] + + if skip_sources[src]: + self.announce ("skipping %s (%s up-to-date)" % (src, obj)) + else: + src = os.path.normpath(src) + obj = os.path.normpath(obj) + self.mkpath(os.path.dirname(obj)) + + if ext == '.res': + # This is already a binary file -- skip it. + continue # the 'for' loop + if ext == '.rc': + # This needs to be compiled to a .res file -- do it now. + try: + self.spawn (["brcc32"] + pp_opts + ["-fo"] + + [obj] + [src]) ### RPD changed this lines only + except DistutilsExecError, msg: + raise CompileError, msg + continue # the 'for' loop + + # The next two are both for the real compiler. + if ext in self._c_extensions: + input_opt = "" + elif ext in self._cpp_extensions: + input_opt = "-P" + else: + # Unknown file type -- no extra options. The compiler + # will probably fail, but let it just in case this is a + # file the compiler recognizes even if we don't. + input_opt = "" + + output_opt = "-o" + obj + + # Compiler command line syntax is: "bcc32 [options] file(s)". + # Note that the source file names must appear at the end of + # the command line. + try: + self.spawn ([self.cc] + compile_opts + pp_opts + + [input_opt, output_opt] + + extra_postargs + [src]) + except DistutilsExecError, msg: + raise CompileError, msg + + return objects + + # compile () + + #################################################################### + # Now we need to replace cw32mt library used by default by distutils + # with cw32mti library as in wxWindows DLL make file + # Othervise we obtain Windows "Core dump" ;-). + # + # Evgeny A Cherkashin + # + #################################################################### + def link (self, target_desc, objects, @@ -135,6 +222,9 @@ class MyMSVCCompiler(MSVCCompiler): extra_postargs=None, build_temp=None): + # XXX this ignores 'build_temp'! should follow the lead of + # msvccompiler.py + (objects, output_dir) = self._fix_object_args (objects, output_dir) (libraries, library_dirs, runtime_library_dirs) = \ self._fix_lib_args (libraries, library_dirs, runtime_library_dirs) @@ -143,52 +233,98 @@ class MyMSVCCompiler(MSVCCompiler): self.warn ("I don't know what to do with 'runtime_library_dirs': " + str (runtime_library_dirs)) - lib_opts = gen_lib_options (self, - library_dirs, runtime_library_dirs, - libraries) if output_dir is not None: output_filename = os.path.join (output_dir, output_filename) if self._need_link (objects, output_filename): + # Figure out linker args based on type of target. if target_desc == CCompiler.EXECUTABLE: + startup_obj = 'c0w32' if debug: - ldflags = self.ldflags_shared_debug[1:] + ld_args = self.ldflags_exe_debug[:] else: - ldflags = self.ldflags_shared[1:] + ld_args = self.ldflags_exe[:] else: + startup_obj = 'c0d32' if debug: - ldflags = self.ldflags_shared_debug + ld_args = self.ldflags_shared_debug[:] else: - ldflags = self.ldflags_shared + ld_args = self.ldflags_shared[:] - export_opts = [] - for sym in (export_symbols or []): - export_opts.append("/EXPORT:" + sym) - ld_args = (ldflags + lib_opts + export_opts + - objects + ['/OUT:' + output_filename]) - - # The MSVC linker generates .lib and .exp files, which cannot be - # suppressed by any linker switches. The .lib files may even be - # needed! Make sure they are generated in the temporary build - # directory. Since they have different names for debug and release - # builds, they can go into the same directory. - if export_symbols is not None: - (dll_name, dll_ext) = os.path.splitext( - os.path.basename(output_filename)) + # Create a temporary exports file for use by the linker + if export_symbols is None: + def_file = '' + else: + head, tail = os.path.split (output_filename) + modname, ext = os.path.splitext (tail) + temp_dir = os.path.dirname(objects[0]) # preserve tree structure + def_file = os.path.join (temp_dir, '%s.def' % modname) + contents = ['EXPORTS'] + for sym in (export_symbols or []): + contents.append(' %s=_%s' % (sym, sym)) + self.execute(write_file, (def_file, contents), + "writing %s" % def_file) + + # Borland C++ has problems with '/' in paths + objects2 = map(os.path.normpath, objects) + # split objects in .obj and .res files + # Borland C++ needs them at different positions in the command line + objects = [startup_obj] + resources = [] + for file in objects2: + (base, ext) = os.path.splitext(os.path.normcase(file)) + if ext == '.res': + resources.append(file) + else: + objects.append(file) + + + for l in library_dirs: + ld_args.append("/L%s" % os.path.normpath(l)) + ld_args.append("/L.") # we sometimes use relative paths + + # list of object files + ld_args.extend(objects) + + # XXX the command-line syntax for Borland C++ is a bit wonky; + # certain filenames are jammed together in one big string, but + # comma-delimited. This doesn't mesh too well with the + # Unix-centric attitude (with a DOS/Windows quoting hack) of + # 'spawn()', so constructing the argument list is a bit + # awkward. Note that doing the obvious thing and jamming all + # the filenames and commas into one argument would be wrong, + # because 'spawn()' would quote any filenames with spaces in + # them. Arghghh!. Apparently it works fine as coded... + + # name of dll/exe file + ld_args.extend([',',output_filename]) + # no map file and start libraries + ld_args.append(',,') + + for lib in libraries: + # see if we find it and if there is a bcpp specific lib + # (xxx_bcpp.lib) + libfile = self.find_library_file(library_dirs, lib, debug) + if libfile is None: + ld_args.append(lib) + # probably a BCPP internal library -- don't warn + # self.warn('library %s not found.' % lib) + else: + # full name which prefers bcpp_xxx.lib over xxx.lib + ld_args.append(libfile) - ## The old code - ##implib_file = os.path.join( - ## os.path.dirname(objects[0]), - ## self.library_filename(dll_name)) + # some default libraries + ld_args.append ('import32') + ld_args.append ('cw32mti') ### mt->mti (as in wx2) - ## The new - implib_file = os.path.join('build', 'ilib', - self.library_filename(dll_name)) - self.mkpath(os.path.dirname(implib_file)) + # def file for export symbols + ld_args.extend([',',def_file]) + # add resource files + ld_args.append(',') + ld_args.extend(resources) - ld_args.append ('/IMPLIB:' + implib_file) if extra_preargs: ld_args[:0] = extra_preargs @@ -213,17 +349,73 @@ class MyMSVCCompiler(MSVCCompiler): from distutils import ccompiler -ccompiler.default_compiler['nt'] = 'my_msvc' +if hasattr(ccompiler, "default_compiler"): + ccompiler.default_compiler['nt'] = 'my_msvc' +elif hasattr(ccompiler, "_default_compilers"): + lst = list(ccompiler._default_compilers) + lst.remove( ('nt', 'msvc') ) + lst.append( ('nt', 'my_msvc') ) + ccompiler._default_compilers = tuple(lst) + + ccompiler.compiler_class['my_msvc'] = ('my_distutils', 'MyMSVCCompiler', 'My MSVC derived class') +ccompiler.compiler_class['my_bcpp'] = ('my_distutils', + 'MyBCPPCompiler', + 'My BCPP derived class') + # make it look like it is part of the package... import my_distutils sys.modules['distutils.my_distutils'] = my_distutils +#---------------------------------------------------------------------- +# More hacking... Distutils in Python 2.1 changed the strip_dir flag +# passed to object_filenames to true, which causes problems for us since +# there are a few duplicate source/object names between some of the +# extensions in wxPython. This hack replaces the CCompiler._prep_compile +# method with this one. + +from distutils.dep_util import newer_pairwise + +def _prep_compile (self, sources, output_dir): + """Determine the list of object files corresponding to 'sources', + and figure out which ones really need to be recompiled. Return a + list of all object files and a dictionary telling which source + files can be skipped. + """ + # Get the list of expected output (object) files + objects = self.object_filenames (sources, + strip_dir=0, + output_dir=output_dir) + + if self.force: + skip_source = {} # rebuild everything + for source in sources: + skip_source[source] = 0 + else: + # Figure out which source files we have to recompile according + # to a simplistic check -- we just compare the source and + # object file, no deep dependency checking involving header + # files. + skip_source = {} # rebuild everything + for source in sources: # no wait, rebuild nothing + skip_source[source] = 1 + + (n_sources, n_objects) = newer_pairwise (sources, objects) + for source in n_sources: # no really, only rebuild what's + skip_source[source] = 0 # out-of-date + + return (objects, skip_source) + +# _prep_compile () + +CCompiler._prep_compile = _prep_compile + + #----------------------------------------------------------------------