# Copyright 2011 The Emscripten Authors.  All rights reserved.
# Emscripten is available under two separate licenses, the MIT license and the
# University of Illinois/NCSA Open Source License.  Both these licenses can be
# found in the LICENSE file.

from __future__ import print_function

from distutils.spawn import find_executable
from subprocess import PIPE, STDOUT
import atexit
import base64
import difflib
import json
import logging
import math
import multiprocessing
import os
import re
import shlex
import shutil
import subprocess
import sys
import tempfile

if sys.version_info < (2, 7, 0):
  print('emscripten requires python 2.7.0 or above (python 2.7.12 or newer is recommended, older python versions are known to run into SSL related issues, https://github.com/emscripten-core/emscripten/issues/6275)', file=sys.stderr)
  sys.exit(1)

if sys.version_info[0] == 3 and sys.version_info < (3, 5):
  print('emscripten requires at least python 3.5 (or python 2.7.12 or above)', file=sys.stderr)
  sys.exit(1)

from .toolchain_profiler import ToolchainProfiler
from .tempfiles import try_delete
from . import jsrun, cache, tempfiles, colored_logger
from . import response_file

__rootpath__ = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
WINDOWS = sys.platform.startswith('win')
MACOS = sys.platform == 'darwin'
LINUX = sys.platform.startswith('linux')
DEBUG = int(os.environ.get('EMCC_DEBUG', '0'))

# can add  %(asctime)s  to see timestamps
logging.basicConfig(format='%(name)s:%(levelname)s: %(message)s',
                    level=logging.DEBUG if DEBUG else logging.INFO)
colored_logger.enable()
logger = logging.getLogger('shared')

if sys.version_info < (2, 7, 12):
  logger.debug('python versions older than 2.7.12 are known to run into outdated SSL certificate related issues, https://github.com/emscripten-core/emscripten/issues/6275')


def exit_with_error(msg, *args):
  logger.error(msg, *args)
  sys.exit(1)


# On Windows python suffers from a particularly nasty bug if python is spawning
# new processes while python itself is spawned from some other non-console
# process.
# Use a custom replacement for Popen on Windows to avoid the "WindowsError:
# [Error 6] The handle is invalid" errors when emcc is driven through cmake or
# mingw32-make.
# See http://bugs.python.org/issue3905
class WindowsPopen(object):
  def __init__(self, args, bufsize=0, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=False,
               shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0):
    self.stdin = stdin
    self.stdout = stdout
    self.stderr = stderr

    # (stdin, stdout, stderr) store what the caller originally wanted to be done with the streams.
    # (stdin_, stdout_, stderr_) will store the fixed set of streams that workaround the bug.
    self.stdin_ = stdin
    self.stdout_ = stdout
    self.stderr_ = stderr

    # If the caller wants one of these PIPEd, we must PIPE them all to avoid the 'handle is invalid' bug.
    if self.stdin_ == PIPE or self.stdout_ == PIPE or self.stderr_ == PIPE:
      if self.stdin_ is None:
        self.stdin_ = PIPE
      if self.stdout_ is None:
        self.stdout_ = PIPE
      if self.stderr_ is None:
        self.stderr_ = PIPE

    # emscripten.py supports reading args from a response file instead of cmdline.
    # Use .rsp to avoid cmdline length limitations on Windows.
    if len(args) >= 2 and args[1].endswith("emscripten.py"):
      response_filename = response_file.create_response_file(args[2:], TEMP_DIR)
      args = args[0:2] + ['@' + response_filename]

    try:
      # Call the process with fixed streams.
      self.process = subprocess.Popen(args, bufsize, executable, self.stdin_, self.stdout_, self.stderr_, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags)
      self.pid = self.process.pid
    except Exception as e:
      logger.error('\nsubprocess.Popen(args=%s) failed! Exception %s\n' % (' '.join(args), str(e)))
      raise

  def communicate(self, input=None):
    output = self.process.communicate(input)
    self.returncode = self.process.returncode

    # If caller never wanted to PIPE stdout or stderr, route the output back to screen to avoid swallowing output.
    if self.stdout is None and self.stdout_ == PIPE and len(output[0].strip()):
      print(output[0], file=sys.stdout)
    if self.stderr is None and self.stderr_ == PIPE and len(output[1].strip()):
      print(output[1], file=sys.stderr)

    # Return a mock object to the caller. This works as long as all emscripten code immediately .communicate()s the result, and doesn't
    # leave the process object around for longer/more exotic uses.
    if self.stdout is None and self.stderr is None:
      return (None, None)
    if self.stdout is None:
      return (None, output[1])
    if self.stderr is None:
      return (output[0], None)
    return (output[0], output[1])

  def poll(self):
    return self.process.poll()

  def kill(self):
    return self.process.kill()


def path_from_root(*pathelems):
  return os.path.join(__rootpath__, *pathelems)


# This is a workaround for https://bugs.python.org/issue9400
class Py2CalledProcessError(subprocess.CalledProcessError):
  def __init__(self, returncode, cmd, output=None, stderr=None):
    super(Exception, self).__init__(returncode, cmd, output, stderr)
    self.returncode = returncode
    self.cmd = cmd
    self.output = output
    self.stderr = stderr


# https://docs.python.org/3/library/subprocess.html#subprocess.CompletedProcess
class Py2CompletedProcess:
  def __init__(self, args, returncode, stdout, stderr):
    self.args = args
    self.returncode = returncode
    self.stdout = stdout
    self.stderr = stderr

  def __repr__(self):
    _repr = ['args=%s, returncode=%s' % (self.args, self.returncode)]
    if self.stdout is not None:
      _repr += 'stdout=' + repr(self.stdout)
    if self.stderr is not None:
      _repr += 'stderr=' + repr(self.stderr)
    return 'CompletedProcess(%s)' % ', '.join(_repr)

  def check_returncode(self):
    if self.returncode != 0:
      raise Py2CalledProcessError(returncode=self.returncode, cmd=self.args, output=self.stdout, stderr=self.stderr)


def run_process(cmd, check=True, input=None, *args, **kw):
  kw.setdefault('universal_newlines', True)

  debug_text = '%sexecuted %s' % ('successfully ' if check else '', ' '.join(cmd))

  if hasattr(subprocess, "run"):
    ret = subprocess.run(cmd, check=check, input=input, *args, **kw)
    logger.debug(debug_text)
    return ret

  # Python 2 compatibility: Introduce Python 3 subprocess.run-like behavior
  if input is not None:
    kw['stdin'] = subprocess.PIPE
  proc = Popen(cmd, *args, **kw)
  stdout, stderr = proc.communicate(input)
  result = Py2CompletedProcess(cmd, proc.returncode, stdout, stderr)
  if check:
    result.check_returncode()
  logger.debug(debug_text)
  return result


def check_call(cmd, *args, **kw):
  try:
    return run_process(cmd, *args, **kw)
  except subprocess.CalledProcessError as e:
    exit_with_error("'%s' failed (%d)", ' '.join(cmd), e.returncode)
  except OSError as e:
    exit_with_error("'%s' failed: %s", ' '.join(cmd), str(e))


def generate_config(path, first_time=False):
  # Note: repr is used to ensure the paths are escaped correctly on Windows.
  # The full string is replaced so that the template stays valid Python.
  config_file = open(path_from_root('tools', 'settings_template_readonly.py')).read().splitlines()
  config_file = config_file[3:] # remove the initial comment
  config_file = '\n'.join(config_file)
  # autodetect some default paths
  config_file = config_file.replace('\'{{{ EMSCRIPTEN_ROOT }}}\'', repr(__rootpath__))
  llvm_root = os.path.dirname(find_executable('llvm-dis') or '/usr/bin/llvm-dis')
  config_file = config_file.replace('\'{{{ LLVM_ROOT }}}\'', repr(llvm_root))

  node = find_executable('nodejs') or find_executable('node') or 'node'
  config_file = config_file.replace('\'{{{ NODE }}}\'', repr(node))

  abspath = os.path.abspath(os.path.expanduser(path))
  # write
  open(abspath, 'w').write(config_file)
  if first_time:
    print('''
==============================================================================
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

It contains our best guesses for the important paths, which are:

  LLVM_ROOT       = %s
  NODE_JS         = %s
  EMSCRIPTEN_ROOT = %s

Please edit the file if any of those are incorrect.

This command will now exit. When you are done editing those paths, re-run it.
==============================================================================
''' % (path, abspath, llvm_root, node, __rootpath__), file=sys.stderr)


# Emscripten configuration is done through the --em-config command line option or
# the EM_CONFIG environment variable. If the specified string value contains newline
# or semicolon-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.

try:
  EM_CONFIG = sys.argv[sys.argv.index('--em-config') + 1]
  # And now remove it from sys.argv
  skip = False
  newargs = []
  for arg in sys.argv:
    if not skip and arg != '--em-config':
      newargs += [arg]
    elif arg == '--em-config':
      skip = True
    elif skip:
      skip = False
  sys.argv = newargs
  # Emscripten compiler spawns other processes, which can reimport shared.py, so make sure that
  # those child processes get the same configuration file by setting it to the currently active environment.
  os.environ['EM_CONFIG'] = EM_CONFIG
except Exception:
  EM_CONFIG = os.environ.get('EM_CONFIG')

if EM_CONFIG and not os.path.isfile(EM_CONFIG):
  if EM_CONFIG.startswith('-'):
    exit_with_error('Passed --em-config without an argument. Usage: --em-config /path/to/.emscripten or --em-config LLVM_ROOT=/path;...')
  if '=' not in EM_CONFIG:
    exit_with_error('File ' + EM_CONFIG + ' passed to --em-config does not exist!')
  else:
    EM_CONFIG = EM_CONFIG.replace(';', '\n') + '\n'

if not EM_CONFIG:
  EM_CONFIG = '~/.emscripten'
if '\n' in EM_CONFIG:
  CONFIG_FILE = None
  logger.debug('EM_CONFIG is specified inline without a file')
else:
  CONFIG_FILE = os.path.expanduser(EM_CONFIG)
  logger.debug('EM_CONFIG is located in ' + CONFIG_FILE)
  if not os.path.exists(CONFIG_FILE):
    generate_config(EM_CONFIG, first_time=True)
    sys.exit(0)

PYTHON = os.getenv('EM_PYTHON', sys.executable)

# The following globals can be overridden by the config file.
# See parse_config_file below.
NODE_JS = None
BINARYEN_ROOT = None
EM_POPEN_WORKAROUND = None
SPIDERMONKEY_ENGINE = None
V8_ENGINE = None
LLVM_ROOT = None
COMPILER_ENGINE = None
LLVM_ADD_VERSION = None
CLANG_ADD_VERSION = None
CLOSURE_COMPILER = None
EMSCRIPTEN_NATIVE_OPTIMIZER = None
JAVA = None
JS_ENGINE = None
JS_ENGINES = []
COMPILER_OPTS = []
FROZEN_CACHE = False


def parse_config_file():
  """Parse the emscripten config file using python's exec"""
  config = {}
  config_text = open(CONFIG_FILE, 'r').read() if CONFIG_FILE else EM_CONFIG
  try:
    exec(config_text, config)
  except Exception as e:
    exit_with_error('Error in evaluating %s (at %s): %s, text: %s', EM_CONFIG, CONFIG_FILE, str(e), config_text)

  CONFIG_KEYS = (
    'NODE_JS',
    'BINARYEN_ROOT',
    'EM_POPEN_WORKAROUND',
    'SPIDERMONKEY_ENGINE',
    'EMSCRIPTEN_NATIVE_OPTIMIZER',
    'V8_ENGINE',
    'LLVM_ROOT',
    'COMPILER_ENGINE',
    'LLVM_ADD_VERSION',
    'CLANG_ADD_VERSION',
    'CLOSURE_COMPILER',
    'JAVA',
    'JS_ENGINE',
    'JS_ENGINES',
    'COMPILER_OPTS',
    'FROZEN_CACHE',
  )

  # Only popogate certain settings from the config file.
  for key in CONFIG_KEYS:
    if key in config:
      globals()[key] = config[key]


# Returns a suggestion where current .emscripten config file might be located
# (if EM_CONFIG env. var is used without a file, this hints to "default"
# location at ~/.emscripten)
def hint_config_file_location():
  if CONFIG_FILE:
    return CONFIG_FILE
  else:
    return '~/.emscripten'


def listify(x):
  if type(x) is not list:
    return [x]
  return x


def fix_js_engine(old, new):
  if old is None:
    return
  global JS_ENGINES
  JS_ENGINES = [new if x == old else x for x in JS_ENGINES]
  return new


parse_config_file()
SPIDERMONKEY_ENGINE = fix_js_engine(SPIDERMONKEY_ENGINE, listify(SPIDERMONKEY_ENGINE))
NODE_JS = fix_js_engine(NODE_JS, listify(NODE_JS))
V8_ENGINE = fix_js_engine(V8_ENGINE, listify(V8_ENGINE))
COMPILER_ENGINE = listify(COMPILER_ENGINE)
JS_ENGINES = [listify(engine) for engine in JS_ENGINES]

if EM_POPEN_WORKAROUND is None:
  EM_POPEN_WORKAROUND = os.environ.get('EM_POPEN_WORKAROUND')

# Install our replacement Popen handler if we are running on Windows to avoid
# python spawn process function.
# nb. This is by default disabled since it has the adverse effect of buffering
# up all logging messages, which makes builds look unresponsive (messages are
# printed only after the whole build finishes). Whether this workaround is
# needed seems to depend on how the host application that invokes emcc has set
# up its stdout and stderr.
if EM_POPEN_WORKAROUND and os.name == 'nt':
  logger.debug('Installing Popen workaround handler to avoid bug http://bugs.python.org/issue3905')
  Popen = WindowsPopen
else:
  Popen = subprocess.Popen

# Verbosity level control for any intermediate subprocess spawns from the compiler. Useful for internal debugging.
# 0: disabled.
# 1: Log stderr of subprocess spawns.
# 2: Log stdout and stderr of subprocess spawns. Print out subprocess commands that were executed.
# 3: Log stdout and stderr, and pass VERBOSE=1 to CMake configure steps.
EM_BUILD_VERBOSE = int(os.getenv('EM_BUILD_VERBOSE', '0'))

# Expectations

actual_clang_version = None


def expected_llvm_version():
  if get_llvm_target() == WASM_TARGET:
    return "10.0"
  else:
    return "6.0"


def get_clang_version():
  global actual_clang_version
  if actual_clang_version is None:
    if not os.path.exists(CLANG):
      exit_with_error('clang executable not found at `%s`' % CLANG)
    proc = check_call([CLANG, '--version'], stdout=PIPE)
    m = re.search(r'[Vv]ersion\s+(\d+\.\d+)', proc.stdout)
    actual_clang_version = m and m.group(1)
  return actual_clang_version


def check_llvm_version():
  expected = expected_llvm_version()
  actual = get_clang_version()
  if expected in actual:
    return True
  logger.warning('LLVM version appears incorrect (seeing "%s", expected "%s")' % (actual, expected))
  return False


def get_llc_targets():
  if not os.path.exists(LLVM_COMPILER):
    exit_with_error('llc executable not found at `%s`' % LLVM_COMPILER)
  try:
    llc_version_info = run_process([LLVM_COMPILER, '--version'], stdout=PIPE).stdout
  except Exception as e:
    return '(no targets could be identified: ' + str(e) + ')'
  if 'Registered Targets:' not in llc_version_info:
    return '(no targets could be identified: ' + llc_version_info + ')'
  pre, targets = llc_version_info.split('Registered Targets:')
  return targets


def has_asm_js_target(targets):
  return 'js' in targets and 'JavaScript (asm.js, emscripten) backend' in targets


def has_wasm_target(targets):
  return 'wasm32' in targets and 'WebAssembly 32-bit' in targets


def check_llvm():
  targets = get_llc_targets()
  if not Settings.WASM_BACKEND:
    if not has_asm_js_target(targets):
      logger.critical('fastcomp in use, but LLVM has not been built with the JavaScript backend as a target, llc reports:')
      print('===========================================================================', file=sys.stderr)
      print(targets, file=sys.stderr)
      print('===========================================================================', file=sys.stderr)
      return False
  else:
    if not has_wasm_target(targets):
      logger.critical('WebAssembly set as target, but LLVM has not been built with the WebAssembly backend, llc reports:')
      print('===========================================================================', file=sys.stderr)
      print(targets, file=sys.stderr)
      print('===========================================================================', file=sys.stderr)
      return False

  return True


EXPECTED_NODE_VERSION = (4, 1, 1)


