import shutil, time, os, sys, json, tempfile, copy, shlex, atexit, subprocess, hashlib, cPickle, re
from subprocess import Popen, PIPE, STDOUT
from tempfile import mkstemp
import jsrun, cache, tempfiles
from response_file import create_response_file
def listify(x):
if type(x) is not list: return [x]
return x
# Temp file utilities
from tempfiles import try_delete
# On Windows python suffers from a particularly nasty bug if python is spawning new processes while python itself is spawned from some other non-console process.
# Use a custom replacement for Popen on Windows to avoid the "WindowsError: [Error 6] The handle is invalid" errors when emcc is driven through cmake or mingw32-make.
# See http://bugs.python.org/issue3905
class WindowsPopen:
def __init__(self, args, bufsize=0, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=False,
shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0):
self.stdin = stdin
self.stdout = stdout
self.stderr = stderr
# (stdin, stdout, stderr) store what the caller originally wanted to be done with the streams.
# (stdin_, stdout_, stderr_) will store the fixed set of streams that workaround the bug.
self.stdin_ = stdin
self.stdout_ = stdout
self.stderr_ = stderr
# If the caller wants one of these PIPEd, we must PIPE them all to avoid the 'handle is invalid' bug.
if self.stdin_ == PIPE or self.stdout_ == PIPE or self.stderr_ == PIPE:
if self.stdin_ == None:
self.stdin_ = PIPE
if self.stdout_ == None:
self.stdout_ = PIPE
if self.stderr_ == None:
self.stderr_ = PIPE
# emscripten.py supports reading args from a response file instead of cmdline.
# Use .rsp to avoid cmdline length limitations on Windows.
if len(args) >= 2 and args[1].endswith("emscripten.py"):
self.response_filename = create_response_file(args[2:], TEMP_DIR)
args = args[0:2] + ['@' + self.response_filename]
try:
# Call the process with fixed streams.
self.process = subprocess.Popen(args, bufsize, executable, self.stdin_, self.stdout_, self.stderr_, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags)
except Exception, e:
print >> sys.stderr, '\nsubprocess.Popen(args=%s) failed! Exception %s\n' % (' '.join(args), str(e))
raise e
def communicate(self, input=None):
output = self.process.communicate(input)
self.returncode = self.process.returncode
# If caller never wanted to PIPE stdout or stderr, route the output back to screen to avoid swallowing output.
if self.stdout == None and self.stdout_ == PIPE and len(output[0].strip()) > 0:
print >> sys.stdout, output[0]
if self.stderr == None and self.stderr_ == PIPE and len(output[1].strip()) > 0:
print >> sys.stderr, output[1]
# Return a mock object to the caller. This works a