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, 2009, 2010 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 5023 2010/06/14 22:05:46 scons"
43 from SCons.Platform import TempFileMunge
51 "escape shell special characters"
55 arg = arg.replace(slash, slash+slash)
57 arg = arg.replace(c, slash+c)
59 return '"' + arg + '"'
61 def exec_system(l, env):
62 stat = os.system(' '.join(l))
67 def exec_spawnvpe(l, env):
68 stat = os.spawnvpe(os.P_WAIT, l[0], l, env)
69 # os.spawnvpe() returns the actual exit code, not the encoding
70 # returned by os.waitpid() or os.system().
73 def exec_fork(l, env):
79 os.execvpe(l[0], l, env)
81 exitval = exitvalmap.get(e[0], e[0])
82 sys.stderr.write("scons: %s: %s\n" % (l[0], e[1]))
86 pid, stat = os.waitpid(pid, 0)
91 def _get_env_command(sh, escape, cmd, args, env):
95 [escape(t[0])+'='+escape(t[1]) for t in env.items()] + \
100 def env_spawn(sh, escape, cmd, args, env):
101 return exec_system([_get_env_command( sh, escape, cmd, args, env)], env)
103 def spawnvpe_spawn(sh, escape, cmd, args, env):
104 return exec_spawnvpe([sh, '-c', ' '.join(args)], env)
106 def fork_spawn(sh, escape, cmd, args, env):
107 return exec_fork([sh, '-c', ' '.join(args)], env)
109 def process_cmd_output(cmd_stdout, cmd_stderr, stdout, stderr):
110 stdout_eof = stderr_eof = 0
111 while not (stdout_eof and stderr_eof):
113 (i,o,e) = select.select([cmd_stdout, cmd_stderr], [], [])
115 str = cmd_stdout.read()
118 elif stdout is not None:
121 str = cmd_stderr.read()
123 #sys.__stderr__.write( "stderr_eof=1\n" )
126 #sys.__stderr__.write( "str(stderr) = %s\n" % str )
128 except select.error, (_errno, _strerror):
129 if _errno != errno.EINTR:
132 def exec_popen3(l, env, stdout, stderr):
133 proc = subprocess.Popen(' '.join(l),
142 def exec_piped_fork(l, env, stdout, stderr):
143 # spawn using fork / exec and providing a pipe for the command's
144 # stdout / stderr stream
146 (rFdOut, wFdOut) = os.pipe()
147 (rFdErr, wFdErr) = os.pipe()
149 (rFdOut, wFdOut) = os.pipe()
159 os.dup2( wFdOut, 1 ) # is there some symbolic way to do that ?
166 os.execvpe(l[0], l, env)
168 exitval = exitvalmap.get(e[0], e[0])
169 stderr.write("scons: %s: %s\n" % (l[0], e[1]))
173 pid, stat = os.waitpid(pid, 0)
177 childOut = os.fdopen( rFdOut )
179 childErr = os.fdopen( rFdErr )
182 process_cmd_output(childOut, childErr, stdout, stderr)
190 def piped_env_spawn(sh, escape, cmd, args, env, stdout, stderr):
191 # spawn using Popen3 combined with the env command
192 # the command name and the command's stdout is written to stdout
193 # the command's stderr is written to stderr
194 return exec_popen3([_get_env_command(sh, escape, cmd, args, env)],
197 def piped_fork_spawn(sh, escape, cmd, args, env, stdout, stderr):
198 # spawn using fork / exec and providing a pipe for the command's
199 # stdout / stderr stream
200 return exec_piped_fork([sh, '-c', ' '.join(args)],
206 # If os.spawnvpe() exists, we use it to spawn commands. Otherwise
207 # if the env utility exists, we use os.system() to spawn commands,
208 # finally we fall back on os.fork()/os.exec().
210 # os.spawnvpe() is prefered because it is the most efficient. But
211 # for Python versions without it, os.system() is prefered because it
212 # is claimed that it works better with threads (i.e. -j) and is more
213 # efficient than forking Python.
215 # NB: Other people on the scons-users mailing list have claimed that
216 # os.fork()/os.exec() works better than os.system(). There may just
217 # not be a default that works best for all users.
219 if 'spawnvpe' in os.__dict__:
220 spawn = spawnvpe_spawn
221 elif env.Detect('env'):
226 if env.Detect('env'):
227 pspawn = piped_env_spawn
229 pspawn = piped_fork_spawn
233 env['ENV']['PATH'] = '/usr/local/bin:/opt/bin:/bin:/usr/bin'
234 env['OBJPREFIX'] = ''
235 env['OBJSUFFIX'] = '.o'
236 env['SHOBJPREFIX'] = '$OBJPREFIX'
237 env['SHOBJSUFFIX'] = '$OBJSUFFIX'
238 env['PROGPREFIX'] = ''
239 env['PROGSUFFIX'] = ''
240 env['LIBPREFIX'] = 'lib'
241 env['LIBSUFFIX'] = '.a'
242 env['SHLIBPREFIX'] = '$LIBPREFIX'
243 env['SHLIBSUFFIX'] = '.so'
244 env['LIBPREFIXES'] = [ '$LIBPREFIX' ]
245 env['LIBSUFFIXES'] = [ '$LIBSUFFIX', '$SHLIBSUFFIX' ]
246 env['PSPAWN'] = pspawn
249 env['ESCAPE'] = escape
250 env['TEMPFILE'] = TempFileMunge
251 env['TEMPFILEPREFIX'] = '@'
252 #Based on LINUX: ARG_MAX=ARG_MAX=131072 - 3000 for environment expansion
253 #Note: specific platforms might rise or lower this value
254 env['MAXLINELENGTH'] = 128072
256 # This platform supports RPATH specifications.
257 env['__RPATH'] = '$_RPATH'
261 # indent-tabs-mode:nil
263 # vim: set expandtab tabstop=4 shiftwidth=4: