1 """SCons.Platform.posix
3 Platform-specific initialization for POSIX (Linux, UNIX, etc.) systems.
5 There normally shouldn't be any need to import this module directly. It
6 will usually be imported through the generic SCons.Platform.Platform()
11 # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
13 # Permission is hereby granted, free of charge, to any person obtaining
14 # a copy of this software and associated documentation files (the
15 # "Software"), to deal in the Software without restriction, including
16 # without limitation the rights to use, copy, modify, merge, publish,
17 # distribute, sublicense, and/or sell copies of the Software, and to
18 # permit persons to whom the Software is furnished to do so, subject to
19 # the following conditions:
21 # The above copyright notice and this permission notice shall be included
22 # in all copies or substantial portions of the Software.
24 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
25 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
26 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 __revision__ = "src/engine/SCons/Platform/posix.py 3842 2008/12/20 22:59:52 scons"
44 from SCons.Platform import TempFileMunge
52 "escape shell special characters"
56 arg = string.replace(arg, slash, slash+slash)
58 arg = string.replace(arg, c, slash+c)
60 return '"' + arg + '"'
62 def exec_system(l, env):
63 stat = os.system(string.join(l))
68 def exec_spawnvpe(l, env):
69 stat = os.spawnvpe(os.P_WAIT, l[0], l, env)
70 # os.spawnvpe() returns the actual exit code, not the encoding
71 # returned by os.waitpid() or os.system().
74 def exec_fork(l, env):
80 os.execvpe(l[0], l, env)
82 exitval = exitvalmap.get(e[0], e[0])
83 sys.stderr.write("scons: %s: %s\n" % (l[0], e[1]))
87 pid, stat = os.waitpid(pid, 0)
92 def _get_env_command(sh, escape, cmd, args, env):
96 map(lambda t, e=escape: e(t[0])+'='+e(t[1]), env.items()) + \
101 def env_spawn(sh, escape, cmd, args, env):
102 return exec_system([_get_env_command( sh, escape, cmd, args, env)], env)
104 def spawnvpe_spawn(sh, escape, cmd, args, env):
105 return exec_spawnvpe([sh, '-c', string.join(args)], env)
107 def fork_spawn(sh, escape, cmd, args, env):
108 return exec_fork([sh, '-c', string.join(args)], env)
110 def process_cmd_output(cmd_stdout, cmd_stderr, stdout, stderr):
111 stdout_eof = stderr_eof = 0
112 while not (stdout_eof and stderr_eof):
114 (i,o,e) = select.select([cmd_stdout, cmd_stderr], [], [])
116 str = cmd_stdout.read()
122 str = cmd_stderr.read()
124 #sys.__stderr__.write( "stderr_eof=1\n" )
127 #sys.__stderr__.write( "str(stderr) = %s\n" % str )
129 except select.error, (_errno, _strerror):
130 if _errno != errno.EINTR:
133 def exec_popen3(l, env, stdout, stderr):
134 proc = subprocess.Popen(string.join(l),
143 def exec_piped_fork(l, env, stdout, stderr):
144 # spawn using fork / exec and providing a pipe for the command's
145 # stdout / stderr stream
147 (rFdOut, wFdOut) = os.pipe()
148 (rFdErr, wFdErr) = os.pipe()
150 (rFdOut, wFdOut) = os.pipe()
160 os.dup2( wFdOut, 1 ) # is there some symbolic way to do that ?
167 os.execvpe(l[0], l, env)
169 exitval = exitvalmap.get(e[0], e[0])
170 stderr.write("scons: %s: %s\n" % (l[0], e[1]))
174 pid, stat = os.waitpid(pid, 0)
178 childOut = os.fdopen( rFdOut )
180 childErr = os.fdopen( rFdErr )
183 process_cmd_output(childOut, childErr, stdout, stderr)
191 def piped_env_spawn(sh, escape, cmd, args, env, stdout, stderr):
192 # spawn using Popen3 combined with the env command
193 # the command name and the command's stdout is written to stdout
194 # the command's stderr is written to stderr
195 return exec_popen3([_get_env_command(sh, escape, cmd, args, env)],
198 def piped_fork_spawn(sh, escape, cmd, args, env, stdout, stderr):
199 # spawn using fork / exec and providing a pipe for the command's
200 # stdout / stderr stream
201 return exec_piped_fork([sh, '-c', string.join(args)],
207 # If os.spawnvpe() exists, we use it to spawn commands. Otherwise
208 # if the env utility exists, we use os.system() to spawn commands,
209 # finally we fall back on os.fork()/os.exec().
211 # os.spawnvpe() is prefered because it is the most efficient. But
212 # for Python versions without it, os.system() is prefered because it
213 # is claimed that it works better with threads (i.e. -j) and is more
214 # efficient than forking Python.
216 # NB: Other people on the scons-users mailing list have claimed that
217 # os.fork()/os.exec() works better than os.system(). There may just
218 # not be a default that works best for all users.
220 if os.__dict__.has_key('spawnvpe'):
221 spawn = spawnvpe_spawn
222 elif env.Detect('env'):
227 if env.Detect('env'):
228 pspawn = piped_env_spawn
230 pspawn = piped_fork_spawn
232 if not env.has_key('ENV'):
234 env['ENV']['PATH'] = '/usr/local/bin:/opt/bin:/bin:/usr/bin'
235 env['OBJPREFIX'] = ''
236 env['OBJSUFFIX'] = '.o'
237 env['SHOBJPREFIX'] = '$OBJPREFIX'
238 env['SHOBJSUFFIX'] = '$OBJSUFFIX'
239 env['PROGPREFIX'] = ''
240 env['PROGSUFFIX'] = ''
241 env['LIBPREFIX'] = 'lib'
242 env['LIBSUFFIX'] = '.a'
243 env['SHLIBPREFIX'] = '$LIBPREFIX'
244 env['SHLIBSUFFIX'] = '.so'
245 env['LIBPREFIXES'] = [ '$LIBPREFIX' ]
246 env['LIBSUFFIXES'] = [ '$LIBSUFFIX', '$SHLIBSUFFIX' ]
247 env['PSPAWN'] = pspawn
250 env['ESCAPE'] = escape
251 env['TEMPFILE'] = TempFileMunge
252 env['TEMPFILEPREFIX'] = '@'
253 #Based on LINUX: ARG_MAX=ARG_MAX=131072 - 3000 for environment expansion
254 #Note: specific platforms might rise or lower this value
255 env['MAXLINELENGTH'] = 128072
257 # This platform supports RPATH specifications.
258 env['__RPATH'] = '$_RPATH'