def check_node_version():
  jsrun.check_engine(NODE_JS)
  try:
    actual = run_process(NODE_JS + ['--version'], stdout=PIPE).stdout.strip()
    version = tuple(map(int, actual.replace('v', '').replace('-pre', '').split('.')))
    if version >= EXPECTED_NODE_VERSION:
      return True
    logger.warning('node version appears too old (seeing "%s", expected "%s")' % (actual, 'v' + ('.'.join(map(str, EXPECTED_NODE_VERSION)))))
    return False
  except Exception as e:
    logger.warning('cannot check node version: %s', e)
    return False


def check_closure_compiler():
  try:
    run_process([JAVA, '-version'], stdout=PIPE, stderr=PIPE)
  except Exception:
    logger.warning('java does not seem to exist, required for closure compiler, which is optional (define JAVA in ' + hint_config_file_location() + ' if you want it)')
    return False
  if not os.path.exists(CLOSURE_COMPILER):
    logger.warning('Closure compiler (%s) does not exist, check the paths in %s' % (CLOSURE_COMPILER, EM_CONFIG))
    return False
  return True


def get_emscripten_version(path):
  return open(path).read().strip().replace('"', '')


EMSCRIPTEN_VERSION = get_emscripten_version(path_from_root('emscripten-version.txt'))
parts = [int(x) for x in EMSCRIPTEN_VERSION.split('.')]
EMSCRIPTEN_VERSION_MAJOR, EMSCRIPTEN_VERSION_MINOR, EMSCRIPTEN_VERSION_TINY = parts
# For the Emscripten-specific WASM metadata section, follows semver, changes
# whenever metadata section changes structure
# NB: major version 0 implies no compatibility
(EMSCRIPTEN_METADATA_MAJOR, EMSCRIPTEN_METADATA_MINOR) = (0, 2)
# For the JS/WASM ABI, specifies the minimum ABI version required of
# the WASM runtime implementation by the generated WASM binary. It follows
# semver and changes whenever C types change size/signedness or
# syscalls change signature. By semver, the maximum ABI version is
# implied to be less than (EMSCRIPTEN_ABI_MAJOR + 1, 0). On an ABI
# change, increment EMSCRIPTEN_ABI_MINOR if EMSCRIPTEN_ABI_MAJOR == 0
# or the ABI change is backwards compatible, otherwise increment
# EMSCRIPTEN_ABI_MAJOR and set EMSCRIPTEN_ABI_MINOR = 0
(EMSCRIPTEN_ABI_MAJOR, EMSCRIPTEN_ABI_MINOR) = (0, 4)


def generate_sanity():
  return EMSCRIPTEN_VERSION + '|' + LLVM_ROOT + '|' + get_clang_version() + ('_wasm' if Settings.WASM_BACKEND else '')


def perform_sanify_checks():
  logger.info('(Emscripten: Running sanity checks)')

  with ToolchainProfiler.profile_block('sanity compiler_engine'):
    if not jsrun.check_engine(COMPILER_ENGINE):
      exit_with_error('The JavaScript shell used for compiling (%s) does not seem to work, check the paths in %s', COMPILER_ENGINE, EM_CONFIG)

  with ToolchainProfiler.profile_block('sanity LLVM'):
    for cmd in [CLANG, LLVM_AR, LLVM_AS, LLVM_NM]:
      if not os.path.exists(cmd) and not os.path.exists(cmd + '.exe'):  # .exe extension required for Windows
        exit_with_error('Cannot find %s, check the paths in %s', cmd, EM_CONFIG)

  # Sanity check passed!
  with ToolchainProfiler.profile_block('sanity closure compiler'):
    if not check_closure_compiler():
      logger.warning('closure compiler will not be available')


def check_sanity(force=False):
  """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).  We also
  re-check sanity and clear the cache when the version changes.
  """
  with ToolchainProfiler.profile_block('sanity'):
    check_llvm_version()
    expected = generate_sanity()
    if os.environ.get('EMCC_SKIP_SANITY_CHECK') == '1':
      return
    reason = None
    if not CONFIG_FILE:
      return # config stored directly in EM_CONFIG => skip sanity checks

    settings_mtime = os.path.getmtime(CONFIG_FILE)
    sanity_file = CONFIG_FILE + '_sanity'
    if Settings.WASM_BACKEND:
      sanity_file += '_wasm'
    if os.path.exists(sanity_file):
      sanity_mtime = os.path.getmtime(sanity_file)
      if sanity_mtime < settings_mtime:
        reason = 'settings file has changed'
      else:
        sanity_data = open(sanity_file).read().rstrip()
        if sanity_data != expected:
          reason = 'system change: %s vs %s' % (expected, sanity_data)
        elif not force:
          return # all is well

    if reason:
      if FROZEN_CACHE:
        logger.warning('(Emscripten: %s, cache may need to be cleared, but FROZEN_CACHE is set)' % reason)
      else:
        logger.warning('(Emscripten: %s, clearing cache)' % reason)
        Cache.erase()
        # the check actually failed, so definitely write out the sanity file, to
        # avoid others later seeing failures too
        force = False

    # some warning, mostly not fatal checks - do them even if EM_IGNORE_SANITY is on
    check_node_version()

    llvm_ok = check_llvm()

    if os.environ.get('EM_IGNORE_SANITY'):
      logger.info('EM_IGNORE_SANITY set, ignoring sanity checks')
      return

    if not llvm_ok:
      exit_with_error('failing sanity checks due to previous llvm failure')

    perform_sanify_checks()

    if not force:
      # Only create/update this file if the sanity check succeeded, i.e., we got here
      with open(sanity_file, 'w') as f:
        f.write(expected)


# Tools/paths
if LLVM_ADD_VERSION is None:
  LLVM_ADD_VERSION = os.getenv('LLVM_ADD_VERSION')

