Package SCons :: Module SConf
[hide private]
[frames] | no frames]

Source Code for Module SCons.SConf

   1  """SCons.SConf 
   2   
   3  Autoconf-like configuration support. 
   4  """ 
   5   
   6  # 
   7  # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation 
   8  # 
   9  # Permission is hereby granted, free of charge, to any person obtaining 
  10  # a copy of this software and associated documentation files (the 
  11  # "Software"), to deal in the Software without restriction, including 
  12  # without limitation the rights to use, copy, modify, merge, publish, 
  13  # distribute, sublicense, and/or sell copies of the Software, and to 
  14  # permit persons to whom the Software is furnished to do so, subject to 
  15  # the following conditions: 
  16  # 
  17  # The above copyright notice and this permission notice shall be included 
  18  # in all copies or substantial portions of the Software. 
  19  # 
  20  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY 
  21  # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 
  22  # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
  23  # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 
  24  # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 
  25  # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 
  26  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
  27  # 
  28   
  29  __revision__ = "src/engine/SCons/SConf.py 3765 2008/11/04 08:12:16 scons" 
  30   
  31  import os 
  32  import re 
  33  import string 
  34  import StringIO 
  35  import sys 
  36  import traceback 
  37  import types 
  38   
  39  import SCons.Action 
  40  import SCons.Builder 
  41  import SCons.Errors 
  42  import SCons.Job 
  43  import SCons.Node.FS 
  44  import SCons.Taskmaster 
  45  import SCons.Util 
  46  import SCons.Warnings 
  47  import SCons.Conftest 
  48   
  49  from SCons.Debug import Trace 
  50   
  51  # Turn off the Conftest error logging 
  52  SCons.Conftest.LogInputFiles = 0 
  53  SCons.Conftest.LogErrorMessages = 0 
  54   
  55  # Set 
  56  build_type = None 
  57  build_types = ['clean', 'help'] 
  58   
