diff options
90 files changed, 18355 insertions, 5436 deletions
@@ -10,3 +10,4 @@ src/relooper.js.raw.js src/relooper/*.o src/relooper/*.out +tests/fake/
\ No newline at end of file @@ -49,4 +49,7 @@ a license to everyone to use it as detailed in LICENSE.) * Manuel Schölling <manuel.schoelling@gmx.de> * Bruce Mitchener, Jr. <bruce.mitchener@gmail.com> * Michael Bishop <mbtyke@gmail.com> +* Roger Braun <roger@rogerbraun.net> +* Vladimir Vukicevic <vladimir@pobox.com> (copyright owned by Mozilla Foundation) +* Lorant Pinter <lorant.pinter@prezi.com> @@ -11,6 +11,8 @@ import os, subprocess, sys from tools import shared DEBUG = os.environ.get('EMCC_DEBUG') +if DEBUG == "0": + DEBUG = None newargs = [shared.LLVM_AR] + sys.argv[1:] @@ -1,4 +1,5 @@ #!/usr/bin/env python2 +# -*- Mode: python -*- ''' emcc - compiler helper script @@ -90,7 +91,10 @@ LLVM_OPT_LEVEL = { 3: 3, } -DEBUG = int(os.environ.get('EMCC_DEBUG') or 0) +DEBUG = os.environ.get('EMCC_DEBUG') +if DEBUG == "0": + DEBUG = None + TEMP_DIR = os.environ.get('EMCC_TEMP_DIR') LEAVE_INPUTS_RAW = os.environ.get('EMCC_LEAVE_INPUTS_RAW') # Do not compile .ll files into .bc, just compile them with emscripten directly # Not recommended, this is mainly for the test runner, or if you have some other @@ -118,6 +122,28 @@ if len(sys.argv) == 1: print 'emcc: no input files' exit(1) +# read response files very early on +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 + print >>sys.stderr, 'emcc: using response file: %s' % response_file + response_file = sys.argv[index][1:] + 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 + sys.argv[index:index+1] = extra_args + #if DEBUG: print >>sys.stderr, "Expanded response file: " + " | ".join(sys.argv) + break + if sys.argv[1] == '--version': revision = '(unknown revision)' here = os.getcwd() @@ -155,16 +181,18 @@ Options that are modified or new in %s include: tools/shared.py and also src/settings.js.) Note: Optimizations are only done when compiling to JavaScript, not to intermediate - bitcode. + bitcode, *unless* you build with + EMCC_OPTIMIZE_NORMALLY=1 (not recommended + unless you know what you are doing!) -O2 As -O1, plus the relooper (loop recreation), plus LLVM -O2 optimizations -O3 As -O2, plus dangerous optimizations that may break the generated code! This adds - -s INLINING_LIMIT=0 -s DOUBLE_MODE=0 -s PRECISE_I64_MATH=0 --closure 1 + --llvm-lto 1 This is not recommended at all. A better idea is to try each of these separately on top of @@ -207,8 +235,8 @@ Options that are modified or new in %s include: 2: -O2 LLVM optimizations 3: -O3 LLVM optimizations (default in -O2+) - --llvm-lto <level> 0: No LLVM LTO (default in -O0) - 1: LLVM LTO (default in -O1+) + --llvm-lto <level> 0: No LLVM LTO (default in -O2 and below) + 1: LLVM LTO (default in -O3) Note: If LLVM optimizations are not run (see --llvm-opts), setting this to 1 has no effect. @@ -374,6 +402,41 @@ Options that are modified or new in %s include: for a later incremental build (where you also enable it) to be sped up. + Caching works separately on 4 parts of compilation: + 'pre' which is types and global variables; that + information is then fed into 'funcs' which are + the functions (which we parallelize), and then + 'post' which adds final information based on + the functions (e.g., do we need long64 support + code). Finally, 'jsfuncs' are JavaScript-level + optimizations. Each of the 4 parts can be cached + separately, but note that they can affect each + other: If you recompile a single C++ file that + changes a global variable - e.g., adds, removes + or modifies a global variable, say by adding + a printf or by adding a compile-time timestamp, + then 'pre' cannot be loaded from the cache. And + since 'pre's output is sent to 'funcs' and 'post', + they will get invalidated as well, and only + 'jsfuncs' will be cached. So avoid modifying + globals to let caching work fully. + + To work around the problem mentioned in the + previous paragraph, you can use + + emscripten_jcache_printf + + when adding debug printfs to your code. That + function is specially preprocessed so that it + does not create a constant string global for + its first argument. See emscripten.h for more + details. Note in particular that you need to + already have a call to that function in your + code *before* you add one and do an incremental + build, so that adding an external reference + (also a global property) does not invalidate + everything. + --clear-cache Manually clears the cache of compiled emscripten system libraries (libc++, libc++abi, libc). This is normally @@ -646,7 +709,8 @@ try: for i in range(len(newargs)): newargs[i] = newargs[i].strip() # On Windows Vista (and possibly others), excessive spaces in the command line leak into the items in this array, so trim e.g. 'foo.cpp ' -> 'foo.cpp' if newargs[i].startswith('-O'): - requested_level = newargs[i][2] + # Let -O default to -O2, which is what gcc does. + requested_level = newargs[i][2:] or '2' if requested_level == 's': print >> sys.stderr, 'emcc: warning: -Os is ignored (use -O0, -O1, -O2)' else: @@ -768,7 +832,7 @@ try: newargs = newargs + [default_cxx_std] if llvm_opts is None: llvm_opts = LLVM_OPT_LEVEL[opt_level] - if llvm_lto is None: llvm_lto = llvm_opts > 0 + if llvm_lto is None: llvm_lto = opt_level >= 3 if opt_level <= 0: keep_llvm_debug = keep_js_debug = True # always keep debug in -O0 if opt_level > 0: keep_llvm_debug = False # JS optimizer wipes out llvm debug info from being visible if closure is None and opt_level == 3: closure = True @@ -930,6 +994,7 @@ try: for input_file in input_files: if input_file.endswith(SOURCE_SUFFIXES): if DEBUG: print >> sys.stderr, 'emcc: compiling source file: ', input_file + input_file = shared.Building.preprocess(input_file, in_temp(uniquename(input_file))) output_file = in_temp(unsuffixed(uniquename(input_file)) + '.o') temp_files.append(output_file) args = newargs + ['-emit-llvm', '-c', input_file, '-o', output_file] @@ -963,7 +1028,15 @@ try: # If we were just asked to generate bitcode, stop there if final_suffix not in JS_CONTAINING_SUFFIXES: if llvm_opts > 0: - print >> sys.stderr, 'emcc: warning: -Ox flags ignored, since not generating JavaScript' + if not os.environ.get('EMCC_OPTIMIZE_NORMALLY'): + print >> sys.stderr, 'emcc: warning: -Ox flags ignored, since not generating JavaScript' + else: + for input_file in input_files: + if input_file.endswith(SOURCE_SUFFIXES): + if DEBUG: print >> sys.stderr, 'emcc: optimizing %s with -O%d since EMCC_OPTIMIZE_NORMALLY defined' % (input_file, llvm_opts) + shared.Building.llvm_opt(in_temp(unsuffixed(uniquename(input_file)) + '.o'), llvm_opts) + else: + if DEBUG: print >> sys.stderr, 'emcc: not optimizing %s despite EMCC_OPTIMIZE_NORMALLY since not source code' % (input_file) if not specified_target: for input_file in input_files: shutil.move(in_temp(unsuffixed(uniquename(input_file)) + '.o'), unsuffixed_basename(input_file) + '.' + final_suffix) @@ -1053,29 +1126,32 @@ try: libcxxabi_symbols = filter(lambda symbol: symbol not in libc_symbols, libcxxabi_symbols) libcxxabi_symbols = set(libcxxabi_symbols) - force = False # If we have libcxx, we must force inclusion of libc, since libcxx uses new internally. Note: this is kind of hacky - + # If we have libcxx, we must force inclusion of libc, since libcxx uses new internally. Note: this is kind of hacky + # Settings this in the environment will avoid checking dependencies and make building big projects a little faster + force = os.environ.get('EMCC_FORCE_STDLIBS') + has = need = None for name, create, fix, library_symbols in [('libcxx', create_libcxx, fix_libcxx, libcxx_symbols), ('libcxxabi', create_libcxxabi, fix_libcxxabi, libcxxabi_symbols), ('libc', create_libc, fix_libc, libc_symbols)]: - need = set() - has = set() - for temp_file in temp_files: - symbols = shared.Building.llvm_nm(temp_file) - for library_symbol in library_symbols: - if library_symbol in symbols.undefs: - need.add(library_symbol) - if library_symbol in symbols.defs: - has.add(library_symbol) - for haz in has: # remove symbols that are supplied by another of the inputs - if haz in need: - need.remove(haz) - if DEBUG: print >> sys.stderr, 'emcc: considering including %s: we need %s and have %s' % (name, str(need), str(has)) + if not force: + need = set() + has = set() + for temp_file in temp_files: + symbols = shared.Building.llvm_nm(temp_file) + for library_symbol in library_symbols: + if library_symbol in symbols.undefs: + need.add(library_symbol) + if library_symbol in symbols.defs: + has.add(library_symbol) + for haz in has: # remove symbols that are supplied by another of the inputs + if haz in need: + need.remove(haz) + if DEBUG: print >> sys.stderr, 'emcc: considering including %s: we need %s and have %s' % (name, str(need), str(has) |