posix.py
上传用户:market2
上传日期:2018-11-18
资源大小:18786k
文件大小:8k
源码类别:

外挂编程

开发平台:

Windows_Unix

  1. """SCons.Platform.posix
  2. Platform-specific initialization for POSIX (Linux, UNIX, etc.) systems.
  3. There normally shouldn't be any need to import this module directly.  It
  4. will usually be imported through the generic SCons.Platform.Platform()
  5. selection method.
  6. """
  7. #
  8. # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
  9. #
  10. # Permission is hereby granted, free of charge, to any person obtaining
  11. # a copy of this software and associated documentation files (the
  12. # "Software"), to deal in the Software without restriction, including
  13. # without limitation the rights to use, copy, modify, merge, publish,
  14. # distribute, sublicense, and/or sell copies of the Software, and to
  15. # permit persons to whom the Software is furnished to do so, subject to
  16. # the following conditions:
  17. #
  18. # The above copyright notice and this permission notice shall be included
  19. # in all copies or substantial portions of the Software.
  20. #
  21. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
  22. # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  23. # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  24. # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  25. # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  26. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  27. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  28. #
  29. __revision__ = "src/engine/SCons/Platform/posix.py 3057 2008/06/09 22:21:00 knight"
  30. import errno
  31. import os
  32. import os.path
  33. import popen2
  34. import string
  35. import sys
  36. import select
  37. import SCons.Util
  38. from SCons.Platform import TempFileMunge
  39. exitvalmap = {
  40.     2 : 127,
  41.     13 : 126,
  42. }
  43. def escape(arg):
  44.     "escape shell special characters"
  45.     slash = '\'
  46.     special = '"$'
  47.     arg = string.replace(arg, slash, slash+slash)
  48.     for c in special:
  49.         arg = string.replace(arg, c, slash+c)
  50.     return '"' + arg + '"'
  51. def exec_system(l, env):
  52.     stat = os.system(string.join(l))
  53.     if stat & 0xff:
  54.         return stat | 0x80
  55.     return stat >> 8
  56. def exec_spawnvpe(l, env):
  57.     stat = os.spawnvpe(os.P_WAIT, l[0], l, env)
  58.     # os.spawnvpe() returns the actual exit code, not the encoding
  59.     # returned by os.waitpid() or os.system().
  60.     return stat
  61. def exec_fork(l, env): 
  62.     pid = os.fork()
  63.     if not pid:
  64.         # Child process.
  65.         exitval = 127
  66.         try:
  67.             os.execvpe(l[0], l, env)
  68.         except OSError, e:
  69.             exitval = exitvalmap.get(e[0], e[0])
  70.             sys.stderr.write("scons: %s: %sn" % (l[0], e[1]))
  71.         os._exit(exitval)
  72.     else:
  73.         # Parent process.
  74.         pid, stat = os.waitpid(pid, 0)
  75.         if stat & 0xff:
  76.             return stat | 0x80
  77.         return stat >> 8
  78. def _get_env_command(sh, escape, cmd, args, env):
  79.     s = string.join(args)
  80.     if env:
  81.         l = ['env', '-'] + 
  82.             map(lambda t, e=escape: t[0]+'='+e(t[1]), env.items()) + 
  83.             [sh, '-c', escape(s)]
  84.         s = string.join(l)
  85.     return s
  86. def env_spawn(sh, escape, cmd, args, env):
  87.     return exec_system([_get_env_command( sh, escape, cmd, args, env)], env)
  88. def spawnvpe_spawn(sh, escape, cmd, args, env):
  89.     return exec_spawnvpe([sh, '-c', string.join(args)], env)
  90. def fork_spawn(sh, escape, cmd, args, env):
  91.     return exec_fork([sh, '-c', string.join(args)], env)
  92. def process_cmd_output(cmd_stdout, cmd_stderr, stdout, stderr):
  93.     stdout_eof = stderr_eof = 0
  94.     while not (stdout_eof and stderr_eof):
  95.         try:
  96.             (i,o,e) = select.select([cmd_stdout, cmd_stderr], [], [])
  97.             if cmd_stdout in i:
  98.                 str = cmd_stdout.read()
  99.                 if len(str) == 0:
  100.                     stdout_eof = 1
  101.                 elif stdout != None:
  102.                     stdout.write(str)
  103.             if cmd_stderr in i:
  104.                 str = cmd_stderr.read()
  105.                 if len(str) == 0:
  106.                     #sys.__stderr__.write( "stderr_eof=1n" )
  107.                     stderr_eof = 1
  108.                 else:
  109.                     #sys.__stderr__.write( "str(stderr) = %sn" % str )
  110.                     stderr.write(str)
  111.         except select.error, (_errno, _strerror):
  112.             if _errno != errno.EINTR:
  113.                 raise
  114. def exec_popen3(l, env, stdout, stderr):
  115.     proc = popen2.Popen3(string.join(l), 1)
  116.     process_cmd_output(proc.fromchild, proc.childerr, stdout, stderr)
  117.     stat = proc.wait()
  118.     if stat & 0xff:
  119.         return stat | 0x80
  120.     return stat >> 8
  121. def exec_piped_fork(l, env, stdout, stderr):
  122.     # spawn using fork / exec and providing a pipe for the command's
  123.     # stdout / stderr stream
  124.     if stdout != stderr:
  125.         (rFdOut, wFdOut) = os.pipe()
  126.         (rFdErr, wFdErr) = os.pipe()
  127.     else:
  128.         (rFdOut, wFdOut) = os.pipe()
  129.         rFdErr = rFdOut
  130.         wFdErr = wFdOut
  131.     # do the fork
  132.     pid = os.fork()
  133.     if not pid:
  134.         # Child process
  135.         os.close( rFdOut )
  136.         if rFdOut != rFdErr:
  137.             os.close( rFdErr )
  138.         os.dup2( wFdOut, 1 ) # is there some symbolic way to do that ?
  139.         os.dup2( wFdErr, 2 )
  140.         os.close( wFdOut )
  141.         if stdout != stderr:
  142.             os.close( wFdErr )
  143.         exitval = 127
  144.         try:
  145.             os.execvpe(l[0], l, env)
  146.         except OSError, e:
  147.             exitval = exitvalmap.get(e[0], e[0])
  148.             stderr.write("scons: %s: %sn" % (l[0], e[1]))
  149.         os._exit(exitval)
  150.     else:
  151.         # Parent process
  152.         pid, stat = os.waitpid(pid, 0)
  153.         os.close( wFdOut )
  154.         if stdout != stderr:
  155.             os.close( wFdErr )
  156.         childOut = os.fdopen( rFdOut )
  157.         if stdout != stderr:
  158.             childErr = os.fdopen( rFdErr )
  159.         else:
  160.             childErr = childOut
  161.         process_cmd_output(childOut, childErr, stdout, stderr)
  162.         os.close( rFdOut )
  163.         if stdout != stderr:
  164.             os.close( rFdErr )
  165.         if stat & 0xff:
  166.             return stat | 0x80
  167.         return stat >> 8
  168. def piped_env_spawn(sh, escape, cmd, args, env, stdout, stderr):
  169.     # spawn using Popen3 combined with the env command
  170.     # the command name and the command's stdout is written to stdout
  171.     # the command's stderr is written to stderr
  172.     return exec_popen3([_get_env_command(sh, escape, cmd, args, env)],
  173.                        env, stdout, stderr)
  174. def piped_fork_spawn(sh, escape, cmd, args, env, stdout, stderr):
  175.     # spawn using fork / exec and providing a pipe for the command's
  176.     # stdout / stderr stream
  177.     return exec_piped_fork([sh, '-c', string.join(args)],
  178.                            env, stdout, stderr)
  179. def generate(env):
  180.     # If os.spawnvpe() exists, we use it to spawn commands.  Otherwise
  181.     # if the env utility exists, we use os.system() to spawn commands,
  182.     # finally we fall back on os.fork()/os.exec().  
  183.     #
  184.     # os.spawnvpe() is prefered because it is the most efficient.  But
  185.     # for Python versions without it, os.system() is prefered because it
  186.     # is claimed that it works better with threads (i.e. -j) and is more
  187.     # efficient than forking Python.
  188.     #
  189.     # NB: Other people on the scons-users mailing list have claimed that
  190.     # os.fork()/os.exec() works better than os.system().  There may just
  191.     # not be a default that works best for all users.
  192.     if os.__dict__.has_key('spawnvpe'):
  193.         spawn = spawnvpe_spawn
  194.     elif env.Detect('env'):
  195.         spawn = env_spawn
  196.     else:
  197.         spawn = fork_spawn
  198.     if env.Detect('env'):
  199.         pspawn = piped_env_spawn
  200.     else:
  201.         pspawn = piped_fork_spawn
  202.     if not env.has_key('ENV'):
  203.         env['ENV']        = {}
  204.     env['ENV']['PATH']    = '/usr/local/bin:/opt/bin:/bin:/usr/bin'
  205.     env['OBJPREFIX']      = ''
  206.     env['OBJSUFFIX']      = '.o'
  207.     env['SHOBJPREFIX']    = '$OBJPREFIX'
  208.     env['SHOBJSUFFIX']    = '$OBJSUFFIX'
  209.     env['PROGPREFIX']     = ''
  210.     env['PROGSUFFIX']     = ''
  211.     env['LIBPREFIX']      = 'lib'
  212.     env['LIBSUFFIX']      = '.a'
  213.     env['SHLIBPREFIX']    = '$LIBPREFIX'
  214.     env['SHLIBSUFFIX']    = '.so'
  215.     env['LIBPREFIXES']    = [ '$LIBPREFIX' ]
  216.     env['LIBSUFFIXES']    = [ '$LIBSUFFIX', '$SHLIBSUFFIX' ]
  217.     env['PSPAWN']         = pspawn
  218.     env['SPAWN']          = spawn
  219.     env['SHELL']          = 'sh'
  220.     env['ESCAPE']         = escape
  221.     env['TEMPFILE']       = TempFileMunge
  222.     env['TEMPFILEPREFIX'] = '@'
  223.     #Based on LINUX: ARG_MAX=ARG_MAX=131072 - 3000 for environment expansion
  224.     #Note: specific platforms might rise or lower this value
  225.     env['MAXLINELENGTH']  = 128072
  226.     # This platform supports RPATH specifications.
  227.     env['__RPATH'] = '$_RPATH'