59 -def SetBuildType(type):
60 global build_type 61 build_type = type
62 63 # to be set, if we are in dry-run mode 64 dryrun = 0 65 66 AUTO=0 # use SCons dependency scanning for up-to-date checks 67 FORCE=1 # force all tests to be rebuilt 68 CACHE=2 # force all tests to be taken from cache (raise an error, if necessary) 69 cache_mode = AUTO 70
71 -def SetCacheMode(mode):
72 """Set the Configure cache mode. mode must be one of "auto", "force", 73 or "cache".""" 74 global cache_mode 75 if mode == "auto": 76 cache_mode = AUTO 77 elif mode == "force": 78 cache_mode = FORCE 79 elif mode == "cache": 80 cache_mode = CACHE 81 else: 82 raise ValueError, "SCons.SConf.SetCacheMode: Unknown mode " + mode
83 84 progress_display = SCons.Util.display # will be overwritten by SCons.Script
85 -def SetProgressDisplay(display):
86 """Set the progress display to use (called from SCons.Script)""" 87 global progress_display 88 progress_display = display
89 90 SConfFS = None 91 92 _ac_build_counter = 0 # incremented, whenever TryBuild is called 93 _ac_config_logs = {} # all config.log files created in this build 94 _ac_config_hs = {} # all config.h files created in this build 95 sconf_global = None # current sconf object 96
97 -def _createConfigH(target, source, env):
98 t = open(str(target[0]), "w") 99 defname = re.sub('[^A-Za-z0-9_]', '_', string.upper(str(target[0]))) 100 t.write("""#ifndef %(DEFNAME)s_SEEN 101 #define %(DEFNAME)s_SEEN 102 103 """ % {'DEFNAME' : defname}) 104 t.write(source[0].get_contents()) 105 t.write(""" 106 #endif /* %(DEFNAME)s_SEEN */ 107 """ % {'DEFNAME' : defname}) 108 t.close()
109
110 -def _stringConfigH(target, source, env):
111 return "scons: Configure: creating " + str(target[0])
112
113 -def CreateConfigHBuilder(env):
114 """Called just before the building targets phase begins.""" 115 if len(_ac_config_hs) == 0: 116 return 117 action = SCons.Action.Action(_createConfigH, 118 _stringConfigH) 119 sconfigHBld = SCons.Builder.Builder(action=action) 120 env.Append( BUILDERS={'SConfigHBuilder':sconfigHBld} ) 121 for k in _ac_config_hs.keys(): 122 env.SConfigHBuilder(k, env.Value(_ac_config_hs[k]))
123
124 -class SConfWarning(SCons.Warnings.Warning):
125 pass
126 SCons.Warnings.enableWarningClass(SConfWarning) 127 128 # some error definitions
129 -class SConfError(SCons.Errors.UserError):
130 - def __init__(self,msg):
132
133 -class ConfigureDryRunError(SConfError):
134 """Raised when a file or directory needs to be updated during a Configure 135 process, but the user requested a dry-run"""
136 - def __init__(self,target):
137 if not isinstance(target, SCons.Node.FS.File): 138 msg = 'Cannot create configure directory "%s" within a dry-run.' % str(target) 139 else: 140 msg = 'Cannot update configure test "%s" within a dry-run.' % str(target) 141 SConfError.__init__(self,msg)
142
143 -class ConfigureCacheError(SConfError):
144 """Raised when a use explicitely requested the cache feature, but the test 145 is run the first time."""
146 - def __init__(self,target):
147 SConfError.__init__(self, '"%s" is not yet built and cache is forced.' % str(target))
148 149 # define actions for building text files
150 -def _createSource( target, source, env ):
151 fd = open(str(target[0]), "w") 152 fd.write(source[0].get_contents()) 153 fd.close()
154 -def _stringSource( target, source, env ):
155 return (str(target[0]) + ' <-\n |' + 156 string.replace( source[0].get_contents(), 157 '\n', "\n |" ) )
158 159 # python 2.2 introduces types.BooleanType 160 BooleanTypes = [types.IntType] 161 if hasattr(types, 'BooleanType'): BooleanTypes.append(types.BooleanType) 162
163 -class SConfBuildInfo(SCons.Node.FS.FileBuildInfo):
164 """ 165 Special build info for targets of configure tests. Additional members 166 are result (did the builder succeed last time?) and string, which 167 contains messages of the original build phase. 168 """ 169 result = None # -> 0/None -> no error, != 0 error 170 string = None # the stdout / stderr output when building the target 171
172 - def set_build_result(self, result, string):
173 self.result = result 174 self.string = string
175 176
177 -class Streamer:
178 """ 179 'Sniffer' for a file-like writable object. Similar to the unix tool tee. 180 """
181 - def __init__(self, orig):
182 self.orig = orig 183 self.s = StringIO.StringIO()
184
185 - def write(self, str):
186 if self.orig: 187 self.orig.write(str) 188 self.s.write(str)
189
190 - def writelines(self, lines):
191 for l in lines: 192 self.write(l + '\n')
193
194 - def getvalue(self):
195 """ 196 Return everything written to orig since the Streamer was created. 197 """ 198 return self.s.getvalue()
199
200 - def flush(self):
201 if self.orig: 202 self.orig.flush() 203 self.s.flush()
204 205
206 -class SConfBuildTask(SCons.Taskmaster.Task):
207 """ 208 This is almost the same as SCons.Script.BuildTask. Handles SConfErrors 209 correctly and knows about the current cache_mode. 210 """
211 - def display(self, message):
212 if sconf_global.logstream: 213 sconf_global.logstream.write("scons: Configure: " + message + "\n")
214
215 - def display_cached_string(self, bi):
216 """ 217 Logs the original builder messages, given the SConfBuildInfo instance 218 bi. 219 """ 220 if not isinstance(bi, SConfBuildInfo): 221 SCons.Warnings.warn(SConfWarning, 222 "The stored build information has an unexpected class: %s" % bi.__class__) 223 else: 224 self.display("The original builder output was:\n" + 225 string.replace(" |" + str(bi.string), 226 "\n", "\n |"))
227
228 - def failed(self):
229 # check, if the reason was a ConfigureDryRunError or a 230 # ConfigureCacheError and if yes, reraise the exception 231 exc_type = self.exc_info()[0] 232 if issubclass(exc_type, SConfError): 233 raise 234 elif issubclass(exc_type, SCons.Errors.BuildError): 235 # we ignore Build Errors (occurs, when a test doesn't pass) 236 # Clear the exception to prevent the contained traceback 237 # to build a reference cycle. 238 self.exc_clear() 239 else: 240 self.display('Caught exception while building "%s":\n' % 241 self.targets[0]) 242 try: 243 excepthook = sys.excepthook 244 except AttributeError: 245 # Earlier versions of Python don't have sys.excepthook... 246 def excepthook(type, value, tb): 247 traceback.print_tb(tb) 248 print type, value
249 apply(excepthook, self.exc_info()) 250 return SCons.Taskmaster.Task.failed(self)
251
252 - def collect_node_states(self):
253 # returns (is_up_to_date, cached_error, cachable) 254 # where is_up_to_date is 1, if the node(s) are up_to_date 255 # cached_error is 1, if the node(s) are up_to_date, but the 256 # build will fail 257 # cachable is 0, if some nodes are not in our cache