import shutil, time, os, sys, json, tempfile, copy, shlex, atexit, subprocess
from subprocess import Popen, PIPE, STDOUT
from tempfile import mkstemp
__rootpath__ = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
def path_from_root(*pathelems):
return os.path.join(__rootpath__, *pathelems)
# 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
# Emscripten. Otherwise, the string is understood to be a path to a settings
# file that contains the required definitions.
EM_CONFIG = os.environ.get('EM_CONFIG')
if not EM_CONFIG:
EM_CONFIG = '~/.emscripten'
if '\n' in EM_CONFIG:
CONFIG_FILE = None
else:
CONFIG_FILE = os.path.expanduser(EM_CONFIG)
if not os.path.exists(CONFIG_FILE):
shutil.copy(path_from_root('tools', 'settings_template_readonly.py'), CONFIG_FILE)
print >> sys.stderr, '''
==============================================================================
Welcome to Emscripten!
This is the first time any of the Emscripten tools has been run.
A settings file has been copied to %s, at absolute path: %s
Please edit that file and change the paths to fit your system. Specifically,
make sure LLVM_ROOT and NODE_JS are correct.
This command will now exit. When you are done editing those paths, re-run it.
==============================================================================
''' % (EM_CONFIG, CONFIG_FILE)
sys.exit(0)
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)
sys.exit(1)
# Expectations
EXPECTED_LLVM_VERSION = (3,1)
def check_llvm_version():
try:
expected = 'clang version ' + '.'.join(map(str, EXPECTED_LLVM_VERSION))
actual = Popen([CLANG, '-v'], stderr=PIPE).communicate()[1].split('\n')[0][0:len(expected)]
if expected != actual:
print >> sys.stderr, 'warning: LLVM version appears incorrect (seeing "%s", expected "%s")' % (actual, expected)
except Exception, e:
print >> sys.stderr, 'warning: Could not verify LLVM version: %s' % str(e)
# Check that basic stuff we need (a JS engine to compile, Node.js, and Clang and LLVM)
# exists.
# The test runner always does this check (through |force|). emcc does this less frequently,
# only when ${EM_CONFIG}_sanity does not exist or is older than EM_CONFIG (so,
# we re-check sanity when the settings are changed)
def check_sanity(force=False):
try:
if not force:
if not CONFIG_FILE:
return # config stored directly in EM_CONFIG => skip sanity checks
settings_mtime = os.stat(CONFIG_FILE).st_mtime
sanity_file = CONFIG_FILE + '_sanity'
try:
sanity_mtime = os.stat(sanity_file).st_mtime
if sanity_mtime > settings_mtime:
return # sanity has been checked
except:
pass
print >> sys.stderr, '(Emscripten: Config file changed, clearing cache)' # LLVM may have changed, etc.
Cache.erase()
check_llvm_version() # just a warning, not a fatal check - do it even if EM_IGNORE_SANITY is on
if os.environ.get('EM_IGNORE_SANITY'):
print >> sys.stderr, 'EM_IGNORE_SANITY set, ignoring sanity checks'
return
print >> sys.stderr, '(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)
sys.exit(0)
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)
sys.exit(0)
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)
sys.exit(0)
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'
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)
# Sanity check passed!
if not force:
# Only create/update this file if the sanity check succeeded, i.e., we got here
f = open(sanity_file, 'w')
f.write('certified\n')
f.close()
except Exception, e:
# Any error here is not worth failing on
print 'WARNING: sanity check failed to run', e
# Tools/paths
LLVM_ADD_VERSION = os.getenv('LLVM_ADD_VERSION')
# Some distributions ship with multiple llvm versions so they add
# the version to the binaries, cope with that
def build_llvm_tool_path(tool):
if LLVM_ADD_VERSION:
return os.path.join(LLVM_ROOT, tool + "-" + LLVM_ADD_VERSION)
else:
return os.path