Package SCons :: Package Platform
[hide private]
[frames] | no frames]

Source Code for Package SCons.Platform

  1  """SCons.Platform 
  2   
  3  SCons platform selection. 
  4   
  5  This looks for modules that define a callable object that can modify a 
  6  construction environment as appropriate for a given platform. 
  7   
  8  Note that we take a more simplistic view of "platform" than Python does. 
  9  We're looking for a single string that determines a set of 
 10  tool-independent variables with which to initialize a construction 
 11  environment.  Consequently, we'll examine both sys.platform and os.name 
 12  (and anything else that might come in to play) in order to return some 
 13  specification which is unique enough for our purposes. 
 14   
 15  Note that because this subsystem just *selects* a callable that can 
 16  modify a construction environment, it's possible for people to define 
 17  their own "platform specification" in an arbitrary callable function. 
 18  No one needs to use or tie in to this subsystem in order to roll 
 19  their own platform definition. 
 20  """ 
 21   
 22  # 
 23  # Copyright (c) 2001 - 2019 The SCons Foundation 
 24  # 
 25  # Permission is hereby granted, free of charge, to any person obtaining 
 26  # a copy of this software and associated documentation files (the 
 27  # "Software"), to deal in the Software without restriction, including 
 28  # without limitation the rights to use, copy, modify, merge, publish, 
 29  # distribute, sublicense, and/or sell copies of the Software, and to 
 30  # permit persons to whom the Software is furnished to do so, subject to 
 31  # the following conditions: 
 32  # 
 33  # The above copyright notice and this permission notice shall be included 
 34  # in all copies or substantial portions of the Software. 
 35  # 
 36  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY 
 37  # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 
 38  # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
 39  # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 
 40  # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 
 41  # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 
 42  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
 43  # 
 44  from __future__ import print_function 
 45   
 46  __revision__ = "src/engine/SCons/Platform/__init__.py 3a41ed6b288cee8d085373ad7fa02894e1903864 2019-01-23 17:30:35 bdeegan" 
 47   
 48  import SCons.compat 
 49   
 50  import imp 
 51  import os 
 52  import sys 
 53  import tempfile 
 54   
 55  import SCons.Errors 
 56  import SCons.Subst 
 57  import SCons.Tool 
 58   
 59   
