Skip to content

Instantly share code, notes, and snippets.

@evanw
Created November 26, 2014 06:11
Show Gist options
  • Save evanw/e5aa506a31a5dfbd807e to your computer and use it in GitHub Desktop.
Save evanw/e5aa506a31a5dfbd807e to your computer and use it in GitHub Desktop.
# This is a simple wrapper for the "emcc" command from the emscripten compiler.
# Unlike the emscripten SDK script, it lets you specify the compiler version
# number. Just pass the version number using the "--version" flag and put the
# flags for "emcc" after the "--":
#
# python emcc_wrapper.py --version 1.27.0 -- -O3 -s NO_EXIT_RUNTIME=1 ...
#
import os
import sys
import pipes
import urllib2
import hashlib
import subprocess
import argparse
cache_folder = os.path.expanduser('~/.emcc_wrapper')
def run(command, **kwargs):
print ' '.join(map(pipes.quote, command))
subprocess.check_call(command, **kwargs)
def mkdir(path):
try:
os.makedirs(path)
except:
pass
def fetch(url):
print 'fetching', url
request = urllib2.urlopen(url)
content = ''
while True:
chunk = request.read(128 * 1024)
if not chunk:
sys.stdout.write('\n')
return content
content += chunk
sys.stdout.write('\r%.1f mb' % (float(len(content)) / (1024 * 1024)))
sys.stdout.flush()
def extract(file, folder):
print 'extracting to', folder
mkdir(folder)
run(['unzip', file, '-d', folder])
def download(url):
path = os.path.join(cache_folder, 'downloads', hashlib.md5(url).hexdigest())
if not os.path.exists(path):
content = fetch(url)
mkdir(os.path.dirname(path))
open(path, 'w').write(content)
return path
def download_github_release(repo, version, path):
url = 'https://github.com/kripken/%s/archive/%s.zip' % (repo, version)
path = os.path.join(cache_folder, version, path)
if not os.path.exists(path):
temp = path + '-temp'
extract(download(url), temp)
nested = os.path.join(temp, '%s-%s' % (repo, version))
if os.path.exists(nested):
os.rename(nested, path)
os.rmdir(temp)
else:
os.rename(temp, path)
return path
def build_llvm(source, version):
target = os.path.join(os.path.dirname(source), 'llvm-build')
if not os.path.exists(target):
mkdir(target)
flags = [
# These are from http://kripken.github.io/emscripten-site/docs/building_from_source/building_fastcomp_manually_from_source.html
'-DCMAKE_BUILD_TYPE=Release',
'-DLLVM_TARGETS_TO_BUILD=X86;JSBackend',
'-DLLVM_INCLUDE_EXAMPLES=OFF',
'-DLLVM_INCLUDE_TESTS=OFF',
'-DCLANG_INCLUDE_EXAMPLES=OFF',
'-DCLANG_INCLUDE_TESTS=OFF',
]
run(['cmake', source] + flags, cwd=target)
run(['make', '-j4'], cwd=target)
return os.path.join(target, 'bin')
def main():
parser = argparse.ArgumentParser()
parser.add_argument('arguments', metavar='ARGUMENT', nargs='*', help='arguments for the real emcc')
parser.add_argument('--version', required=True, help='the emscripten SDK version')
parser.add_argument('--python', default='python', help='the python binary to use')
options = parser.parse_args()
emscripten_path = download_github_release('emscripten', options.version, 'emscripten')
llvm_path = download_github_release('emscripten-fastcomp', options.version, 'emscripten-fastcomp')
clang_path = download_github_release('emscripten-fastcomp-clang', options.version, os.path.join('emscripten-fastcomp', 'tools', 'clang'))
bin_path = build_llvm(llvm_path, options.version)
config = [
('EMSCRIPTEN_ROOT', emscripten_path),
('LLVM_ROOT', bin_path),
('NODE_JS', 'node'),
('COMPILER_ENGINE', 'node'),
('JS_ENGINES', ['node']),
]
command = [options.python, os.path.join(emscripten_path, 'emcc')]
command += ['--em-config', ';'.join('%s=%s' % (name, repr(value)) for name, value in config)]
command += options.arguments
run(command)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment