Add some documentation to the SCons-version-switching hack
[senf.git] / scons / scons-1.2.0 / engine / SCons / Platform / __init__.py
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 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
45 __revision__ = "src/engine/SCons/Platform/__init__.py 3842 2008/12/20 22:59:52 scons"
46
47 import imp
48 import os
49 import string
50 import sys
51 import tempfile
52
53 import SCons.Errors
54 import SCons.Tool
55
56 def platform_default():
57     """Return the platform string for our execution environment.
58
59     The returned value should map to one of the SCons/Platform/*.py
60     files.  Since we're architecture independent, though, we don't
61     care about the machine architecture.
62     """
63     osname = os.name
64     if osname == 'java':
65         osname = os._osType
66     if osname == 'posix':
67         if sys.platform == 'cygwin':
68             return 'cygwin'
69         elif string.find(sys.platform, 'irix') != -1:
70             return 'irix'
71         elif string.find(sys.platform, 'sunos') != -1:
72             return 'sunos'
73         elif string.find(sys.platform, 'hp-ux') != -1:
74             return 'hpux'
75         elif string.find(sys.platform, 'aix') != -1:
76             return 'aix'
77         elif string.find(sys.platform, 'darwin') != -1:
78             return 'darwin'
79         else:
80             return 'posix'
81     elif os.name == 'os2':
82         return 'os2'
83     else:
84         return sys.platform
85
86 def platform_module(name = platform_default()):
87     """Return the imported module for the platform.
88
89     This looks for a module name that matches the specified argument.
90     If the name is unspecified, we fetch the appropriate default for
91     our execution environment.
92     """
93     full_name = 'SCons.Platform.' + name
94     if not sys.modules.has_key(full_name):
95         if os.name == 'java':
96             eval(full_name)
97         else:
98             try:
99                 file, path, desc = imp.find_module(name,
100                                         sys.modules['SCons.Platform'].__path__)
101                 try:
102                     mod = imp.load_module(full_name, file, path, desc)
103                 finally:
104                     if file:
105                         file.close()
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 def DefaultToolList(platform, env):
117     """Select a default tool list for the specified platform.
118     """
119     return SCons.Tool.tool_list(platform, env)
120
121 class PlatformSpec:
122     def __init__(self, name):
123         self.name = name
124
125     def __str__(self):
126         return self.name
127         
128 class TempFileMunge:
129     """A callable class.  You can set an Environment variable to this,
130     then call it with a string argument, then it will perform temporary
131     file substitution on it.  This is used to circumvent the long command
132     line limitation.
133
134     Example usage:
135     env["TEMPFILE"] = TempFileMunge
136     env["LINKCOM"] = "${TEMPFILE('$LINK $TARGET $SOURCES')}"
137
138     By default, the name of the temporary file used begins with a
139     prefix of '@'.  This may be configred for other tool chains by
140     setting '$TEMPFILEPREFIX'.
141
142     env["TEMPFILEPREFIX"] = '-@'        # diab compiler
143     env["TEMPFILEPREFIX"] = '-via'      # arm tool chain
144     """
145     def __init__(self, cmd):
146         self.cmd = cmd
147
148     def __call__(self, target, source, env, for_signature):
149         if for_signature:
150             return self.cmd
151         cmd = env.subst_list(self.cmd, 0, target, source)[0]
152         try:
153             maxline = int(env.subst('$MAXLINELENGTH'))
154         except ValueError:
155             maxline = 2048
156
157         if (reduce(lambda x, y: x + len(y), cmd, 0) + len(cmd)) <= maxline:
158             return self.cmd
159
160         # We do a normpath because mktemp() has what appears to be
161         # a bug in Windows that will use a forward slash as a path
162         # delimiter.  Windows's link mistakes that for a command line
163         # switch and barfs.
164         #
165         # We use the .lnk suffix for the benefit of the Phar Lap
166         # linkloc linker, which likes to append an .lnk suffix if
167         # none is given.
168         tmp = os.path.normpath(tempfile.mktemp('.lnk'))
169         native_tmp = SCons.Util.get_native_path(tmp)
170
171         if env['SHELL'] and env['SHELL'] == 'sh':
172             # The sh shell will try to escape the backslashes in the
173             # path, so unescape them.
174             native_tmp = string.replace(native_tmp, '\\', r'\\\\')
175             # In Cygwin, we want to use rm to delete the temporary
176             # file, because del does not exist in the sh shell.
177             rm = env.Detect('rm') or 'del'
178         else:
179             # Don't use 'rm' if the shell is not sh, because rm won't
180             # work with the Windows shells (cmd.exe or command.com) or
181             # Windows path names.
182             rm = 'del'
183
184         prefix = env.subst('$TEMPFILEPREFIX')
185         if not prefix:
186             prefix = '@'
187
188         args = map(SCons.Subst.quote_spaces, cmd[1:])
189         open(tmp, 'w').write(string.join(args, " ") + "\n")
190         # XXX Using the SCons.Action.print_actions value directly
191         # like this is bogus, but expedient.  This class should
192         # really be rewritten as an Action that defines the
193         # __call__() and strfunction() methods and lets the
194         # normal action-execution logic handle whether or not to
195         # print/execute the action.  The problem, though, is all
196         # of that is decided before we execute this method as
197         # part of expanding the $TEMPFILE construction variable.
198         # Consequently, refactoring this will have to wait until
199         # we get more flexible with allowing Actions to exist
200         # independently and get strung together arbitrarily like
201         # Ant tasks.  In the meantime, it's going to be more
202         # user-friendly to not let obsession with architectural
203         # purity get in the way of just being helpful, so we'll
204         # reach into SCons.Action directly.
205         if SCons.Action.print_actions:
206             print("Using tempfile "+native_tmp+" for command line:\n"+
207                   str(cmd[0]) + " " + string.join(args," "))
208         return [ cmd[0], prefix + native_tmp + '\n' + rm, native_tmp ]
209     
210 def Platform(name = platform_default()):
211     """Select a canned Platform specification.
212     """
213     module = platform_module(name)
214     spec = PlatformSpec(name)
215     spec.__call__ = module.generate
216     return spec