60 -def platform_default():
61 """Return the platform string for our execution environment. 62 63 The returned value should map to one of the SCons/Platform/*.py 64 files. Since we're architecture independent, though, we don't 65 care about the machine architecture. 66 """ 67 osname = os.name 68 if osname == 'java': 69 osname = os._osType 70 if osname == 'posix': 71 if sys.platform == 'cygwin': 72 return 'cygwin' 73 elif sys.platform.find('irix') != -1: 74 return 'irix' 75 elif sys.platform.find('sunos') != -1: 76 return 'sunos' 77 elif sys.platform.find('hp-ux') != -1: 78 return 'hpux' 79 elif sys.platform.find('aix') != -1: 80 return 'aix' 81 elif sys.platform.find('darwin') != -1: 82 return 'darwin' 83 else: 84 return 'posix' 85 elif os.name == 'os2': 86 return 'os2' 87 else: 88 return sys.platform
89 90
91 -def platform_module(name = platform_default()):
92 """Return the imported module for the platform. 93 94 This looks for a module name that matches the specified argument. 95 If the name is unspecified, we fetch the appropriate default for 96 our execution environment. 97 """ 98 full_name = 'SCons.Platform.' + name 99 if full_name not in sys.modules: 100 if os.name == 'java': 101 eval(full_name) 102 else: 103 try: 104 file, path, desc = imp.find_module(name, 105 sys.modules['SCons.Platform'].__path__) 106 try: 107 mod = imp.load_module(full_name, file, path, desc) 108 finally: 109 if file: 110 file.close() 111 except ImportError: 112 try: 113 import zipimport 114 importer = zipimport.zipimporter( sys.modules['SCons.Platform'].__path__[0] ) 115 mod = importer.load_module(full_name) 116 except ImportError: 117 raise SCons.Errors.UserError("No platform named '%s'" % name) 118 setattr(SCons.Platform, name, mod) 119 return sys.modules[full_name]
120 121
122 -def DefaultToolList(platform, env):
123 """Select a default tool list for the specified platform. 124 """ 125 return SCons.Tool.tool_list(platform, env)
126 127
128 -class PlatformSpec(object):
129 - def __init__(self, name, generate):
130 self.name = name 131 self.generate = generate
132
133 - def __call__(self, *args, **kw):
134 return self.generate(*args, **kw)
135
136 - def __str__(self):
137 return self.name
138 139
140 -class TempFileMunge(object):
141 """A callable class. You can set an Environment variable to this, 142 then call it with a string argument, then it will perform temporary 143 file substitution on it. This is used to circumvent the long command 144 line limitation. 145 146 Example usage: 147 env["TEMPFILE"] = TempFileMunge 148 env["LINKCOM"] = "${TEMPFILE('$LINK $TARGET $SOURCES','$LINKCOMSTR')}" 149 150 By default, the name of the temporary file used begins with a 151 prefix of '@'. This may be configured for other tool chains by 152 setting '$TEMPFILEPREFIX': 153 env["TEMPFILEPREFIX"] = '-@' # diab compiler 154 env["TEMPFILEPREFIX"] = '-via' # arm tool chain 155 env["TEMPFILEPREFIX"] = '' # (the empty string) PC Lint 156 157 You can configure the extension of the temporary file through the 158 TEMPFILEEXTENSION variable, which defaults to '.lnk' (see comments 159 in the code below): 160 env["TEMPFILEEXTENSION"] = '.lnt' # PC Lint 161 """
162 - def __init__(self, cmd, cmdstr = None):
163 self.cmd = cmd 164 self.cmdstr = cmdstr
165
166 - def __call__(self, target, source, env, for_signature):
167 if for_signature: 168 # If we're being called for signature calculation, it's 169 # because we're being called by the string expansion in 170 # Subst.py, which has the logic to strip any $( $) that 171 # may be in the command line we squirreled away. So we 172 # just return the raw command line and let the upper 173 # string substitution layers do their thing. 174 return self.cmd 175 176 # Now we're actually being called because someone is actually 177 # going to try to execute the command, so we have to do our 178 # own expansion. 179 cmd = env.subst_list(self.cmd, SCons.Subst.SUBST_CMD, target, source)[0] 180 try: 181 maxline = int(env.subst('$MAXLINELENGTH')) 182 except ValueError: 183 maxline = 2048 184 185 length = 0 186 for c in cmd: 187 length += len(c) 188 length += len(cmd) - 1 189 if length <= maxline: 190 return self.cmd 191 192 # Check if we already created the temporary file for this target 193 # It should have been previously done by Action.strfunction() call 194 node = target[0] if SCons.Util.is_List(target) else target 195 cmdlist = getattr(node.attributes, 'tempfile_cmdlist', None) \ 196 if node is not None else None 197 if cmdlist is not None: 198 return cmdlist 199 200 # We do a normpath because mktemp() has what appears to be 201 # a bug in Windows that will use a forward slash as a path 202 # delimiter. Windows' link mistakes that for a command line 203 # switch and barfs. 204 # 205 # Default to the .lnk suffix for the benefit of the Phar Lap 206 # linkloc linker, which likes to append an .lnk suffix if 207 # none is given. 208 if env.has_key('TEMPFILESUFFIX'): 209 suffix = env.subst('$TEMPFILESUFFIX') 210 else: 211 suffix = '.lnk' 212 213 fd, tmp = tempfile.mkstemp(suffix, text=True) 214 native_tmp = SCons.Util.get_native_path(os.path.normpath(tmp)) 215 216 if env.get('SHELL', None) == 'sh': 217 # The sh shell will try to escape the backslashes in the 218 # path, so unescape them. 219 native_tmp = native_tmp.replace('\\', r'\\\\') 220 # In Cygwin, we want to use rm to delete the temporary 221 # file, because del does not exist in the sh shell. 222 rm = env.Detect('rm') or 'del' 223 else: 224 # Don't use 'rm' if the shell is not sh, because rm won't 225 # work with the Windows shells (cmd.exe or command.com) or 226 # Windows path names. 227 rm = 'del' 228 229 prefix = env.subst('$TEMPFILEPREFIX') 230 if not prefix: 231 prefix = '@' 232 233 args = list(map(SCons.Subst.quote_spaces, cmd[1:])) 234 os.write(fd, bytearray(" ".join(args) + "\n",'utf-8')) 235 os.close(fd) 236 # XXX Using the SCons.Action.print_actions value directly 237 # like this is bogus, but expedient. This class should 238 # really be rewritten as an Action that defines the 239 # __call__() and strfunction() methods and lets the 240 # normal action-execution logic handle whether or not to 241 # print/execute the action. The problem, though, is all 242 # of that is decided before we execute this method as 243 # part of expanding the $TEMPFILE construction variable. 244 # Consequently, refactoring this will have to wait until 245 # we get more flexible with allowing Actions to exist 246 # independently and get strung together arbitrarily like 247 # Ant tasks. In the meantime, it's going to be more 248 # user-friendly to not let obsession with architectural 249 # purity get in the way of just being helpful, so we'll 250 # reach into SCons.Action directly. 251 if SCons.Action.print_actions: 252 cmdstr = env.subst(self.cmdstr, SCons.Subst.SUBST_RAW, target, 253 source) if self.cmdstr is not None else '' 254 # Print our message only if XXXCOMSTR returns an empty string 255 if len(cmdstr) == 0 : 256 cmdstr = ("Using tempfile "+native_tmp+" for command line:\n"+ 257 str(cmd[0]) + " " + " ".join(args)) 258 self._print_cmd_str(target, source, env, cmdstr) 259 260 # Store the temporary file command list into the target Node.attributes 261 # to avoid creating two temporary files one for print and one for execute. 262 cmdlist = [ cmd[0], prefix + native_tmp + '\n' + rm, native_tmp ] 263 if node is not None: 264 try : 265 setattr(node.attributes, 'tempfile_cmdlist', cmdlist) 266 except AttributeError: 267 pass 268 return cmdlist
269
270 - def _print_cmd_str(self, target, source, env, cmdstr):
271 # check if the user has specified a cmd line print function 272 print_func = None 273 try: 274 get = env.get 275 except AttributeError: 276 pass 277 else: 278 print_func = get('PRINT_CMD_LINE_FUNC') 279 280 # use the default action cmd line print if user did not supply one 281 if not print_func: 282 action = SCons.Action._ActionAction() 283 action.print_cmd_line(cmdstr, target, source, env) 284 else: 285 print_func(cmdstr, target, source, env)
286 287
288 -def Platform(name = platform_default()):
289 """Select a canned Platform specification. 290 """ 291 module = platform_module(name) 292 spec = PlatformSpec(name, module.generate) 293 return spec
294 295 # Local Variables: 296 # tab-width:4 297 # indent-tabs-mode:nil 298 # End: 299 # vim: set expandtab tabstop=4 shiftwidth=4: 300