OLD | NEW |
(Empty) | |
| 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 subsysem 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, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 The S
Cons 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 |
| 45 __revision__ = "src/engine/SCons/Platform/__init__.py 5134 2010/08/16 23:02:40 b
deegan" |
| 46 |
| 47 import SCons.compat |
| 48 |
| 49 import imp |
| 50 import os |
| 51 import sys |
| 52 import tempfile |
| 53 |
| 54 import SCons.Errors |
| 55 import SCons.Subst |
| 56 import SCons.Tool |
| 57 |
| 58 def platform_default(): |
| 59 """Return the platform string for our execution environment. |
| 60 |
| 61 The returned value should map to one of the SCons/Platform/*.py |
| 62 files. Since we're architecture independent, though, we don't |
| 63 care about the machine architecture. |
| 64 """ |
| 65 osname = os.name |
| 66 if osname == 'java': |
| 67 osname = os._osType |
| 68 if osname == 'posix': |
| 69 if sys.platform == 'cygwin': |
| 70 return 'cygwin' |
| 71 elif sys.platform.find('irix') != -1: |
| 72 return 'irix' |
| 73 elif sys.platform.find('sunos') != -1: |
| 74 return 'sunos' |
| 75 elif sys.platform.find('hp-ux') != -1: |
| 76 return 'hpux' |
| 77 elif sys.platform.find('aix') != -1: |
| 78 return 'aix' |
| 79 elif sys.platform.find('darwin') != -1: |
| 80 return 'darwin' |
| 81 else: |
| 82 return 'posix' |
| 83 elif os.name == 'os2': |
| 84 return 'os2' |
| 85 else: |
| 86 return sys.platform |
| 87 |
| 88 def platform_module(name = platform_default()): |
| 89 """Return the imported module for the platform. |
| 90 |
| 91 This looks for a module name that matches the specified argument. |
| 92 If the name is unspecified, we fetch the appropriate default for |
| 93 our execution environment. |
| 94 """ |
| 95 full_name = 'SCons.Platform.' + name |
| 96 if full_name not in sys.modules: |
| 97 if os.name == 'java': |
| 98 eval(full_name) |
| 99 else: |
| 100 try: |
| 101 file, path, desc = imp.find_module(name, |
| 102 sys.modules['SCons.Platform'].__path__) |
| 103 try: |
| 104 mod = imp.load_module(full_name, file, path, desc) |
| 105 finally: |
| 106 if file: |
| 107 file.close() |
| 108 except ImportError: |
| 109 try: |
| 110 import zipimport |
| 111 importer = zipimport.zipimporter( sys.modules['SCons.Platfor
m'].__path__[0] ) |
| 112 mod = importer.load_module(full_name) |
| 113 except ImportError: |
| 114 raise SCons.Errors.UserError("No platform named '%s'" % name
) |
| 115 setattr(SCons.Platform, name, mod) |
| 116 return sys.modules[full_name] |
| 117 |
| 118 def DefaultToolList(platform, env): |
| 119 """Select a default tool list for the specified platform. |
| 120 """ |
| 121 return SCons.Tool.tool_list(platform, env) |
| 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 class TempFileMunge(object): |
| 135 """A callable class. You can set an Environment variable to this, |
| 136 then call it with a string argument, then it will perform temporary |
| 137 file substitution on it. This is used to circumvent the long command |
| 138 line limitation. |
| 139 |
| 140 Example usage: |
| 141 env["TEMPFILE"] = TempFileMunge |
| 142 env["LINKCOM"] = "${TEMPFILE('$LINK $TARGET $SOURCES')}" |
| 143 |
| 144 By default, the name of the temporary file used begins with a |
| 145 prefix of '@'. This may be configred for other tool chains by |
| 146 setting '$TEMPFILEPREFIX'. |
| 147 |
| 148 env["TEMPFILEPREFIX"] = '-@' # diab compiler |
| 149 env["TEMPFILEPREFIX"] = '-via' # arm tool chain |
| 150 """ |
| 151 def __init__(self, cmd): |
| 152 self.cmd = cmd |
| 153 |
| 154 def __call__(self, target, source, env, for_signature): |
| 155 if for_signature: |
| 156 # If we're being called for signature calculation, it's |
| 157 # because we're being called by the string expansion in |
| 158 # Subst.py, which has the logic to strip any $( $) that |
| 159 # may be in the command line we squirreled away. So we |
| 160 # just return the raw command line and let the upper |
| 161 # string substitution layers do their thing. |
| 162 return self.cmd |
| 163 |
| 164 # Now we're actually being called because someone is actually |
| 165 # going to try to execute the command, so we have to do our |
| 166 # own expansion. |
| 167 cmd = env.subst_list(self.cmd, SCons.Subst.SUBST_CMD, target, source)[0] |
| 168 try: |
| 169 maxline = int(env.subst('$MAXLINELENGTH')) |
| 170 except ValueError: |
| 171 maxline = 2048 |
| 172 |
| 173 length = 0 |
| 174 for c in cmd: |
| 175 length += len(c) |
| 176 if length <= maxline: |
| 177 return self.cmd |
| 178 |
| 179 # We do a normpath because mktemp() has what appears to be |
| 180 # a bug in Windows that will use a forward slash as a path |
| 181 # delimiter. Windows's link mistakes that for a command line |
| 182 # switch and barfs. |
| 183 # |
| 184 # We use the .lnk suffix for the benefit of the Phar Lap |
| 185 # linkloc linker, which likes to append an .lnk suffix if |
| 186 # none is given. |
| 187 (fd, tmp) = tempfile.mkstemp('.lnk', text=True) |
| 188 native_tmp = SCons.Util.get_native_path(os.path.normpath(tmp)) |
| 189 |
| 190 if env['SHELL'] and env['SHELL'] == 'sh': |
| 191 # The sh shell will try to escape the backslashes in the |
| 192 # path, so unescape them. |
| 193 native_tmp = native_tmp.replace('\\', r'\\\\') |
| 194 # In Cygwin, we want to use rm to delete the temporary |
| 195 # file, because del does not exist in the sh shell. |
| 196 rm = env.Detect('rm') or 'del' |
| 197 else: |
| 198 # Don't use 'rm' if the shell is not sh, because rm won't |
| 199 # work with the Windows shells (cmd.exe or command.com) or |
| 200 # Windows path names. |
| 201 rm = 'del' |
| 202 |
| 203 prefix = env.subst('$TEMPFILEPREFIX') |
| 204 if not prefix: |
| 205 prefix = '@' |
| 206 |
| 207 args = list(map(SCons.Subst.quote_spaces, cmd[1:])) |
| 208 os.write(fd, " ".join(args) + "\n") |
| 209 os.close(fd) |
| 210 # XXX Using the SCons.Action.print_actions value directly |
| 211 # like this is bogus, but expedient. This class should |
| 212 # really be rewritten as an Action that defines the |
| 213 # __call__() and strfunction() methods and lets the |
| 214 # normal action-execution logic handle whether or not to |
| 215 # print/execute the action. The problem, though, is all |
| 216 # of that is decided before we execute this method as |
| 217 # part of expanding the $TEMPFILE construction variable. |
| 218 # Consequently, refactoring this will have to wait until |
| 219 # we get more flexible with allowing Actions to exist |
| 220 # independently and get strung together arbitrarily like |
| 221 # Ant tasks. In the meantime, it's going to be more |
| 222 # user-friendly to not let obsession with architectural |
| 223 # purity get in the way of just being helpful, so we'll |
| 224 # reach into SCons.Action directly. |
| 225 if SCons.Action.print_actions: |
| 226 print("Using tempfile "+native_tmp+" for command line:\n"+ |
| 227 str(cmd[0]) + " " + " ".join(args)) |
| 228 return [ cmd[0], prefix + native_tmp + '\n' + rm, native_tmp ] |
| 229 |
| 230 def Platform(name = platform_default()): |
| 231 """Select a canned Platform specification. |
| 232 """ |
| 233 module = platform_module(name) |
| 234 spec = PlatformSpec(name, module.generate) |
| 235 return spec |
| 236 |
| 237 # Local Variables: |
| 238 # tab-width:4 |
| 239 # indent-tabs-mode:nil |
| 240 # End: |
| 241 # vim: set expandtab tabstop=4 shiftwidth=4: |
OLD | NEW |