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 2928 2008/04/29 22:44:09 knight" 
 30   
 31  import SCons.compat 
 32   
 33  import os 
 34  import re 
 35  import string 
 36  import StringIO 
 37  import sys 
 38  import traceback 
 39  import types 
 40   
 41  import SCons.Action 
 42  import SCons.Builder 
 43  import SCons.Errors 
 44  import SCons.Job 
 45  import SCons.Node.FS 
 46  import SCons.Taskmaster 
 47  import SCons.Util 
 48  import SCons.Warnings 
 49  import SCons.Conftest 
 50   
 51  from SCons.Debug import Trace 
 52   
 53  # Turn off the Conftest error logging 
 54  SCons.Conftest.LogInputFiles = 0 
 55  SCons.Conftest.LogErrorMessages = 0 
 56   
 57  # Set 
 58  build_type = None 
 59  build_types = ['clean', 'help'] 
 60   
61 -def SetBuildType(type):
62 global build_type 63 build_type = type
64 65 # to be set, if we are in dry-run mode 66 dryrun = 0 67 68 AUTO=0 # use SCons dependency scanning for up-to-date checks 69 FORCE=1 # force all tests to be rebuilt 70 CACHE=2 # force all tests to be taken from cache (raise an error, if necessary) 71 cache_mode = AUTO 72
73 -def SetCacheMode(mode):
74 """Set the Configure cache mode. mode must be one of "auto", "force", 75 or "cache".""" 76 global cache_mode 77 if mode == "auto": 78 cache_mode = AUTO 79 elif mode == "force": 80 cache_mode = FORCE 81 elif mode == "cache": 82 cache_mode = CACHE 83 else: 84 raise ValueError, "SCons.SConf.SetCacheMode: Unknown mode " + mode
85 86 progress_display = SCons.Util.display # will be overwritten by SCons.Script
87 -def SetProgressDisplay(display):
88 """Set the progress display to use (called from SCons.Script)""" 89 global progress_display 90 progress_display = display
91 92 SConfFS = None 93 94 _ac_build_counter = 0 # incremented, whenever TryBuild is called 95 _ac_config_logs = {} # all config.log files created in this build 96 _ac_config_hs = {} # all config.h files created in this build 97 sconf_global = None # current sconf object 98
99 -def _createConfigH(target, source, env):
100 t = open(str(target[0]), "w") 101 defname = re.sub('[^A-Za-z0-9_]', '_', string.upper(str(target[0]))) 102 t.write("""#ifndef %(DEFNAME)s_SEEN 103 #define %(DEFNAME)s_SEEN 104 105 """ % {'DEFNAME' : defname}) 106 t.write(source[0].get_contents()) 107 t.write(""" 108 #endif /* %(DEFNAME)s_SEEN */ 109 """ % {'DEFNAME' : defname}) 110 t.close()
111
112 -def _stringConfigH(target, source, env):
113 return "scons: Configure: creating " + str(target[0])
114
115 -def CreateConfigHBuilder(env):
116 """Called just before the building targets phase begins.""" 117 if len(_ac_config_hs) == 0: 118 return 119 action = SCons.Action.Action(_createConfigH, 120 _stringConfigH) 121 sconfigHBld = SCons.Builder.Builder(action=action) 122 env.Append( BUILDERS={'SConfigHBuilder':sconfigHBld} ) 123 for k in _ac_config_hs.keys(): 124 env.SConfigHBuilder(k, env.Value(_ac_config_hs[k]))
125
126 -class SConfWarning(SCons.Warnings.Warning):
127 pass
128 SCons.Warnings.enableWarningClass(SConfWarning) 129 130 # some error definitions
131 -class SConfError(SCons.Errors.UserError):
132 - def __init__(self,msg):
134
135 -class ConfigureDryRunError(SConfError):
136 """Raised when a file or directory needs to be updated during a Configure 137 process, but the user requested a dry-run"""
138 - def __init__(self,target):
139 if not isinstance(target, SCons.Node.FS.File): 140 msg = 'Cannot create configure directory "%s" within a dry-run.' % str(target) 141 else: 142 msg = 'Cannot update configure test "%s" within a dry-run.' % str(target) 143 SConfError.__init__(self,msg)
144
145 -class ConfigureCacheError(SConfError):
146 """Raised when a use explicitely requested the cache feature, but the test 147 is run the first time."""
148 - def __init__(self,target):
149 SConfError.__init__(self, '"%s" is not yet built and cache is forced.' % str(target))
150 151 # define actions for building text files
152 -def _createSource( target, source, env ):
153 fd = open(str(target[0]), "w") 154 fd.write(source[0].get_contents()) 155 fd.close()
156 -def _stringSource( target, source, env ):
157 return (str(target[0]) + ' <-\n |' + 158 string.replace( source[0].get_contents(), 159 '\n', "\n |" ) )
160 161 # python 2.2 introduces types.BooleanType 162 BooleanTypes = [types.IntType] 163 if hasattr(types, 'BooleanType'): BooleanTypes.append(types.BooleanType) 164
165 -class SConfBuildInfo(SCons.Node.FS.FileBuildInfo):
166 """ 167 Special build info for targets of configure tests. Additional members 168 are result (did the builder succeed last time?) and string, which 169 contains messages of the original build phase. 170 """ 171 result = None # -> 0/None -> no error, != 0 error 172 string = None # the stdout / stderr output when building the target 173
174 - def set_build_result(self, result, string):
175 self.result = result 176 self.string = string
177 178
179 -class Streamer:
180 """ 181 'Sniffer' for a file-like writable object. Similar to the unix tool tee. 182 """
183 - def __init__(self, orig):
184 self.orig = orig 185 self.s = StringIO.StringIO()
186
187 - def write(self, str):
188 if self.orig: 189 self.orig.write(str) 190 self.s.write(str)
191
192 - def writelines(self, lines):
193 for l in lines: 194 self.write(l + '\n')
195
196 - def getvalue(self):
197 """ 198 Return everything written to orig since the Streamer was created. 199 """ 200 return self.s.getvalue()
201
202 - def flush(self):
203 if self.orig: 204 self.orig.flush() 205 self.s.flush()
206 207
208 -class SConfBuildTask(SCons.Taskmaster.Task):
209 """ 210 This is almost the same as SCons.Script.BuildTask. Handles SConfErrors 211 correctly and knows about the current cache_mode. 212 """
213 - def display(self, message):
214 if sconf_global.logstream: 215 sconf_global.logstream.write("scons: Configure: " + message + "\n")
216
217 - def display_cached_string(self, bi):
218 """ 219 Logs the original builder messages, given the SConfBuildInfo instance 220 bi. 221 """ 222 if not isinstance(bi, SConfBuildInfo): 223 SCons.Warnings.warn(SConfWarning, 224 "The stored build information has an unexpected class: %s" % bi.__class__) 225 else: 226 self.display("The original builder output was:\n" + 227 string.replace(" |" + str(bi.string), 228 "\n", "\n |"))
229
230 - def failed(self):
231 # check, if the reason was a ConfigureDryRunError or a 232 # ConfigureCacheError and if yes, reraise the exception 233 exc_type = self.exc_info()[0] 234 if issubclass(exc_type, SConfError): 235 raise 236 elif issubclass(exc_type, SCons.Errors.BuildError): 237 # we ignore Build Errors (occurs, when a test doesn't pass) 238 pass 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 25