aboutsummaryrefslogtreecommitdiff
path: root/emcc
diff options
context:
space:
mode:
Diffstat (limited to 'emcc')
-rwxr-xr-xemcc317
1 files changed, 179 insertions, 138 deletions
diff --git a/emcc b/emcc
index 7fe2f5a0..0ee117ca 100755
--- a/emcc
+++ b/emcc
@@ -28,34 +28,6 @@ Example uses:
so it should relay everything to gcc/g++. You should not define that when
running make, of course.
- * With CMake, the same command will work (with cmake instead of ./configure). You may also be
- able to do the following in your CMakeLists.txt:
-
- SET(CMAKE_C_COMPILER "PATH/emcc")
- SET(CMAKE_CXX_COMPILER "PATH/em++")
- SET(CMAKE_LINKER "PATH/emcc")
- SET(CMAKE_CXX_LINKER "PATH/emcc")
- SET(CMAKE_C_LINK_EXECUTABLE "PATH/emcc")
- SET(CMAKE_CXX_LINK_EXECUTABLE "PATH/emcc")
- SET(CMAKE_AR "PATH/emar")
- SET(CMAKE_RANLIB "PATH/emranlib")
-
- * For SCons the shared.py can be imported like so:
- __file__ = str(Dir('#/project_path_to_emscripten/dummy/dummy'))
- __rootpath__ = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
- def path_from_root(*pathelems):
- return os.path.join(__rootpath__, *pathelems)
- sys.path += [path_from_root('')]
- from tools.shared import *
-
- For using the Emscripten compilers/linkers/etc. you can do:
- env = Environment()
- ...
- env.Append(CCFLAGS = COMPILER_OPTS)
- env.Replace(LINK = LLVM_LD)
- env.Replace(LD = LLVM_LD)
- TODO: Document all relevant setup changes
-
After setting that up, run your build system normally.
Note the appearance of em++ instead of emcc
@@ -75,12 +47,14 @@ emcc can be influenced by a few environment variables:
EMMAKEN_COMPILER - The compiler to be used, if you don't want the default clang.
'''
-import os, sys, shutil, tempfile, subprocess, shlex, time, re
+import os, sys, shutil, tempfile, subprocess, shlex, time, re, logging
from subprocess import PIPE, STDOUT
from tools import shared
from tools.shared import Compression, execute, suffix, unsuffixed, unsuffixed_basename
from tools.response_file import read_response_file
+logging = logging.getLogger('emcc')
+
# 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
# llvm opt level 3, and speed-wise emcc level 2 is already the slowest/most optimizing
@@ -107,10 +81,10 @@ AUTODEBUG = os.environ.get('EMCC_AUTODEBUG') # If set to 1, we will run the auto
# dlmalloc makes it hard to compare native and js builds
EMCC_CFLAGS = os.environ.get('EMCC_CFLAGS') # Additional compiler flags that we treat as if they were passed to us on the commandline
-if DEBUG: print >> sys.stderr, '\nemcc invocation: ', ' '.join(sys.argv), (' + ' + EMCC_CFLAGS if EMCC_CFLAGS else '')
+logging.debug('invocation: ' + ' '.join(sys.argv) + (' + ' + EMCC_CFLAGS if EMCC_CFLAGS else ''))
if EMCC_CFLAGS: sys.argv.append(EMCC_CFLAGS)
-if DEBUG and LEAVE_INPUTS_RAW: print >> sys.stderr, 'emcc: leaving inputs raw'
+if DEBUG and LEAVE_INPUTS_RAW: logging.warning('leaving inputs raw')
stdout = PIPE if not DEBUG else None # suppress output of child processes
stderr = PIPE if not DEBUG else None # unless we are in DEBUG mode
@@ -120,7 +94,7 @@ shared.check_sanity(force=DEBUG)
# Handle some global flags
if len(sys.argv) == 1:
- print 'emcc: no input files'
+ logging.warning('no input files')
exit(1)
# read response files very early on
@@ -136,23 +110,7 @@ while response_file:
sys.argv[index:index+1] = extra_args
break
-if sys.argv[1] == '--version':
- revision = '(unknown revision)'
- here = os.getcwd()
- os.chdir(shared.path_from_root())
- try:
- revision = execute(['git', 'show'], stdout=PIPE, stderr=PIPE)[0].split('\n')[0]
- except:
- pass
- finally:
- os.chdir(here)
- print '''emcc (Emscripten GCC-like replacement) %s (%s)
-Copyright (C) 2013 the Emscripten authors (see AUTHORS.txt)
-This is free and open source software under the MIT license.
-There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- ''' % (shared.EMSCRIPTEN_VERSION, revision)
- exit(0)
-elif sys.argv[1] == '--help':
+if len(sys.argv) == 1 or sys.argv[1] == '--help':
this = os.path.basename('em++' if os.environ.get('EMMAKEN_CXX') else 'emcc')
print '''%s [options] file...
@@ -177,10 +135,14 @@ Options that are modified or new in %s include:
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
+ LLVM -O2 optimizations, and
+
+ -s ALIASING_FUNCTION_POINTERS=1
+
-O3 As -O2, plus dangerous optimizations that may
break the generated code! This adds
+ -s FORCE_ALIGNED_MEMORY=1
-s DOUBLE_MODE=0
-s PRECISE_I64_MATH=0
--closure 1
@@ -188,7 +150,8 @@ Options that are modified or new in %s include:
This is not recommended at all. A better idea
is to try each of these separately on top of
- -O2 to see what works. See the wiki for more
+ -O2 to see what works. See the wiki and
+ src/settings.js (for the -s options) for more
information.
-s OPTION=VALUE JavaScript code generation option passed
@@ -255,6 +218,11 @@ Options that are modified or new in %s include:
may require some changes to the code. This
is run by default in -O3.
+ In asm.js mode, closure will only be used on the
+ 'shell' code around the compiled code (the
+ compiled code will be processed by the custom
+ asm.js minifier).
+
Note: If closure compiler hits an out-of-memory,
try adjusting JAVA_HEAP_SIZE in the environment
(for example, to 4096m for 4GB).
@@ -441,6 +409,10 @@ Options that are modified or new in %s include:
(also a global property) does not invalidate
everything.
+ Note that you should use -g during the linking
+ stage (bitcode to JS), for jcache to work
+ (otherwise, JS minification can confuse it).
+
--clear-cache Manually clears the cache of compiled
emscripten system libraries (libc++,
libc++abi, libc). This is normally
@@ -493,6 +465,24 @@ emcc: supported targets: llvm bitcode, javascript, NOT elf
(autoconf likes to see elf above to enable shared object support)
''' % (this, this, this)
exit(0)
+
+elif sys.argv[1] == '--version':
+ revision = '(unknown revision)'
+ here = os.getcwd()
+ os.chdir(shared.path_from_root())
+ try:
+ revision = execute(['git', 'show'], stdout=PIPE, stderr=PIPE)[0].split('\n')[0]
+ except:
+ pass
+ finally:
+ os.chdir(here)
+ print '''emcc (Emscripten GCC-like replacement) %s (%s)
+Copyright (C) 2013 the Emscripten authors (see AUTHORS.txt)
+This is free and open source software under the MIT license.
+There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ ''' % (shared.EMSCRIPTEN_VERSION, revision)
+ exit(0)
+
elif len(sys.argv) == 2 and sys.argv[1] == '-v': # -v with no inputs
print 'emcc (Emscripten GCC-like replacement + linker emulating GNU ld ) 2.0'
exit(subprocess.call([shared.CLANG, '-v']))
@@ -502,7 +492,7 @@ def is_minus_s_for_emcc(newargs,i):
if i+1 < len(newargs) and '=' in newargs[i+1]: # -s OPT=VALUE is for us, -s by itself is a linker option
return True
else:
- print >> sys.stderr, 'emcc: warning: treating -s as linker option and not as -s OPT=VALUE for js compilation'
+ logging.warning('treating -s as linker option and not as -s OPT=VALUE for js compilation')
return False
# If this is a configure-type thing, do not compile to JavaScript, instead use clang
@@ -557,8 +547,9 @@ if CONFIGURE_CONFIG or CMAKE_CONFIG:
cmd = [compiler] + list(filter_emscripten_options(sys.argv[1:]))
if not use_js: cmd += shared.EMSDK_OPTS + ['-DEMSCRIPTEN']
+ if use_js: cmd += ['-s', 'ERROR_ON_UNDEFINED_SYMBOLS=1'] # configure tests should fail when an undefined symbol exists
- if DEBUG: print >> sys.stderr, 'emcc, just configuring: ', ' '.join(cmd)
+ logging.debug('just configuring: ' + ' '.join(cmd))
if debug_configure: open(tempout, 'a').write('emcc, just configuring: ' + ' '.join(cmd) + '\n\n')
if not use_js:
@@ -629,7 +620,7 @@ def uniquename(name):
if len(sys.argv) == 1 or sys.argv[1] in ['x', 't']:
# noop ar
- if DEBUG: print >> sys.stderr, 'emcc, just ar'
+ logging.debug('just ar')
sys.exit(0)
use_cxx = True
@@ -646,7 +637,7 @@ for i in range(1, len(sys.argv)):
if '-M' in sys.argv or '-MM' in sys.argv:
# Just output dependencies, do not compile. Warning: clang and gcc behave differently with -MF! (clang seems to not recognize it)
cmd = [CC] + shared.COMPILER_OPTS + sys.argv[1:]
- if DEBUG: print >> sys.stderr, 'emcc, just dependencies: ', ' '.join(cmd)
+ logging.debug('just dependencies: ' + ' '.join(cmd))
exit(subprocess.call(cmd))
# Check if a target is specified
@@ -672,10 +663,10 @@ else:
if header: # header or such
if len(sys.argv) >= 3: # if there is a source and a target, then copy, otherwise do nothing
sys.argv = filter(lambda arg: not arg.startswith('-I'), sys.argv)
- if DEBUG: print >> sys.stderr, 'Just copy:', sys.argv[-1], target
+ logging.debug('Just copy:' + sys.argv[-1] + target)
shutil.copy(sys.argv[-1], target)
else:
- if DEBUG: print >> sys.stderr, 'No-op.'
+ logging.debug('No-op.')
exit(0)
if TEMP_DIR:
@@ -842,14 +833,14 @@ try:
newargs[i] = ''
newargs[i+1] = ''
elif newargs[i] == '--remove-duplicates':
- print >> sys.stderr, 'emcc: warning: --remove-duplicates is deprecated as it is no longer needed. If you cannot link without it, file a bug with a testcase'
+ logging.warning ('--remove-duplicates is deprecated as it is no longer needed. If you cannot link without it, file a bug with a testcase')
newargs[i] = ''
elif newargs[i] == '--jcache':
jcache = True
newargs[i] = ''
elif newargs[i] == '--clear-cache':
newargs[i] = ''
- print >> sys.stderr, 'emcc: clearing cache'
+ logging.warning('clearing cache')
shared.Cache.erase()
sys.exit(0)
elif newargs[i] == '--save-bc':
@@ -864,7 +855,7 @@ try:
newargs[i+1] = ''
elif newargs[i].startswith(('-I/', '-L/')):
if not absolute_warning_shown:
- print >> sys.stderr, 'emcc: warning: -I or -L of an absolute path encountered. If this is to a local system header/library, it may cause problems (local system files make sense for compiling natively on your system, but not necessarily to JavaScript)' # Of course an absolute path to a non-system-specific library or header is fine, and you can ignore this warning. The danger are system headers that are e.g. x86 specific and nonportable. The emscripten bundled headers are modified to be portable, local system ones are generally not
+ logging.warning ('-I or -L of an absolute path encountered. If this is to a local system header/library, it may cause problems (local system files make sense for compiling natively on your system, but not necessarily to JavaScript)') # Of course an absolute path to a non-system-specific library or header is fine, and you can ignore this warning. The danger are system headers that are e.g. x86 specific and nonportable. The emscripten bundled headers are modified to be portable, local system ones are generally not
absolute_warning_shown = True
newargs = [ arg for arg in newargs if arg is not '' ]
@@ -881,7 +872,7 @@ try:
if DEBUG: start_time = time.time() # done after parsing arguments, which might affect debug state
if closure:
- assert os.path.exists(shared.CLOSURE_COMPILER), 'emcc: fatal: Closure compiler (%s) does not exist' % shared.CLOSURE_COMPILER
+ assert os.path.exists(shared.CLOSURE_COMPILER), logging.error('fatal: Closure compiler (%s) does not exist' % shared.CLOSURE_COMPILER)
for i in range(len(newargs)):
if newargs[i] == '-s':
@@ -937,9 +928,9 @@ try:
libs.append(l)
newargs[i] = ''
else:
- print >> sys.stderr, 'emcc: %s: warning: Not valid LLVM bitcode' % arg
+ logging.warning(arg + ' is not valid LLVM bitcode')
else:
- print >> sys.stderr, 'emcc: %s: error: No such file or directory' % arg
+ logging.error(arg + ': No such file or directory')
exit(1)
elif arg.startswith('-L'):
lib_dirs.append(arg[2:])
@@ -961,12 +952,12 @@ try:
# do not link in libs when just generating object code (not an 'executable', i.e. JS, or a library)
if ('.' + final_suffix) in BITCODE_SUFFIXES and len(libs) > 0:
- print >> sys.stderr, 'emcc: warning: not linking against libraries since only compiling to bitcode'
+ logging.warning('not linking against libraries since only compiling to bitcode')
libs = []
# Find library files
for lib in libs:
- if DEBUG: print >> sys.stderr, 'emcc: looking for library "%s"' % lib
+ logging.debug('looking for library "%s"' % lib)
found = False
for prefix in LIB_PREFIXES:
for suff in STATICLIB_SUFFIXES + DYNAMICLIB_SUFFIXES:
@@ -974,7 +965,7 @@ try:
for lib_dir in lib_dirs:
path = os.path.join(lib_dir, name)
if os.path.exists(path):
- if DEBUG: print >> sys.stderr, 'emcc: found library "%s" at %s' % (lib, path)
+ logging.debug('found library "%s" at %s' % (lib, path))
input_files.append(path)
found = True
break
@@ -985,8 +976,7 @@ try:
input_files = filter(lambda input_file: not input_file.endswith(DYNAMICLIB_SUFFIXES), input_files)
if len(input_files) == 0:
- print >> sys.stderr, 'emcc: no input files'
- print >> sys.stderr, 'note that input files without a known suffix are ignored, make sure your input files end with one of: ' + str(SOURCE_SUFFIXES + BITCODE_SUFFIXES + DYNAMICLIB_SUFFIXES + STATICLIB_SUFFIXES + ASSEMBLY_SUFFIXES)
+ logging.error('no input files\nnote that input files without a known suffix are ignored, make sure your input files end with one of: ' + str(SOURCE_SUFFIXES + BITCODE_SUFFIXES + DYNAMICLIB_SUFFIXES + STATICLIB_SUFFIXES + ASSEMBLY_SUFFIXES))
exit(0)
newargs += CC_ADDITIONAL_ARGS
@@ -1013,55 +1003,69 @@ try:
if bind:
shared.Settings.ASM_JS = 0
- print >> sys.stderr, 'emcc: warning: disabling asm.js because it is not compatible with embind yet'
- if closure:
- print >> sys.stderr, 'emcc: warning: disabling closure because it is not compatible with asm.js code generation'
- closure = False
+ logging.warning('disabling asm.js because it is not compatible with embind yet')
if shared.Settings.CORRECT_SIGNS != 1:
- print >> sys.stderr, 'emcc: warning: setting CORRECT_SIGNS to 1 for asm.js code generation'
+ logging.warning('setting CORRECT_SIGNS to 1 for asm.js code generation')
shared.Settings.CORRECT_SIGNS = 1
if shared.Settings.CORRECT_OVERFLOWS != 1:
- print >> sys.stderr, 'emcc: warning: setting CORRECT_OVERFLOWS to 1 for asm.js code generation'
+ logging.warning('setting CORRECT_OVERFLOWS to 1 for asm.js code generation')
shared.Settings.CORRECT_OVERFLOWS = 1
assert not shared.Settings.PGO, 'cannot run PGO in ASM_JS mode'
+ if shared.Settings.ASSERTIONS and shared.Settings.ALIASING_FUNCTION_POINTERS:
+ logging.warning('ALIASING_FUNCTION_POINTERS is on, function pointer comparisons may be invalid across types')
+
if shared.Settings.CORRECT_SIGNS >= 2 or shared.Settings.CORRECT_OVERFLOWS >= 2 or shared.Settings.CORRECT_ROUNDINGS >= 2:
keep_llvm_debug = True # must keep debug info to do line-by-line operations
if (keep_llvm_debug or keep_js_debug) and closure:
- print >> sys.stderr, 'emcc: warning: disabling closure because debug info was requested'
+ logging.warning('disabling closure because debug info was requested')
closure = False
+ if jcache and not keep_js_debug: print >> sys.stderr, 'emcc: warning: it is recommended to run jcache with -g when compiling bitcode to JS'
+
if minify_whitespace is None:
minify_whitespace = opt_level >= 2 and not keep_js_debug
+ assert shared.LLVM_TARGET in shared.COMPILER_OPTS
+ if shared.LLVM_TARGET == 'i386-pc-linux-gnu':
+ shared.Settings.TARGET_X86 = 1
+ shared.Settings.TARGET_LE32 = 0
+ assert 'le32-unknown-nacl' not in shared.COMPILER_OPTS
+ elif shared.LLVM_TARGET == 'le32-unknown-nacl':
+ shared.Settings.TARGET_LE32 = 1
+ shared.Settings.TARGET_X86 = 0
+ assert 'i386-pc-linux-gnu' not in shared.COMPILER_OPTS
+ else:
+ raise Exception('unknown llvm target: ' + str(shared.LLVM_TARGET))
+
## Compile source code to bitcode
- if DEBUG: print >> sys.stderr, 'emcc: compiling to bitcode'
+ logging.debug('compiling to bitcode')
temp_files = []
# First, generate LLVM bitcode. For each input file, we get base.o with bitcode
for input_file in input_files:
if input_file.endswith(SOURCE_SUFFIXES):
- if DEBUG: print >> sys.stderr, 'emcc: compiling source file: ', input_file
+ logging.debug('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]
- if DEBUG: print >> sys.stderr, "emcc running:", call, ' '.join(args)
+ logging.debug("running:" + call + ' '.join(args))
execute([call] + args) # let compiler frontend print directly, so colors are saved (PIPE kills that)
if not os.path.exists(output_file):
- print >> sys.stderr, 'emcc: compiler frontend failed to generate LLVM bitcode, halting'
+ logging.error('compiler frontend failed to generate LLVM bitcode, halting')
sys.exit(1)
else: # bitcode
if input_file.endswith(BITCODE_SUFFIXES):
- if DEBUG: print >> sys.stderr, 'emcc: copying bitcode file: ', input_file
+ logging.debug('copying bitcode file: ' + input_file)
temp_file = in_temp(unsuffixed(uniquename(input_file)) + '.o')
shutil.copyfile(input_file, temp_file)
temp_files.append(temp_file)
elif input_file.endswith(DYNAMICLIB_SUFFIXES) or shared.Building.is_ar(input_file):
- if DEBUG: print >> sys.stderr, 'emcc: copying library file: ', input_file
+ logging.debug('copying library file: ' + input_file)
temp_file = in_temp(uniquename(input_file))
shutil.copyfile(input_file, temp_file)
temp_files.append(temp_file)
@@ -1069,7 +1073,7 @@ try:
if not LEAVE_INPUTS_RAW:
# Note that by assembling the .ll file, then disassembling it later, we will
# remove annotations which is a good thing for compilation time
- if DEBUG: print >> sys.stderr, 'emcc: assembling assembly file: ', input_file
+ logging.debug('assembling assembly file: ' + input_file)
temp_file = in_temp(unsuffixed(uniquename(input_file)) + '.o')
shared.Building.llvm_as(input_file, temp_file)
temp_files.append(temp_file)
@@ -1080,14 +1084,14 @@ try:
if final_suffix not in JS_CONTAINING_SUFFIXES:
if llvm_opts > 0:
if not os.environ.get('EMCC_OPTIMIZE_NORMALLY'):
- print >> sys.stderr, 'emcc: warning: -Ox flags ignored, since not generating JavaScript'
+ logging.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)
+ logging.debug('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)
+ logging.debug('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)
@@ -1098,13 +1102,13 @@ try:
assert len(original_input_files) == 1 or not has_dash_c, 'fatal error: cannot specify -o with -c with multiple files' + str(sys.argv) + ':' + str(original_input_files)
# We have a specified target (-o <target>), which is not JavaScript or HTML, and
# we have multiple files: Link them
- if DEBUG: print >> sys.stderr, 'emcc: link: ' + str(temp_files), specified_target
+ logging.debug('link: ' + str(temp_files) + specified_target)
shared.Building.link(temp_files, specified_target)
exit(0)
## Continue on to create JavaScript
- if DEBUG: print >> sys.stderr, 'emcc: will generate JavaScript'
+ logging.debug('will generate JavaScript')
extra_files_to_link = []
@@ -1112,8 +1116,6 @@ try:
not shared.Settings.BUILD_AS_SHARED_LIB == 2: # shared lib 2 use the library in the parent
# Check if we need to include some libraries that we compile. (We implement libc ourselves in js, but
# compile a malloc implementation and stdlibc++.)
- # Note that we assume a single symbol is enough to know if we have/do not have dlmalloc etc. If you
- # include just a few symbols but want the rest, this will not work.
def read_symbols(path, exclude=None):
symbols = map(lambda line: line.strip().split(' ')[1], open(path).readlines())
@@ -1124,6 +1126,7 @@ try:
# XXX We also need to add libc symbols that use malloc, for example strdup. It's very rare to use just them and not
# a normal malloc symbol (like free, after calling strdup), so we haven't hit this yet, but it is possible.
libc_symbols = read_symbols(shared.path_from_root('system', 'lib', 'libc.symbols'))
+ sdl_symbols = read_symbols(shared.path_from_root('system', 'lib', 'sdl.symbols'))
libcextra_symbols = read_symbols(shared.path_from_root('system', 'lib', 'libcextra.symbols'))
libcxx_symbols = read_symbols(shared.path_from_root('system', 'lib', 'libcxx', 'symbols'), exclude=libc_symbols)
libcxxabi_symbols = read_symbols(shared.path_from_root('system', 'lib', 'libcxxabi', 'symbols'), exclude=libc_symbols)
@@ -1153,7 +1156,7 @@ try:
# libc
def create_libc():
- if DEBUG: print >> sys.stderr, 'emcc: building libc for cache'
+ logging.debug(' building libc for cache')
libc_files = [
'dlmalloc.c',
os.path.join('libcxx', 'new.cpp'),
@@ -1170,7 +1173,7 @@ try:
];
return build_libc('libc.bc', libc_files)
- def fix_libc(need):
+ def apply_libc(need):
# libc needs some sign correction. # If we are in mode 0, switch to 2. We will add our lines
try:
if shared.Settings.CORRECT_SIGNS == 0: raise Exception('we need to change to 2')
@@ -1180,11 +1183,31 @@ try:
shared.Settings.CORRECT_SIGNS_LINES = [shared.path_from_root('src', 'dlmalloc.c') + ':' + str(i+4) for i in [4816, 4191, 4246, 4199, 4205, 4235, 4227]]
# If we are in mode 1, we are correcting everything anyhow. If we are in mode 3, we will be corrected
# so all is well anyhow too.
+ return True
# libcextra
def create_libcextra():
- if DEBUG: print >> sys.stderr, 'emcc: building libcextra for cache'
+ logging.debug('building libcextra for cache')
musl_files = [
+ ['ctype', [
+ 'iswalnum.c',
+ 'iswalpha.c',
+ 'iswblank.c',
+ 'iswcntrl.c',
+ 'iswctype.c',
+ 'iswdigit.c',
+ 'iswgraph.c',
+ 'iswlower.c',
+ 'iswprint.c',
+ 'iswpunct.c',
+ 'iswspace.c',
+ 'iswupper.c',
+ 'iswxdigit.c',
+ 'towctrans.c',
+ 'wcswidth.c',
+ 'wctrans.c',
+ 'wcwidth.c',
+ ]],
['multibyte', [
'btowc.c',
'mblen.c',
@@ -1238,12 +1261,9 @@ try:
libcextra_files += [os.path.join('libc', 'musl', 'src', directory, source) for source in sources]
return build_libc('libcextra.bc', libcextra_files)
- def fix_libcextra(need):
- pass
-
# libcxx
def create_libcxx():
- if DEBUG: print >> sys.stderr, 'emcc: building libcxx for cache'
+ logging.debug('building libcxx for cache')
libcxx_files = [
'algorithm.cpp',
'condition_variable.cpp',
@@ -1270,39 +1290,59 @@ try:
]
return build_libcxx(os.path.join('system', 'lib', 'libcxx'), 'libcxx.bc', libcxx_files)
- def fix_libcxx(need):
+ def apply_libcxx(need):
assert shared.Settings.QUANTUM_SIZE == 4, 'We do not support libc++ with QUANTUM_SIZE == 1'
# libcxx might need corrections, so turn them all on. TODO: check which are actually needed
shared.Settings.CORRECT_SIGNS = shared.Settings.CORRECT_OVERFLOWS = shared.Settings.CORRECT_ROUNDINGS = 1
- #print >> sys.stderr, 'emcc: info: using libcxx turns on CORRECT_* options'
+ #logging.info('using libcxx turns on CORRECT_* options')
+ return True
# libcxxabi - just for dynamic_cast for now
def create_libcxxabi():
- if DEBUG: print >> sys.stderr, 'emcc: building libcxxabi for cache'
+ logging.debug('building libcxxabi for cache')
libcxxabi_files = [
'typeinfo.cpp',
'private_typeinfo.cpp'
]
return build_libcxx(os.path.join('system', 'lib', 'libcxxabi', 'src'), 'libcxxabi.bc', libcxxabi_files)
- def fix_libcxxabi(need):
+ def apply_libcxxabi(need):
assert shared.Settings.QUANTUM_SIZE == 4, 'We do not support libc++abi with QUANTUM_SIZE == 1'
- #print >> sys.stderr, 'emcc: info: using libcxxabi, this may need CORRECT_* options'
+ #logging.info('using libcxxabi, this may need CORRECT_* options')
#shared.Settings.CORRECT_SIGNS = shared.Settings.CORRECT_OVERFLOWS = shared.Settings.CORRECT_ROUNDINGS = 1
+ return True
+
+ # SDL. We include code that demands malloc/free if not already required, so we have proper malloc/free from JS SDL code.
+ # Note that the Force instance here can be optimized out, but we still export malloc/free, so they will be kept alive.
+ def create_sdl():
+ return build_libcxx(os.path.join('system', 'lib'), 'sdl.bc', ['sdl.cpp'])
+
+ def apply_sdl(need):
+ return 'SDL_Init' in all_needed and ('malloc' not in all_needed or 'free' not in all_needed)
- # 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')
+
+ # Scan symbols
+ all_needed = set()
+ symbolses = map(lambda temp_file: shared.Building.llvm_nm(temp_file), temp_files)
+ for symbols in symbolses:
+ all_needed.update(symbols.undefs)
+ for symbols in symbolses:
+ all_needed.difference_update(symbols.defs)
+
+ # Go over libraries to figure out which we must include
+ # If we have libcxx, we must force inclusion of libc, since libcxx uses new internally. Note: this is kind of hacky.
has = need = None
- for name, create, fix, library_symbols in [('libcxx', create_libcxx, fix_libcxx, libcxx_symbols),
- ('libcextra', create_libcextra, fix_libcextra, libcextra_symbols),
- ('libcxxabi', create_libcxxabi, fix_libcxxabi, libcxxabi_symbols),
- ('libc', create_libc, fix_libc, libc_symbols)]:
+ for name, create, apply_, library_symbols in [('libcxx', create_libcxx, apply_libcxx, libcxx_symbols),
+ ('libcextra', create_libcextra, lambda x: True, libcextra_symbols),
+ ('libcxxabi', create_libcxxabi, apply_libcxxabi, libcxxabi_symbols),
+ ('sdl', create_sdl, apply_sdl, sdl_symbols),
+ ('libc', create_libc, apply_libc, libc_symbols)]:
if not force:
need = set()
has = set()
- for temp_file in temp_files:
- symbols = shared.Building.llvm_nm(temp_file)
+ for symbols in symbolses:
for library_symbol in library_symbols:
if library_symbol in symbols.undefs:
need.add(library_symbol)
@@ -1311,25 +1351,23 @@ try:
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 force or len(need) > 0:
+ logging.debug('considering %s: we need %s and have %s' % (name, str(need), str(has)))
+ if (force or len(need) > 0) and apply_(need):
# We need to build and link the library in
- if DEBUG: print >> sys.stderr, 'emcc: including %s' % name
+ logging.debug('including %s' % name)
libfile = shared.Cache.get(name, create)
extra_files_to_link.append(libfile)
force = True
- if fix and need:
- fix(need)
# First, combine the bitcode files if there are several. We must also link if we have a singleton .a
if len(input_files) + len(extra_files_to_link) > 1 or \
(not LEAVE_INPUTS_RAW and not (suffix(temp_files[0]) in BITCODE_SUFFIXES or suffix(temp_files[0]) in DYNAMICLIB_SUFFIXES) and shared.Building.is_ar(temp_files[0])):
linker_inputs = temp_files + extra_files_to_link
- if DEBUG: print >> sys.stderr, 'emcc: linking: ', linker_inputs
+ logging.debug('linking: ' + str(linker_inputs))
t0 = time.time()
shared.Building.link(linker_inputs, in_temp(target_basename + '.bc'))
t1 = time.time()
- if DEBUG: print >> sys.stderr, 'emcc: linking took %.2f seconds' % (t1 - t0)
+ logging.debug(' linking took %.2f seconds' % (t1 - t0))
final = in_temp(target_basename + '.bc')
else:
if not LEAVE_INPUTS_RAW:
@@ -1340,7 +1378,7 @@ try:
shutil.copyfile(input_files[0], final)
if DEBUG:
- print >> sys.stderr, 'emcc: saving intermediate processing steps to %s' % shared.EMSCRIPTEN_TEMP_DIR
+ logging.debug('saving intermediate processing steps to %s' % shared.EMSCRIPTEN_TEMP_DIR)
intermediate_counter = 0
intermediate_time = None
@@ -1350,7 +1388,7 @@ try:
intermediate_counter += 1
now = time.time()
if intermediate_time:
- print >> sys.stderr, 'emcc: step took %.2f seconds' % (now - intermediate_time)
+ logging.debug(' step took %.2f seconds' % (now - intermediate_time))
intermediate_time = now
if not LEAVE_INPUTS_RAW: save_intermediate('basebc', 'bc')
@@ -1364,7 +1402,7 @@ try:
if DEBUG: save_intermediate('opt', 'bc')
# Do LTO in a separate pass to work around LLVM bug XXX (see failure e.g. in cubescript)
else:
- if DEBUG: print >> sys.stderr, 'emcc: not running opt because EMCC_OPTIMIZE_NORMALLY was specified, opt should have been run before'
+ logging.debug('not running opt because EMCC_OPTIMIZE_NORMALLY was specified, opt should have been run before')
if shared.Building.can_build_standalone():
# If we can LTO, do it before dce, since it opens up dce opportunities
if llvm_lto and shared.Building.can_use_unsafe_opts():
@@ -1388,13 +1426,13 @@ try:
if DEBUG: save_intermediate('ll', 'll')
if AUTODEBUG:
- if DEBUG: print >> sys.stderr, 'emcc: autodebug'
+ logging.debug('autodebug')
execute([shared.PYTHON, shared.AUTODEBUGGER, final, final + '.ad.ll'])
final += '.ad.ll'
if DEBUG: save_intermediate('autodebug', 'll')
# Emscripten
- if DEBUG: print >> sys.stderr, 'emcc: LLVM => JS'
+ logging.debug('LLVM => JS')
extra_args = [] if not js_libraries else ['--libraries', ','.join(map(os.path.abspath, js_libraries))]
if jcache: extra_args.append('--jcache')
final = shared.Building.emscripten(final, append_ext=False, extra_args=extra_args)
@@ -1402,7 +1440,7 @@ try:
# Embed and preload files
if len(preload_files) + len(embed_files) > 0:
- if DEBUG: print >> sys.stderr, 'emcc: setting up files'
+ logging.debug('setting up files')
file_args = []
if len(preload_files) > 0:
file_args.append('--preload')
@@ -1422,7 +1460,7 @@ try:
# Apply pre and postjs files
if pre_js or post_js:
- if DEBUG: print >> sys.stderr, 'emcc: applying pre/postjses'
+ logging.debug('applying pre/postjses')
src = open(final).read()
final += '.pp.js'
open(final, 'w').write(pre_js + src + post_js)
@@ -1430,7 +1468,7 @@ try:
# Add bindings glue if used
if bind:
- if DEBUG: print >> sys.stderr, 'emcc: adding embind glue'
+ logging.debug('adding embind glue')
src = open(final).read().replace('// {{PRE_RUN_ADDITIONS}}', '// {{PRE_RUN_ADDITIONS}}\n' +
open(shared.path_from_root('src', 'embind', 'embind.js')).read() +
open(shared.path_from_root('src', 'embind', 'emval.js')).read()
@@ -1444,7 +1482,7 @@ try:
shutil.copyfile(final, final + '.tr.js')
final += '.tr.js'
posix = True if not shared.WINDOWS else False
- if DEBUG: print >> sys.stderr, 'emcc: applying transform: %s' % js_transform
+ logging.debug('applying transform: %s' % js_transform)
execute(shlex.split(js_transform, posix=posix) + [os.path.abspath(final)])
if DEBUG: save_intermediate('transformed')
@@ -1456,7 +1494,7 @@ try:
if DEBUG != '2':
if shared.Settings.ASM_JS:
js_optimizer_queue = ['asm'] + js_optimizer_queue
- if DEBUG: print >> sys.stderr, 'emcc: applying js optimization passes:', js_optimizer_queue
+ logging.debug('applying js optimization passes: %s', js_optimizer_queue)
final = shared.Building.js_optimizer(final, js_optimizer_queue, jcache)
if DEBUG: save_intermediate('js_opts')
else:
@@ -1464,13 +1502,13 @@ try:
passes = [name]
if shared.Settings.ASM_JS:
passes = ['asm'] + passes
- print >> sys.stderr, 'emcc: applying js optimization pass:', passes
+ logging.debug('applying js optimization pass: %s', passes)
final = shared.Building.js_optimizer(final, passes, jcache)
save_intermediate(name)
js_optimizer_queue = []
if opt_level >= 1:
- if DEBUG: print >> sys.stderr, 'emcc: running pre-closure post-opts'
+ logging.debug('running pre-closure post-opts')
if DEBUG == '2':
# Clean up the syntax a bit
@@ -1488,24 +1526,27 @@ try:
if shared.Settings.RELOOP and not shared.Settings.ASM_JS:
js_optimizer_queue += ['optimizeShiftsAggressive', get_eliminate()] # aggressive shifts optimization requires loops, it breaks on switches
- if closure:
+ if closure and not shared.Settings.ASM_JS:
flush_js_optimizer_queue()
- if DEBUG: print >> sys.stderr, 'emcc: running closure'
+ logging.debug('running closure')
final = shared.Building.closure_compiler(final)
if DEBUG: save_intermediate('closure')
if opt_level >= 1:
- if DEBUG: print >> sys.stderr, 'emcc: running post-closure post-opts'
+ logging.debug('running post-closure post-opts')
js_optimizer_queue += ['simplifyExpressionsPost']
- if not closure and shared.Settings.RELOOP and not keep_js_debug:
+ if (not closure or shared.Settings.ASM_JS) and shared.Settings.RELOOP and not keep_js_debug:
# do this if closure is not enabled (it gives similar speedups), and we do not need to keep debug info around
js_optimizer_queue += ['registerize']
if minify_whitespace:
js_optimizer_queue += ['compress']
+ if closure and shared.Settings.ASM_JS:
+ js_optimizer_queue += ['closure']
+
js_optimizer_queue += ['last']
flush_js_optimizer_queue()
@@ -1517,7 +1558,7 @@ try:
if memory_init_file:
if shared.Settings.USE_TYPED_ARRAYS != 2:
- if type(memory_init_file) == int: print >> sys.stderr, 'emcc: warning: memory init file requires typed arrays mode 2'
+ if type(memory_init_file) == int: logging.warning('memory init file requires typed arrays mode 2')
else:
memfile = target + '.mem'
shared.try_delete(memfile)
@@ -1533,19 +1574,19 @@ try:
if os.path.abspath(memfile) != os.path.abspath(memfile):
shutil.copyfile(memfile, temp_memfile)
return 'loadMemoryInitializer("%s");' % os.path.basename(memfile)
- src = re.sub('/\* memory initializer \*/ allocate\(([\d,\.concat\(\)\[\]\\n ]+)"i8", ALLOC_NONE, TOTAL_STACK\)', repl, src, count=1)
+ src = re.sub('/\* memory initializer \*/ allocate\(([\d,\.concat\(\)\[\]\\n ]+)"i8", ALLOC_NONE, Runtime\.GLOBAL_BASE\)', repl, src, count=1)
open(final + '.mem.js', 'w').write(src)
final += '.mem.js'
if DEBUG:
if os.path.exists(memfile):
save_intermediate('meminit')
- print >> sys.stderr, 'emcc: wrote memory initialization to %s' % memfile
+ logging.debug('wrote memory initialization to %s' % memfile)
else:
- print >> sys.stderr, 'emcc: did not see memory initialization'
+ logging.debug('did not see memory initialization')
# If we were asked to also generate HTML, do that
if final_suffix == 'html':
- if DEBUG: print >> sys.stderr, 'emcc: generating HTML'
+ logging.debug('generating HTML')
shell = open(shell_path).read()
html = open(target, 'w')
if not Compression.on:
@@ -1622,7 +1663,7 @@ try:
# copy final JS to output
shutil.move(final, target)
- if DEBUG: print >> sys.stderr, 'emcc: total time: %.2f seconds' % (time.time() - start_time)
+ if DEBUG: logging.debug('total time: %.2f seconds' % (time.time() - start_time))
finally:
if not TEMP_DIR:
@@ -1631,5 +1672,5 @@ finally:
except:
pass
else:
- print >> sys.stderr, 'emcc saved files are in:', temp_dir
+ logging.info('emcc saved files are in:' + temp_dir)