if CLANG_ADD_VERSION is None:
  CLANG_ADD_VERSION = os.getenv('CLANG_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.join(LLVM_ROOT, tool)


# Some distributions ship with multiple clang versions so they add
# the version to the binaries, cope with that
def build_clang_tool_path(tool):
  if CLANG_ADD_VERSION:
    return os.path.join(LLVM_ROOT, tool + "-" + CLANG_ADD_VERSION)
  else:
    return os.path.join(LLVM_ROOT, tool)


# These extra args need to be passed to Clang when targeting a native host system executable
CACHED_CLANG_NATIVE_ARGS = None


def get_clang_native_args():
  global CACHED_CLANG_NATIVE_ARGS
  if CACHED_CLANG_NATIVE_ARGS is not None:
    return CACHED_CLANG_NATIVE_ARGS
  CACHED_CLANG_NATIVE_ARGS = []
  if MACOS:
    CACHED_CLANG_NATIVE_ARGS = ['-isystem', path_from_root('system', 'include', 'libcxx')]
  elif os.name == 'nt':
    CACHED_CLANG_NATIVE_ARGS = ['-DWIN32']
    # TODO: If Windows.h et al. are needed, will need to add something like '-isystemC:/Program Files (x86)/Microsoft SDKs/Windows/v7.1A/Include'.
  return CACHED_CLANG_NATIVE_ARGS


# This environment needs to be present when targeting a native host system executable
CACHED_CLANG_NATIVE_ENV = None


def get_clang_native_env():
  global CACHED_CLANG_NATIVE_ENV
  if CACHED_CLANG_NATIVE_ENV is not None:
    return CACHED_CLANG_NATIVE_ENV
  env = os.environ.copy()

  if MACOS:
    path = run_process(['xcrun', '--show-sdk-path'], stdout=PIPE).stdout.strip()
    logging.debug('Using MacOS SDKROOT: ' + path)
    env['SDKROOT'] = path
  elif WINDOWS:
    # If already running in Visual Studio Command Prompt manually, no need to
    # add anything here, so just return.
    if 'VSINSTALLDIR' in env and 'INCLUDE' in env and 'LIB' in env:
      CACHED_CLANG_NATIVE_ENV = env
      return env

    # Guess where VS2015 is installed (VSINSTALLDIR env. var in VS2015 X64 Command Prompt)
    if 'VSINSTALLDIR' in env:
      visual_studio_path = env['VSINSTALLDIR']
    elif 'VS140COMNTOOLS' in env:
      visual_studio_path = os.path.normpath(os.path.join(env['VS140COMNTOOLS'], '../..'))
    elif 'ProgramFiles(x86)' in env:
      visual_studio_path = os.path.normpath(os.path.join(env['ProgramFiles(x86)'], 'Microsoft Visual Studio 14.0'))
    elif 'ProgramFiles' in env:
      visual_studio_path = os.path.normpath(os.path.join(env['ProgramFiles'], 'Microsoft Visual Studio 14.0'))
    else:
      visual_studio_path = 'C:\\Program Files (x86)\\Microsoft Visual Studio 14.0'
    if not os.path.isdir(visual_studio_path):
      raise Exception('Visual Studio 2015 was not found in "' + visual_studio_path + '"! Run in Visual Studio X64 command prompt to avoid the need to autoguess this location (or set VSINSTALLDIR env var).')

    # Guess where Program Files (x86) is located
    if 'ProgramFiles(x86)' in env:
      prog_files_x86 = env['ProgramFiles(x86)']
    elif 'ProgramFiles' in env:
      prog_files_x86 = env['ProgramFiles']
    elif os.path.isdir('C:\\Program Files (x86)'):
      prog_files_x86 = 'C:\\Program Files (x86)'
    elif os.path.isdir('C:\\Program Files'):
      prog_files_x86 = 'C:\\Program Files'
    else:
      raise Exception('Unable to detect Program files directory for native Visual Studio build!')

    # Guess where Windows 8.1 SDK is located
    if 'WindowsSdkDir' in env:
      windows8_sdk_dir = env['WindowsSdkDir']
    elif os.path.isdir(os.path.join(prog_files_x86, 'Windows Kits', '8.1')):
      windows8_sdk_dir = os.path.join(prog_files_x86, 'Windows Kits', '8.1')
    if not os.path.isdir(windows8_sdk_dir):
      raise Exception('Windows 8.1 SDK was not found in "' + windows8_sdk_dir + '"! Run in Visual Studio command prompt to avoid the need to autoguess this location (or set WindowsSdkDir env var).')

    # Guess where Windows 10 SDK is located
    if os.path.isdir(os.path.join(prog_files_x86, 'Windows Kits', '10')):
      windows10_sdk_dir = os.path.join(prog_files_x86, 'Windows Kits', '10')
    if not os.path.isdir(windows10_sdk_dir):
      raise Exception('Windows 10 SDK was not found in "' + windows10_sdk_dir + '"! Run in Visual Studio command prompt to avoid the need to autoguess this location.')

    env.setdefault('VSINSTALLDIR', visual_studio_path)
    env.setdefault('VCINSTALLDIR', os.path.join(visual_studio_path, 'VC'))

    windows10sdk_kits_include_dir = os.path.join(windows10_sdk_dir, 'Include')
    windows10sdk_kit_version_name = [x for x in os.listdir(windows10sdk_kits_include_dir) if os.path.isdir(os.path.join(windows10sdk_kits_include_dir, x))][0] # e.g. "10.0.10150.0" or "10.0.10240.0"

    def append_item(key, item):
      if key not in env or len(env[key].strip()) == 0:
        env[key] = item
      else:
        env[key] = env[key] + ';' + item

    append_item('INCLUDE', os.path.join(env['VCINSTALLDIR'], 'INCLUDE'))
    append_item('INCLUDE', os.path.join(env['VCINSTALLDIR'], 'ATLMFC', 'INCLUDE'))
    append_item('INCLUDE', os.path.join(windows10_sdk_dir, 'include', windows10sdk_kit_version_name, 'ucrt'))
    #   append_item('INCLUDE', 'C:\\Program Files (x86)\\Windows Kits\\NETFXSDK\\4.6.1\\include\\um') # VS2015 X64 command prompt has this, but not needed for Emscripten
    append_item('INCLUDE', os.path.join(env['VCINSTALLDIR'], 'ATLMFC', 'INCLUDE'))
    append_item('INCLUDE', os.path.join(windows8_sdk_dir, 'include', 'shared'))
    append_item('INCLUDE', os.path.join(windows8_sdk_dir, 'include', 'um'))
    append_item('INCLUDE', os.path.join(windows8_sdk_dir, 'include', 'winrt'))
    logger.debug('VS2015 native build INCLUDE: ' + env['INCLUDE'])

    append_item('LIB', os.path.join(env['VCINSTALLDIR'], 'LIB', 'amd64'))
    append_item('LIB', os.path.join(env['VCINSTALLDIR'], 'ATLMFC', 'LIB', 'amd64'))
    append_item('LIB', os.path.join(windows10_sdk_dir, 'lib', windows10sdk_kit_version_name, 'ucrt', 'x64'))
    #   append_item('LIB', 'C:\\Program Files (x86)\\Windows Kits\\NETFXSDK\\4.6.1\\lib\\um\\x64') # VS2015 X64 command prompt has this, but not needed for Emscripten
    append_item('LIB', os.path.join(windows8_sdk_dir, 'lib', 'winv6.3', 'um', 'x64'))
    logger.debug('VS2015 native build LIB: ' + env['LIB'])

    env['PATH'] = env['PATH'] + ';' + os.path.join(env['VCINSTALLDIR'], 'BIN')
    logger.debug('VS2015 native build PATH: ' + env['PATH'])

  # Current configuration above is all Visual Studio -specific, so on non-Windowses, no action needed.

  CACHED_CLANG_NATIVE_ENV = env
  return env


def exe_suffix(cmd):
  return cmd + '.exe' if WINDOWS else cmd


CLANG_CC = os.path.expanduser(build_clang_tool_path(exe_suffix('clang')))
CLANG_CPP = os.path.expanduser(build_clang_tool_path(exe_suffix('clang++')))
CLANG = CLANG_CPP
LLVM_LINK = build_llvm_tool_path(exe_suffix('llvm-link'))
LLVM_AR = build_llvm_tool_path(exe_suffix('llvm-ar'))
LLVM_OPT = os.path.expanduser(build_llvm_tool_path(exe_suffix('opt')))
LLVM_AS = os.path.expanduser(build_llvm_tool_path(exe_suffix('llvm-as')))
LLVM_DIS = os.path.expanduser(build_llvm_tool_path(exe_suffix('llvm-dis')))
LLVM_NM = os.path.expanduser(build_llvm_tool_path(exe_suffix('llvm-nm')))
LLVM_INTERPRETER = os.path.expanduser(build_llvm_tool_path(exe_suffix('lli')))
LLVM_COMPILER = os.path.expanduser(build_llvm_tool_path(exe_suffix('llc')))
LLVM_DWARFDUMP = os.path.expanduser(build_llvm_tool_path(exe_suffix('llvm-dwarfdump')))
WASM_LD = os.path.expanduser(build_llvm_tool_path(exe_suffix('wasm-ld')))

EMSCRIPTEN = path_from_root('emscripten.py')
EMCC = path_from_root('emcc.py')
EMXX = path_from_root('em++.py')
EMAR = path_from_root('emar.py')
EMRANLIB = path_from_root('emranlib')
EMCONFIG = path_from_root('em-config')
EMLINK = path_from_root('emlink.py')
EMCONFIGURE = path_from_root('emconfigure.py')
EMMAKE = path_from_root('emmake.py')
AUTODEBUGGER = path_from_root('tools', 'autodebugger.py')
EXEC_LLVM = path_from_root('tools', 'exec_llvm.py')
FILE_PACKAGER = path_from_root('tools', 'file_packager.py')


# Temp dir. Create a random one, unless EMCC_DEBUG is set, in which case use TEMP_DIR/emscripten_temp
def safe_ensure_dirs(dirname):
  try:
    os.makedirs(dirname)
  except OSError:
    # Python 2 compatibility: makedirs does not support exist_ok parameter
    # Ignore error for already existing dirname as exist_ok does
    if not os.path.isdir(dirname):
      raise


# Returns a path to EMSCRIPTEN_TEMP_DIR, creating one if it didn't exist.
def get_emscripten_temp_dir():
  global configuration, EMSCRIPTEN_TEMP_DIR
  if not EMSCRIPTEN_TEMP_DIR:
    EMSCRIPTEN_TEMP_DIR = tempfile.mkdtemp(prefix='emscripten_temp_', dir=configuration.TEMP_DIR)

    def prepare_to_clean_temp(d):
      def clean_temp():
        try_delete(d)

      atexit.register(clean_temp)
    prepare_to_clean_temp(EMSCRIPTEN_TEMP_DIR) # this global var might change later
  return EMSCRIPTEN_TEMP_DIR


def get_canonical_temp_dir(temp_dir):
  return os.path.join(temp_dir, 'emscripten_temp')


class WarningManager(object):
  warnings = {
    'ABSOLUTE_PATHS': {
      'enabled': False,  # warning about absolute-paths is disabled by default
      'printed': False,
      'message': '-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).',
    },
    'SEPARATE_ASM': {
      'enabled': True,
      'printed': False,
      'message': "--separate-asm works best when compiling to HTML. Otherwise, you must yourself load the '.asm.js' file that is emitted separately, and must do so before loading the main '.js' file.",
    },
    'ALMOST_ASM': {
      'enabled': True,
      'printed': False,
      'message': 'not all asm.js optimizations are possible with ALLOW_MEMORY_GROWTH, disabling those.',
    },
  }

  @staticmethod
  def capture_warnings(cmd_args):
    for i in range(len(cmd_args)):
      if not cmd_args[i].startswith('-W'):
        continue

      # special case pre-existing warn-absolute-paths
      if cmd_args[i] == '-Wwarn-absolute-paths':
        cmd_args[i] = ''
        WarningManager.warnings['ABSOLUTE_PATHS']['enabled'] = True
      elif cmd_args[i] == '-Wno-warn-absolute-paths':
        cmd_args[i] = ''
        WarningManager.warnings['ABSOLUTE_PATHS']['enabled'] = False
      else:
        # convert to string representation of Warning
        warning_enum = cmd_args[i].replace('-Wno-', '').replace('-W', '')
        warning_enum = warning_enum.upper().replace('-', '_')

        if warning_enum in WarningManager.warnings:
          WarningManager.warnings[warning_enum]['enabled'] = not cmd_args[i].startswith('-Wno-')
          cmd_args[i] = ''

    return cmd_args

  @staticmethod
  def warn(warning_type, message=None):
    warning = WarningManager.warnings[warning_type]
    if warning['enabled'] and not warning['printed']:
      warning['printed'] = True
      logger.warning((message or warning['message']) + ' [-W' + warning_type.lower().replace('_', '-') + ']')


class Configuration(object):
  def __init__(self, environ=os.environ):
    self.EMSCRIPTEN_TEMP_DIR = None

    self.TEMP_DIR = environ.get("EMCC_TEMP_DIR", tempfile.gettempdir())
    if not os.path.isdir(self.TEMP_DIR):
      exit_with_error("The temporary directory `" + self.TEMP_DIR + "` does not exist! Please make sure that the path is correct.")

    self.CANONICAL_TEMP_DIR = get_canonical_temp_dir(self.TEMP_DIR)

    if DEBUG:
      try:
        self.EMSCRIPTEN_TEMP_DIR = self.CANONICAL_TEMP_DIR
        safe_ensure_dirs(self.EMSCRIPTEN_TEMP_DIR)
      except Exception as e:
        logger.error(str(e) + 'Could not create canonical temp dir. Check definition of TEMP_DIR in ' + hint_config_file_location())

  def get_temp_files(self):
    return tempfiles.TempFiles(
      tmp=self.TEMP_DIR if not DEBUG else get_emscripten_temp_dir(),
      save_debug_files=os.environ.get('EMCC_DEBUG_SAVE'))


def apply_configuration():
  global configuration, EMSCRIPTEN_TEMP_DIR, CANONICAL_TEMP_DIR, TEMP_DIR
  configuration = Configuration()
  EMSCRIPTEN_TEMP_DIR = configuration.EMSCRIPTEN_TEMP_DIR
  CANONICAL_TEMP_DIR = configuration.CANONICAL_TEMP_DIR
  TEMP_DIR = configuration.TEMP_DIR


apply_configuration()

# EM_CONFIG stuff
if JS_ENGINES is None:
  if JS_ENGINE is None:
    raise 'ERROR: %s does not seem to have JS_ENGINES or JS_ENGINE set up' % EM_CONFIG
  else:
    JS_ENGINES = [JS_ENGINE]

if CLOSURE_COMPILER is None:
  CLOSURE_COMPILER = path_from_root('third_party', 'closure-compiler', 'compiler.jar')

if JAVA is None:
  logger.debug('JAVA not defined in ' + hint_config_file_location() + ', using "java"')
  JAVA = 'java'

# Additional compiler options

# Target choice.
ASM_JS_TARGET = 'asmjs-unknown-emscripten'
WASM_TARGET = 'wasm32-unknown-emscripten'


def check_vanilla():
  global LLVM_TARGET
  # if the env var tells us what to do, do that
  if 'EMCC_WASM_BACKEND' in os.environ:
    if os.environ['EMCC_WASM_BACKEND'] != '0':
      logger.debug('EMCC_WASM_BACKEND tells us to use wasm backend')
      LLVM_TARGET = WASM_TARGET
    else:
      logger.debug('EMCC_WASM_BACKEND tells us to use asm.js backend')
      LLVM_TARGET = ASM_JS_TARGET
  else:
    # if we are using vanilla LLVM, i.e. we don't have our asm.js backend, then we
    # must use wasm (or at least try to). to know that, we have to run llc to
    # see which backends it has. we cache this result.
    temp_cache = cache.Cache(use_subdir=False)

    def check_vanilla():
      logger.debug('testing for asm.js target, because if not present (i.e. this is plain vanilla llvm, not emscripten fastcomp), we will use the wasm target instead (set EMCC_WASM_BACKEND to skip this check)')
      targets = get_llc_targets()
      return has_wasm_target(targets) and not has_asm_js_target(targets)

    def get_vanilla_file():
      saved_file = os.path.join(temp_cache.dirname, 'is_vanilla.txt')
      open(saved_file, 'w').write(('1' if check_vanilla() else '0') + ':' + LLVM_ROOT)
      return saved_file

    is_vanilla_file = temp_cache.get('is_vanilla.txt', get_vanilla_file)
    if CONFIG_FILE and os.path.getmtime(CONFIG_FILE) > os.path.getmtime(is_vanilla_file):
      logger.debug('config file changed since we checked vanilla; re-checking')
      is_vanilla_file = temp_cache.get('is_vanilla.txt', get_vanilla_file, force=True)
    try:
      contents = open(is_vanilla_file).read()
      middle = contents.index(':')
      is_vanilla = int(contents[:middle])
      llvm_used = contents[middle + 1:]
      if llvm_used != LLVM_ROOT:
        logger.debug('regenerating vanilla check since other llvm')
        temp_cache.get('is_vanilla.txt', get_vanilla_file, force=True)
        is_vanilla = check_vanilla()
    except Exception as e:
      logger.debug('failed to use vanilla file, will re-check: ' + str(e))
      is_vanilla = check_vanilla()
    temp_cache = None
    if is_vanilla:
      logger.debug('check tells us to use wasm backend')
      LLVM_TARGET = WASM_TARGET
    else:
      logger.debug('check tells us to use asm.js backend')
      LLVM_TARGET = ASM_JS_TARGET


check_vanilla()


def get_llvm_target():
  assert LLVM_TARGET is not None
  return LLVM_TARGET


# Set the LIBCPP ABI version to at least 2 so that we get nicely aligned string
# data and other nice fixes.
COMPILER_OPTS += [# '-fno-threadsafe-statics', # disabled due to issue 1289
                  '-target', get_llvm_target(),
                  '-D__EMSCRIPTEN_major__=' + str(EMSCRIPTEN_VERSION_MAJOR),
                  '-D__EMSCRIPTEN_minor__=' + str(EMSCRIPTEN_VERSION_MINOR),
                  '-D__EMSCRIPTEN_tiny__=' + str(EMSCRIPTEN_VERSION_TINY),
                  '-D_LIBCPP_ABI_VERSION=2']

if get_llvm_target() == WASM_TARGET:
  # wasm target does not automatically define emscripten stuff, so do it here.
  COMPILER_OPTS += ['-Dunix',
                    '-D__unix',
                    '-D__unix__']

# Changes to default clang behavior

# Implicit functions can cause horribly confusing function pointer type errors, see #2175
# If your codebase really needs them - very unrecommended! - you can disable the error with
#   -Wno-error=implicit-function-declaration
# or disable even a warning about it with
#   -Wno-implicit-function-declaration
COMPILER_OPTS += ['-Werror=implicit-function-declaration']


def emsdk_opts():
  if os.environ.get('EMMAKEN_NO_SDK'):
    return []

  # Disable system C and C++ include directories, and add our own (using
  # -idirafter so they are last, like system dirs, which allows projects to
  # override them)
  c_include_paths = [
    path_from_root('system', 'include', 'compat'),
    path_from_root('system', 'include'),
    path_from_root('system', 'include', 'libc'),
    path_from_root('system', 'include', 'libc', 'arch', 'emscripten'),
    path_from_root('system', 'local', 'include')
  ]

  cxx_include_paths = [
    path_from_root('system', 'include', 'libcxx'),
    path_from_root('system', 'include', 'libcxxabi')
  ]

  c_opts = ['-Xclang', '-nostdsysteminc']

  def include_directive(paths):
    result = []
    for path in paths:
      result += ['-Xclang', '-isystem' + path]
    return result

  # libcxx include paths must be defined before libc's include paths otherwise libcxx will not build
  return c_opts + include_directive(cxx_include_paths) + include_directive(c_include_paths)


EMSDK_OPTS = emsdk_opts()
COMPILER_OPTS += EMSDK_OPTS

# Engine tweaks
if SPIDERMONKEY_ENGINE:
  new_spidermonkey = SPIDERMONKEY_ENGINE
  if '-w' not in str(new_spidermonkey):
    new_spidermonkey += ['-w']
  SPIDERMONKEY_ENGINE = fix_js_engine(SPIDERMONKEY_ENGINE, new_spidermonkey)


# Utilities
def run_js(filename, engine=None, *args, **kw):
  if engine is None:
    engine = JS_ENGINES[0]
  return jsrun.run_js(filename, engine, *args, **kw)


def to_cc(cxx):
  # By default, LLVM_GCC and CLANG are really the C++ versions. This gets an explicit C version
  dirname, basename = os.path.split(cxx)
  basename = basename.replace('clang++', 'clang').replace('g++', 'gcc').replace('em++', 'emcc')
  return os.path.join(dirname, basename)


def unique_ordered(values):
  """return a list of unique values in an input list, without changing order
  (list(set(.)) would change order randomly).
  """
  seen = set()

  def check(value):
    if value in seen:
      return False
    seen.add(value)
    return True

  return list(filter(check, values))


SIZE_SUFFIXES = {suffix: 1024 ** i for i, suffix in enumerate(['b', 'kb', 'mb', 'gb', 'tb'])}


def expand_byte_size_suffixes(value):
  """Given a string with KB/MB size suffixes, such as "32MB", computes how
  many bytes that is and returns it as an integer.
  """
  match = re.match(r'\s*(\d+)\s*([kmgt]?b)$', value, re.I)
  if not match:
    try:
      return int(value)
    except ValueError:
      raise Exception("Invalid byte size, valid suffixes: KB, MB, GB, TB")
  value, suffix = match.groups()
  return int(value) * SIZE_SUFFIXES[suffix.lower()]


# Settings. A global singleton. Not pretty, but nicer than passing |, settings| everywhere
class SettingsManager(object):

  class __impl(object):
    attrs = {}

    def __init__(self):
      self.reset()

    @classmethod
    def reset(cls):
      cls.attrs = {}

      # Load the JS defaults into python.
      settings = open(path_from_root('src', 'settings.js')).read().replace('//', '#')
      settings = re.sub(r'var ([\w\d]+)', r'attrs["\1"]', settings)
      exec(settings, {'attrs': cls.attrs})

      if 'EMCC_STRICT' in os.environ:
        cls.attrs['STRICT'] = int(os.environ.get('EMCC_STRICT'))

      # Special handling for LEGACY_SETTINGS.  See src/setting.js for more
      # details
      cls.legacy_settings = {}
      cls.alt_names = {}
      for legacy in cls.attrs['LEGACY_SETTINGS']:
        if len(legacy) == 2:
          name, new_name = legacy
          cls.legacy_settings[name] = (None, 'setting renamed to ' + new_name)
          cls.alt_names[name] = new_name
          cls.alt_names[new_name] = name
          default_value = cls.attrs[new_name]
        else:
          name, fixed_values, err = legacy
          cls.legacy_settings[name] = (fixed_values, err)
          default_value = fixed_values[0]
        assert name not in cls.attrs, 'legacy setting (%s) cannot also be a regular setting' % name
        if not cls.attrs['STRICT']:
          cls.attrs[name] = default_value

      if get_llvm_target() == WASM_TARGET:
        cls.attrs['WASM_BACKEND'] = 1

    # Transforms the Settings information into emcc-compatible args (-s X=Y, etc.). Basically
    # the reverse of load_settings, except for -Ox which is relevant there but not here
    @classmethod
    def serialize(cls):
      ret = []
      for key, value in cls.attrs.items():
        if key == key.upper():  # this is a hack. all of our settings are ALL_CAPS, python internals are not
          jsoned = json.dumps(value, sort_keys=True)
          ret += ['-s', key + '=' + jsoned]
      return ret

    @classmethod
    def to_dict(cls):
      return cls.attrs.copy()

    @classmethod
    def copy(cls, values):
      cls.attrs = values

    @classmethod
    def apply_opt_level(cls, opt_level, shrink_level=0, noisy=False):
      if opt_level >= 1:
        cls.attrs['ASM_JS'] = 1
        cls.attrs['ASSERTIONS'] = 0
        cls.attrs['ALIASING_FUNCTION_POINTERS'] = 1
      if shrink_level >= 2:
        cls.attrs['EVAL_CTORS'] = 1

    def keys(self):
      return self.attrs.keys()

    def __getattr__(self, attr):
      if attr in self.attrs:
        return self.attrs[attr]
      else:
        raise AttributeError("Settings object has no attribute '%s'" % attr)

    def __setattr__(self, attr, value):
      if attr == 'STRICT' and value:
        for a in self.legacy_settings:
          self.attrs.pop(a, None)

      if attr in self.legacy_settings:
        if self.attrs['STRICT']:
          exit_with_error('legacy setting used in strict mode: %s', attr)
        fixed_values, error_message = self.legacy_settings[attr]
        if fixed_values and value not in fixed_values:
          exit_with_error('Invalid command line option -s ' + attr + '=' + str(value) + ': ' + error_message)
        else:
          logger.debug('Option -s ' + attr + '=' + str(value) + ' has been removed from the codebase. (' + error_message + ')')

      if attr in self.alt_names:
        alt_name = self.alt_names[attr]
        self.attrs[alt_name] = value

      if attr not in self.attrs:
        logger.error('Assigning a non-existent settings attribute "%s"' % attr)
        suggestions = ', '.join(difflib.get_close_matches(attr, list(self.attrs.keys())))
        if suggestions:
          logger.error(' - did you mean one of %s?' % suggestions)
        logger.error(" - perhaps a typo in emcc's  -s X=Y  notation?")
        logger.error(' - (see src/settings.js for valid values)')
        sys.exit(1)

      self.attrs[attr] = value

    @classmethod
    def get(cls, key):
      return cls.attrs.get(key)

    @classmethod
    def __getitem__(cls, key):
      return cls.attrs[key]

    @classmethod
    def target_environment_may_be(self, environment):
      return self.attrs['ENVIRONMENT'] == '' or environment in self.attrs['ENVIRONMENT'].split(',')

  __instance = None

  @staticmethod
  def instance():
    if SettingsManager.__instance is None:
      SettingsManager.__instance = SettingsManager.__impl()
    return SettingsManager.__instance

  def __getattr__(self, attr):
    return getattr(self.instance(), attr)

  def __setattr__(self, attr, value):
    return setattr(self.instance(), attr, value)

  def get(self, key):
    return self.instance().get(key)

  def __getitem__(self, key):
    return self.instance()[key]


def verify_settings():
  if Settings.ASM_JS not in [1, 2]:
    exit_with_error('emcc: ASM_JS can only be set to either 1 or 2')

  if Settings.SAFE_HEAP not in [0, 1]:
    exit_with_error('emcc: SAVE_HEAP must be 0 or 1 in fastcomp')

  if Settings.WASM and Settings.EXPORT_FUNCTION_TABLES:
      exit_with_error('emcc: EXPORT_FUNCTION_TABLES incompatible with WASM')

  if Settings.WASM_BACKEND:
    if not Settings.WASM:
      # When the user requests non-wasm output, we enable wasm2js. that is,
      # we still compile to wasm normally, but we compile the final output
      # to js.
      Settings.WASM = 1
      Settings.WASM2JS = 1

    if Settings.CYBERDWARF:
      exit_with_error('emcc: CYBERDWARF is not supported by the LLVM wasm backend')

    if Settings.EMTERPRETIFY:
      exit_with_error('emcc: EMTERPRETIFY is not supported by the LLVM wasm backend')

    if Settings.EMULATED_FUNCTION_POINTERS:
      exit_with_error('emcc: EMULATED_FUNCTION_POINTERS is not meaningful with the wasm backend.')


Settings = SettingsManager()
verify_settings()


# llvm-ar appears to just use basenames inside archives. as a result, files with the same basename
# will trample each other when we extract them. to help warn of such situations, we warn if there
# are duplicate entries in the archive
def warn_if_duplicate_entries(archive_contents, archive_filename):
  if len(archive_contents) != len(set(archive_contents)):
    logger.warning('%s: archive file contains duplicate entries. This is not supported by emscripten. Only the last member with a given name will be linked in which can result in undefined symbols. You should either rename your source files, or use `emar` to create you archives which works around this issue.' % archive_filename)
    warned = set()
    for i in range(len(archive_contents)):
      curr = archive_contents[i]
      if curr not in warned and curr in archive_contents[i + 1:]:
        logger.warning('   duplicate: %s' % curr)
        warned.add(curr)


# This function creates a temporary directory specified by the 'dir' field in
# the returned dictionary. Caller is responsible for cleaning up those files
# after done.
def extract_archive_contents(archive_file):
  lines = run_process([LLVM_AR, 't', archive_file], stdout=PIPE).stdout.splitlines()
  # ignore empty lines
  contents = [l for l in lines if len(l)]
  if len(contents) == 0:
    logger.debug('Archive %s appears to be empty (recommendation: link an .so instead of .a)' % archive_file)
    return {
      'returncode': 0,
      'dir': None,
      'files': []
    }

  # `ar` files can only contains filenames. Just to be sure,  verify that each
  # file has only as filename component and is not absolute
  for f in contents:
    assert not os.path.dirname(f)
    assert not os.path.isabs(f)

  warn_if_duplicate_entries(contents, archive_file)

  # create temp dir
  temp_dir = tempfile.mkdtemp('_archive_contents', 'emscripten_temp_')

  # extract file in temp dir
  proc = run_process([LLVM_AR, 'xo', archive_file], stdout=PIPE, stderr=STDOUT, cwd=temp_dir)
  abs_contents = [os.path.join(temp_dir, c) for c in contents]

  # check that all files were created
  missing_contents = [x for x in abs_contents if not os.path.exists(x)]
  if missing_contents:
    exit_with_error('llvm-ar failed to extract file(s) ' + str(missing_contents) + ' from archive file ' + f + '! Error:' + str(proc.stdout))

  return {
    'returncode': proc.returncode,
    'dir': temp_dir,
    'files': abs_contents
  }


class ObjectFileInfo(object):
  def __init__(self, returncode, output, defs=set(), undefs=set(), commons=set()):
    self.returncode = returncode
    self.output = output
    self.defs = defs
    self.undefs = undefs
    self.commons = commons

  def is_valid_for_nm(self):
    return self.returncode == 0


# Due to a python pickling issue, the following two functions must be at top
# level, or multiprocessing pool spawn won't find them.
def g_llvm_nm_uncached(filename):
  return Building.llvm_nm_uncached(filename)


def g_multiprocessing_initializer(*args):
  for item in args:
    (key, value) = item.split('=', 1)
    if key == 'EMCC_POOL_CWD':
      os.chdir(value)
    else:
      os.environ[key] = value


def print_compiler_stage(cmd):
  """Emulate the '-v' of clang/gcc by printing the name of the sub-command
  before executing it."""
  if '-v' in COMPILER_OPTS:
    print(' "%s" %s' % (cmd[0], ' '.join(cmd[1:])), file=sys.stderr)
    sys.stderr.flush()


def static_library_name(name):
  if Settings.WASM_BACKEND and Settings.WASM_OBJECT_FILES:
    return name + '.a'
  else:
    return name + '.bc'


def mangle_c_symbol_name(name):
  return '_' + name if not name.startswith('$') else name[1:]


def demangle_c_symbol_name(name):
  return name[1:] if name.startswith('_') else '$' + name


#  Building
class Building(object):
  COMPILER = CLANG
  JS_ENGINE_OVERRIDE = None # Used to pass the JS engine override from runner.py -> test_benchmark.py
  multiprocessing_pool = None

  # internal caches
  internal_nm_cache = {} # cache results of nm - it can be slow to run
  uninternal_nm_cache = {}
  ar_contents = {} # Stores the object files contained in different archive files passed as input
  _is_ar_cache = {}

  # clear internal caches. this is not normally needed, except if the clang/LLVM
  # used changes inside this invocation of Building, which can happen in the benchmarker
  # when it compares different builds.
  @staticmethod
  def clear():
    Building.internal_nm_cache = {}
    Building.uninternal_nm_cache = {}
    Building.ar_contents = {}
    Building._is_ar_cache = {}

  @staticmethod
  def get_num_cores():
    return int(os.environ.get('EMCC_CORES', multiprocessing.cpu_count()))

  # Multiprocessing pools are very slow to build up and tear down, and having several pools throughout
  # the application has a problem of overallocating child processes. Therefore maintain a single
  # centralized pool that is shared between all pooled task invocations.
  @staticmethod
  def get_multiprocessing_pool():
    if not Building.multiprocessing_pool:
      cores = Building.get_num_cores()
      if DEBUG:
        # When in EMCC_DEBUG mode, only use a single core in the pool, so that
        # logging is not all jumbled up.
        cores = 1

      # If running with one core only, create a mock instance of a pool that does not
      # actually spawn any new subprocesses. Very useful for internal debugging.
      if cores == 1:
        class FakeMultiprocessor(object):
          def map(self, func, tasks, *args, **kwargs):
            results = []
            for t in tasks:
              results += [func(t)]
            return results

          def map_async(self, func, tasks, *args, **kwargs):
            class Result:
              def __init__(self, func, tasks):
                self.func = func
                self.tasks = tasks

              def get(self, timeout):
                results = []
                for t in tasks:
                  results += [func(t)]
                return results

            return Result(func, tasks)

        Building.multiprocessing_pool = FakeMultiprocessor()
      else:
        child_env = [
          # Multiprocessing pool children must have their current working
          # directory set to a safe path that is guaranteed not to die in
          # between of executing commands, or otherwise the pool children will
          # have trouble spawning subprocesses of their own.
          'EMCC_POOL_CWD=' + path_from_root(),
          # Multiprocessing pool children need to avoid all calling
          # check_vanilla() again and again, otherwise the compiler can deadlock
          # when building system libs, because the multiprocess parent can have
          # the Emscripten cache directory locked for write access, and the
          # EMCC_WASM_BACKEND check also requires locked access to the cache,
          # which the multiprocess children would not get.
          'EMCC_WASM_BACKEND=%s' % Settings.WASM_BACKEND,
          # Multiprocessing pool children can't spawn their own linear number of
          # children, that could cause a quadratic amount of spawned processes.
          'EMCC_CORES=1'
        ]
        Building.multiprocessing_pool = multiprocessing.Pool(processes=cores, initializer=g_multiprocessing_initializer, initargs=child_env)

        def close_multiprocessing_pool():
          try:
            # Shut down the pool explicitly, because leaving that for Python to do at process shutdown is buggy and can generate
            # noisy "WindowsError: [Error 5] Access is denied" spam which is not fatal.
            Building.multiprocessing_pool.terminate()
            Building.multiprocessing_pool.join()
            Building.multiprocessing_pool = None
          except OSError as e:
            # Mute the "WindowsError: [Error 5] Access is denied" errors, raise all others through
            if not (sys.platform.startswith('win') and isinstance(e, WindowsError) and e.winerror == 5):
              raise
        atexit.register(close_multiprocessing_pool)

    return Building.multiprocessing_pool

  # When creating environment variables for Makefiles to execute, we need to doublequote the commands if they have spaces in them..
  @staticmethod
  def doublequote_spaces(arg):
    arg = arg[:] # Operate on a copy of the input string/list
    if isinstance(arg, list):
      for i in range(len(arg)):
        arg[i] = Building.doublequote_spaces(arg[i])
      return arg

    if ' ' in arg and (not (arg.startswith('"') and arg.endswith('"'))) and (not (arg.startswith("'") and arg.endswith("'"))):
      return '"' + arg.replace('"', '\\"') + '"'

    return arg

  # .. but for Popen, we cannot have doublequotes, so provide functionality to remove them when needed.
  @staticmethod
  def remove_quotes(arg):
    arg = arg[:] # Operate on a copy of the input string/list
    if isinstance(arg, list):
      for i in range(len(arg)):
        arg[i] = Building.remove_quotes(arg[i])
      return arg

    if arg.startswith('"') and arg.endswith('"'):
      return arg[1:-1].replace('\\"', '"')
    elif arg.startswith("'") and arg.endswith("'"):
      return arg[1:-1].replace("\\'", "'")
    else:
      return arg

  @staticmethod
  def get_building_env(native=False, doublequote_commands=False, cflags=[]):
    def nop(arg):
      return arg
    quote = Building.doublequote_spaces if doublequote_commands else nop
    env = os.environ.copy()
    if native:
      env['CC'] = quote(CLANG_CC)
      env['CXX'] = quote(CLANG_CPP)
      env['LD'] = quote(CLANG)
      # get a non-native one, and see if we have some of its effects - remove them if so
      non_native = Building.get_building_env(cflags=cflags)
      # the ones that a non-native would modify
      EMSCRIPTEN_MODIFIES = ['LDSHARED', 'AR', 'CROSS_COMPILE', 'NM', 'RANLIB']
      for dangerous in EMSCRIPTEN_MODIFIES:
        if env.get(dangerous) and env.get(dangerous) == non_native.get(dangerous):
          del env[dangerous] # better to delete it than leave it, as the non-native one is definitely wrong
      return env
    # point CC etc. to the em* tools.
    # on windows, we must specify python explicitly. on other platforms, we prefer
    # not to, as some configure scripts expect e.g. CC to be a literal executable
    # (but "python emcc.py" is not a file that exists).
    # note that we point to emcc etc. here, without a suffix, instead of to
    # emcc.py etc. The unsuffixed versions have the python_selector logic that can
    # pick the right version as needed (which is not crucial right now as we support
    # both 2 and 3, but eventually we may be 3-only).
    env['CC'] = quote(unsuffixed(EMCC)) if not WINDOWS else 'python %s' % quote(EMCC)
    env['CXX'] = quote(unsuffixed(EMXX)) if not WINDOWS else 'python %s' % quote(EMXX)
    env['AR'] = quote(unsuffixed(EMAR)) if not WINDOWS else 'python %s' % quote(EMAR)
    env['LD'] = quote(unsuffixed(EMCC)) if not WINDOWS else 'python %s' % quote(EMCC)
    env['NM'] = quote(LLVM_NM)
    env['LDSHARED'] = quote(unsuffixed(EMCC)) if not WINDOWS else 'python %s' % quote(EMCC)
    env['RANLIB'] = quote(unsuffixed(EMRANLIB)) if not WINDOWS else 'python %s' % quote(EMRANLIB)
    env['EMMAKEN_COMPILER'] = quote(Building.COMPILER)
    env['EMSCRIPTEN_TOOLS'] = path_from_root('tools')
    if cflags:
      env['CFLAGS'] = env['EMMAKEN_CFLAGS'] = ' '.join(cflags)
    env['HOST_CC'] = quote(CLANG_CC)
    env['HOST_CXX'] = quote(CLANG_CPP)
    env['HOST_CFLAGS'] = "-W" # if set to nothing, CFLAGS is used, which we don't want
    env['HOST_CXXFLAGS'] = "-W" # if set to nothing, CXXFLAGS is used, which we don't want
    env['PKG_CONFIG_LIBDIR'] = path_from_root('system', 'local', 'lib', 'pkgconfig') + os.path.pathsep + path_from_root('system', 'lib', 'pkgconfig')
    env['PKG_CONFIG_PATH'] = os.environ.get('EM_PKG_CONFIG_PATH', '')
    env['EMSCRIPTEN'] = path_from_root()
    env['PATH'] = path_from_root('system', 'bin') + os.pathsep + env['PATH']
    env['CROSS_COMPILE'] = path_from_root('em') # produces /path/to/emscripten/em , which then can have 'cc', 'ar', etc appended to it
    return env

  # if we are in emmake mode, i.e., we changed the env to run emcc etc., then show the message and abort
  @staticmethod
  def ensure_no_emmake(message):
    non_native = Building.get_building_env()
    if os.environ.get('CC') == non_native.get('CC'):
      # the environment CC is the one we change to when forcing our em* tools
      exit_with_error(message)

  # Finds the given executable 'program' in PATH. Operates like the Unix tool 'which'.
  @staticmethod
  def which(program):
    def is_exe(fpath):
      return os.path.isfile(fpath) and os.access(fpath, os.X_OK)

    if os.path.isabs(program):
      if os.path.isfile(program):
        return program

      if WINDOWS:
        for suffix in ['.exe', '.cmd', '.bat']:
          if is_exe(program + suffix):
            return program + suffix

    fpath, fname = os.path.split(program)
    if fpath:
      if is_exe(program):
        return program
    else:
      for path in os.environ["PATH"].split(os.pathsep):
        path = path.strip('"')
        exe_file = os.path.join(path, program)
        if is_exe(exe_file):
          return exe_file
        if WINDOWS:
          for suffix in ('.exe', '.cmd', '.bat'):
            if is_exe(exe_file + suffix):
              return exe_file + suffix

    return None

  # Returns a clone of the given environment with all directories that contain sh.exe removed from the PATH.
  # Used to work around CMake limitation with MinGW Makefiles, where sh.exe is not allowed to be present.
  @staticmethod
  def remove_sh_exe_from_path(env):
    env = env.copy()
    if not WINDOWS:
      return env
    path = env['PATH'].split(';')
    path = [p for p in path if not os.path.exists(os.path.join(p, 'sh.exe'))]
    env['PATH'] = ';'.join(path)
    return env

  @staticmethod
  def handle_CMake_toolchain(args, env):

    def has_substr(array, substr):
      for arg in array:
        if substr in arg:
          return True
      return False

    # Append the Emscripten toolchain file if the user didn't specify one.
    if not has_substr(args, '-DCMAKE_TOOLCHAIN_FILE'):
      args.append('-DCMAKE_TOOLCHAIN_FILE=' + path_from_root('cmake', 'Modules', 'Platform', 'Emscripten.cmake'))

    # On Windows specify MinGW Makefiles or ninja if we have them and no other toolchain was specified, to keep CMake
    # from pulling in a native Visual Studio, or Unix Makefiles.
    if WINDOWS and '-G' not in args:
      if Building.which('mingw32-make'):
        args += ['-G', 'MinGW Makefiles']
      elif Building.which('ninja'):
        args += ['-G', 'Ninja']

    # CMake has a requirement that it wants sh.exe off PATH if MinGW Makefiles is being used. This happens quite often,
    # so do this automatically on behalf of the user. See http://www.cmake.org/Wiki/CMake_MinGW_Compiler_Issues
    if WINDOWS and 'MinGW Makefiles' in args:
      env = Building.remove_sh_exe_from_path(env)

    return (args, env)

  @staticmethod
  def configure(args, stdout=None, stderr=None, env=None, cflags=[]):
    if not args:
      return
    if env is None:
      env = Building.get_building_env(cflags=cflags)
    if 'cmake' in args[0]:
      # Note: EMMAKEN_JUST_CONFIGURE shall not be enabled when configuring with CMake. This is because CMake
      #       does expect to be able to do config-time builds with emcc.
      args, env = Building.handle_CMake_toolchain(args, env)
    else:
      # When we configure via a ./configure script, don't do config-time compilation with emcc, but instead
      # do builds natively with Clang. This is a heuristic emulation that may or may not work.
      env['EMMAKEN_JUST_CONFIGURE'] = '1'
    if EM_BUILD_VERBOSE >= 3:
      print('configure: ' + str(args), file=sys.stderr)
    if EM_BUILD_VERBOSE >= 2:
      stdout = None
    if EM_BUILD_VERBOSE >= 1:
      stderr = None
    run_process(args, stdout=stdout, stderr=stderr, env=env)
    if 'EMMAKEN_JUST_CONFIGURE' in env:
      del env['EMMAKEN_JUST_CONFIGURE']

  @staticmethod
  def make(args, stdout=None, stderr=None, env=None, cflags=[]):
    if env is None:
      env = Building.get_building_env(cflags=cflags)
    if not args:
      exit_with_error('Executable to run not specified.')
    # args += ['VERBOSE=1']

    # On Windows prefer building with mingw32-make instead of make, if it exists.
    if WINDOWS:
      if args[0] == 'make':
        mingw32_make = Building.which('mingw32-make')
        if mingw32_make:
          args[0] = mingw32_make

      if 'mingw32-make' in args[0]:
        env = Building.remove_sh_exe_from_path(env)

    # On Windows, run the execution through shell to get PATH expansion and
    # executable extension lookup, e.g. 'sdl2-config' will match with
    # 'sdl2-config.bat' in PATH.
    if EM_BUILD_VERBOSE >= 2:
      stdout = None
    if EM_BUILD_VERBOSE >= 1:
      stderr = None
    print('make: ' + str(args), file=sys.stderr)
    run_process(args, stdout=stdout, stderr=stderr, env=env, shell=WINDOWS)

  @staticmethod
  def make_paths_absolute(f):
    if f.startswith('-'):  # skip flags
      return f
    else:
      return os.path.abspath(f)

  # Runs llvm-nm in parallel for the given list of files.
  # The results are populated in Building.uninternal_nm_cache
  # multiprocessing_pool: An existing multiprocessing pool to reuse for the operation, or None
  # to have the function allocate its own.
  @staticmethod
  def parallel_llvm_nm(files):
    with ToolchainProfiler.profile_block('parallel_llvm_nm'):
      pool = Building.get_multiprocessing_pool()
      object_contents = pool.map(g_llvm_nm_uncached, files)

      for i, file in enumerate(files):
        if object_contents[i].returncode != 0:
          logger.debug('llvm-nm failed on file ' + file + ': return code ' + str(object_contents[i].returncode) + ', error: ' + object_contents[i].output)
        Building.uninternal_nm_cache[file] = object_contents[i]
      return object_contents

  @staticmethod
  def read_link_inputs(files):
    with ToolchainProfiler.profile_block('read_link_inputs'):
      # Before performing the link, we need to look at each input file to determine which symbols
      # each of them provides. Do this in multiple parallel processes.
      archive_names = [] # .a files passed in to the command line to the link
      object_names = [] # .o/.bc files passed in to the command line to the link
      for f in files:
        absolute_path_f = Building.make_paths_absolute(f)

        if absolute_path_f not in Building.ar_contents and Building.is_ar(absolute_path_f):
          archive_names.append(absolute_path_f)
        elif absolute_path_f not in Building.uninternal_nm_cache and Building.is_bitcode(absolute_path_f):
          object_names.append(absolute_path_f)

      # Archives contain objects, so process all archives first in parallel to obtain the object files in them.
      pool = Building.get_multiprocessing_pool()
      object_names_in_archives = pool.map(extract_archive_contents, archive_names)

      def clean_temporary_archive_contents_directory(directory):
        def clean_at_exit():
          try_delete(directory)
        if directory:
          atexit.register(clean_at_exit)

      for n in range(len(archive_names)):
        if object_names_in_archives[n]['returncode'] != 0:
          raise Exception('llvm-ar failed on archive ' + archive_names[n] + '!')
        Building.ar_contents[archive_names[n]] = object_names_in_archives[n]['files']
        clean_temporary_archive_contents_directory(object_names_in_archives[n]['dir'])

      for o in object_names_in_archives:
        for f in o['files']:
          if f not in Building.uninternal_nm_cache:
            object_names.append(f)

      # Next, extract symbols from all object files (either standalone or inside archives we just extracted)
      # The results are not used here directly, but populated to llvm-nm cache structure.
      Building.parallel_llvm_nm(object_names)

  @staticmethod
  def llvm_backend_args():
    # disable slow and relatively unimportant optimization passes
    args = ['-combiner-global-alias-analysis=false']

    # asm.js-style exception handling
    if Settings.DISABLE_EXCEPTION_CATCHING != 1:
      args += ['-enable-emscripten-cxx-exceptions']
    if Settings.DISABLE_EXCEPTION_CATCHING == 2:
      whitelist = ','.join(Settings.EXCEPTION_CATCHING_WHITELIST or ['__fake'])
      args += ['-emscripten-cxx-exceptions-whitelist=' + whitelist]

    # asm.js-style setjmp/longjmp handling
    args += ['-enable-emscripten-sjlj']

    # better (smaller, sometimes faster) codegen, see binaryen#1054
    # and https://bugs.llvm.org/show_bug.cgi?id=39488
    args += ['-disable-lsr']

    return args

  @staticmethod
  def link_to_object(linker_inputs, target):
    # link using lld for the wasm backend with wasm object files,
    # other otherwise for linking of bitcode we must use our python
    # code (necessary for asm.js, for wasm bitcode see
    # https://bugs.llvm.org/show_bug.cgi?id=40654)
    if Settings.WASM_BACKEND and Settings.WASM_OBJECT_FILES:
      Building.link_lld(linker_inputs, target, ['--relocatable'])
    else:
      Building.link(linker_inputs, target)

  @staticmethod
  def link_llvm(linker_inputs, target):
    # runs llvm-link to link things.
    cmd = [LLVM_LINK] + linker_inputs + ['-o', target]
    cmd = Building.get_command_with_possible_response_file(cmd)
    print_compiler_stage(cmd)
    output = run_process(cmd, stdout=PIPE).stdout
    assert os.path.exists(target) and (output is None or 'Could not open input file' not in output), 'Linking error: ' + output
    return target

  @staticmethod
  def link_lld(args, target, opts=[], lto_level=0):
    # runs lld to link things.
    # lld doesn't currently support --start-group/--end-group since the
    # semantics are more like the windows linker where there is no need for
    # grouping.
    args = [a for a in args if a not in ('--start-group', '--end-group')]
    if not os.path.exists(WASM_LD) or run_process([WASM_LD, '--version'], stdout=PIPE, stderr=PIPE, check=False).returncode != 0:
      exit_with_error('linker binary not found in LLVM direcotry: %s', WASM_LD)

    # Emscripten currently expects linkable output (SIDE_MODULE/MAIN_MODULE) to
    # include all archive contents.
    if Settings.LINKABLE:
      args.insert(0, '--whole-archive')
      args.append('--no-whole-archive')

    cmd = [
        WASM_LD,
        '-o',
        target,
        '--allow-undefined',
        '--import-memory',
        '--import-table',
        '--lto-O%d' % lto_level,
    ] + args

    if Settings.USE_PTHREADS:
      cmd.append('--shared-memory')

    for a in Building.llvm_backend_args():
      cmd += ['-mllvm', a]

    # emscripten-wasm-finalize currently depends on the presence of debug
    # symbols for renaming of the __invoke symbols
    # TODO(sbc): Re-enable once emscripten-wasm-finalize is fixed or we
    # no longer need to rename these symbols.
    # if Settings.DEBUG_LEVEL < 2 and not Settings.PROFILING_FUNCS:
    #   cmd.append('--strip-debug')

    if Settings.RELOCATABLE:
      if Settings.MAIN_MODULE == 2 or Settings.SIDE_MODULE == 2:
        cmd.append('--no-export-dynamic')
      else:
        cmd.append('--no-gc-sections')
        cmd.append('--export-dynamic')

    if Settings.MAIN_MODULE == 1 or Settings.EXPORT_ALL:
      cmd.append('--export-all')

    cmd += [
      '--export',
      '__wasm_call_ctors',
      '--export',
      '__data_end'
    ]
    for export in Settings.EXPORTED_FUNCTIONS:
      cmd += ['--export', export[1:]] # Strip the leading underscore

    if Settings.RELOCATABLE:
      if Settings.SIDE_MODULE:
        cmd.append('-shared')
      else:
        cmd.append('-pie')

    if not Settings.SIDE_MODULE:
      cmd += [
        '-z', 'stack-size=%s' % Settings.TOTAL_STACK,
        '--initial-memory=%d' % Settings.TOTAL_MEMORY,
        '--no-entry'
      ]
      if Settings.WASM_MEM_MAX != -1:
        cmd.append('--max-memory=%d' % Settings.WASM_MEM_MAX)
      elif not Settings.ALLOW_MEMORY_GROWTH:
        cmd.append('--max-memory=%d' % Settings.TOTAL_MEMORY)
      if not Settings.RELOCATABLE:
        cmd.append('--global-base=%s' % Settings.GLOBAL_BASE)

    cmd += opts

    print_compiler_stage(cmd)
    cmd = Building.get_command_with_possible_response_file(cmd)
    check_call(cmd)
    return target

  @staticmethod
  def link(files, target, force_archive_contents=False, just_calculate=False):
    # "Full-featured" linking: looks into archives (duplicates lld functionality)
    actual_files = []
    # Tracking unresolveds is necessary for .a linking, see below.
    # Specify all possible entry points to seed the linking process.
    # For a simple application, this would just be "main".
    unresolved_symbols = set([func[1:] for func in Settings.EXPORTED_FUNCTIONS])
    resolved_symbols = set()
    # Paths of already included object files from archives.
    added_contents = set()
    has_ar = False
    for f in files:
      if not f.startswith('-'):
        has_ar = has_ar or Building.is_ar(Building.make_paths_absolute(f))

    # If we have only one archive or the force_archive_contents flag is set,
    # then we will add every object file we see, regardless of whether it
    # resolves any undefined symbols.
    force_add_all = len(files) == 1 or force_archive_contents

    # Considers an object file for inclusion in the link. The object is included
    # if force_add=True or if the object provides a currently undefined symbol.
    # If the object is included, the symbol tables are updated and the function
    # returns True.
    def consider_object(f, force_add=False):
      new_symbols = Building.llvm_nm(f)
      # Check if the object was valid according to llvm-nm. It also accepts
      # native object files.
      if not new_symbols.is_valid_for_nm():
        logger.warning('object %s is not valid according to llvm-nm, cannot link' % (f))
        return False
      # Check the object is valid for us, and not a native object file.
      if not Building.is_bitcode(f):
        logger.warning('object %s is not a valid object file for emscripten, cannot link' % (f))
        return False
      provided = new_symbols.defs.union(new_symbols.commons)
      do_add = force_add or not unresolved_symbols.isdisjoint(provided)
      if do_add:
        logger.debug('adding object %s to link' % (f))
        # Update resolved_symbols table with newly resolved symbols
        resolved_symbols.update(provided)
        # Update unresolved_symbols table by adding newly unresolved symbols and
        # removing newly resolved symbols.
        unresolved_symbols.update(new_symbols.undefs.difference(resolved_symbols))
        unresolved_symbols.difference_update(provided)
        actual_files.append(f)
      return do_add

    # Traverse a single archive. The object files are repeatedly scanned for
    # newly satisfied symbols until no new symbols are found. Returns true if
    # any object files were added to the link.
    def consider_archive(f, force_add):
      added_any_objects = False
      loop_again = True
      logger.debug('considering archive %s' % (f))
      contents = Building.ar_contents[f]
      while loop_again: # repeatedly traverse until we have everything we need
        loop_again = False
        for content in contents:
          if content in added_contents:
            continue
          # Link in the .o if it provides symbols, *or* this is a singleton archive (which is apparently an exception in gcc ld)
          if consider_object(content, force_add=force_add):
            added_contents.add(content)
            loop_again = True
            added_any_objects = True
      logger.debug('done running loop of archive %s' % (f))
      return added_any_objects

    Building.read_link_inputs([x for x in files if not x.startswith('-')])

    # Rescan a group of archives until we don't find any more objects to link.
    def scan_archive_group(group):
      loop_again = True
      logger.debug('starting archive group loop')
      while loop_again:
        loop_again = False
        for archive in group:
          if consider_archive(archive, force_add=False):
            loop_again = True
      logger.debug('done with archive group loop')

    current_archive_group = None
    in_whole_archive = False
    for f in files:
      absolute_path_f = Building.make_paths_absolute(f)
      if f.startswith('-'):
        if f in ['--start-group', '-(']:
          assert current_archive_group is None, 'Nested --start-group, missing --end-group?'
          current_archive_group = []
        elif f in ['--end-group', '-)']:
          assert current_archive_group is not None, '--end-group without --start-group'
          scan_archive_group(current_archive_group)
          current_archive_group = None
        elif f in ['--whole-archive', '-whole-archive']:
          in_whole_archive = True
        elif f in ['--no-whole-archive', '-no-whole-archive']:
          in_whole_archive = False
        else:
          # Command line flags should already be vetted by the time this method
          # is called, so this is an internal error
          assert False, 'unsupported link flag: ' + f
      elif not Building.is_ar(absolute_path_f):
        if Building.is_bitcode(absolute_path_f):
          if has_ar:
            consider_object(absolute_path_f, force_add=True)
          else:
            # If there are no archives then we can simply link all valid object
            # files and skip the symbol table stuff.
            actual_files.append(f)
        else:
          logging.debug('ignoring non-bitcode file for link: %s' % absolute_path_f)
      else:
        # Extract object files from ar archives, and link according to gnu ld semantics
        # (link in an entire .o from the archive if it supplies symbols still unresolved)
        consider_archive(absolute_path_f, in_whole_archive or force_add_all)
        # If we're inside a --start-group/--end-group section, add to the list
        # so we can loop back around later.
        if current_archive_group is not None:
          current_archive_group.append(absolute_path_f)

    # We have to consider the possibility that --start-group was used without a matching
    # --end-group; GNU ld permits this behavior and implicitly treats the end of the
    # command line as having an --end-group.
    if current_archive_group:
      logger.debug('--start-group without matching --end-group, rescanning')
      scan_archive_group(current_archive_group)
      current_archive_group = None

    try_delete(target)

    # Finish link
    # tolerate people trying to link a.so a.so etc.
    actual_files = unique_ordered(actual_files)

    if not just_calculate:
      logger.debug('emcc: Building.linking: %s to %s', actual_files, target)
      Building.link_llvm(actual_files, target)
      return target
    else:
      # just calculating; return the link arguments which is the final list of files to link
      return actual_files

  @staticmethod
  def get_command_with_possible_response_file(cmd):
    # 8k is a bit of an arbitrary limit, but a reasonable one
    # for max command line size before we use a response file
    if len(' '.join(cmd)) <= 8192:
      return cmd

    logger.debug('using response file for %s' % cmd[0])
    filename = response_file.create_response_file(cmd[1:], TEMP_DIR)
    new_cmd = [cmd[0], "@" + filename]
    return new_cmd

  # LLVM optimizations
  # @param opt A list of LLVM optimization parameters
  @staticmethod
  def llvm_opt(filename, opts, out=None):
    inputs = filename
    if not isinstance(inputs, list):
      inputs = [inputs]
    else:
      assert out, 'must provide out if llvm_opt on a list of inputs'
    assert len(opts), 'should not call opt with nothing to do'
    opts = opts[:]
    # TODO: disable inlining when needed
    # if not Building.can_inline():
    #   opts.append('-disable-inlining')
    # opts += ['-debug-pass=Arguments']
    # TODO: move vectorization logic to clang/LLVM?
    if not Settings.WASM_BACKEND:
      if not Settings.SIMD:
        opts += ['-disable-loop-vectorization', '-disable-slp-vectorization', '-vectorize-loops=false', '-vectorize-slp=false']
      else:
        opts += ['-force-vector-width=4']

    target = out or (filename + '.opt.bc')
    cmd = [LLVM_OPT] + inputs + opts + ['-o', target]
    cmd = Building.get_command_with_possible_response_file(cmd)
    print_compiler_stage(cmd)
    try:
      run_process(cmd, stdout=PIPE)
      assert os.path.exists(target), 'llvm optimizer emitted no output.'
    except subprocess.CalledProcessError as e:
      for i in inputs:
        if not os.path.exists(i):
          logger.warning('Note: Input file "' + i + '" did not exist.')
        elif not Building.is_bitcode(i):
          logger.warning('Note: Input file "' + i + '" exists but was not an LLVM bitcode file suitable for Emscripten. Perhaps accidentally mixing native built object files with Emscripten?')
      exit_with_error('Failed to run llvm optimizations: ' + e.output)
    if not out:
      shutil.move(filename + '.opt.bc', filename)
    return target

  @staticmethod
  def llvm_dis(input_filename, output_filename):
    # LLVM binary ==> LLVM assembly
    try_delete(output_filename)
    output = run_process([LLVM_DIS, input_filename, '-o', output_filename], stdout=PIPE).stdout
    assert os.path.exists(output_filename), 'Could not create .ll file: ' + output

  @staticmethod
  def llvm_as(input_filename, output_filename):
    # LLVM assembly ==> LLVM binary
    try_delete(output_filename)
    output = run_process([LLVM_AS, input_filename, '-o', output_filename], stdout=PIPE).stdout
    assert os.path.exists(output_filename), 'Could not create bc file: ' + output

  @staticmethod
  def parse_symbols(output, include_internal=False):
    defs = []
    undefs = []
    commons = []
    for line in output.split('\n'):
      if not line or line[0] == '#':
        continue
      # e.g.  filename.o:  , saying which file it's from
      if ':' in line:
        continue
      parts = [seg for seg in line.split(' ') if len(seg)]
      # pnacl-nm will print zero offsets for bitcode, and newer llvm-nm will print present symbols as  -------- T name
      if len(parts) == 3 and parts[0] == "--------" or re.match(r'^[\da-f]{8}$', parts[0]):
        parts.pop(0)
      if len(parts) == 2:  # ignore lines with absolute offsets, these are not bitcode anyhow (e.g. |00000630 t d_source_name|)
        status, symbol = parts
        if status == 'U':
          undefs.append(symbol)
        elif status == 'C':
          commons.append(symbol)
        elif (not include_internal and status == status.upper()) or \
             (include_internal and status in ['W', 't', 'T', 'd', 'D']): # FIXME: using WTD in the previous line fails due to llvm-nm behavior on macOS,
          #        so for now we assume all uppercase are normally defined external symbols
          defs.append(symbol)
    return ObjectFileInfo(0, None, set(defs), set(undefs), set(commons))

  @staticmethod
  def llvm_nm_uncached(filename, stdout=PIPE, stderr=PIPE, include_internal=False):
    # LLVM binary ==> list of symbols
    proc = run_process([LLVM_NM, filename], stdout=stdout, stderr=stderr, check=False)
    if proc.returncode == 0:
      return Building.parse_symbols(proc.stdout, include_internal)
    else:
      return ObjectFileInfo(proc.returncode, str(proc.stdout) + str(proc.stderr))

  @staticmethod
  def llvm_nm(filename, stdout=PIPE, stderr=PIPE, include_internal=False):
    # Always use absolute paths to maximize cache usage
    filename = os.path.abspath(filename)

    if include_internal and filename in Building.internal_nm_cache:
      return Building.internal_nm_cache[filename]
    elif not include_internal and filename in Building.uninternal_nm_cache:
      return Building.uninternal_nm_cache[filename]

    ret = Building.llvm_nm_uncached(filename, stdout, stderr, include_internal)

    if ret.returncode != 0:
      logger.debug('llvm-nm failed on file ' + filename + ': return code ' + str(ret.returncode) + ', error: ' + ret.output)

    # Even if we fail, write the results to the NM cache so that we don't keep trying to llvm-nm the failing file again later.
    if include_internal:
      Building.internal_nm_cache[filename] = ret
    else:
      Building.uninternal_nm_cache[filename] = ret

    return ret

  @staticmethod
  def emcc(filename, args=[], output_filename=None, stdout=None, stderr=None, env=None):
    if output_filename is None:
      output_filename = filename + '.o'
    try_delete(output_filename)
    run_process([PYTHON, EMCC, filename] + args + ['-o', output_filename], stdout=stdout, stderr=stderr, env=env)

  @staticmethod
  def emar(action, output_filename, filenames, stdout=None, stderr=None, env=None):
    try_delete(output_filename)
    cmd = [PYTHON, EMAR, action, output_filename] + filenames[:5]

    response_filename = response_file.create_response_file(filenames, TEMP_DIR)
    cmd = [PYTHON, EMAR, action, output_filename] + ['@' + response_filename]
    try:
      run_process(cmd, stdout=stdout, stderr=stderr, env=env)
    finally:
      try_delete(response_filename)

    if 'c' in action:
      assert os.path.exists(output_filename), 'emar could not create output file: ' + output_filename

  @staticmethod
  def emscripten(infile, memfile, js_libraries):
    if path_from_root() not in sys.path:
      sys.path += [path_from_root()]
    import emscripten
    # Run Emscripten
    outfile = infile + '.o.js'
    with ToolchainProfiler.profile_block('emscripten.py'):
      emscripten.run(infile, outfile, memfile, js_libraries)

    # Detect compilation crashes and errors
    assert os.path.exists(outfile), 'Emscripten failed to generate .js'

    return outfile

  @staticmethod
  def can_inline():
    return Settings.INLINING_LIMIT == 0

  @staticmethod
  def need_asm_js_file():
    # Explicitly separate asm.js requires it
    if Settings.SEPARATE_ASM:
      return True
    return False

  @staticmethod
  def is_wasm_only():
    # not even wasm, much less wasm-only
    if not Settings.WASM:
      return False
    # llvm backend can only ever produce wasm
    if Settings.WASM_BACKEND:
      return True
    # fastcomp can emit wasm-only code.
    # also disable this mode if it depends on special optimizations that are not yet
    # compatible with it.
    if not Settings.LEGALIZE_JS_FFI:
      # the user has requested no legalization for JS, and so we are not
      # emitting code compatible with JS, and there is no reason not to
      # be wasm-only, regardless of everything else
      return True
    if Settings.RUNNING_JS_OPTS:
      # if the JS optimizer runs, it must run on valid asm.js
      return False
    if Settings.RELOCATABLE and Settings.EMULATED_FUNCTION_POINTERS:
      # FIXME(https://github.com/emscripten-core/emscripten/issues/5370)
      # emulation function pointers work properly, but calling between
      # modules as wasm-only needs more work
      return False
    return True

  @staticmethod
  def get_safe_internalize():
    if Settings.LINKABLE:
      return [] # do not internalize anything

    exps = Settings.EXPORTED_FUNCTIONS
    internalize_public_api = '-internalize-public-api-'
    internalize_list = ','.join([demangle_c_symbol_name(exp) for exp in exps])

    # EXPORTED_FUNCTIONS can potentially be very large.
    # 8k is a bit of an arbitrary limit, but a reasonable one
    # for max command line size before we use a response file
    if len(internalize_list) > 8192:
      logger.debug('using response file for EXPORTED_FUNCTIONS in internalize')
      finalized_exports = '\n'.join([exp[1:] for exp in exps])
      internalize_list_file = configuration.get_temp_files().get(suffix='.response').name
      with open(internalize_list_file, 'w') as f:
        f.write(finalized_exports)
      internalize_public_api += 'file=' + internalize_list_file
    else:
      internalize_public_api += 'list=' + internalize_list

    # internalize carefully, llvm 3.2 will remove even main if not told not to
    return ['-internalize', internalize_public_api]

  @staticmethod
  def opt_level_to_str(opt_level, shrink_level=0):
    # convert opt_level/shrink_level pair to a string argument like -O1
    if opt_level == 0:
      return '-O0'
    if shrink_level == 1:
      return '-Os'
    elif shrink_level >= 2:
      return '-Oz'
    else:
      return '-O' + str(min(opt_level, 3))

  @staticmethod
  def js_optimizer(filename, passes, debug=False, extra_info=None, output_filename=None, just_split=False, just_concat=False, extra_closure_args=[]):
    from . import js_optimizer
    ret = js_optimizer.run(filename, passes, NODE_JS, debug, extra_info, just_split, just_concat, extra_closure_args)
    if output_filename:
      safe_move(ret, output_filename)
      ret = output_filename
    return ret

  # run JS optimizer on some JS, ignoring asm.js contents if any - just run on it all
  @staticmethod
  def js_optimizer_no_asmjs(filename, passes, return_output=False, extra_info=None, acorn=False):
    if not acorn:
      optimizer = path_from_root('tools', 'js-optimizer.js')
    else:
      optimizer = path_from_root('tools', 'acorn-optimizer.js')
    original_filename = filename
    if extra_info is not None:
      temp_files = configuration.get_temp_files()
      temp = temp_files.get('.js').name
      shutil.copyfile(filename, temp)
      with open(temp, 'a') as f:
        f.write('// EXTRA_INFO: ' + extra_info)
      filename = temp
    cmd = NODE_JS + [optimizer, filename] + passes
    if not return_output:
      next = original_filename + '.jso.js'
      configuration.get_temp_files().note(next)
      run_process(cmd, stdout=open(next, 'w'))
      return next
    else:
      return run_process(cmd, stdout=PIPE).stdout

  @staticmethod
  def acorn_optimizer(filename, passes, extra_info=None, return_output=False):
    return Building.js_optimizer_no_asmjs(filename, passes, extra_info=extra_info, return_output=return_output, acorn=True)

  # evals ctors. if binaryen_bin is provided, it is the dir of the binaryen tool for this, and we are in wasm mode
  @staticmethod
  def eval_ctors(js_file, binary_file, binaryen_bin='', debug_info=False):
    cmd = [PYTHON, path_from_root('tools', 'ctor_evaller.py'), js_file, binary_file, str(Settings.TOTAL_MEMORY), str(Settings.TOTAL_STACK), str(Settings.GLOBAL_BASE), binaryen_bin, str(int(debug_info))]
    if binaryen_bin:
      cmd += Building.get_binaryen_feature_flags()
    check_call(cmd)

  @staticmethod
  def eliminate_duplicate_funcs(filename):
    from . import duplicate_function_eliminator
    duplicate_function_eliminator.eliminate_duplicate_funcs(filename)

  @staticmethod
  def calculate_reachable_functions(infile, initial_list, can_reach=True):
    with ToolchainProfiler.profile_block('calculate_reachable_functions'):
      from . import asm_module
      temp = configuration.get_temp_files().get('.js').name
      Building.js_optimizer(infile, ['dumpCallGraph'], output_filename=temp, just_concat=True)
      asm = asm_module.AsmModule(temp)
      lines = asm.funcs_js.split('\n')
      can_call = {}
      for i in range(len(lines)):
        line = lines[i]
        if line.startswith('// REACHABLE '):
          curr = json.loads(line[len('// REACHABLE '):])
          func = curr[0]
          targets = curr[2]
          can_call[func] = set(targets)
      # function tables too - treat a function all as a function that can call anything in it, which is effectively what it is
      for name, funcs in asm.tables.items():
        can_call[name] = set([x.strip() for x in funcs[1:-1].split(',')])
      # print can_call
      # Note: We ignore calls in from outside the asm module, so you could do emterpreted => outside => emterpreted, and we would
      #       miss the first one there. But this is acceptable to do, because we can't save such a stack anyhow, due to the outside!
      # print 'can call', can_call, '\n!!!\n', asm.tables, '!'
      reachable_from = {}
      for func, targets in can_call.items():
        for target in targets:
          if target not in reachable_from:
            reachable_from[target] = set()
          reachable_from[target].add(func)
      # print 'reachable from', reachable_from
      to_check = initial_list[:]
      advised = set()
      if can_reach:
        # find all functions that can reach the initial list
        while len(to_check):
          curr = to_check.pop()
          if curr in reachable_from:
            for reacher in reachable_from[curr]:
              if reacher not in advised:
                if not JS.is_dyn_call(reacher) and not JS.is_function_table(reacher):
                  advised.add(str(reacher))
                to_check.append(reacher)
      else:
        # find all functions that are reachable from the initial list, including it
        # all tables are assumed reachable, as they can be called from dyncall from outside
        for name, funcs in asm.tables.items():
          to_check.append(name)
        while len(to_check):
          curr = to_check.pop()
          if not JS.is_function_table(curr):
            advised.add(curr)
          if curr in can_call:
            for target in can_call[curr]:
              if target not in advised:
                advised.add(str(target))
                to_check.append(target)
      return {'reachable': list(advised), 'total_funcs': len(can_call)}

  @staticmethod
  def closure_compiler(filename, pretty=True, advanced=True, extra_closure_args=[]):
    with ToolchainProfiler.profile_block('closure_compiler'):
      if not check_closure_compiler():
        logger.error('Cannot run closure compiler')
        raise Exception('closure compiler check failed')

      # Closure annotations file contains suppressions and annotations to different symbols
      CLOSURE_ANNOTATIONS = [path_from_root('src', 'closure-annotations.js')]

      if not Settings.ASMFS:
        # If we have filesystem disabled, tell Closure not to bark when there are syscalls emitted that still reference the nonexisting FS object.
        if Settings.FILESYSTEM:
          CLOSURE_ANNOTATIONS += [path_from_root('src', 'closure-defined-fs-annotation.js')]
        else:
          CLOSURE_ANNOTATIONS += [path_from_root('src', 'closure-undefined-fs-annotation.js')]

      # Closure externs file contains known symbols to be extern to the minification, Closure
      # should not minify these symbol names.
      CLOSURE_EXTERNS = [path_from_root('src', 'closure-externs.js')]

      # Closure compiler needs to know about all exports that come from the asm.js/wasm module, because to optimize for small code size,
      # the exported symbols are added to global scope via a foreach loop in a way that evades Closure's static analysis. With an explicit
      # externs file for the exports, Closure is able to reason about the exports.
      if Settings.MODULE_EXPORTS and not Settings.DECLARE_ASM_MODULE_EXPORTS:
        # Generate an exports file that records all the exported symbols from asm.js/wasm module.
        module_exports_suppressions = '\n'.join(['/**\n * @suppress {duplicate, undefinedVars}\n */\nvar %s;\n' % i for i in Settings.MODULE_EXPORTS])
        exports_file = configuration.get_temp_files().get('_module_exports.js')
        exports_file.write(module_exports_suppressions.encode())
        exports_file.close()

        CLOSURE_EXTERNS += [exports_file.name]

      # Node.js specific externs
      if Settings.target_environment_may_be('node'):
        NODE_EXTERNS_BASE = path_from_root('third_party', 'closure-compiler', 'node-externs')
        NODE_EXTERNS = os.listdir(NODE_EXTERNS_BASE)
        NODE_EXTERNS = [os.path.join(NODE_EXTERNS_BASE, name) for name in NODE_EXTERNS
                        if name.endswith('.js')]
        CLOSURE_EXTERNS += [path_from_root('src', 'node-externs.js')] + NODE_EXTERNS

      # V8/SpiderMonkey shell specific externs
      if Settings.target_environment_may_be('shell'):
        V8_EXTERNS = [path_from_root('src', 'v8-externs.js')]
        SPIDERMONKEY_EXTERNS = [path_from_root('src', 'spidermonkey-externs.js')]
        CLOSURE_EXTERNS += V8_EXTERNS + SPIDERMONKEY_EXTERNS

      # Web environment specific externs
      if Settings.target_environment_may_be('web') or Settings.target_environment_may_be('worker'):
        BROWSER_EXTERNS_BASE = path_from_root('third_party', 'closure-compiler', 'browser-externs')
        BROWSER_EXTERNS = os.listdir(BROWSER_EXTERNS_BASE)
        BROWSER_EXTERNS = [os.path.join(BROWSER_EXTERNS_BASE, name) for name in BROWSER_EXTERNS
                           if name.endswith('.js')]
        CLOSURE_EXTERNS += BROWSER_EXTERNS

      # 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
      outfile = filename + '.cc.js'
      args = [JAVA,
              '-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' if advanced else 'SIMPLE_OPTIMIZATIONS',
              '--language_in', 'ECMASCRIPT5']
      for a in CLOSURE_ANNOTATIONS:
        args += ['--js', a]
      for e in CLOSURE_EXTERNS:
        args += ['--externs', e]
      args += ['--js_output_file', outfile]

      if Settings.IGNORE_CLOSURE_COMPILER_ERRORS:
        args.append('--jscomp_off=*')
      if pretty:
        args += ['--formatting', 'PRETTY_PRINT']
      if os.environ.get('EMCC_CLOSURE_ARGS'):
        args += shlex.split(os.environ.get('EMCC_CLOSURE_ARGS'))
      args += extra_closure_args
      args += ['--js', filename]
      logger.debug('closure compiler: ' + ' '.join(args))
      proc = run_process(args, stderr=PIPE, check=False)
      if proc.returncode != 0:
        sys.stderr.write(proc.stderr)
        hint = ''
        if not pretty:
          hint = ' the error message may be clearer with -g1'
        exit_with_error('closure compiler failed (rc: %d.%s)', proc.returncode, hint)

      return outfile

  # minify the final wasm+JS combination. this is done after all the JS
  # and wasm optimizations; here we do the very final optimizations on them
  @staticmethod
  def minify_wasm_js(js_file, wasm_file, expensive_optimizations, minify_whitespace, debug_info):
    # start with JSDCE, to clean up obvious JS garbage. When optimizing for size,
    # use AJSDCE (aggressive JS DCE, performs multiple iterations). Clean up
    # whitespace if necessary too.
    passes = []
    if not Settings.LINKABLE:
      passes.append('JSDCE' if not expensive_optimizations else 'AJSDCE')
    if minify_whitespace:
      passes.append('minifyWhitespace')
    if passes:
      logger.debug('running cleanup on shell code: ' + ' '.join(passes))
      js_file = Building.acorn_optimizer(js_file, passes)
    # if we can optimize this js+wasm combination under the assumption no one else
    # will see the internals, do so
    if not Settings.LINKABLE:
      # if we are optimizing for size, shrink the combined wasm+JS
      # TODO: support this when a symbol map is used
      if expensive_optimizations:
        js_file = Building.metadce(js_file, wasm_file, minify_whitespace=minify_whitespace, debug_info=debug_info)
        # now that we removed unneeded communication between js and wasm, we can clean up
        # the js some more.
        passes = ['AJSDCE']
        if minify_whitespace:
          passes.append('minifyWhitespace')
        logger.debug('running post-meta-DCE cleanup on shell code: ' + ' '.join(passes))
        js_file = Building.acorn_optimizer(js_file, passes)
        # also minify the names used between js and wasm, if we emitting JS (then the JS knows how to load the minified names)
        # If we are building with DECLARE_ASM_MODULE_EXPORTS=0, we must *not* minify the exports from the wasm module, since in DECLARE_ASM_MODULE_EXPORTS=0 mode, the code that
        # reads out the exports is compacted by design that it does not have a chance to unminify the functions. If we are building with DECLARE_ASM_MODULE_EXPORTS=1, we might
        # as well minify wasm exports to regain some of the code size loss that setting DECLARE_ASM_MODULE_EXPORTS=1 caused.
        if Settings.EMITTING_JS and not Settings.AUTODEBUG:
          js_file = Building.minify_wasm_imports_and_exports(js_file, wasm_file, minify_whitespace=minify_whitespace, minify_exports=Settings.DECLARE_ASM_MODULE_EXPORTS, debug_info=debug_info)
    return js_file

  # run binaryen's wasm-metadce to dce both js and wasm
  @staticmethod
  def metadce(js_file, wasm_file, minify_whitespace, debug_info):
    logger.debug('running meta-DCE')
    temp_files = configuration.get_temp_files()
    # first, get the JS part of the graph
    extra_info = '{ "exports": [' + ','.join(map(lambda x: '["' + x + '","' + x + '"]', Settings.MODULE_EXPORTS)) + ']}'
    txt = Building.acorn_optimizer(js_file, ['emitDCEGraph', 'noPrint'], return_output=True, extra_info=extra_info)
    graph = json.loads(txt)
    # add exports based on the backend output, that are not present in the JS
    if not Settings.DECLARE_ASM_MODULE_EXPORTS:
      exports = set()
      for item in graph:
        if 'export' in item:
          exports.add(item['export'])
      for export in Settings.MODULE_EXPORTS:
        if export not in exports:
          graph.append({
            'export': export,
            'name': 'emcc$export$' + export,
            'reaches': []
          })
    # ensure that functions expected to be exported to the outside are roots
    for item in graph:
      if 'export' in item:
        export = item['export']
        # wasm backend's exports are prefixed differently inside the wasm
        if Settings.WASM_BACKEND:
          export = '_' + export
        if export in Building.user_requested_exports or Settings.EXPORT_ALL:
          item['root'] = True
    if Settings.WASM_BACKEND:
      # wasm backend's imports are prefixed differently inside the wasm
      for item in graph:
        if 'import' in item:
          if item['import'][1][0] == '_':
            item['import'][1] = item['import'][1][1:]
    # map import names from wasm to JS, using the actual name the wasm uses for the import
    import_name_map = {}
    for item in graph:
      if 'import' in item:
        import_name_map[item['name']] = 'emcc$import$' + item['import'][1]
    temp = temp_files.get('.txt').name
    txt = json.dumps(graph)
    with open(temp, 'w') as f:
      f.write(txt)
    # run wasm-metadce
    cmd = [os.path.join(Building.get_binaryen_bin(), 'wasm-metadce'), '--graph-file=' + temp, wasm_file, '-o', wasm_file]
    if debug_info:
      cmd += ['-g']
    out = run_process(cmd, stdout=PIPE).stdout
    # find the unused things in js
    unused = []
    PREFIX = 'unused: '
    for line in out.splitlines():
      if line.startswith(PREFIX):
        name = line.replace(PREFIX, '').strip()
        if name in import_name_map:
          name = import_name_map[name]
        unused.append(name)
    # remove them
    passes = ['applyDCEGraphRemovals']
    if minify_whitespace:
      passes.append('minifyWhitespace')
    extra_info = {'unused': unused}
    return Building.acorn_optimizer(js_file, passes, extra_info=json.dumps(extra_info))

  @staticmethod
  def minify_wasm_imports_and_exports(js_file, wasm_file, minify_whitespace, minify_exports, debug_info):
    logger.debug('minifying wasm imports and exports')
    # run the pass
    cmd = [os.path.join(Building.get_binaryen_bin(), 'wasm-opt'), '--minify-imports-and-exports' if minify_exports else '--minify-imports', wasm_file, '-o', wasm_file]
    cmd += Building.get_binaryen_feature_flags()
    if debug_info:
      cmd.append('-g')
    out = check_call(cmd, stdout=PIPE).stdout
    # get the mapping
    SEP = ' => '
    mapping = {}
    for line in out.split('\n'):
      if SEP in line:
        old, new = line.strip().split(SEP)
        assert old not in mapping, 'imports must be unique'
        mapping[old] = new
    # apply them
    passes = ['applyImportAndExportNameChanges']
    if minify_whitespace:
      passes.append('minifyWhitespace')
    extra_info = {'mapping': mapping}
    return Building.acorn_optimizer(js_file, passes, extra_info=json.dumps(extra_info))

  @staticmethod
  def wasm2js(js_file, wasm_file, opt_level, minify_whitespace, use_closure_compiler, debug_info, symbols_file=None):
    logger.debug('wasm2js')
    cmd = [os.path.join(Building.get_binaryen_bin(), 'wasm2js'), '--emscripten', wasm_file]
    if opt_level > 0:
      cmd += ['-O']
    if symbols_file:
      cmd += ['--symbols-file=%s' % symbols_file]
    cmd += Building.get_binaryen_feature_flags()
    wasm2js_js = run_process(cmd, stdout=PIPE).stdout
    if DEBUG:
      with open(os.path.join(get_emscripten_temp_dir(), 'wasm2js-output.js'), 'w') as f:
        f.write(wasm2js_js)
    # JS optimizations
    if opt_level >= 2:
      passes = []
      # it may be useful to also run: simplifyIfs, registerize, asmLastOpts
      # passes += ['simplifyExpressions'] # XXX fails on wasm3js.test_sqlite
      if not debug_info:
        passes += ['minifyNames']
      if minify_whitespace:
        passes += ['minifyWhitespace']
      passes += ['last']
      if passes:
        # hackish fixups to work around wasm2js style and the js optimizer FIXME
        wasm2js_js = '// EMSCRIPTEN_START_ASM\n' + wasm2js_js + '// EMSCRIPTEN_END_ASM\n'
        wasm2js_js = wasm2js_js.replace('// EMSCRIPTEN_START_FUNCS;\n', '// EMSCRIPTEN_START_FUNCS\n')
        wasm2js_js = wasm2js_js.replace('// EMSCRIPTEN_END_FUNCS;\n', '// EMSCRIPTEN_END_FUNCS\n')
        wasm2js_js = wasm2js_js.replace('\n function $', '\nfunction $')
        wasm2js_js = wasm2js_js.replace('\n }', '\n}')
        wasm2js_js += '\n// EMSCRIPTEN_GENERATED_FUNCTIONS\n'
        temp = configuration.get_temp_files().get('.js').name
        with open(temp, 'w') as f:
          f.write(wasm2js_js)
        temp = Building.js_optimizer(temp, passes)
        with open(temp) as f:
          wasm2js_js = f.read()
    # Closure compiler: in mode 1, we just minify the shell. In mode 2, we
    # minify the wasm2js output as well, which is ok since it isn't
    # validating asm.js.
    # TODO: in the non-closure case, we could run a lightweight general-
    #       purpose JS minifier here.
    if use_closure_compiler == 2:
      temp = configuration.get_temp_files().get('.js').name
      with open(temp, 'a') as f:
        f.write(wasm2js_js)
      temp = Building.closure_compiler(temp,
                                       pretty=not minify_whitespace,
                                       advanced=False)
      with open(temp) as f:
        wasm2js_js = f.read()
      # closure may leave a trailing `;`, which would be invalid given where we place
      # this code (inside parens)
      wasm2js_js = wasm2js_js.strip()
      if wasm2js_js[-1] == ';':
        wasm2js_js = wasm2js_js[:-1]
    with open(js_file) as f:
      all_js = f.read()
    # quoted notation, something like Module['__wasm2jsInstantiate__']
    finds = re.findall(r'''[\w\d_$]+\[['"]__wasm2jsInstantiate__['"]\]''', all_js)
    if not finds:
      # post-closure notation, something like a.__wasm2jsInstantiate__
      finds = re.findall(r'''[\w\d_$]+\.__wasm2jsInstantiate__''', all_js)
    assert len(finds) == 1
    marker = finds[0]
    all_js = all_js.replace(marker, '(\n' + wasm2js_js + '\n)')
    # replace the placeholder with the actual code
    js_file = js_file + '.wasm2js.js'
    with open(js_file, 'w') as f:
      f.write(all_js)
    if not DEBUG:
      try_delete(wasm_file)
    return js_file

  @staticmethod
  def apply_wasm_memory_growth(js_file):
    logger.debug('supporting wasm memory growth with pthreads')
    fixed = Building.js_optimizer_no_asmjs(js_file, ['growableHeap'])
    ret = js_file + '.pgrow.js'
    with open(fixed, 'r') as fixed_f:
      with open(ret, 'w') as ret_f:
        with open(path_from_root('src', 'growableHeap.js')) as support_code_f:
          ret_f.write(support_code_f.read() + '\n' + fixed_f.read())
    return ret

  @staticmethod
  def handle_final_wasm_symbols(wasm_file, symbols_file, debug_info):
    logger.debug('handle_final_wasm_symbols')
    cmd = [os.path.join(Building.get_binaryen_bin(), 'wasm-opt'), wasm_file]
    if symbols_file:
      cmd += ['--print-function-map']
    if not debug_info:
      # to remove debug info, we just write to that same file, and without -g
      cmd += ['-o', wasm_file]
    cmd += Building.get_binaryen_feature_flags()
    # ignore stderr because if wasm-opt is run without a -o it will warn
    output = check_call(cmd, stdout=PIPE).stdout
    if symbols_file:
      with open(symbols_file, 'w') as f:
        f.write(output)

  # the exports the user requested
  user_requested_exports = []

  @staticmethod
  def is_ar(filename):
    try:
      if Building._is_ar_cache.get(filename):
        return Building._is_ar_cache[filename]
      header = open(filename, 'rb').read(8)
      sigcheck = header == b'!<arch>\n'
      Building._is_ar_cache[filename] = sigcheck
      return sigcheck
    except Exception as e:
      logger.debug('Building.is_ar failed to test whether file \'%s\' is a llvm archive file! Failed on exception: %s' % (filename, e))
      return False

  @staticmethod
  def is_bitcode(filename):
    try:
      # look for magic signature
      b = open(filename, 'rb').read(4)
      if b[:2] == b'BC':
        return True
      # on macOS, there is a 20-byte prefix which starts with little endian
      # encoding of 0x0B17C0DE
      elif b == b'\xDE\xC0\x17\x0B':
        b = bytearray(open(filename, 'rb').read(22))
        return b[20:] == b'BC'
    except IndexError:
      # not enough characters in the input
      # note that logging will be done on the caller function
      pass
    return False

  @staticmethod
  def is_wasm(filename):
    magic = open(filename, 'rb').read(4)
    return magic == b'\0asm'

  @staticmethod
  # Given the name of a special Emscripten-implemented system library, returns an array of absolute paths to JS library
  # files inside emscripten/src/ that corresponds to the library name.
  def path_to_system_js_libraries(library_name):
    # Some native libraries are implemented in Emscripten as system side JS libraries
    js_system_libraries = {
      'c': '',
      'dl': '',
      'EGL': 'library_egl.js',
      'GL': 'library_webgl.js',
      'GLESv2': 'library_webgl.js',
      'GLEW': 'library_glew.js',
      'glfw': 'library_glfw.js',
      'glfw3': 'library_glfw.js',
      'GLU': '',
      'glut': 'library_glut.js',
      'm': '',
      'openal': 'library_openal.js',
      'rt': '',
      'pthread': '',
      'X11': 'library_xlib.js',
      'SDL': 'library_sdl.js',
      'stdc++': '',
      'uuid': 'library_uuid.js'
    }
    library_files = []
    if library_name in js_system_libraries:
      if len(js_system_libraries[library_name]):
        library_files += js_system_libraries[library_name] if isinstance(js_system_libraries[library_name], list) else [js_system_libraries[library_name]]

    elif library_name.endswith('.js') and os.path.isfile(path_from_root('src', 'library_' + library_name)):
      library_files += ['library_' + library_name]
    else:
      exit_with_error('emcc: cannot find library "%s"', library_name)

    return library_files

  @staticmethod
  def get_binaryen_feature_flags():
    # start with the MVP features, add the rest as needed
    ret = ['--mvp-features']
    if Settings.USE_PTHREADS:
      ret += ['--enable-threads']
    if Settings.SIMD:
      ret += ['--enable-simd']
    ret += Settings.BINARYEN_FEATURES
    return ret

  @staticmethod
  def get_binaryen_bin():
    assert Settings.WASM, 'non wasm builds should not ask for binaryen'
    if not BINARYEN_ROOT:
      # ensure we have the port available if needed.
      from . import system_libs
      system_libs.get_port('binaryen', Settings)
      assert os.path.exists(BINARYEN_ROOT)
    return os.path.join(BINARYEN_ROOT, 'bin')


# compatibility with existing emcc, etc. scripts
Cache = cache.Cache()
chunkify = cache.chunkify


def reconfigure_cache():
  global Cache
  Cache = cache.Cache()


# Placeholder strings used for SINGLE_FILE
class FilenameReplacementStrings:
  WASM_TEXT_FILE = '{{{ FILENAME_REPLACEMENT_STRINGS_WASM_TEXT_FILE }}}'
  WASM_BINARY_FILE = '{{{ FILENAME_REPLACEMENT_STRINGS_WASM_BINARY_FILE }}}'
  ASMJS_CODE_FILE = '{{{ FILENAME_REPLACEMENT_STRINGS_ASMJS_CODE_FILE }}}'


class JS(object):
  memory_initializer_pattern = r'/\* memory initializer \*/ allocate\(\[([\d, ]*)\], "i8", ALLOC_NONE, ([\d+\.GLOBAL_BASEHgb]+)\);'
  no_memory_initializer_pattern = r'/\* no memory initializer \*/'

  memory_staticbump_pattern = r'STATICTOP = STATIC_BASE \+ (\d+);'

  global_initializers_pattern = r'/\* global initializers \*/ __ATINIT__.push\((.+)\);'

  module_export_name_substitution_pattern = '"__EMSCRIPTEN_PRIVATE_MODULE_EXPORT_NAME_SUBSTITUTION__"'

  @staticmethod
  def to_nice_ident(ident): # limited version of the JS function toNiceIdent
    return ident.replace('%', '$').replace('@', '_').replace('.', '_')

  # Returns the given string with escapes added so that it can safely be placed inside a string in JS code.
  @staticmethod
  def escape_for_js_string(s):
    s = s.replace('\\', '/').replace("'", "\\'").replace('"', '\\"')
    return s

  # Returns the subresource location for run-time access
  @staticmethod
  def get_subresource_location(path, data_uri=None):
    if data_uri is None:
      data_uri = Settings.SINGLE_FILE
    if data_uri:
      with open(path, 'rb') as f:
        data = base64.b64encode(f.read())
      return 'data:application/octet-stream;base64,' + asstr(data)
    else:
      return os.path.basename(path)

  @staticmethod
  def make_initializer(sig, settings=None):
    settings = settings or Settings
    if sig == 'i':
      return '0'
    elif sig == 'f' and settings.get('PRECISE_F32'):
      return 'Math_fround(0)'
    elif sig == 'j':
      if settings:
        assert settings['WASM'], 'j aka i64 only makes sense in wasm-only mode in binaryen'
      return 'i64(0)'
    elif sig == 'F':
      return 'SIMD_Float32x4_check(SIMD_Float32x4(0,0,0,0))'
    elif sig == 'D':
      return 'SIMD_Float64x2_check(SIMD_Float64x2(0,0,0,0))'
    elif sig == 'B':
      return 'SIMD_Int8x16_check(SIMD_Int8x16(0,0,0,0))'
    elif sig == 'S':
      return 'SIMD_Int16x8_check(SIMD_Int16x8(0,0,0,0))'
    elif sig == 'I':
      return 'SIMD_Int32x4_check(SIMD_Int32x4(0,0,0,0))'
    else:
      return '+0'

  FLOAT_SIGS = ['f', 'd']

  @staticmethod
  def make_coercion(value, sig, settings=None, ffi_arg=False, ffi_result=False, convert_from=None):
    settings = settings or Settings
    if sig == 'i':
      if convert_from in JS.FLOAT_SIGS:
        value = '(~~' + value + ')'
      return value + '|0'
    if sig in JS.FLOAT_SIGS and convert_from == 'i':
      value = '(' + value + '|0)'
    if sig == 'f' and settings.get('PRECISE_F32'):
      if ffi_arg:
        return '+Math_fround(' + value + ')'
      elif ffi_result:
        return 'Math_fround(+(' + value + '))'
      else:
        return 'Math_fround(' + value + ')'
    elif sig == 'd' or sig == 'f':
      return '+' + value
    elif sig == 'j':
      if settings:
        assert settings['WASM'], 'j aka i64 only makes sense in wasm-only mode in binaryen'
      return 'i64(' + value + ')'
    elif sig == 'F':
      return 'SIMD_Float32x4_check(' + value + ')'
    elif sig == 'D':
      return 'SIMD_Float64x2_check(' + value + ')'
    elif sig == 'B':
      return 'SIMD_Int8x16_check(' + value + ')'
    elif sig == 'S':
      return 'SIMD_Int16x8_check(' + value + ')'
    elif sig == 'I':
      return 'SIMD_Int32x4_check(' + value + ')'
    else:
      return value

  @staticmethod
  def legalize_sig(sig):
    ret = [sig[0]]
    for s in sig[1:]:
      if s != 'j':
        ret.append(s)
      else:
        # an i64 is legalized into i32, i32
        ret.append('i')
        ret.append('i')
    return ''.join(ret)

  @staticmethod
  def make_extcall(sig, named=True):
    args = ','.join(['a' + str(i) for i in range(1, len(sig))])
    args = 'index' + (',' if args else '') + args
    # C++ exceptions are numbers, and longjmp is a string 'longjmp'
    ret = '''function%s(%s) {
  %sModule["dynCall_%s"](%s);
}''' % ((' extCall_' + sig) if named else '', args, 'return ' if sig[0] != 'v' else '', sig, args)
    return ret

  @staticmethod
  def make_jscall(sig):
    fnargs = ','.join('a' + str(i) for i in range(1, len(sig)))
    args = (',' if fnargs else '') + fnargs
    ret = '''\
function jsCall_%s(index%s) {
    %sfunctionPointers[index](%s);
}''' % (sig, args, 'return ' if sig[0] != 'v' else '', fnargs)
    return ret

  @staticmethod
  def make_dynCall(sig):
    # Optimize dynCall accesses in the case when not building with dynamic
    # linking enabled.
    if not Settings.MAIN_MODULE and not Settings.SIDE_MODULE:
      return 'dynCall_' + sig
    else:
      return 'Module["dynCall_' + sig + '"]'

  @staticmethod
  def make_invoke(sig, named=True):
    if sig == 'X':
      # 'X' means the generic unknown signature, used in wasm dynamic linking
      # to indicate an invoke that the main JS may not have defined, so we
      # go through this (which may be slower, as we don't declare the
      # arguments explicitly). In non-wasm dynamic linking, the other modules
      # have JS and so can define their own invokes to be linked in.
      # This only makes sense in function pointer emulation mode, where we
      # can do a direct table call.
      assert Settings.WASM
      assert Settings.WASM_BACKEND or Settings.EMULATED_FUNCTION_POINTERS
      args = ''
      body = '''
        var args = Array.prototype.slice.call(arguments);
        return wasmTable.get(args[0]).apply(null, args.slice(1));
      '''
    else:
      legal_sig = JS.legalize_sig(sig) # TODO: do this in extcall, jscall?
      args = ','.join(['a' + str(i) for i in range(1, len(legal_sig))])
      args = 'index' + (',' if args else '') + args
      ret = 'return ' if sig[0] != 'v' else ''
      body = '%s%s(%s);' % (ret, JS.make_dynCall(sig), args)
    # C++ exceptions are numbers, and longjmp is a string 'longjmp'
    if Settings.SUPPORT_LONGJMP:
      rethrow = "if (e !== e+0 && e !== 'longjmp') throw e;"
    else:
      rethrow = "if (e !== e+0) throw e;"

    ret = '''function%s(%s) {
  var sp = stackSave();
  try {
    %s
  } catch(e) {
    stackRestore(sp);
    %s
    _setThrew(1, 0);
  }
}''' % ((' invoke_' + sig) if named else '', args, body, rethrow)
    return ret

  @staticmethod
  def align(x, by):
    while x % by != 0:
      x += 1
    return x

  @staticmethod
  def generate_string_initializer(s):
    if Settings.ASSERTIONS:
      # append checksum of length and content
      crcTable = []
      for i in range(256):
        crc = i
        for bit in range(8):
          crc = (crc >> 1) ^ ((crc & 1) * 0xedb88320)
        crcTable.append(crc)
      crc = 0xffffffff
      n = len(s)
      crc = crcTable[(crc ^ n) & 0xff] ^ (crc >> 8)
      crc = crcTable[(crc ^ (n >> 8)) & 0xff] ^ (crc >> 8)
      for i in s:
        crc = crcTable[(crc ^ i) & 0xff] ^ (crc >> 8)
      for i in range(4):
        s.append((crc >> (8 * i)) & 0xff)
    s = ''.join(map(chr, s))
    s = s.replace('\\', '\\\\').replace("'", "\\'")
    s = s.replace('\n', '\\n').replace('\r', '\\r')

    # Escape the ^Z (= 0x1a = substitute) ASCII character and all characters higher than 7-bit ASCII.
    def escape(x):
      return '\\x{:02x}'.format(ord(x.group()))

    return re.sub('[\x1a\x80-\xff]', escape, s)

  @staticmethod
  def is_dyn_call(func):
    return func.startswith('dynCall_')

  @staticmethod
  def is_function_table(name):
    return name.startswith('FUNCTION_TABLE_')


class WebAssembly(object):
  @staticmethod
  def lebify(x):
    assert x >= 0, 'TODO: signed'
    ret = []
    while 1:
      byte = x & 127
      x >>= 7
      more = x != 0
      if more:
        byte = byte | 128
      ret.append(byte)
      if not more:
        break
    return bytearray(ret)

  @staticmethod
  def delebify(buf, offset):
    result = 0
    shift = 0
    while True:
      byte = bytearray(buf[offset:offset + 1])[0]
      offset += 1
      result |= (byte & 0x7f) << shift
      if not (byte & 0x80):
        break
      shift += 7
    return (result, offset)

  @staticmethod
  def add_emscripten_metadata(js_file, wasm_file):
    WASM_PAGE_SIZE = 65536

    mem_size = Settings.TOTAL_MEMORY // WASM_PAGE_SIZE
    table_size = Settings.WASM_TABLE_SIZE
    global_base = Settings.GLOBAL_BASE

    js = open(js_file).read()
    if Settings.WASM_BACKEND:
      tempdouble_ptr = 0
    else:
      m = re.search(r"(^|\s)tempDoublePtr\s+=\s+(\d+)", js)
      tempdouble_ptr = int(m.group(2))
    m = re.search(r"(^|\s)DYNAMIC_BASE\s+=\s+(\d+)", js)
    dynamic_base = int(m.group(2))
    m = re.search(r"(^|\s)DYNAMICTOP_PTR\s+=\s+(\d+)", js)
    dynamictop_ptr = int(m.group(2))

    logger.debug('creating wasm emscripten metadata section with mem size %d, table size %d' % (mem_size, table_size,))
    name = b'\x13emscripten_metadata' # section name, including prefixed size
    contents = (
      # metadata section version
      WebAssembly.lebify(EMSCRIPTEN_METADATA_MAJOR) +
      WebAssembly.lebify(EMSCRIPTEN_METADATA_MINOR) +

      # NB: The structure of the following should only be changed
      #     if EMSCRIPTEN_METADATA_MAJOR is incremented
      # Minimum ABI version
      WebAssembly.lebify(EMSCRIPTEN_ABI_MAJOR) +
      WebAssembly.lebify(EMSCRIPTEN_ABI_MINOR) +

      WebAssembly.lebify(int(Settings.WASM_BACKEND)) +
      WebAssembly.lebify(mem_size) +
      WebAssembly.lebify(table_size) +
      WebAssembly.lebify(global_base) +
      WebAssembly.lebify(dynamic_base) +
      WebAssembly.lebify(dynamictop_ptr) +
      WebAssembly.lebify(tempdouble_ptr)

      # NB: more data can be appended here as long as you increase
      #     the EMSCRIPTEN_METADATA_MINOR
    )

    orig = open(wasm_file, 'rb').read()
    with open(wasm_file, 'wb') as f:
      f.write(orig[0:8]) # copy magic number and version
      # write the special section
      f.write(b'\0') # user section is code 0
      # need to find the size of this section
      size = len(name) + len(contents)
      f.write(WebAssembly.lebify(size))
      f.write(name)
      f.write(contents)
      f.write(orig[8:])

  @staticmethod
  def make_shared_library(js_file, wasm_file, needed_dynlibs):
    # a wasm shared library has a special "dylink" section, see tools-conventions repo
    assert not Settings.WASM_BACKEND
    mem_align = Settings.MAX_GLOBAL_ALIGN
    mem_size = Settings.STATIC_BUMP
    table_size = Settings.WASM_TABLE_SIZE
    mem_align = int(math.log(mem_align, 2))
    logger.debug('creating wasm dynamic library with mem size %d, table size %d, align %d' % (mem_size, table_size, mem_align))

    # Write new wasm binary with 'dylink' section
    wasm = open(wasm_file, 'rb').read()
    section_name = b"\06dylink" # section name, including prefixed size
    contents = (WebAssembly.lebify(mem_size) + WebAssembly.lebify(mem_align) +
                WebAssembly.lebify(table_size) + WebAssembly.lebify(0))

    # we extend "dylink" section with information about which shared libraries
    # our shared library needs. This is similar to DT_NEEDED entries in ELF.
    #
    # In theory we could avoid doing this, since every import in wasm has
    # "module" and "name" attributes, but currently emscripten almost always
    # uses just "env" for "module". This way we have to embed information about
    # required libraries for the dynamic linker somewhere, and "dylink" section
    # seems to be the most relevant place.
    #
    # Binary format of the extension:
    #
    #   needed_dynlibs_count        varuint32       ; number of needed shared libraries
    #   needed_dynlibs_entries      dynlib_entry*   ; repeated dynamic library entries as described below
    #
    # dynlib_entry:
    #
    #   dynlib_name_len             varuint32       ; length of dynlib_name_str in bytes
    #   dynlib_name_str             bytes           ; name of a needed dynamic library: valid UTF-8 byte sequence
    #
    # a proposal has been filed to include the extension into "dylink" specification:
    # https://github.com/WebAssembly/tool-conventions/pull/77
    contents += WebAssembly.lebify(len(needed_dynlibs))
    for dyn_needed in needed_dynlibs:
      dyn_needed = bytes(asbytes(dyn_needed))
      contents += WebAssembly.lebify(len(dyn_needed))
      contents += dyn_needed

    section_size = len(section_name) + len(contents)
    wso = js_file + '.wso'
    with open(wso, 'wb') as f:
      # copy magic number and version
      f.write(wasm[0:8])
      # write the special section
      f.write(b'\0') # user section is code 0
      f.write(WebAssembly.lebify(section_size))
      f.write(section_name)
      f.write(contents)
      # copy rest of binary
      f.write(wasm[8:])
    return wso


# Python 2-3 compatibility helper function:
# Converts a string to the native str type.
def asstr(s):
  if str is bytes:
    if isinstance(s, type(u'')):
      return s.encode('utf-8')
  elif isinstance(s, bytes):
    return s.decode('utf-8')
  return s


def asbytes(s):
  if isinstance(s, bytes):
    # Do not attempt to encode bytes
    return s
  return s.encode('utf-8')


def unsuffixed(name):
  """Return the filename without the extention.

  If there are multiple extensions this strips only the final one.
  """
  return os.path.splitext(name)[0]


def unsuffixed_basename(name):
  return os.path.basename(unsuffixed(name))


def safe_move(src, dst):
  src = os.path.abspath(src)
  dst = os.path.abspath(dst)
  if os.path.isdir(dst):
    dst = os.path.join(dst, os.path.basename(src))
  if src == dst:
    return
  if dst == '/dev/null':
    return
  logging.debug('move: %s -> %s', src, dst)
  shutil.move(src, dst)


def safe_copy(src, dst):
  src = os.path.abspath(src)
  dst = os.path.abspath(dst)
  if os.path.isdir(dst):
    dst = os.path.join(dst, os.path.basename(src))
  if src == dst:
    return
  if dst == '/dev/null':
    return
  shutil.copyfile(src, dst)


def read_and_preprocess(filename, expand_macros=False):
  temp_dir = get_emscripten_temp_dir()
  # Create a settings file with the current settings to pass to the JS preprocessor
  # Note: Settings.serialize returns an array of -s options i.e. ['-s', '<setting1>', '-s', '<setting2>', ...]
  #       we only want the actual settings, hence the [1::2] slice operation.
  settings_str = "var " + ";\nvar ".join(Settings.serialize()[1::2])
  settings_file = os.path.join(temp_dir, 'settings.js')
  open(settings_file, 'w').write(settings_str)

  # Run the JS preprocessor
  # N.B. We can't use the default stdout=PIPE here as it only allows 64K of output before it hangs
  # and shell.html is bigger than that!
  # See https://thraxil.org/users/anders/posts/2008/03/13/Subprocess-Hanging-PIPE-is-your-enemy/
  (path, file) = os.path.split(filename)
  if not path:
    path = None
  stdout = os.path.join(temp_dir, 'stdout')
  args = [settings_file, file]
  if expand_macros:
    args += ['--expandMacros']

  run_js(path_from_root('tools/preprocessor.js'), NODE_JS, args, True, stdout=open(stdout, 'w'), cwd=path)
  out = open(stdout, 'r').read()

  return out


# Generates a suitable fetch-worker.js script from the given input source JS file (which is an asm.js build output),
# and writes it out to location output_file. fetch-worker.js is the root entry point for a dedicated filesystem web
# worker in -s ASMFS=1 mode.
def make_fetch_worker(source_file, output_file):
  src = open(source_file, 'r').read()
  funcs_to_import = ['alignUp', '_emscripten_get_heap_size', '_emscripten_resize_heap', 'stringToUTF8', 'UTF8ToString', 'UTF8ArrayToString', 'intArrayFromString', 'lengthBytesUTF8', 'stringToUTF8Array', '_emscripten_is_main_runtime_thread', '_emscripten_futex_wait']
  asm_funcs_to_import = ['_malloc', '_free', '_sbrk', '___pthread_mutex_lock', '___pthread_mutex_unlock', '_pthread_mutexattr_init', '_pthread_mutex_init']
  function_prologue = '''this.onerror = function(e) {
  console.error(e);
}

'''
  asm_start = src.find('// EMSCRIPTEN_START_ASM')
  for func in funcs_to_import + asm_funcs_to_import:
    loc = src.find('function ' + func + '(', asm_start if func in asm_funcs_to_import else 0)
    if loc == -1:
      exit_with_error('failed to find function %s!', func)
    end_loc = src.find('{', loc) + 1
    nesting_level = 1
    while nesting_level > 0:
      if src[end_loc] == '{':
        nesting_level += 1
      if src[end_loc] == '}':
        nesting_level -= 1
      end_loc += 1

    func_code = src[loc:end_loc]
    function_prologue = function_prologue + '\n' + func_code

  fetch_worker_src = function_prologue + '\n' + read_and_preprocess(path_from_root('src', 'fetch-worker.js'), expand_macros=True)
  open(output_file, 'w').write(fetch_worker_src)
