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 e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" 
 47   
 48  import SCons.compat 
 49   
 50  import importlib 
 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 # the specific platform module is a relative import 105 mod = importlib.import_module("." + name, __name__) 106 except ImportError: 107 try: 108 import zipimport 109 importer = zipimport.zipimporter( sys.modules['SCons.Platform'].__path__[0] ) 110 mod = importer.load_module(full_name) 111 except ImportError: 112 raise SCons.Errors.UserError("No platform named '%s'" % name) 113 setattr(SCons.Platform, name, mod) 114 return sys.modules[full_name]
115 116
117 -def DefaultToolList(platform, env):
118 """Select a default tool list for the specified platform. 119 """ 120 return SCons.Tool.tool_list(platform, env)
121 122
123 -class PlatformSpec(object):
124 - def __init__(self, name, generate):
125 self.name = name 126 self.generate = generate
127
128 - def __call__(self, *args, **kw):
129 return self.generate(*args, **kw)
130
131 - def __str__(self):
132 return self.name
133 134
135 -class TempFileMunge(object):
136 """A callable class. You can set an Environment variable to this, 137 then call it with a string argument, then it will perform temporary 138 file substitution on it. This is used to circumvent the long command 139 line limitation. 140 141 Example usage: 142 env["TEMPFILE"] = TempFileMunge 143 env["LINKCOM"] = "${TEMPFILE('$LINK $TARGET $SOURCES','$LINKCOMSTR')}" 144 145 By default, the name of the temporary file used begins with a 146 prefix of '@'. This may be configured for other tool chains by 147 setting '$TEMPFILEPREFIX': 148 env["TEMPFILEPREFIX"] = '-@' # diab compiler 149 env["TEMPFILEPREFIX"] = '-via' # arm tool chain 150 env["TEMPFILEPREFIX"] = '' # (the empty string) PC Lint 151 152 You can configure the extension of the temporary file through the 153 TEMPFILESUFFIX variable, which defaults to '.lnk' (see comments 154 in the code below): 155 env["TEMPFILESUFFIX"] = '.lnt' # PC Lint 156 """
157 - def __init__(self, cmd, cmdstr = None):
158 self.cmd = cmd 159 self.cmdstr = cmdstr
160
161 - def __call__(self, target, source, env, for_signature):
162 if for_signature: 163 # If we're being called for signature calculation, it's 164 # because we're being called by the string expansion in 165 # Subst.py, which has the logic to strip any $( $) that 166 # may be in the command line we squirreled away. So we 167 # just return the raw command line and let the upper 168 # string substitution layers do their thing. 169 return self.cmd 170 171 # Now we're actually being called because someone is actually 172 # going to try to execute the command, so we have to do our 173 # own expansion. 174 cmd = env.subst_list(self.cmd, SCons.Subst.SUBST_CMD, target, source)[0] 175 try: 176 maxline = int(env.subst('$MAXLINELENGTH')) 177 except ValueError: 178 maxline = 2048 179 180 length = 0 181 for c in cmd: 182 length += len(c) 183 length += len(cmd) - 1 184 if length <= maxline: 185 return self.cmd 186 187 # Check if we already created the temporary file for this target 188 # It should have been previously done by Action.strfunction() call 189 node = target[0] if SCons.Util.is_List(target) else target 190 cmdlist = getattr(node.attributes, 'tempfile_cmdlist', None) \ 191 if node is not None else None 192 if cmdlist is not None: 193 return cmdlist 194 195 # We do a normpath because mktemp() has what appears to be 196 # a bug in Windows that will use a forward slash as a path 197 # delimiter. Windows' link mistakes that for a command line 198 # switch and barfs. 199 # 200 # Default to the .lnk suffix for the benefit of the Phar Lap 201 # linkloc linker, which likes to append an .lnk suffix if 202 # none is given. 203 if env.has_key('TEMPFILESUFFIX'): 204 suffix = env.subst('$TEMPFILESUFFIX') 205 else: 206 suffix = '.lnk' 207 208 fd, tmp = tempfile.mkstemp(suffix, text=True) 209 native_tmp = SCons.Util.get_native_path(os.path.normpath(tmp)) 210 211 if env.get('SHELL', None) == 'sh': 212 # The sh shell will try to escape the backslashes in the 213 # path, so unescape them. 214 native_tmp = native_tmp.replace('\\', r'\\\\') 215 # In Cygwin, we want to use rm to delete the temporary 216 # file, because del does not exist in the sh shell. 217 rm = env.Detect('rm') or 'del' 218 else: 219 # Don't use 'rm' if the shell is not sh, because rm won't 220 # work with the Windows shells (cmd.exe or command.com) or 221 # Windows path names. 222 rm = 'del' 223 224 prefix = env.subst('$TEMPFILEPREFIX') 225 if not prefix: 226 prefix = '@' 227 228 args = list(map(SCons.Subst.quote_spaces, cmd[1:])) 229 join_char = env.get('TEMPFILEARGJOIN',' ') 230 os.write(fd, bytearray(join_char.join(args) + "\n",'utf-8')) 231 os.close(fd) 232 233 # XXX Using the SCons.Action.print_actions value directly 234 # like this is bogus, but expedient. This class should 235 # really be rewritten as an Action that defines the 236 # __call__() and strfunction() methods and lets the 237 # normal action-execution logic handle whether or not to 238 # print/execute the action. The problem, though, is all 239 # of that is decided before we execute this method as 240 # part of expanding the $TEMPFILE construction variable. 241 # Consequently, refactoring this will have to wait until 242 # we get more flexible with allowing Actions to exist 243 # independently and get strung together arbitrarily like 244 # Ant tasks. In the meantime, it's going to be more 245 # user-friendly to not let obsession with architectural 246 # purity get in the way of just being helpful, so we'll 247 # reach into SCons.Action directly. 248 if SCons.Action.print_actions: 249 cmdstr = env.subst(self.cmdstr, SCons.Subst.SUBST_RAW, target, 250 source) if self.cmdstr is not None else '' 251 # Print our message only if XXXCOMSTR returns an empty string 252 if len(cmdstr) == 0 : 253 cmdstr = ("Using tempfile "+native_tmp+" for command line:\n"+ 254 str(cmd[0]) + " " + " ".join(args)) 255 self._print_cmd_str(target, source, env, cmdstr) 256 257 # Store the temporary file command list into the target Node.attributes 258 # to avoid creating two temporary files one for print and one for execute. 259 cmdlist = [ cmd[0], prefix + native_tmp + '\n' + rm, native_tmp ] 260 if node is not None: 261 try : 262 setattr(node.attributes, 'tempfile_cmdlist', cmdlist) 263 except AttributeError: 264 pass 265 return cmdlist
266
267 - def _print_cmd_str(self, target, source, env, cmdstr):
268 # check if the user has specified a cmd line print function 269 print_func = None 270 try: 271 get = env.get 272 except AttributeError: 273 pass 274 else: 275 print_func = get('PRINT_CMD_LINE_FUNC') 276 277 # use the default action cmd line print if user did not supply one 278 if not print_func: 279 action = SCons.Action._ActionAction() 280 action.print_cmd_line(cmdstr, target, source, env) 281 else: 282 print_func(cmdstr, target, source, env)
283 284
285 -def Platform(name = platform_default()):
286 """Select a canned Platform specification. 287 """ 288 module = platform_module(name) 289 spec = PlatformSpec(name, module.generate) 290 return spec
291 292 # Local Variables: 293 # tab-width:4 294 # indent-tabs-mode:nil 295 # End: 296 # vim: set expandtab tabstop=4 shiftwidth=4: 297