diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/file_packager.py | 52 | ||||
-rw-r--r-- | tools/response_file.py | 28 | ||||
-rw-r--r-- | tools/shared.py | 18 |
3 files changed, 84 insertions, 14 deletions
diff --git a/tools/file_packager.py b/tools/file_packager.py index 73ff4919..e434e813 100644 --- a/tools/file_packager.py +++ b/tools/file_packager.py @@ -11,7 +11,7 @@ data downloads. Usage: - file_packager.py TARGET [--preload A [B..]] [--embed C [D..]] [--compress COMPRESSION_DATA] [--pre-run] [--crunch[=X]] + file_packager.py TARGET [--preload A [B..]] [--embed C [D..]] [--compress COMPRESSION_DATA] [--pre-run] [--crunch[=X]] [--js-output=OUTPUT.js] [--no-force] --pre-run Will generate wrapper code that does preloading in Module.preRun. This is necessary if you add this code before the main file has been loading, which includes necessary components like addRunDependency. @@ -24,6 +24,10 @@ Usage: DDS files will not be crunched if the .crn is more recent than the .dds. This prevents a lot of unneeded computation. + --js-output=FILE Writes output in FILE, if not specified, standard output is used. + + --no-force Don't create output if no valid input file is specified. + Notes: * The file packager generates unix-style file paths. So if you are on windows and a file is accessed at @@ -39,6 +43,11 @@ import shared from shared import Compression, execute, suffix, unsuffixed from subprocess import Popen, PIPE, STDOUT +if len(sys.argv) == 1: + print '''Usage: file_packager.py TARGET [--preload A...] [--embed B...] [--compress COMPRESSION_DATA] [--pre-run] [--crunch[=X]] [--js-output=OUTPUT.js] [--no-force] +See the source for more details.''' + sys.exit(0) + data_target = sys.argv[1] IMAGE_SUFFIXES = ('.jpg', '.png', '.bmp') @@ -59,6 +68,8 @@ in_compress = 0 pre_run = False crunch = 0 plugins = [] +jsoutput = None +force = True for arg in sys.argv[1:]: if arg == '--preload': @@ -80,6 +91,10 @@ for arg in sys.argv[1:]: in_preload = False in_embed = False in_compress = 0 + elif arg == '--no-force': + force = False + elif arg.startswith('--js-output'): + jsoutput = arg.split('=')[1] if '=' in arg else None elif arg.startswith('--crunch'): from shared import CRUNCH crunch = arg.split('=')[1] if '=' in arg else '128' @@ -93,9 +108,15 @@ for arg in sys.argv[1:]: in_embed = False in_compress = 0 elif in_preload: - data_files.append({ 'name': arg, 'mode': 'preload' }) + if os.path.isfile(arg) or os.path.isdir(arg): + data_files.append({ 'name': arg, 'mode': 'preload' }) + else: + print >> sys.stderr, 'Warning: ' + arg + ' does not exist, ignoring.' elif in_embed: - data_files.append({ 'name': arg, 'mode': 'embed' }) + if os.path.isfile(arg) or os.path.isdir(arg): + data_files.append({ 'name': arg, 'mode': 'embed' }) + else: + print >> sys.stderr, 'Warning:' + arg + ' does not exist, ignoring.' elif in_compress: if in_compress == 1: Compression.encoder = arg @@ -107,7 +128,10 @@ for arg in sys.argv[1:]: Compression.js_name = arg in_compress = 0 -print ''' +if (not force) and len(data_files) == 0: + has_preloaded = False + +ret = ''' (function() { ''' @@ -152,7 +176,7 @@ for file_ in data_files: # Crunch files if crunch: shutil.copyfile(shared.path_from_root('tools', 'crunch-worker.js'), 'crunch-worker.js') - print ''' + ret += ''' var decrunchWorker = new Worker('crunch-worker.js'); var decrunchCallbacks = []; decrunchWorker.onmessage = function(msg) { @@ -386,26 +410,30 @@ if has_preloaded: ''' % (data_target, os.path.basename(Compression.compressed_name(data_target) if Compression.on else data_target), use_data, data_target) # use basename because from the browser's point of view, we need to find the datafile in the same dir as the html file if pre_run: - print ''' + ret += ''' if (typeof Module == 'undefined') Module = {}; if (!Module['preRun']) Module['preRun'] = []; Module["preRun"].push(function() { ''' - -print code +ret += code if pre_run: - print ' });\n' + ret += ' });\n' if crunch: - print ''' + ret += ''' if (!Module['postRun']) Module['postRun'] = []; Module["postRun"].push(function() { decrunchWorker.terminate(); }); ''' -print ''' +ret += ''' })(); ''' - +if force or len(data_files) > 0: + if jsoutput == None: + print ret + else: + f = open(jsoutput, 'w') + f.write(ret) diff --git a/tools/response_file.py b/tools/response_file.py new file mode 100644 index 00000000..312cda73 --- /dev/null +++ b/tools/response_file.py @@ -0,0 +1,28 @@ +import tempfile, os, sys, shlex + +# Routes the given cmdline param list in args into a new response file and returns the filename to it. +# The returned filename has a suffix '.rsp'. +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 a response file, and returns the list of cmdline params found in the file. +# The parameter response_filename may start with '@'. +def read_response_file(response_filename): + if response_filename.startswith('@'): + 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() + args = shlex.split(args) + return args diff --git a/tools/shared.py b/tools/shared.py index 72f4868e..d5a37c03 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -2,6 +2,7 @@ import shutil, time, os, sys, json, tempfile, copy, shlex, atexit, subprocess, h 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] @@ -34,9 +35,15 @@ class WindowsPopen: self.stdout_ = PIPE if self.stderr_ == None: 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"): + 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)) @@ -67,6 +74,13 @@ class WindowsPopen: def kill(self): return self.process.kill() + + def __del__(self): + try: + # Clean up the temporary response file that was used to spawn this process, so that we don't leave temp files around. + tempfiles.try_delete(self.response_filename) + except: + pass # Mute all exceptions in dtor, particularly if we didn't use a response file, self.response_filename doesn't exist. # Install our replacement Popen handler if we are running on Windows to avoid python spawn process function. if os.name == 'nt': |