posix.py
上传用户:market2
上传日期:2018-11-18
资源大小:18786k
文件大小:8k
- """SCons.Platform.posix
- Platform-specific initialization for POSIX (Linux, UNIX, etc.) systems.
- There normally shouldn't be any need to import this module directly. It
- will usually be imported through the generic SCons.Platform.Platform()
- selection method.
- """
- #
- # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
- #
- # Permission is hereby granted, free of charge, to any person obtaining
- # a copy of this software and associated documentation files (the
- # "Software"), to deal in the Software without restriction, including
- # without limitation the rights to use, copy, modify, merge, publish,
- # distribute, sublicense, and/or sell copies of the Software, and to
- # permit persons to whom the Software is furnished to do so, subject to
- # the following conditions:
- #
- # The above copyright notice and this permission notice shall be included
- # in all copies or substantial portions of the Software.
- #
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
- # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
- # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- #
- __revision__ = "src/engine/SCons/Platform/posix.py 3057 2008/06/09 22:21:00 knight"
- import errno
- import os
- import os.path
- import popen2
- import string
- import sys
- import select
- import SCons.Util
- from SCons.Platform import TempFileMunge
- exitvalmap = {
- 2 : 127,
- 13 : 126,
- }
- def escape(arg):
- "escape shell special characters"
- slash = '\'
- special = '"$'
- arg = string.replace(arg, slash, slash+slash)
- for c in special:
- arg = string.replace(arg, c, slash+c)
- return '"' + arg + '"'
- def exec_system(l, env):
- stat = os.system(string.join(l))
- if stat & 0xff:
- return stat | 0x80
- return stat >> 8
- def exec_spawnvpe(l, env):
- stat = os.spawnvpe(os.P_WAIT, l[0], l, env)
- # os.spawnvpe() returns the actual exit code, not the encoding
- # returned by os.waitpid() or os.system().
- return stat
- def exec_fork(l, env):
- pid = os.fork()
- if not pid:
- # Child process.
- exitval = 127
- try:
- os.execvpe(l[0], l, env)
- except OSError, e:
- exitval = exitvalmap.get(e[0], e[0])
- sys.stderr.write("scons: %s: %sn" % (l[0], e[1]))
- os._exit(exitval)
- else:
- # Parent process.
- pid, stat = os.waitpid(pid, 0)
- if stat & 0xff:
- return stat | 0x80
- return stat >> 8
- def _get_env_command(sh, escape, cmd, args, env):
- s = string.join(args)
- if env:
- l = ['env', '-'] +
- map(lambda t, e=escape: t[0]+'='+e(t[1]), env.items()) +
- [sh, '-c', escape(s)]
- s = string.join(l)
- return s
- def env_spawn(sh, escape, cmd, args, env):
- return exec_system([_get_env_command( sh, escape, cmd, args, env)], env)
- def spawnvpe_spawn(sh, escape, cmd, args, env):
- return exec_spawnvpe([sh, '-c', string.join(args)], env)
- def fork_spawn(sh, escape, cmd, args, env):
- return exec_fork([sh, '-c', string.join(args)], env)
- def process_cmd_output(cmd_stdout, cmd_stderr, stdout, stderr):
- stdout_eof = stderr_eof = 0
- while not (stdout_eof and stderr_eof):
- try:
- (i,o,e) = select.select([cmd_stdout, cmd_stderr], [], [])
- if cmd_stdout in i:
- str = cmd_stdout.read()
- if len(str) == 0:
- stdout_eof = 1
- elif stdout != None:
- stdout.write(str)
- if cmd_stderr in i:
- str = cmd_stderr.read()
- if len(str) == 0:
- #sys.__stderr__.write( "stderr_eof=1n" )
- stderr_eof = 1
- else:
- #sys.__stderr__.write( "str(stderr) = %sn" % str )
- stderr.write(str)
- except select.error, (_errno, _strerror):
- if _errno != errno.EINTR:
- raise
- def exec_popen3(l, env, stdout, stderr):
- proc = popen2.Popen3(string.join(l), 1)
- process_cmd_output(proc.fromchild, proc.childerr, stdout, stderr)
- stat = proc.wait()
- if stat & 0xff:
- return stat | 0x80
- return stat >> 8
- def exec_piped_fork(l, env, stdout, stderr):
- # spawn using fork / exec and providing a pipe for the command's
- # stdout / stderr stream
- if stdout != stderr:
- (rFdOut, wFdOut) = os.pipe()
- (rFdErr, wFdErr) = os.pipe()
- else:
- (rFdOut, wFdOut) = os.pipe()
- rFdErr = rFdOut
- wFdErr = wFdOut
- # do the fork
- pid = os.fork()
- if not pid:
- # Child process
- os.close( rFdOut )
- if rFdOut != rFdErr:
- os.close( rFdErr )
- os.dup2( wFdOut, 1 ) # is there some symbolic way to do that ?
- os.dup2( wFdErr, 2 )
- os.close( wFdOut )
- if stdout != stderr:
- os.close( wFdErr )
- exitval = 127
- try:
- os.execvpe(l[0], l, env)
- except OSError, e:
- exitval = exitvalmap.get(e[0], e[0])
- stderr.write("scons: %s: %sn" % (l[0], e[1]))
- os._exit(exitval)
- else:
- # Parent process
- pid, stat = os.waitpid(pid, 0)
- os.close( wFdOut )
- if stdout != stderr:
- os.close( wFdErr )
- childOut = os.fdopen( rFdOut )
- if stdout != stderr:
- childErr = os.fdopen( rFdErr )
- else:
- childErr = childOut
- process_cmd_output(childOut, childErr, stdout, stderr)
- os.close( rFdOut )
- if stdout != stderr:
- os.close( rFdErr )
- if stat & 0xff:
- return stat | 0x80
- return stat >> 8
- def piped_env_spawn(sh, escape, cmd, args, env, stdout, stderr):
- # spawn using Popen3 combined with the env command
- # the command name and the command's stdout is written to stdout
- # the command's stderr is written to stderr
- return exec_popen3([_get_env_command(sh, escape, cmd, args, env)],
- env, stdout, stderr)
- def piped_fork_spawn(sh, escape, cmd, args, env, stdout, stderr):
- # spawn using fork / exec and providing a pipe for the command's
- # stdout / stderr stream
- return exec_piped_fork([sh, '-c', string.join(args)],
- env, stdout, stderr)
- def generate(env):
- # If os.spawnvpe() exists, we use it to spawn commands. Otherwise
- # if the env utility exists, we use os.system() to spawn commands,
- # finally we fall back on os.fork()/os.exec().
- #
- # os.spawnvpe() is prefered because it is the most efficient. But
- # for Python versions without it, os.system() is prefered because it
- # is claimed that it works better with threads (i.e. -j) and is more
- # efficient than forking Python.
- #
- # NB: Other people on the scons-users mailing list have claimed that
- # os.fork()/os.exec() works better than os.system(). There may just
- # not be a default that works best for all users.
- if os.__dict__.has_key('spawnvpe'):
- spawn = spawnvpe_spawn
- elif env.Detect('env'):
- spawn = env_spawn
- else:
- spawn = fork_spawn
- if env.Detect('env'):
- pspawn = piped_env_spawn
- else:
- pspawn = piped_fork_spawn
- if not env.has_key('ENV'):
- env['ENV'] = {}
- env['ENV']['PATH'] = '/usr/local/bin:/opt/bin:/bin:/usr/bin'
- env['OBJPREFIX'] = ''
- env['OBJSUFFIX'] = '.o'
- env['SHOBJPREFIX'] = '$OBJPREFIX'
- env['SHOBJSUFFIX'] = '$OBJSUFFIX'
- env['PROGPREFIX'] = ''
- env['PROGSUFFIX'] = ''
- env['LIBPREFIX'] = 'lib'
- env['LIBSUFFIX'] = '.a'
- env['SHLIBPREFIX'] = '$LIBPREFIX'
- env['SHLIBSUFFIX'] = '.so'
- env['LIBPREFIXES'] = [ '$LIBPREFIX' ]
- env['LIBSUFFIXES'] = [ '$LIBSUFFIX', '$SHLIBSUFFIX' ]
- env['PSPAWN'] = pspawn
- env['SPAWN'] = spawn
- env['SHELL'] = 'sh'
- env['ESCAPE'] = escape
- env['TEMPFILE'] = TempFileMunge
- env['TEMPFILEPREFIX'] = '@'
- #Based on LINUX: ARG_MAX=ARG_MAX=131072 - 3000 for environment expansion
- #Note: specific platforms might rise or lower this value
- env['MAXLINELENGTH'] = 128072
- # This platform supports RPATH specifications.
- env['__RPATH'] = '$_RPATH'