aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÉloi Rivard <azmeuk@gmail.com>2013-04-27 13:06:42 +0200
committerÉloi Rivard <azmeuk@gmail.com>2013-05-03 10:13:04 +0200
commitce122916a38c1fdc8b82e3eb4804c979fe06a242 (patch)
treed1b2d58997bc157dc75f2b2b4da62dc7bf12abe3
parent34bce791b6b1c34e85c5deda7fb71869dcdd6435 (diff)
* Added some colors to messages displayed from python files.
-rwxr-xr-xemcc137
-rw-r--r--tools/shared.py174
2 files changed, 202 insertions, 109 deletions
diff --git a/emcc b/emcc
index 3df65236..7e020a61 100755
--- a/emcc
+++ b/emcc
@@ -75,12 +75,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 +109,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.error('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 +122,7 @@ shared.check_sanity(force=DEBUG)
# Handle some global flags
if len(sys.argv) == 1:
- print 'emcc: no input files'
+ logging.error('no input files')
exit(1)
# read response files very early on
@@ -506,7 +508,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
@@ -563,7 +565,7 @@ if CONFIGURE_CONFIG or CMAKE_CONFIG:
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:
@@ -634,7 +636,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
@@ -651,7 +653,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
@@ -677,10 +679,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:
@@ -847,14 +849,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.info('clearing cache')
shared.Cache.erase()
sys.exit(0)
elif newargs[i] == '--save-bc':
@@ -869,7 +871,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 '' ]
@@ -886,7 +888,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':
@@ -939,9 +941,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:])
@@ -963,12 +965,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:
@@ -976,7 +978,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
@@ -987,8 +989,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
@@ -1015,15 +1016,15 @@ try:
if bind:
shared.Settings.ASM_JS = 0
- print >> sys.stderr, 'emcc: warning: disabling asm.js because it is not compatible with embind yet'
+ logging.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'
+ logging.warning('disabling closure because it is not compatible with asm.js code generation')
closure = False
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'
@@ -1031,7 +1032,7 @@ try:
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'
@@ -1053,31 +1054,31 @@ try:
## 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)
@@ -1085,7 +1086,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)
@@ -1096,14 +1097,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)
@@ -1114,13 +1115,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 = []
@@ -1169,7 +1170,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'),
@@ -1199,7 +1200,7 @@ try:
# 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',
@@ -1278,7 +1279,7 @@ try:
# 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',
@@ -1309,11 +1310,11 @@ try:
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')
# 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'
@@ -1322,7 +1323,7 @@ try:
def fix_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
# If we have libcxx, we must force inclusion of libc, since libcxx uses new internally. Note: this is kind of hacky
@@ -1346,10 +1347,10 @@ 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))
+ logging.debug('considering including %s: we need %s and have %s' % (name, str(need), str(has)))
if force or len(need) > 0:
# 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
@@ -1360,11 +1361,11 @@ try:
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: ', 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:
@@ -1375,7 +1376,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
@@ -1385,7 +1386,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')
@@ -1399,7 +1400,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():
@@ -1423,13 +1424,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)
@@ -1437,7 +1438,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')
@@ -1457,7 +1458,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)
@@ -1465,7 +1466,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()
@@ -1479,7 +1480,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')
@@ -1491,7 +1492,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:', js_optimizer_queue)
final = shared.Building.js_optimizer(final, js_optimizer_queue, jcache)
if DEBUG: save_intermediate('js_opts')
else:
@@ -1499,13 +1500,13 @@ try:
passes = [name]
if shared.Settings.ASM_JS:
passes = ['asm'] + passes
- print >> sys.stderr, 'emcc: applying js optimization pass:', passes
+ logging.info('applying js optimization pass:', 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
@@ -1526,12 +1527,12 @@ try:
if closure:
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:
@@ -1552,7 +1553,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)
@@ -1574,13 +1575,13 @@ try:
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:
@@ -1657,7 +1658,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:
@@ -1666,5 +1667,5 @@ finally:
except:
pass
else:
- print >> sys.stderr, 'emcc saved files are in:', temp_dir
+ logging.info('emcc saved files are in:' + temp_dir)
diff --git a/tools/shared.py b/tools/shared.py
index e9284bf7..97d30f0c 100644
--- a/tools/shared.py
+++ b/tools/shared.py
@@ -3,6 +3,7 @@ from subprocess import Popen, PIPE, STDOUT
from tempfile import mkstemp
import jsrun, cache, tempfiles
from response_file import create_response_file
+import logging, platform
def listify(x):
if type(x) is not list: return [x]
@@ -90,6 +91,100 @@ __rootpath__ = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
def path_from_root(*pathelems):
return os.path.join(__rootpath__, *pathelems)
+def add_coloring_to_emit_windows(fn):
+ def _out_handle(self):
+ import ctypes
+ return ctypes.windll.kernel32.GetStdHandle(self.STD_OUTPUT_HANDLE)
+ out_handle = property(_out_handle)
+
+ def _set_color(self, code):
+ import ctypes
+ # Constants from the Windows API
+ self.STD_OUTPUT_HANDLE = -11
+ hdl = ctypes.windll.kernel32.GetStdHandle(self.STD_OUTPUT_HANDLE)
+ ctypes.windll.kernel32.SetConsoleTextAttribute(hdl, code)
+
+ setattr(logging.StreamHandler, '_set_color', _set_color)
+
+ def new(*args):
+ FOREGROUND_BLUE = 0x0001 # text color contains blue.
+ FOREGROUND_GREEN = 0x0002 # text color contains green.
+ FOREGROUND_RED = 0x0004 # text color contains red.
+ FOREGROUND_INTENSITY = 0x0008 # text color is intensified.
+ FOREGROUND_WHITE = FOREGROUND_BLUE|FOREGROUND_GREEN |FOREGROUND_RED
+ # winbase.h
+ STD_INPUT_HANDLE = -10
+ STD_OUTPUT_HANDLE = -11
+ STD_ERROR_HANDLE = -12
+
+ # wincon.h
+ FOREGROUND_BLACK = 0x0000
+ FOREGROUND_BLUE = 0x0001
+ FOREGROUND_GREEN = 0x0002
+ FOREGROUND_CYAN = 0x0003
+ FOREGROUND_RED = 0x0004
+ FOREGROUND_MAGENTA = 0x0005
+ FOREGROUND_YELLOW = 0x0006
+ FOREGROUND_GREY = 0x0007
+ FOREGROUND_INTENSITY = 0x0008 # foreground color is intensified.
+
+ BACKGROUND_BLACK = 0x0000
+ BACKGROUND_BLUE = 0x0010
+ BACKGROUND_GREEN = 0x0020
+ BACKGROUND_CYAN = 0x0030
+ BACKGROUND_RED = 0x0040
+ BACKGROUND_MAGENTA = 0x0050
+ BACKGROUND_YELLOW = 0x0060
+ BACKGROUND_GREY = 0x0070
+ BACKGROUND_INTENSITY = 0x0080 # background color is intensified.
+ levelno = args[1].levelno
+ if(levelno>=50):
+ color = BACKGROUND_YELLOW | FOREGROUND_RED | FOREGROUND_INTENSITY | BACKGROUND_INTENSITY
+ elif(levelno>=40):
+ color = FOREGROUND_RED | FOREGROUND_INTENSITY
+ elif(levelno>=30):
+ color = FOREGROUND_YELLOW | FOREGROUND_INTENSITY
+ elif(levelno>=20):
+ color = FOREGROUND_GREEN
+ elif(levelno>=10):
+ color = FOREGROUND_MAGENTA
+ else:
+ color = FOREGROUND_WHITE
+ args[0]._set_color(color)
+ ret = fn(*args)
+ args[0]._set_color( FOREGROUND_WHITE )
+ #print "after"
+ return ret
+ return new
+
+def add_coloring_to_emit_ansi(fn):
+ # add methods we need to the class
+ def new(*args):
+ levelno = args[1].levelno
+ if(levelno>=50):
+ color = '\x1b[31m' # red
+ elif(levelno>=40):
+ color = '\x1b[31m' # red
+ elif(levelno>=30):
+ color = '\x1b[33m' # yellow
+ elif(levelno>=20):
+ color = '\x1b[32m' # green
+ elif(levelno>=10):
+ color = '\x1b[35m' # pink
+ else:
+ color = '\x1b[0m' # normal
+ args[1].msg = color + args[1].msg + '\x1b[0m' # normal
+ #print "after"
+ return fn(*args)
+ return new
+
+WINDOWS = sys.platform.startswith('win')
+
+if WINDOWS:
+ logging.StreamHandler.emit = add_coloring_to_emit_windows(logging.StreamHandler.emit)
+else:
+ logging.StreamHandler.emit = add_coloring_to_emit_ansi(logging.StreamHandler.emit)
+
# Emscripten configuration is done through the EM_CONFIG environment variable.
# If the string value contained in this environment variable contains newline
# separated definitions, then these definitions will be used to configure
@@ -157,7 +252,7 @@ try:
config_text = open(CONFIG_FILE, 'r').read() if CONFIG_FILE else EM_CONFIG
exec(config_text)
except Exception, e:
- print >> sys.stderr, 'Error in evaluating %s (at %s): %s, text: %s' % (EM_CONFIG, CONFIG_FILE, str(e), config_text)
+ logging.error('Error in evaluating %s (at %s): %s, text: %s' % (EM_CONFIG, CONFIG_FILE, str(e), config_text))
sys.exit(1)
# Expectations
@@ -169,14 +264,14 @@ def check_clang_version():
actual = Popen([CLANG, '-v'], stderr=PIPE).communicate()[1].split('\n')[0]
if expected in actual:
return True
- print >> sys.stderr, 'warning: LLVM version appears incorrect (seeing "%s", expected "%s")' % (actual, expected)
+ logging.warning('LLVM version appears incorrect (seeing "%s", expected "%s")' % (actual, expected))
return False
def check_llvm_version():
try:
check_clang_version();
except Exception, e:
- print >> sys.stderr, 'warning: Could not verify LLVM version: %s' % str(e)
+ logging.warning('Could not verify LLVM version: %s' % str(e))
EXPECTED_NODE_VERSION = (0,6,8)
@@ -187,10 +282,10 @@ def check_node_version():
version = tuple(map(int, actual.replace('v', '').split('.')))
if version >= EXPECTED_NODE_VERSION:
return True
- print >> sys.stderr, 'warning: node version appears too old (seeing "%s", expected "%s")' % (actual, 'v' + ('.'.join(map(str, EXPECTED_NODE_VERSION))))
+ logging.warning('node version appears too old (seeing "%s", expected "%s")' % (actual, 'v' + ('.'.join(map(str, EXPECTED_NODE_VERSION)))))
return False
except Exception, e:
- print >> sys.stderr, 'warning: cannot check node version:', e
+ logging.warning('cannot check node version:' + e)
return False
# Check that basic stuff we need (a JS engine to compile, Node.js, and Clang and LLVM)
@@ -227,7 +322,7 @@ def check_sanity(force=False):
except Exception, e:
reason = 'unknown: ' + str(e)
if reason:
- print >> sys.stderr, '(Emscripten: %s, clearing cache)' % reason
+ logging.info('(Emscripten: %s, clearing cache)' % reason)
Cache.erase()
# some warning, not fatal checks - do them even if EM_IGNORE_SANITY is on
@@ -235,32 +330,32 @@ def check_sanity(force=False):
check_node_version()
if os.environ.get('EM_IGNORE_SANITY'):
- print >> sys.stderr, 'EM_IGNORE_SANITY set, ignoring sanity checks'
+ logging.info('EM_IGNORE_SANITY set, ignoring sanity checks')
return
- print >> sys.stderr, '(Emscripten: Running sanity checks)'
+ logging.info('(Emscripten: Running sanity checks)')
if not check_engine(COMPILER_ENGINE):
- print >> sys.stderr, 'FATAL: The JavaScript shell used for compiling (%s) does not seem to work, check the paths in %s' % (COMPILER_ENGINE, EM_CONFIG)
+ logging.critical('The JavaScript shell used for compiling (%s) does not seem to work, check the paths in %s' % (COMPILER_ENGINE, EM_CONFIG))
sys.exit(1)
if NODE_JS != COMPILER_ENGINE:
if not check_engine(NODE_JS):
- print >> sys.stderr, 'FATAL: Node.js (%s) does not seem to work, check the paths in %s' % (NODE_JS, EM_CONFIG)
+ logging.critical('Node.js (%s) does not seem to work, check the paths in %s' % (NODE_JS, EM_CONFIG))
sys.exit(1)
for cmd in [CLANG, LLVM_LINK, LLVM_AR, LLVM_OPT, LLVM_AS, LLVM_DIS, LLVM_NM]:
if not os.path.exists(cmd) and not os.path.exists(cmd + '.exe'): # .exe extension required for Windows
- print >> sys.stderr, 'FATAL: Cannot find %s, check the paths in %s' % (cmd, EM_CONFIG)
+ logging.critical('Cannot find %s, check the paths in %s' % (cmd, EM_CONFIG))
sys.exit(1)
try:
subprocess.call([JAVA, '-version'], stdout=PIPE, stderr=PIPE)
except:
- print >> sys.stderr, 'WARNING: java does not seem to exist, required for closure compiler. -O2 and above will fail. You need to define JAVA in ~/.emscripten'
+ logging.warning('java does not seem to exist, required for closure compiler. -O2 and above will fail. You need to define JAVA in ~/.emscripten')
if not os.path.exists(CLOSURE_COMPILER):
- print >> sys.stderr, 'WARNING: Closure compiler (%s) does not exist, check the paths in %s. -O2 and above will fail' % (CLOSURE_COMPILER, EM_CONFIG)
+ logging.warning('Closure compiler (%s) does not exist, check the paths in %s. -O2 and above will fail' % (CLOSURE_COMPILER, EM_CONFIG))
# Sanity check passed!
@@ -335,7 +430,7 @@ class Configuration:
try:
self.TEMP_DIR = TEMP_DIR
except NameError:
- print >> sys.stderr, 'TEMP_DIR not defined in ~/.emscripten, using /tmp'
+ logging.info('TEMP_DIR not defined in ~/.emscripten, using /tmp')
self.TEMP_DIR = '/tmp'
self.CANONICAL_TEMP_DIR = os.path.join(self.TEMP_DIR, 'emscripten_temp')
@@ -346,23 +441,22 @@ class Configuration:
if not os.path.exists(self.EMSCRIPTEN_TEMP_DIR):
os.makedirs(self.EMSCRIPTEN_TEMP_DIR)
except Exception, e:
- print >> sys.stderr, e, 'Could not create canonical temp dir. Check definition of TEMP_DIR in ~/.emscripten'
+ logging.debug(e + 'Could not create canonical temp dir. Check definition of TEMP_DIR in ~/.emscripten')
def get_temp_files(self):
return tempfiles.TempFiles(
tmp=self.TEMP_DIR if not self.DEBUG else self.EMSCRIPTEN_TEMP_DIR,
save_debug_files=os.environ.get('EMCC_DEBUG_SAVE'))
- def debug_log(self, msg):
- if self.DEBUG:
- print >> sys.stderr, msg
-
configuration = Configuration(environ=os.environ)
DEBUG = configuration.DEBUG
EMSCRIPTEN_TEMP_DIR = configuration.EMSCRIPTEN_TEMP_DIR
DEBUG_CACHE = configuration.DEBUG_CACHE
CANONICAL_TEMP_DIR = configuration.CANONICAL_TEMP_DIR
+level = logging.DEBUG if os.environ.get('EMCC_DEBUG') else logging.INFO
+logging.basicConfig(level=level, format='%(levelname)-8s %(name)s: %(message)s')
+
if not EMSCRIPTEN_TEMP_DIR:
EMSCRIPTEN_TEMP_DIR = tempfile.mkdtemp(prefix='emscripten_temp_', dir=configuration.TEMP_DIR)
def clean_temp():
@@ -388,13 +482,13 @@ except:
try:
PYTHON
except:
- if DEBUG: print >> sys.stderr, 'PYTHON not defined in ~/.emscripten, using "python"'
+ logging.debug('PYTHON not defined in ~/.emscripten, using "python"')
PYTHON = 'python'
try:
JAVA
except:
- if DEBUG: print >> sys.stderr, 'JAVA not defined in ~/.emscripten, using "java"'
+ logging.debug('JAVA not defined in ~/.emscripten, using "java"')
JAVA = 'java'
# Additional compiler options
@@ -450,8 +544,6 @@ try:
except NameError:
pass
-WINDOWS = sys.platform.startswith('win')
-
# If we have 'env', we should use that to find python, because |python| may fail while |env python| may work
# (For example, if system python is 3.x while we need 2.x, and env gives 2.x if told to do so.)
ENV_PREFIX = []
@@ -585,7 +677,7 @@ class Settings:
# Aside from these, -O3 also runs closure compiler and llvm lto
Settings.DOUBLE_MODE = 0
Settings.PRECISE_I64_MATH = 0
- if noisy: print >> sys.stderr, 'Warning: Applying some potentially unsafe optimizations! (Use -O2 if this fails.)'
+ if noisy: logging.warning('Applying some potentially unsafe optimizations! (Use -O2 if this fails.)')
global Settings
Settings = Settings2
@@ -671,7 +763,7 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e
process = Popen(args, stdout=stdout, stderr=stderr, env=env)
process.communicate()
except Exception, e:
- print >> sys.stderr, 'Error: Exception thrown when invoking Popen in configure with args: "%s"!' % ' '.join(args)
+ logging.error('Exception thrown when invoking Popen in configure with args: "%s"!' % ' '.join(args))
raise
del env['EMMAKEN_JUST_CONFIGURE']
if process.returncode is not 0:
@@ -682,14 +774,14 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e
if env is None:
env = Building.get_building_env()
if not args:
- print >> sys.stderr, 'Error: Executable to run not specified.'
+ logging.error('Executable to run not specified.')
sys.exit(1)
#args += ['VERBOSE=1']
try:
process = Popen(args, stdout=stdout, stderr=stderr, env=env)
process.communicate()
except Exception, e:
- print >> sys.stderr, 'Error: Exception thrown when invoking Popen in make with args: "%s"!' % ' '.join(args)
+ logging.error('Exception thrown when invoking Popen in make with args: "%s"!' % ' '.join(args))
raise
if process.returncode is not 0:
raise subprocess.CalledProcessError(cmd=args, returncode=process.returncode)
@@ -796,7 +888,7 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e
contents = filter(lambda x: len(x) > 0, Popen([LLVM_AR, 't', f], stdout=PIPE).communicate()[0].split('\n'))
#print >> sys.stderr, ' considering archive', f, ':', contents
if len(contents) == 0:
- print >> sys.stderr, 'Warning: Archive %s appears to be empty (recommendation: link an .so instead of .a)' % f
+ logging.debug('Archive %s appears to be empty (recommendation: link an .so instead of .a)' % f)
else:
for content in contents: # ar will silently fail if the directory for the file does not exist, so make all the necessary directories
dirname = os.path.dirname(content)
@@ -833,7 +925,7 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e
# Finish link
actual_files = unique_ordered(actual_files) # tolerate people trying to link a.so a.so etc.
- if DEBUG: print >>sys.stderr, 'emcc: llvm-linking:', actual_files
+ logging.debug('emcc: llvm-linking:', actual_files)
# check for too-long command line
link_cmd = [LLVM_LINK] + actual_files + ['-o', target]
@@ -841,7 +933,7 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e
# for max command line size before we use a respose file
response_file = None
if WINDOWS and len(' '.join(link_cmd)) > 8192:
- if DEBUG: print >>sys.stderr, 'using response file for llvm-link'
+ logging.debug('using response file for llvm-link')
[response_fd, response_file] = mkstemp(suffix='.response', dir=TEMP_DIR)
link_cmd = [LLVM_LINK, "@" + response_file]
@@ -858,7 +950,7 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e
link_cmd.append(target)
if len(' '.join(link_cmd)) > 8192:
- print >>sys.stderr, 'emcc: warning: link command line is very long, even with response file -- use paths with no spaces'
+ logging.warning('emcc: link command line is very long, even with response file -- use paths with no spaces')
output = Popen(link_cmd, stdout=PIPE).communicate()[0]
@@ -887,7 +979,7 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e
if type(opts) is int:
opts = Building.pick_llvm_opts(opts)
#opts += ['-debug-pass=Arguments']
- if DEBUG: print >> sys.stderr, 'emcc: LLVM opts:', opts
+ logging.debug('emcc: LLVM opts:', opts)
output = Popen([LLVM_OPT, filename] + opts + ['-o=' + filename + '.opt.bc'], stdout=PIPE).communicate()[0]
assert os.path.exists(filename + '.opt.bc'), 'Failed to run llvm optimizations: ' + output
shutil.move(filename + '.opt.bc', filename)
@@ -1148,7 +1240,7 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e
Building._is_ar_cache[filename] = sigcheck
return sigcheck
except Exception, e:
- if DEBUG: print >> sys.stderr, 'shared.Building.is_ar failed to test whether file \'%s\' is a llvm archive file! Failed on exception: %s' % (filename, e)
+ logging.debug('Building.is_ar failed to test whether file \'%s\' is a llvm archive file! Failed on exception: %s' % (filename, e))
return False
@staticmethod
@@ -1175,8 +1267,8 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e
curr = os.getcwd()
try:
ok = False
- print >> sys.stderr, '======================================='
- print >> sys.stderr, 'bootstrapping relooper...'
+ logging.info('=======================================')
+ logging.info('bootstrapping relooper...')
os.chdir(path_from_root('src'))
emcc_debug = os.environ.get('EMCC_DEBUG')
@@ -1201,19 +1293,19 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e
f.close()
# bootstrap phase 1: generate unrelooped relooper, for which we do not need a relooper (so we cannot recurse infinitely in this function)
- print >> sys.stderr, ' bootstrap phase 1'
+ logging.info(' bootstrap phase 1')
make(1)
# bootstrap phase 2: generate relooped relooper, using the unrelooped relooper (we see relooper.js exists so we cannot recurse infinitely in this function)
- print >> sys.stderr, ' bootstrap phase 2'
+ logging.info(' bootstrap phase 2')
make(2)
- print >> sys.stderr, 'bootstrapping relooper succeeded'
- print >> sys.stderr, '======================================='
+ logging.info('bootstrapping relooper succeeded')
+ logging.info('=======================================')
ok = True
finally:
os.chdir(curr)
if emcc_debug: os.environ['EMCC_DEBUG'] = emcc_debug
if not ok:
- print >> sys.stderr, 'bootstrapping relooper failed. You may need to manually create relooper.js by compiling it, see src/relooper/emscripten'
+ logging.error('bootstrapping relooper failed. You may need to manually create relooper.js by compiling it, see src/relooper/emscripten')
1/0
@staticmethod
@@ -1274,7 +1366,7 @@ def execute(cmd, *args, **kw):
except:
if not isinstance(cmd, str):
cmd = ' '.join(cmd)
- print >> sys.stderr, 'Invoking Process failed: <<< ' + cmd + ' >>>'
+ logging.error('Invoking Process failed: <<< ' + cmd + ' >>>')
raise
def suffix(name):