From 1bba31d9a2dd24824a36b7e02cab7a9502587269 Mon Sep 17 00:00:00 2001 From: Jeremy Hylton Date: Thu, 13 Jun 2002 17:28:18 +0000 Subject: [PATCH] Refactor compile() method implementations. Always use _setup_compile() to do the grunt work of processing arguments, figuring out which files to compile, and emitting debug messages for files that are up-to-date. Use _get_cc_args() when possible. --- Lib/distutils/bcppcompiler.py | 101 +++++++++------------ Lib/distutils/cygwinccompiler.py | 83 ++++++----------- Lib/distutils/emxccompiler.py | 65 +++++-------- Lib/distutils/msvccompiler.py | 151 ++++++++++++++----------------- Lib/distutils/unixccompiler.py | 40 +++----- 5 files changed, 173 insertions(+), 267 deletions(-) diff --git a/Lib/distutils/bcppcompiler.py b/Lib/distutils/bcppcompiler.py index 019244cd16c..6e9d6c64de7 100644 --- a/Lib/distutils/bcppcompiler.py +++ b/Lib/distutils/bcppcompiler.py @@ -80,23 +80,13 @@ class BCPPCompiler(CCompiler) : # -- Worker methods ------------------------------------------------ - 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) + def compile(self, sources, + output_dir=None, macros=None, include_dirs=None, debug=0, + extra_preargs=None, extra_postargs=None, depends=None): + + macros, objects, extra_postargs, pp_opts, build = \ + self._setup_compile(output_dir, macros, include_dirs, sources, + depends, extra_postargs) compile_opts = extra_preargs or [] compile_opts.append ('-c') if debug: @@ -104,50 +94,47 @@ class BCPPCompiler(CCompiler) : 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] + for obj, (src, ext) in build.items(): + # XXX why do the normpath here? + src = os.path.normpath(src) + obj = os.path.normpath(obj) + # XXX _setup_compile() did a mkpath() too but before the normpath. + # Is it possible to skip the normpath? + self.mkpath(os.path.dirname(obj)) - if skip_sources[src]: - log.debug("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", "-fo", obj, src]) - 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. + 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 ([self.cc] + compile_opts + pp_opts + - [input_opt, output_opt] + - extra_postargs + [src]) + self.spawn (["brcc32", "-fo", obj, src]) 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 diff --git a/Lib/distutils/cygwinccompiler.py b/Lib/distutils/cygwinccompiler.py index 443c9bcfb70..302293ac25f 100644 --- a/Lib/distutils/cygwinccompiler.py +++ b/Lib/distutils/cygwinccompiler.py @@ -62,10 +62,7 @@ class CygwinCCompiler (UnixCCompiler): shared_lib_format = "%s%s" exe_extension = ".exe" - def __init__ (self, - verbose=0, - dry_run=0, - force=0): + def __init__ (self, verbose=0, dry_run=0, force=0): UnixCCompiler.__init__ (self, verbose, dry_run, force) @@ -74,11 +71,12 @@ class CygwinCCompiler (UnixCCompiler): (status, details)) if status is not CONFIG_H_OK: self.warn( - "Python's pyconfig.h doesn't seem to support your compiler. " + - ("Reason: %s." % details) + - "Compiling may fail because of undefined preprocessor macros.") + "Python's pyconfig.h doesn't seem to support your compiler. " + "Reason: %s. " + "Compiling may fail because of undefined preprocessor macros." + % details) - (self.gcc_version, self.ld_version, self.dllwrap_version) = \ + self.gcc_version, self.ld_version, self.dllwrap_version = \ get_versions() self.debug_print(self.compiler_type + ": gcc %s, ld %s, dllwrap %s\n" % (self.gcc_version, @@ -120,58 +118,33 @@ class CygwinCCompiler (UnixCCompiler): # we put here a adapted version of it. # (If we would call compile() in the base class, it would do some # initializations a second time, this is why all is done here.) - def compile (self, - sources, - output_dir=None, - macros=None, - include_dirs=None, - debug=0, - extra_preargs=None, - extra_postargs=None): + def compile(self, sources, + output_dir=None, macros=None, include_dirs=None, debug=0, + extra_preargs=None, extra_postargs=None, depends=None): + + macros, objects, extra_postargs, pp_opts, build = \ + self._setup_compile(output_dir, macros, include_dirs, sources, + depends, extra_postargs) + cc_args = self._get_cc_args(pp_opts, debug, extra_preargs) - (output_dir, macros, include_dirs) = \ - self._fix_compile_args (output_dir, macros, include_dirs) - (objects, skip_sources) = self._prep_compile (sources, output_dir) - - # Figure out the options for the compiler command line. - pp_opts = gen_preprocess_options (macros, include_dirs) - cc_args = pp_opts + ['-c'] - if debug: - cc_args[:0] = ['-g'] - if extra_preargs: - cc_args[:0] = extra_preargs - if extra_postargs is None: - extra_postargs = [] - - # Compile all source files that weren't eliminated by - # '_prep_compile()'. - for i in range (len (sources)): - src = sources[i] ; obj = objects[i] - ext = (os.path.splitext (src))[1] - if skip_sources[src]: - log.debug("skipping %s (%s up-to-date)", src, obj) - else: - self.mkpath (os.path.dirname (obj)) - if ext == '.rc' or ext == '.res': - # gcc needs '.res' and '.rc' compiled to object files !!! - try: - self.spawn (["windres","-i",src,"-o",obj]) - except DistutilsExecError, msg: - raise CompileError, msg - else: # for other files use the C-compiler - try: - self.spawn (self.compiler_so + cc_args + - [src, '-o', obj] + - extra_postargs) - except DistutilsExecError, msg: - raise CompileError, msg + for obj, (src, ext) in build.items(): + if ext == '.rc' or ext == '.res': + # gcc needs '.res' and '.rc' compiled to object files !!! + try: + self.spawn (["windres","-i",src,"-o",obj]) + except DistutilsExecError, msg: + raise CompileError, msg + else: # for other files use the C-compiler + try: + self.spawn (self.compiler_so + cc_args + + [src, '-o', obj] + + extra_postargs) + except DistutilsExecError, msg: + raise CompileError, msg # Return *all* object filenames, not just the ones we just built. return objects - # compile () - - def link (self, target_desc, objects, diff --git a/Lib/distutils/emxccompiler.py b/Lib/distutils/emxccompiler.py index 644c6fc3912..c2c73b0dec9 100644 --- a/Lib/distutils/emxccompiler.py +++ b/Lib/distutils/emxccompiler.py @@ -81,51 +81,30 @@ class EMXCCompiler (UnixCCompiler): # we put here a adapted version of it. # (If we would call compile() in the base class, it would do some # initializations a second time, this is why all is done here.) - 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) + def compile(self, sources, + output_dir=None, macros=None, include_dirs=None, debug=0, + extra_preargs=None, extra_postargs=None, depends=None): + + macros, objects, extra_postargs, pp_opts, build = \ + self._setup_compile(output_dir, macros, include_dirs, sources, + depends, extra_postargs) + cc_args = self._get_cc_args(pp_opts, debug, extra_preargs) - # Figure out the options for the compiler command line. - pp_opts = gen_preprocess_options (macros, include_dirs) - cc_args = pp_opts + ['-c'] - if debug: - cc_args[:0] = ['-g'] - if extra_preargs: - cc_args[:0] = extra_preargs - if extra_postargs is None: - extra_postargs = [] - - # Compile all source files that weren't eliminated by - # '_prep_compile()'. - for i in range (len (sources)): - src = sources[i] ; obj = objects[i] - ext = (os.path.splitext (src))[1] - if skip_sources[src]: - log.debug("skipping %s (%s up-to-date)", src, obj) - else: - self.mkpath (os.path.dirname (obj)) - if ext == '.rc': - # gcc requires '.rc' compiled to binary ('.res') files !!! - try: - self.spawn (["rc","-r",src]) - except DistutilsExecError, msg: - raise CompileError, msg - else: # for other files use the C-compiler - try: - self.spawn (self.compiler_so + cc_args + - [src, '-o', obj] + - extra_postargs) - except DistutilsExecError, msg: - raise CompileError, msg + for obj, (src, ext) in build.items(): + if ext == '.rc': + # gcc requires '.rc' compiled to binary ('.res') files !!! + try: + self.spawn (["rc","-r",src]) + except DistutilsExecError, msg: + raise CompileError, msg + else: # for other files use the C-compiler + try: + self.spawn (self.compiler_so + cc_args + + [src, '-o', obj] + + extra_postargs) + except DistutilsExecError, msg: + raise CompileError, msg # Return *all* object filenames, not just the ones we just built. return objects diff --git a/Lib/distutils/msvccompiler.py b/Lib/distutils/msvccompiler.py index ade8172d3bb..8460eea9677 100644 --- a/Lib/distutils/msvccompiler.py +++ b/Lib/distutils/msvccompiler.py @@ -277,101 +277,84 @@ class MSVCCompiler (CCompiler) : # object_filenames () - def compile (self, - sources, - output_dir=None, - macros=None, - include_dirs=None, - debug=0, - extra_preargs=None, - extra_postargs=None): + def compile(self, sources, + output_dir=None, macros=None, include_dirs=None, debug=0, + extra_preargs=None, extra_postargs=None, depends=None): - (output_dir, macros, include_dirs) = \ - self._fix_compile_args (output_dir, macros, include_dirs) - (objects, skip_sources) = self._prep_compile (sources, output_dir) + macros, objects, extra_postargs, pp_opts, build = \ + self._setup_compile(output_dir, macros, include_dirs, sources, + depends, extra_postargs) - 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) + compile_opts.extend(self.compile_options_debug) else: - compile_opts.extend (self.compile_options) + compile_opts.extend(self.compile_options) - for i in range (len (sources)): - src = sources[i] ; obj = objects[i] - ext = (os.path.splitext (src))[1] + for obj, (src, ext) in build.items(): + if debug: + # pass the full pathname to MSVC in debug mode, + # this allows the debugger to find the source file + # without asking the user to browse for it + src = os.path.abspath(src) - if skip_sources[src]: - log.debug("skipping %s (%s up-to-date)", src, obj) - else: - self.mkpath (os.path.dirname (obj)) - - if debug: - # pass the full pathname to MSVC in debug mode, - # this allows the debugger to find the source file - # without asking the user to browse for it - src = os.path.abspath(src) - - if ext in self._c_extensions: - input_opt = "/Tc" + src - elif ext in self._cpp_extensions: - input_opt = "/Tp" + src - elif ext in self._rc_extensions: - # compile .RC to .RES file - input_opt = src - output_opt = "/fo" + obj - try: - self.spawn ([self.rc] + - [output_opt] + [input_opt]) - except DistutilsExecError, msg: - raise CompileError, msg - continue - elif ext in self._mc_extensions: - - # Compile .MC to .RC file to .RES file. - # * '-h dir' specifies the directory for the - # generated include file - # * '-r dir' specifies the target directory of the - # generated RC file and the binary message resource - # it includes - # - # For now (since there are no options to change this), - # we use the source-directory for the include file and - # the build directory for the RC file and message - # resources. This works at least for win32all. - - h_dir = os.path.dirname (src) - rc_dir = os.path.dirname (obj) - try: - # first compile .MC to .RC and .H file - self.spawn ([self.mc] + - ['-h', h_dir, '-r', rc_dir] + [src]) - base, _ = os.path.splitext (os.path.basename (src)) - rc_file = os.path.join (rc_dir, base + '.rc') - # then compile .RC to .RES file - self.spawn ([self.rc] + - ["/fo" + obj] + [rc_file]) - - except DistutilsExecError, msg: - raise CompileError, msg - continue - else: - # how to handle this file? - raise CompileError ( - "Don't know how to compile %s to %s" % \ - (src, obj)) - - output_opt = "/Fo" + obj + if ext in self._c_extensions: + input_opt = "/Tc" + src + elif ext in self._cpp_extensions: + input_opt = "/Tp" + src + elif ext in self._rc_extensions: + # compile .RC to .RES file + input_opt = src + output_opt = "/fo" + obj try: - self.spawn ([self.cc] + compile_opts + pp_opts + - [input_opt, output_opt] + - extra_postargs) + self.spawn ([self.rc] + + [output_opt] + [input_opt]) except DistutilsExecError, msg: raise CompileError, msg + continue + elif ext in self._mc_extensions: + + # Compile .MC to .RC file to .RES file. + # * '-h dir' specifies the directory for the + # generated include file + # * '-r dir' specifies the target directory of the + # generated RC file and the binary message resource + # it includes + # + # For now (since there are no options to change this), + # we use the source-directory for the include file and + # the build directory for the RC file and message + # resources. This works at least for win32all. + + h_dir = os.path.dirname (src) + rc_dir = os.path.dirname (obj) + try: + # first compile .MC to .RC and .H file + self.spawn ([self.mc] + + ['-h', h_dir, '-r', rc_dir] + [src]) + base, _ = os.path.splitext (os.path.basename (src)) + rc_file = os.path.join (rc_dir, base + '.rc') + # then compile .RC to .RES file + self.spawn ([self.rc] + + ["/fo" + obj] + [rc_file]) + + except DistutilsExecError, msg: + raise CompileError, msg + continue + else: + # how to handle this file? + raise CompileError ( + "Don't know how to compile %s to %s" % \ + (src, obj)) + + output_opt = "/Fo" + obj + try: + self.spawn ([self.cc] + compile_opts + pp_opts + + [input_opt, output_opt] + + extra_postargs) + except DistutilsExecError, msg: + raise CompileError, msg return objects diff --git a/Lib/distutils/unixccompiler.py b/Lib/distutils/unixccompiler.py index abf7a2643be..c887a882261 100644 --- a/Lib/distutils/unixccompiler.py +++ b/Lib/distutils/unixccompiler.py @@ -107,35 +107,19 @@ class UnixCCompiler(CCompiler): 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) + extra_preargs=None, extra_postargs=None, depends=None): + + macros, objects, extra_postargs, pp_opts, build = \ + self._setup_compile(output_dir, macros, include_dirs, sources, + depends, extra_postargs) + cc_args = self._get_cc_args(pp_opts, debug, extra_preargs) - # Figure out the options for the compiler command line. - pp_opts = gen_preprocess_options(macros, include_dirs) - cc_args = pp_opts + ['-c'] - if debug: - cc_args[:0] = ['-g'] - if extra_preargs: - cc_args[:0] = extra_preargs - if extra_postargs is None: - extra_postargs = [] - - # Compile all source files that weren't eliminated by - # '_prep_compile()'. - for i in range(len(sources)): - src = sources[i] - obj = objects[i] - if skip_sources[src]: - log.debug("skipping %s (%s up-to-date)", src, obj) - else: - self.mkpath(os.path.dirname(obj)) - try: - self.spawn(self.compiler_so + cc_args + - [src, '-o', obj] + extra_postargs) - except DistutilsExecError, msg: - raise CompileError, msg + for obj, (src, ext) in build.items(): + try: + self.spawn(self.compiler_so + cc_args + + [src, '-o', obj] + extra_postargs) + except DistutilsExecError, msg: + raise CompileError, msg # Return *all* object filenames, not just the ones we just built. return objects