diff options
Diffstat (limited to 'tools/shared.py')
-rw-r--r-- | tools/shared.py | 76 |
1 files changed, 63 insertions, 13 deletions
diff --git a/tools/shared.py b/tools/shared.py index bdfec8ed..44fc428a 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -33,7 +33,8 @@ else: config_file = config_file.replace('{{{ LLVM_ROOT }}}', llvm_root) node = 'node' try: - node = Popen(['which', 'node'], stdout=PIPE).communicate()[0].replace('\n', '') + node = Popen(['which', 'node'], stdout=PIPE).communicate()[0].replace('\n', '') or \ + Popen(['which', 'nodejs'], stdout=PIPE).communicate()[0].replace('\n', '') except: pass config_file = config_file.replace('{{{ NODE }}}', node) @@ -533,6 +534,8 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e @staticmethod def configure(args, stdout=None, stderr=None, env=None): + if not args: + return if env is None: env = Building.get_building_env() env['EMMAKEN_JUST_CONFIGURE'] = '1' @@ -617,7 +620,7 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e actual_files = [] unresolved_symbols = set(['main']) # tracking unresolveds is necessary for .a linking, see below. (and main is always a necessary symbol) resolved_symbols = set() - temp_dir = None + temp_dirs = [] files = map(os.path.abspath, files) for f in files: if not Building.is_ar(f): @@ -631,7 +634,8 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e # (link in an entire .o from the archive if it supplies symbols still unresolved) cwd = os.getcwd() try: - temp_dir = os.path.join(EMSCRIPTEN_TEMP_DIR, 'ar_output_' + str(os.getpid())) + temp_dir = os.path.join(EMSCRIPTEN_TEMP_DIR, 'ar_output_' + str(os.getpid()) + '_' + str(len(temp_dirs))) + temp_dirs.append(temp_dir) if not os.path.exists(temp_dir): os.makedirs(temp_dir) os.chdir(temp_dir) @@ -684,7 +688,7 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e # Finish link output = Popen([LLVM_LINK] + actual_files + ['-o', target], stdout=PIPE).communicate()[0] assert os.path.exists(target) and (output is None or 'Could not open input file' not in output), 'Linking error: ' + output + '\nemcc: If you get duplicate symbol errors, try --remove-duplicates' - if temp_dir: + for temp_dir in temp_dirs: try_delete(temp_dir) # Emscripten optimizations that we run on the .ll file @@ -908,15 +912,60 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e Building.LLVM_OPT_OPTS = opts return opts + MAX_JS_PROCESS_SIZE = 12*1024*1024 + BEST_JS_PROCESS_SIZE = 8*1024*1024 + + @staticmethod + def splitter(filename, addendum, func, args=[]): + # Split up huge files into pieces small enough for node/uglify/etc. to handle + js = open(filename).read() + if len(js) > Building.MAX_JS_PROCESS_SIZE: + if os.environ.get('EMCC_DEBUG'): print >> sys.stderr, 'splitting up js file' + + suffix_marker = '// EMSCRIPTEN_GENERATED_FUNCTIONS' + suffix_start = js.find(suffix_marker) + suffix = '' + if suffix_start >= 0: + suffix = js[suffix_start:js.find('\n', suffix_start)] + '\n' + + filename += addendum + f = open(filename, 'w') + + i = 0 + f_start = 0 + while True: + f_end = f_start + while f_end-f_start < Building.BEST_JS_PROCESS_SIZE and f_end != -1: + f_end = js.find('\n}\n', f_end+1) + chunk = js[f_start:(-1 if f_end == -1 else f_end+3)] + suffix + temp_in_file = filename + '.p%d.js' % i + if os.environ.get('EMCC_DEBUG'): print >> sys.stderr, ' split %d, size %d' % (i, len(chunk)) + i += 1 + open(temp_in_file, 'w').write(chunk) + temp_out_file = func(*([temp_in_file] + args + [False])) # maybe_big is now false + f.write( + ''.join(filter(lambda line: not line.startswith(suffix_marker), open(temp_out_file).readlines())) + ) + if f_end == -1: break + f_start = f_end+3 + if f_start >= len(js): break + + f.write(suffix) + f.close() + return filename + @staticmethod - def js_optimizer(filename, passes): - if not check_engine(NODE_JS): - raise Exception('Node.js appears to be missing or broken, looked at: ' + str(NODE_JS)) + def js_optimizer(filename, passes, maybe_big=True): + if maybe_big: + # When we split up, we cannot do unGlobalize, the only pass which is *not* function-local + args = [filter(lambda p: p != 'unGlobalize', passes)] + ret = Building.splitter(filename, addendum='.jo.js', func=Building.js_optimizer, args=args) + if ret: return ret if type(passes) == str: passes = [passes] - # XXX Disable crankshaft to work around v8 bug 1895 - output = Popen([NODE_JS, '--nocrankshaft', JS_OPTIMIZER, filename] + passes, stdout=PIPE).communicate()[0] + # XXX Might need to disable crankshaft to work around v8 bug 1895 , '--nocrankshaft' + output = Popen([NODE_JS, JS_OPTIMIZER, filename] + passes, stdout=PIPE).communicate()[0] assert len(output) > 0 and not output.startswith('Assertion failed'), 'Error in js optimizer: ' + output filename += '.jo.js' f = open(filename, 'w') @@ -925,9 +974,10 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e return filename @staticmethod - def eliminator(filename): - if not check_engine(NODE_JS): - raise Exception('Node.js appears to be missing or broken, looked at: ' + str(NODE_JS)) + def eliminator(filename, maybe_big=True): + if maybe_big: + ret = Building.splitter(filename, addendum='.el.js', func=Building.eliminator) + if ret: return ret coffee = path_from_root('tools', 'eliminator', 'node_modules', 'coffee-script', 'bin', 'coffee') eliminator = path_from_root('tools', 'eliminator', 'eliminator.coffee') @@ -948,7 +998,7 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e # Something like this (adjust memory as needed): # java -Xmx1024m -jar CLOSURE_COMPILER --compilation_level ADVANCED_OPTIMIZATIONS --variable_map_output_file src.cpp.o.js.vars --js src.cpp.o.js --js_output_file src.cpp.o.cc.js args = [JAVA, - '-Xmx1024m', + '-Xmx' + (os.environ.get('JAVA_HEAP_SIZE') or '1024m'), # if you need a larger Java heap, use this environment variable '-jar', CLOSURE_COMPILER, '--compilation_level', 'ADVANCED_OPTIMIZATIONS', '--formatting', 'PRETTY_PRINT', |