Extend the use of response files to cover the case when emcc invokes emscripten.py, so that Windows command line length limitations don't break the test_asm_pgo on Windows.

This commit is contained in:
Jukka Jylänki 2013-04-06 21:12:55 +03:00
Родитель bc234c204c
Коммит 1c4f763de4
5 изменённых файлов: 59 добавлений и 15 удалений

14
emcc
Просмотреть файл

@ -79,6 +79,7 @@ import os, sys, shutil, tempfile, subprocess, shlex, time, re
from subprocess import PIPE, STDOUT from subprocess import PIPE, STDOUT
from tools import shared from tools import shared
from tools.shared import Compression, execute, suffix, unsuffixed, unsuffixed_basename from tools.shared import Compression, execute, suffix, unsuffixed, unsuffixed_basename
from tools.response_file import read_and_delete_response_file
# Mapping of emcc opt levels to llvm opt levels. We use llvm opt level 3 in emcc opt # Mapping of emcc opt levels to llvm opt levels. We use llvm opt level 3 in emcc opt
# levels 2 and 3 (emcc 3 is unsafe opts, so unsuitable for the only level to get # levels 2 and 3 (emcc 3 is unsafe opts, so unsuitable for the only level to get
@ -129,19 +130,10 @@ while response_file:
for index in range(1, len(sys.argv)): for index in range(1, len(sys.argv)):
if sys.argv[index][0] == '@': if sys.argv[index][0] == '@':
# found one, loop again next time # found one, loop again next time
response_file = sys.argv[index][1:] response_file = True
print >>sys.stderr, 'emcc: using response file: %s' % response_file extra_args = read_and_delete_response_file(sys.argv[index])
if not os.path.exists(response_file):
print >>sys.stderr, 'emcc: error: Response file not found: %s' % response_file
exit(1)
response_fd = open(response_file, 'r')
extra_args = shlex.split(response_fd.read())
response_fd.close()
# slice in extra_args in place of the response file arg # slice in extra_args in place of the response file arg
sys.argv[index:index+1] = extra_args sys.argv[index:index+1] = extra_args
#if DEBUG: print >>sys.stderr, "Expanded response file: " + " | ".join(sys.argv)
break break
if sys.argv[1] == '--version': if sys.argv[1] == '--version':

Просмотреть файл

@ -12,6 +12,7 @@ headers, for the libc implementation in JS).
import os, sys, json, optparse, subprocess, re, time, multiprocessing, functools import os, sys, json, optparse, subprocess, re, time, multiprocessing, functools
from tools import jsrun, cache as cache_module, tempfiles from tools import jsrun, cache as cache_module, tempfiles
from tools.response_file import read_and_delete_response_file
__rootpath__ = os.path.abspath(os.path.dirname(__file__)) __rootpath__ = os.path.abspath(os.path.dirname(__file__))
def path_from_root(*pathelems): def path_from_root(*pathelems):
@ -629,6 +630,18 @@ def main(args, compiler_engine, cache, jcache, relooper, temp_files, DEBUG, DEBU
jcache=jcache, temp_files=temp_files, DEBUG=DEBUG, DEBUG_CACHE=DEBUG_CACHE) jcache=jcache, temp_files=temp_files, DEBUG=DEBUG, DEBUG_CACHE=DEBUG_CACHE)
def _main(environ): def _main(environ):
response_file = True
while response_file:
response_file = None
for index in range(1, len(sys.argv)):
if sys.argv[index][0] == '@':
# found one, loop again next time
response_file = True
response_file_args = read_and_delete_response_file(sys.argv[index])
# slice in extra_args in place of the response file arg
sys.argv[index:index+1] = response_file_args
break
parser = optparse.OptionParser( parser = optparse.OptionParser(
usage='usage: %prog [-h] [-H HEADERS] [-o OUTFILE] [-c COMPILER_ENGINE] [-s FOO=BAR]* infile', usage='usage: %prog [-h] [-H HEADERS] [-o OUTFILE] [-c COMPILER_ENGINE] [-s FOO=BAR]* infile',
description=('You should normally never use this! Use emcc instead. ' description=('You should normally never use this! Use emcc instead. '

Просмотреть файл

@ -8079,11 +8079,11 @@ def process(filename):
shutil.move(self.in_dir('src.cpp.o.js'), self.in_dir('pgo.js')) shutil.move(self.in_dir('src.cpp.o.js'), self.in_dir('pgo.js'))
pgo_output = run_js(self.in_dir('pgo.js')).split('\n')[1] pgo_output = run_js(self.in_dir('pgo.js')).split('\n')[1]
open('pgo_data', 'w').write(pgo_output) open('pgo_data.rsp', 'w').write(pgo_output)
# with response file # with response file
self.emcc_args += ['@pgo_data'] self.emcc_args += ['@pgo_data.rsp']
self.do_run(src, output) self.do_run(src, output)
self.emcc_args.pop() self.emcc_args.pop()
shutil.move(self.in_dir('src.cpp.o.js'), self.in_dir('pgoed.js')) shutil.move(self.in_dir('src.cpp.o.js'), self.in_dir('pgoed.js'))

31
tools/response_file.py Normal file
Просмотреть файл

@ -0,0 +1,31 @@
import tempfile, os, sys, shlex
from tempfiles import try_delete
# Routes the given cmdline param list in args into a new .rsp file and returns the filename to it.
# The returned filename has '@' prepended to it already for convenience.
def create_response_file(args, directory):
(response_fd, response_filename) = tempfile.mkstemp(prefix='emscripten_', suffix='.rsp', dir=directory, text=True)
response_fd = os.fdopen(response_fd, "w")
#print >> sys.stderr, "Creating response file '%s'" % response_filename
args = map(lambda p: p.replace(' ', '').replace('\\', '\\\\').replace('"', '\\"'), args)
response_fd.write(' '.join(args))
response_fd.close
return '@' + response_filename
# Reads and deletes a .rsp file, and returns the list of cmdline params found in the file.
def read_and_delete_response_file(response_filename):
# Ensure safety so that this function can never accidentally delete any non-.rsp files if things go wrong!
if not (response_filename.startswith('@') and response_filename.endswith('.rsp')):
raise Exception("'%s' is not a valid response file name! Response file names must start with '@' and end in '.rsp'!" % response_filename)
response_filename = response_filename[1:]
#print >> sys.stderr, "Using response file '%s'" % response_filename
if not os.path.exists(response_filename):
raise Exception("Response file '%s' not found!" % response_filename)
response_fd = open(response_filename, 'r')
args = response_fd.read()
response_fd.close()
try_delete(response_filename)
args = shlex.split(args)
return args

Просмотреть файл

@ -2,6 +2,7 @@ import shutil, time, os, sys, json, tempfile, copy, shlex, atexit, subprocess, h
from subprocess import Popen, PIPE, STDOUT from subprocess import Popen, PIPE, STDOUT
from tempfile import mkstemp from tempfile import mkstemp
import jsrun, cache, tempfiles import jsrun, cache, tempfiles
from response_file import create_response_file
def listify(x): def listify(x):
if type(x) is not list: return [x] if type(x) is not list: return [x]
@ -34,13 +35,20 @@ class WindowsPopen:
self.stdout_ = PIPE self.stdout_ = PIPE
if self.stderr_ == None: if self.stderr_ == None:
self.stderr_ = PIPE self.stderr_ = PIPE
# Call the process with fixed streams. # 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"):
response_filename = create_response_file(args[2:], TEMP_DIR)
args = args[0:2] + [response_filename]
try: 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) 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: except Exception, e:
print >> sys.stderr, '\nsubprocess.Popen(args=%s) failed! Exception %s\n' % (' '.join(args), str(e)) print >> sys.stderr, '\nsubprocess.Popen(args=%s) failed! Exception %s\n' % (' '.join(args), str(e))
raise e raise e
raise
def communicate(self, input=None): def communicate(self, input=None):
output = self.process.communicate(input) output = self.process.communicate(input)