2013-09-05 16:42:27 +03:00
#!/usr/bin/env python
2015-03-31 15:44:34 +02:00
from __future__ import print_function
import sys, optparse, subprocess, os, os.path, errno, zipfile, string, json, platform, shutil, tarfile, tempfile, multiprocessing
if sys.version_info >= (3,):
from urllib.parse import urljoin
from urllib.request import urlopen
from urllib.error import HTTPError
else:
from urlparse import urljoin
from urllib2 import urlopen, HTTPError
2013-09-05 16:42:27 +03:00
2013-09-05 16:54:15 +03:00
# EMSDK_DEV is a developer mode flag, which, if true, the SDK is downloaded from a 'staging' online source,
# instead of the public source. New releases are first deployed to the staging source for testing, before
# being published to the public. Don't enable this unless you develop EMSDK itself and need to access the
# staging source repository instead.
2013-09-05 16:42:27 +03:00
EMSDK_DEV = bool(os.getenv('EMSDK_DEV')) if os.getenv('EMSDK_DEV') != None else False
2013-09-05 16:54:15 +03:00
2014-07-03 13:43:37 +03:00
if EMSDK_DEV:
2015-03-31 15:44:34 +02:00
print('EMSDK_DEV active.')
2013-09-05 16:42:27 +03:00
emsdk_master_server = 'http://clb.demon.fi/emscripten_dev/'
else:
2013-09-30 13:40:08 +03:00
emsdk_master_server = 'https://s3.amazonaws.com/mozilla-games/emscripten/'
2013-09-30 14:02:58 +03:00
2015-03-31 15:44:34 +02:00
emsdk_packages_url = urljoin(emsdk_master_server, 'packages/')
2013-09-30 14:02:58 +03:00
2013-09-05 16:42:27 +03:00
emscripten_git_repo = 'git@github.com:kripken/emscripten.git'
WINDOWS = False
if os.name == 'nt':
WINDOWS = True
ENVPATH_SEPARATOR = ';'
LINUX = False
if platform.system() == 'Linux':
LINUX = True
ENVPATH_SEPARATOR = ':'
OSX = False
if platform.mac_ver()[0] != '':
OSX = True
ENVPATH_SEPARATOR = ':'
2015-01-23 16:21:21 +02:00
emscripten_config_directory = os.path.expanduser("~/")
2014-11-18 15:24:32 +02:00
EMSDK_SET_ENV = 'emsdk_set_env.bat' if WINDOWS else 'emsdk_set_env.sh'
2015-01-12 17:58:16 +02:00
CMAKE_GENERATOR = 'Unix Makefiles'
if WINDOWS:
build_with_visualstudio = True
if build_with_visualstudio:
CMAKE_GENERATOR = 'Visual Studio 12'
else:
CMAKE_GENERATOR += 'MinGW Makefiles'
2014-04-24 00:57:59 +03:00
def win_get_environment_variable(key, system=True):
2014-07-03 17:56:57 +03:00
prev_path = os.environ['PATH']
2014-04-24 00:57:59 +03:00
try:
2014-07-03 17:56:57 +03:00
py = find_used_python()
if py:
py_path = to_native_path(py.expand_vars(py.activated_path))
os.environ['PATH'] = os.environ['PATH'] + ';' + py_path
import win32api, win32con
2014-04-24 00:57:59 +03:00
if system: # Read globally from ALL USERS section.
folder = win32api.RegOpenKey(win32con.HKEY_LOCAL_MACHINE, 'SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment')
else: # Register locally from CURRENT USER section.
folder = win32api.RegOpenKey(win32con.HKEY_CURRENT_USER, 'Environment')
value = str(win32api.RegQueryValueEx(folder, key)[0])
2015-03-31 15:44:34 +02:00
except Exception as e:
2014-04-24 00:57:59 +03:00
if e[0] != 2: # 'The system cannot find the file specified.'
2015-03-31 15:44:34 +02:00
print('Failed to read environment variable ' + key + ':', file=sys.stderr)
print(str(e), file=sys.stderr)
2014-04-24 00:57:59 +03:00
win32api.RegCloseKey(folder)
2014-07-03 17:56:57 +03:00
os.environ['PATH'] = prev_path
2014-04-24 00:57:59 +03:00
return None
win32api.RegCloseKey(folder)
2014-07-03 17:56:57 +03:00
os.environ['PATH'] = prev_path
2014-04-24 00:57:59 +03:00
return value
def win_environment_variable_exists(key, system=True):
value = win_get_environment_variable(key, system)
return value != None and len(value) > 0
def win_get_active_environment_variable(key):
value = win_get_environment_variable(key, False)
if value != None:
return value
return win_get_environment_variable(key, True)
def win_set_environment_variable(key, value, system=True):
2014-04-24 13:10:04 +03:00
# print >> sys.stderr, 'set ' + str(key) + '=' + str(value) + ', in system=' + str(system)
2014-04-24 00:57:59 +03:00
previous_value = win_get_environment_variable(key, system)
if previous_value == value:
return # No need to elevate UAC for nothing to set the same value, skip.
if not value:
try:
if system:
value = subprocess.call(['REG', 'DELETE', 'SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment', '/V', key, '/f'], stdout=subprocess.PIPE)
else:
value = subprocess.call(['REG', 'DELETE', 'HKCU\\Environment', '/V', key, '/f'], stdout=subprocess.PIPE)
2015-03-31 15:44:34 +02:00
except Exception as e:
2014-04-24 00:57:59 +03:00
return
return
try:
if system:
cmd = ['bin/elevate.exe', 'SETX', '/M']
else:
cmd = ['SETX']
retcode = subprocess.call(cmd + [key, value], stdout=subprocess.PIPE)
if retcode is not 0:
2015-03-31 15:44:34 +02:00
print('ERROR! Failed to set environment variable ' + key + '=' + value + '. You may need to set it manually.', file=sys.stderr)
except Exception as e:
print('ERROR! Failed to set environment variable ' + key + '=' + value + ':', file=sys.stderr)
print(str(e), file=sys.stderr)
print('You may need to set it manually.', file=sys.stderr)
2014-04-24 00:57:59 +03:00
def win_delete_environment_variable(key, system=True):
win_set_environment_variable(key, None, system)
2013-09-05 16:42:27 +03:00
# Returns the absolute pathname to the given path inside the Emscripten SDK.
2013-11-13 19:25:57 +02:00
def sdk_path(path):
if os.path.isabs(path):
return path
else:
return to_unix_path(os.path.join(os.path.dirname(os.path.realpath(__file__)), path))
2013-09-05 16:42:27 +03:00
def emsdk_path(): return to_unix_path(os.path.dirname(os.path.realpath(__file__)))
2013-09-05 19:15:32 +03:00
# Modifies the given file in-place to contain '\r\n' line endings.
def file_to_crlf(filename):
text = open(filename, 'r').read()
text = text.replace('\r\n', '\n').replace('\n', '\r\n')
2013-09-05 19:29:34 +03:00
open(filename, 'wb').write(text)
2013-09-05 19:15:32 +03:00
# Modifies the given file in-place to contain '\n' line endings.
def file_to_lf(filename):
text = open(filename, 'r').read()
text = text.replace('\r\n', '\n')
2013-09-05 19:29:34 +03:00
open(filename, 'wb').write(text)
2013-09-05 19:15:32 +03:00
2013-10-28 13:14:21 +02:00
# Removes a single file, suppressing exceptions on failure.
def rmfile(filename):
try:
os.remove(filename)
except:
pass
2013-09-05 19:15:32 +03:00
def fix_lineendings(filename):
if WINDOWS:
file_to_crlf(filename)
else:
file_to_lf(filename)
2013-09-05 16:42:27 +03:00
# http://stackoverflow.com/questions/600268/mkdir-p-functionality-in-python
def mkdir_p(path):
if os.path.exists(path):
return
try:
os.makedirs(path)
except OSError as exc: # Python >2.5
if exc.errno == errno.EEXIST and os.path.isdir(path):
pass
else: raise
def num_files_in_directory(path):
if not os.path.isdir(path):
return 0
return len([name for name in os.listdir(path) if os.path.exists(os.path.join(path, name))])
def run(cmd, cwd=None):
process = subprocess.Popen(cmd, cwd=cwd, env=os.environ.copy())
process.communicate()
if process.returncode != 0:
2015-03-31 15:44:34 +02:00
print(str(cmd) + ' failed with error code ' + str(process.returncode) + '!')
2013-09-05 16:42:27 +03:00
return process.returncode
# http://pythonicprose.blogspot.fi/2009/10/python-extract-targz-archive.html
2013-09-30 14:16:46 +03:00
def untargz(source_filename, dest_dir, unpack_even_if_exists=False):
if not unpack_even_if_exists and num_files_in_directory(dest_dir) > 0:
2015-03-31 15:44:34 +02:00
print("File '" + source_filename + "' has already been unpacked, skipping.")
2013-09-05 16:42:27 +03:00
return True
2015-03-31 15:44:34 +02:00
print("Unpacking '" + source_filename + "' to '" + dest_dir + "'")
2013-09-05 16:42:27 +03:00
mkdir_p(dest_dir)
run(['tar', '-xvf', sdk_path(source_filename), '--strip', '1'], cwd=dest_dir)
#tfile = tarfile.open(source_filename, 'r:gz')
#tfile.extractall(dest_dir)
return True
# http://stackoverflow.com/questions/12886768/simple-way-to-unzip-file-in-python-on-all-oses
2013-09-30 14:27:20 +03:00
def unzip(source_filename, dest_dir, unpack_even_if_exists=False):
2013-09-30 14:16:46 +03:00
if not unpack_even_if_exists and num_files_in_directory(dest_dir) > 0:
2015-03-31 15:44:34 +02:00
print("File '" + source_filename + "' has already been unpacked, skipping.")
2013-09-05 16:42:27 +03:00
return True
2015-03-31 15:44:34 +02:00
print("Unpacking '" + source_filename + "' to '" + dest_dir + "'")
2013-09-05 16:42:27 +03:00
mkdir_p(dest_dir)
2013-10-28 17:49:40 +02:00
common_subdir = None
2013-11-19 15:26:45 +02:00
try:
with zipfile.ZipFile(source_filename) as zf:
# Implement '--strip 1' behavior to unzipping by testing if all the files in the zip reside in a common subdirectory, and if so,
# we move the output tree at the end of uncompression step.
for member in zf.infolist():
words = member.filename.split('/')
if len(words) > 1: # If there is a directory component?
if common_subdir == None:
common_subdir = words[0]
elif common_subdir != words[0]:
common_subdir = ''
break
unzip_to_dir = dest_dir
if common_subdir:
unzip_to_dir = os.path.join('/'.join(dest_dir.split('/')[:-1]), 'unzip_temp')
# Now do the actual decompress.
for member in zf.infolist():
# Path traversal defense copied from
# http://hg.python.org/cpython/file/tip/Lib/http/server.py#l789
words = member.filename.split('/')
path = unzip_to_dir
for word in words[:-1]:
drive, word = os.path.splitdrive(word)
head, word = os.path.split(word)
if word in (os.curdir, os.pardir, ''): continue
path = os.path.join(path, word)
zf.extract(member, unzip_to_dir)
if common_subdir:
try:
if os.path.exists(dest_dir):
shutil.rmtree(dest_dir)
except:
pass
shutil.copytree(os.path.join(unzip_to_dir, common_subdir), dest_dir)
try:
shutil.rmtree(unzip_to_dir)
except:
pass
2015-03-31 15:44:34 +02:00
except zipfile.BadZipfile as e:
print("Unzipping file '" + source_filename + "' failed due to reason: " + str(e) + "! Removing the corrupted zip file.")
2013-11-19 15:26:45 +02:00
rmfile(source_filename)
return False
2015-03-31 15:44:34 +02:00
except Exception as e:
print("Unzipping file '" + source_filename + "' failed due to reason: " + str(e))
2013-11-19 15:26:45 +02:00
return False
2013-10-28 17:49:40 +02:00
2013-09-05 16:42:27 +03:00
return True
# This function interprets whether the given string looks like a path to a directory instead of a file, without looking at the actual filesystem.
# 'a/b/c' points to directory, so does 'a/b/c/', but 'a/b/c.x' is parsed as a filename
def path_points_to_directory(path):
if path == '.':
return True
last_slash = max(path.rfind('/'), path.rfind('\\'))
last_dot = path.rfind('.')
no_suffix = last_dot < last_slash or last_dot == -1
if no_suffix:
return True
suffix = path[last_dot:]
if suffix == '.exe' or suffix == '.zip': # Very simple logic for the only file suffixes used by emsdk downloader. Other suffixes, like 'clang-3.2' are treated as dirs.
return False
else:
return True
2013-09-30 14:27:20 +03:00
# On success, returns the filename on the disk pointing to the destination file that was produced
# On failure, returns None.
2013-09-05 16:42:27 +03:00
def download_file(url, dstpath, download_even_if_exists=False):
file_name = url.split('/')[-1]
if path_points_to_directory(dstpath):
file_name = os.path.join(dstpath, file_name)
else:
file_name = dstpath
2013-09-30 14:27:20 +03:00
2013-11-13 19:25:57 +02:00
# Treat all relative destination paths as relative to the SDK root directory, not the current working directory.
file_name = sdk_path(file_name)
2013-09-05 16:42:27 +03:00
if os.path.exists(file_name) and not download_even_if_exists:
2015-03-31 15:44:34 +02:00
print("File '" + file_name + "' already downloaded, skipping.")
2013-09-30 14:27:20 +03:00
return file_name
2013-09-05 16:52:01 +03:00
try:
2015-03-31 15:44:34 +02:00
u = urlopen(url)
2013-09-05 16:52:01 +03:00
mkdir_p(os.path.dirname(file_name))
2013-11-19 15:26:45 +02:00
with open(file_name, 'wb') as f:
meta = u.info()
file_size = int(meta.getheaders("Content-Length")[0])
2015-03-31 15:44:34 +02:00
print("Downloading: %s from %s Bytes: %s" % (file_name, url, file_size))
2013-11-19 15:26:45 +02:00
file_size_dl = 0
block_sz = 8192
while True:
buffer = u.read(block_sz)
if not buffer:
break
file_size_dl += len(buffer)
f.write(buffer)
status = r"%10d [%3.2f%%]" % (file_size_dl, file_size_dl * 100. / file_size)
status = status + chr(8)*(len(status)+1)
2015-03-31 15:44:34 +02:00
print(status, end=' ')
except HTTPError as e:
print("HTTP error with URL '" + url + "': " + str(e))
2013-11-19 15:26:45 +02:00
rmfile(file_name)
return None
2015-03-31 15:44:34 +02:00
except Exception as e:
print("Error downloading URL '" + url + "': " + str(e))
2013-11-19 15:26:45 +02:00
rmfile(file_name)
2013-09-30 14:27:20 +03:00
return None
return file_name
2013-09-05 16:42:27 +03:00
2013-09-05 19:15:32 +03:00
def download_text_file(url, dstpath, download_even_if_exists=False):
2013-09-30 14:27:20 +03:00
filename = download_file(url, dstpath, download_even_if_exists)
fix_lineendings(os.path.join(emsdk_path(), filename))
2013-09-05 19:15:32 +03:00
2013-09-05 16:42:27 +03:00
def run_get_output(cmd, cwd=None):
2015-03-31 16:40:12 +02:00
process = subprocess.Popen(cmd, cwd=cwd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, env=os.environ.copy(), universal_newlines=True)
2013-09-05 16:42:27 +03:00
(stdout, stderr) = process.communicate()
return (process.returncode, stdout, stderr)
2014-07-28 20:22:48 +03:00
# Finds the given executable 'program' in PATH. Operates like the Unix tool 'which'.
def which(program):
def is_exe(fpath):
return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
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 and not '.' in fname:
if is_exe(exe_file + '.exe'):
return exe_file + '.exe'
if is_exe(exe_file + '.cmd'):
return exe_file + '.cmd'
if is_exe(exe_file + '.bat'):
return exe_file + '.bat'
return None
2014-09-07 05:43:14 -04:00
# must_succeed: If false, the search is performed silently without printing out errors if not found. Empty string is returned if git is not found.
# If true, the search is required to succeed, and the execution will terminate with sys.exit(1) if not found.
def GIT(must_succeed=True):
# The order in the following is important, and specifies the preferred order of using the git tools.
# Primarily use git from emsdk if installed. If not, use system git.
gits = ['git/1.9.4/bin/git.exe', which('git')]
for git in gits:
try:
(ret, stdout, stderr) = run_get_output([git, '--version'])
if ret == 0:
return git
except:
pass
if must_succeed:
2013-09-05 16:42:27 +03:00
if WINDOWS:
2015-03-31 15:44:34 +02:00
print("ERROR: git executable was not found. Please install it by typing 'emsdk install git-1.9.4', or alternatively by installing it manually from http://git-scm.com/downloads . If you install git manually, remember to add it to PATH")
2014-09-07 05:43:14 -04:00
elif OSX:
2015-03-31 15:44:34 +02:00
print("ERROR: git executable was not found. Please install git for this operation! This can be done from http://git-scm.com/ , or by installing XCode and then the XCode Command Line Tools (see http://stackoverflow.com/questions/9329243/xcode-4-4-command-line-tools )")
2014-09-07 05:43:14 -04:00
elif LINUX:
2015-03-31 15:44:34 +02:00
print("ERROR: git executable was not found. Please install git for this operation! This can be probably be done using your package manager, see http://git-scm.com/book/en/Getting-Started-Installing-Git")
2014-09-07 05:43:14 -04:00
else:
2015-03-31 15:44:34 +02:00
print("ERROR: git executable was not found. Please install git for this operation!")
2013-09-05 16:42:27 +03:00
sys.exit(1)
2014-09-07 05:43:14 -04:00
return '' # Not found
2013-09-05 16:42:27 +03:00
def git_repo_version(repo_path):
(returncode, stdout, stderr) = run_get_output([GIT(), 'log', '-n', '1', '--pretty="%aD %H"'], cwd=repo_path)
if returncode == 0:
return stdout.strip()
else:
return ""
def git_clone(url, dstpath):
if os.path.isdir(os.path.join(dstpath, '.git')):
2015-03-31 15:44:34 +02:00
print("Repository '" + url + "' already cloned to directory '" + dstpath + "', skipping.")
2013-09-05 16:42:27 +03:00
return True
mkdir_p(dstpath)
return run([GIT(), 'clone', url, dstpath]) == 0
def git_checkout_and_pull(repo_path, branch):
run([GIT(), 'fetch', 'origin'], repo_path)
try:
2015-03-31 15:44:34 +02:00
print("Fetching latest changes to the branch '" + branch + "' for '" + repo_path + "'...")
2013-09-05 16:42:27 +03:00
run([GIT(), 'fetch', 'origin'], repo_path)
# run([GIT, 'checkout', '-b', branch, '--track', 'origin/'+branch], repo_path)
run([GIT(), 'checkout', '--quiet', branch], repo_path) # this line assumes that the user has not gone and manually messed with the repo and added new remotes to ambiguate the checkout.
run([GIT(), 'merge', '--ff-only', 'origin/'+branch], repo_path) # this line assumes that the user has not gone and made local changes to the repo
except:
2015-03-31 15:44:34 +02:00
print('git operation failed!')
2013-09-05 16:42:27 +03:00
return False
2015-03-31 15:44:34 +02:00
print("Successfully updated and checked out branch '" + branch + "' on repository '" + repo_path + "'")
print("Current repository version: " + git_repo_version(repo_path))
2013-09-05 16:42:27 +03:00
return True
def git_clone_checkout_and_pull(url, dstpath, branch):
success = git_clone(url, dstpath)
if not success:
return False
success = git_checkout_and_pull(dstpath, branch)
return success
2014-07-03 23:38:51 +03:00
# The root directory of the build.
def fastcomp_build_dir(tool):
2015-01-12 17:58:16 +02:00
generator_suffix = ''
if CMAKE_GENERATOR == 'Visual Studio 10': generator_suffix = '_vs2010'
elif CMAKE_GENERATOR == 'Visual Studio 11': generator_suffix = '_vs2012'
elif CMAKE_GENERATOR == 'Visual Studio 12': generator_suffix = '_vs2013'
elif CMAKE_GENERATOR == 'MinGW Makefiles': generator_suffix = '_mingw'
2014-07-03 23:38:51 +03:00
2015-01-12 17:58:16 +02:00
bitness_suffix = '_32' if tool.bitness == 32 else '_64'
build_dir = 'build_' + tool.git_branch + generator_suffix + bitness_suffix
2014-07-03 23:38:51 +03:00
return build_dir
# The directory where the binaries are produced.
def fastcomp_build_bin_dir(tool):
build_dir = fastcomp_build_dir(tool)
2015-01-12 17:58:16 +02:00
if WINDOWS and 'Visual Studio' in CMAKE_GENERATOR:
2015-01-13 13:33:13 +02:00
old_llvm_bin_dir = os.path.join(build_dir, 'bin\\RelWithDebInfo')
new_llvm_bin_dir = os.path.join(build_dir, 'RelWithDebInfo\\bin')
if os.path.exists(os.path.join(tool.install_path, new_llvm_bin_dir)):
return new_llvm_bin_dir
if os.path.exists(os.path.join(tool.install_path, old_llvm_bin_dir)): return old_llvm_bin_dir
return new_llvm_bin_dir
2014-07-03 23:38:51 +03:00
else:
return os.path.join(build_dir, 'bin')
2014-12-19 17:57:01 -05:00
make_env = os.environ.copy()
def find_msbuild(sln_file):
search_paths_vs2013 = [os.path.join(os.environ['ProgramFiles'], 'MSBuild/12.0/Bin/amd64'),
os.path.join(os.environ['ProgramFiles(x86)'], 'MSBuild/12.0/Bin/amd64'),
os.path.join(os.environ['ProgramFiles'], 'MSBuild/12.0/Bin'),
os.path.join(os.environ['ProgramFiles(x86)'], 'MSBuild/12.0/Bin'),]
search_paths_old = [os.path.join(os.environ["WINDIR"], 'Microsoft.NET/Framework/v4.0.30319')]
contents = open(sln_file, 'r').read()
if '# Visual Studio Express 2013' in contents or '# Visual Studio 2013' in contents:
search_paths = search_paths_vs2013 + search_paths_old
make_env['VCTargetsPath'] = os.path.join(os.environ['ProgramFiles(x86)'], 'MSBuild/Microsoft.Cpp/v4.0/V120')
else:
search_paths = search_paths_old + search_paths_vs2013
for path in search_paths:
p = os.path.join(path, 'MSBuild.exe')
if os.path.isfile(p): return p
def make_build(build_root, build_type):
2014-07-08 11:07:19 +03:00
cpu_cores = max(multiprocessing.cpu_count()-1, 1) # Don't saturate all cores to not steal the whole system, but be aggressive.
if cpu_cores > 1:
2015-03-31 15:44:34 +02:00
print('Performing a parallel build with ' + str(cpu_cores) + ' cores.')
2014-07-08 11:07:19 +03:00
else:
2015-03-31 15:44:34 +02:00
print('Performing a singlethreaded build.')
2014-07-03 23:38:51 +03:00
if WINDOWS:
2015-01-12 17:58:16 +02:00
if 'Visual Studio' in CMAKE_GENERATOR:
2014-12-19 17:57:01 -05:00
solution_name = subprocess.check_output(['dir', '/b', '*.sln'], shell=True, cwd=build_root).strip()
make = [find_msbuild(os.path.join(build_root, solution_name)), '/maxcpucount:' + str(cpu_cores), '/t:Build', '/p:Configuration='+build_type, '/nologo', '/verbosity:minimal', solution_name]
2014-07-03 23:38:51 +03:00
else:
2014-07-20 04:57:41 -04:00
make = ['mingw32-make', '-j' + str(cpu_cores)]
2014-07-03 23:38:51 +03:00
else:
2014-07-20 04:57:41 -04:00
make = ['make', '-j' + str(cpu_cores)]
2014-07-03 23:38:51 +03:00
2014-12-19 17:16:19 -05:00
# Build
2014-07-03 23:38:51 +03:00
try:
2015-03-31 15:44:34 +02:00
print('Running build: ' + str(make))
2014-12-19 17:57:01 -05:00
ret = subprocess.check_call(make, cwd=build_root, env=make_env)
2014-07-03 23:38:51 +03:00
if ret != 0:
2015-03-31 15:44:34 +02:00
print('Build failed with exit code ' + ret + '!', file=sys.stderr)
print('Working directory: ' + build_root, file=sys.stderr)
2014-07-03 23:38:51 +03:00
return False
2015-03-31 15:44:34 +02:00
except Exception as e:
print('Build failed due to exception!', file=sys.stderr)
print('Working directory: ' + build_root, file=sys.stderr)
print(str(e), file=sys.stderr)
2014-07-03 23:38:51 +03:00
return False
2014-12-19 17:16:19 -05:00
return True
2014-12-19 17:57:01 -05:00
def cmake_configure(generator, build_root, src_root, build_type, extra_cmake_args = []):
2014-12-19 17:16:19 -05:00
# Configure
if not os.path.isdir(build_root): os.mkdir(build_root) # Create build output directory if it doesn't yet exist.
2014-07-03 23:38:51 +03:00
try:
2014-12-19 17:57:01 -05:00
if generator: generator = ['-G', generator]
else: generator = []
cmdline = ['cmake'] + generator + ['-DCMAKE_BUILD_TYPE='+build_type] + extra_cmake_args + [src_root]
2015-03-31 15:44:34 +02:00
print('Running CMake: ' + str(cmdline))
2014-12-19 17:16:19 -05:00
ret = subprocess.check_call(cmdline, cwd=build_root)
2014-07-03 23:38:51 +03:00
if ret != 0:
2015-03-31 15:44:34 +02:00
print('CMake invocation failed with exit code ' + ret + '!', file=sys.stderr)
print('Working directory: ' + build_root, file=sys.stderr)
2015-03-17 14:27:03 +02:00
return False
2015-03-31 15:44:34 +02:00
except OSError as e:
2015-03-17 14:27:03 +02:00
if e.errno == errno.ENOENT:
2015-03-31 15:44:34 +02:00
print(str(e), file=sys.stderr)
print('Could not run CMake, perhaps it has not been installed?', file=sys.stderr)
2015-03-17 14:27:03 +02:00
if WINDOWS:
2015-03-31 15:44:34 +02:00
print('Installing this package requires CMake. Get it from http://www.cmake.org/', file=sys.stderr)
2015-03-17 14:27:03 +02:00
elif LINUX:
2015-03-31 15:44:34 +02:00
print('Installing this package requires CMake. Get it via your system package manager (e.g. sudo apt-get install cmake), or from http://www.cmake.org/', file=sys.stderr)
2015-03-17 14:27:03 +02:00
elif OSX:
2015-03-31 15:44:34 +02:00
print('Installing this package requires CMake. Get it via a OSX package manager (Homebrew: "brew install cmake", or MacPorts: "sudo port install cmake"), or from http://www.cmake.org/', file=sys.stderr)
2014-07-03 23:38:51 +03:00
return False
2015-03-17 14:27:03 +02:00
raise
2015-03-31 15:44:34 +02:00
except Exception as e:
print('CMake invocation failed due to exception!', file=sys.stderr)
print('Working directory: ' + build_root, file=sys.stderr)
print(str(e), file=sys.stderr)
2014-07-03 23:38:51 +03:00
return False
2014-12-19 17:16:19 -05:00
2014-07-03 23:38:51 +03:00
return True
2014-12-19 17:16:19 -05:00
def build_fastcomp_tool(tool):
fastcomp_root = tool.installation_path()
fastcomp_src_root = os.path.join(fastcomp_root, 'src')
2015-03-18 14:22:48 +02:00
success = git_clone_checkout_and_pull(tool.url, fastcomp_src_root, tool.git_branch)
if not success: return False
2014-12-19 17:16:19 -05:00
clang_root = os.path.join(fastcomp_src_root, 'tools/clang')
2015-03-18 14:22:48 +02:00
success = git_clone_checkout_and_pull(tool.clang_url, clang_root, tool.git_branch)
if not success: return False
2015-01-12 17:58:16 +02:00
cmake_generator = CMAKE_GENERATOR
if 'Visual Studio' in CMAKE_GENERATOR and tool.bitness == 64:
cmake_generator += ' Win64'
2014-12-19 17:16:19 -05:00
build_dir = fastcomp_build_dir(tool)
build_root = os.path.join(fastcomp_root, build_dir)
2014-12-19 17:57:01 -05:00
build_type = tool.cmake_build_type
2014-12-19 17:16:19 -05:00
# Configure
2015-01-12 17:58:16 +02:00
success = cmake_configure(cmake_generator, build_root, fastcomp_src_root, build_type, ['-DLLVM_TARGETS_TO_BUILD=X86;JSBackend',
2014-12-19 17:16:19 -05:00
'-DLLVM_INCLUDE_EXAMPLES=OFF', '-DLLVM_INCLUDE_TESTS=OFF', '-DCLANG_INCLUDE_EXAMPLES=OFF', '-DCLANG_INCLUDE_TESTS=OFF'])
if not success: return False
2014-12-19 17:57:01 -05:00
# Make
success = make_build(build_root, build_type)
return success
def build_optimizer_tool(tool):
src_root = os.path.join(tool.installation_path(), 'tools', 'optimizer')
build_root = os.path.join(tool.installation_path(), 'tools', 'optimizer_build')
build_type = tool.cmake_build_type
# Configure
success = cmake_configure(None, build_root, src_root, build_type)
if not success: return False
# Make
success = make_build(build_root, build_type)
2014-12-19 17:16:19 -05:00
return success
2014-07-03 23:38:51 +03:00
2013-09-30 14:02:58 +03:00
def download_and_unzip(zipfile, dest_dir, download_even_if_exists=False):
if not download_even_if_exists and num_files_in_directory(dest_dir) > 0:
2015-03-31 15:44:34 +02:00
print("The contents of file '" + zipfile + "' already exist in destination '" + dest_dir + "', skipping.")
2013-09-30 14:02:58 +03:00
return True
2015-03-31 15:44:34 +02:00
dst_file = download_file(urljoin(emsdk_packages_url, zipfile), 'zips/', download_even_if_exists)
2013-09-30 14:27:20 +03:00
if not dst_file:
2013-09-05 16:42:27 +03:00
return False
if zipfile.endswith('.zip'):
2013-09-30 14:27:20 +03:00
return unzip(dst_file, dest_dir, unpack_even_if_exists=download_even_if_exists)
2013-09-05 16:42:27 +03:00
else:
2013-09-30 14:27:20 +03:00
return untargz(dst_file, dest_dir, unpack_even_if_exists=download_even_if_exists)
2013-09-05 16:42:27 +03:00
def to_unix_path(p):
return p.replace('\\', '/')
2014-07-03 15:14:45 +03:00
def to_native_path(p):
if WINDOWS:
return to_unix_path(p).replace('/', '\\')
else:
return to_unix_path(p)
2013-09-05 16:42:27 +03:00
# Finds and returns a list of the directories that need to be added to PATH for the given set of tools.
def get_required_path(active_tools):
2014-07-03 15:14:45 +03:00
path_add = [to_native_path(emsdk_path())]
2013-09-05 16:42:27 +03:00
for tool in active_tools:
if hasattr(tool, 'activated_path'):
2014-07-03 15:14:45 +03:00
path_add += [to_native_path(tool.expand_vars(tool.activated_path))]
2013-09-05 16:42:27 +03:00
return path_add
# Returns the absolute path to the file '.emscripten' for the current user on this system.
def dot_emscripten_path():
2015-01-23 16:21:21 +02:00
return os.path.join(emscripten_config_directory, ".emscripten")
2013-09-05 16:42:27 +03:00
dot_emscripten = {}
def parse_key_value(line):
if not line:
return ('', '')
eq = line.find('=')
if eq != -1:
key = line[0:eq].strip()
value = line[eq+1:].strip()
return (key, value)
else:
return (key, '')
def load_dot_emscripten():
global dot_emscripten
dot_emscripten = {}
lines = []
try:
lines = open(dot_emscripten_path(), "r").read().split('\n')
except:
pass
for line in lines:
try:
(key, value) = parse_key_value(line)
if value != '':
dot_emscripten[key] = value
# print "Got '" + key + "' = '" + value + "'"
except:
pass
2013-11-17 14:33:02 +02:00
def generate_dot_emscripten(active_tools):
2015-01-23 16:21:21 +02:00
global emscripten_config_directory
if emscripten_config_directory == emsdk_path():
temp_dir = sdk_path('.tmp')
mkdir_p(temp_dir)
else:
temp_dir = tempfile.gettempdir().replace('\\', '/')
2013-09-05 16:42:27 +03:00
cfg = 'import os\n'
2014-07-07 15:04:48 +03:00
cfg += '''SPIDERMONKEY_ENGINE = ''
NODE_JS = 'node'
'''
2013-09-05 16:42:27 +03:00
for tool in active_tools:
tool_cfg = tool.activated_config()
if tool_cfg:
2014-12-19 17:57:01 -05:00
tool_cfg = tool_cfg.replace(';', '\n')
2013-09-05 16:42:27 +03:00
cfg += tool_cfg + '\n'
2014-03-14 13:43:25 +02:00
cfg += '''V8_ENGINE = ''
2013-11-13 18:38:34 +02:00
TEMP_DIR = ''' + "'" + temp_dir + "'" + '''
2013-09-05 16:42:27 +03:00
COMPILER_ENGINE = NODE_JS
JS_ENGINES = [NODE_JS]
'''
with open(dot_emscripten_path(), "w") as text_file: text_file.write(cfg)
# Clear old cached emscripten content.
try:
2015-01-23 16:21:21 +02:00
shutil.rmtree(os.path.join(emscripten_config_directory, ".emscripten_cache"), ignore_errors=True)
os.remove(os.path.join(emscripten_config_directory, ".emscripten_sanity"))
os.remove(os.path.join(emscripten_config_directory, ".emscripten_cache__last_clear"))
2013-09-05 16:42:27 +03:00
except:
pass
2015-03-31 15:44:34 +02:00
print("The Emscripten configuration file " + os.path.normpath(dot_emscripten_path()) + " has been rewritten with the following contents:")
print('')
print(cfg.strip())
print('')
2013-09-05 16:42:27 +03:00
path_add = get_required_path(active_tools)
2014-07-03 13:43:37 +03:00
if not WINDOWS:
2014-07-07 15:08:32 +03:00
emsdk_env = os.path.relpath(sdk_path('emsdk_env.sh'))
if not '/' in emsdk_env:
emsdk_env = './emsdk_env.sh'
2015-03-31 15:44:34 +02:00
print("To conveniently access the selected set of tools from the command line, consider adding the following directories to PATH, or call 'source " + emsdk_env + "' to do this for you.")
print('')
print(' ' + ENVPATH_SEPARATOR.join(path_add))
2013-09-05 16:42:27 +03:00
2013-11-08 13:53:07 +02:00
def find_msbuild_dir():
2013-11-22 11:16:31 +02:00
if 'ProgramFiles' in os.environ and os.environ['ProgramFiles']:
program_files = os.environ['ProgramFiles']
else:
2013-11-08 13:53:07 +02:00
program_files = 'C:/Program Files'
2013-11-22 11:16:31 +02:00
if 'ProgramFiles(x86)' in os.environ and os.environ['ProgramFiles(x86)']:
program_files_x86 = os.environ['ProgramFiles(x86)']
else:
2013-11-08 13:53:07 +02:00
program_files_x86 = 'C:/Program Files (x86)'
MSBUILDX86_DIR = os.path.join(program_files_x86, "MSBuild/Microsoft.Cpp/v4.0/Platforms")
MSBUILD_DIR = os.path.join(program_files, "MSBuild/Microsoft.Cpp/v4.0/Platforms")
if os.path.exists(MSBUILDX86_DIR):
return MSBUILDX86_DIR
elif os.path.exists(MSBUILD_DIR):
return MSBUILD_DIR
else:
return '' # No MSbuild installed.
2013-09-05 16:42:27 +03:00
def get_installed_vstool_version(installed_path):
try:
return open(installed_path + "/version.txt", "r").read()
except:
return None
class Tool:
def __init__(self, data):
# Convert the dictionary representation of the tool in 'data' to members of this class for convenience.
for key in data:
2015-03-31 22:31:45 +02:00
if sys.version_info < (3,) and isinstance(data[key], unicode):
2015-01-26 11:39:36 +02:00
setattr(self, key, data[key].encode('Latin-1'))
else:
setattr(self, key, data[key])
2013-09-05 16:42:27 +03:00
def __str__(self):
s = self.id + '-' + self.version
if hasattr(self, 'bitness'):
s += '-' + str(self.bitness) + 'bit'
return s
2014-04-24 00:57:59 +03:00
def expand_vars(self, str):
if WINDOWS and '%MSBuildPlatformsDir%' in str:
str = str.replace('%MSBuildPlatformsDir%', find_msbuild_dir())
2015-01-19 09:42:00 +02:00
if '%cmake_build_type%' in str:
str = str.replace('%cmake_build_type%', (self.cmake_build_type + '/') if WINDOWS else '')
2014-04-24 00:57:59 +03:00
if '%installation_dir%' in str:
str = str.replace('%installation_dir%', sdk_path(self.installation_dir()))
str = str.replace('%.exe%', '.exe' if WINDOWS else '')
2014-07-03 23:38:51 +03:00
if '%fastcomp_build_dir%' in str:
str = str.replace('%fastcomp_build_dir%', fastcomp_build_dir(self))
if '%fastcomp_build_bin_dir%' in str:
str = str.replace('%fastcomp_build_bin_dir%', fastcomp_build_bin_dir(self))
2014-04-24 00:57:59 +03:00
return str
2013-09-05 16:42:27 +03:00
# Specifies the target path where this tool will be installed to. This could either be a directory or a filename (e.g. in case of node.js)
def installation_path(self):
if WINDOWS and hasattr(self, 'windows_install_path'):
2014-04-24 00:57:59 +03:00
pth = self.expand_vars(self.windows_install_path)
2013-11-13 19:25:57 +02:00
return sdk_path(pth)
2014-07-03 23:38:51 +03:00
if hasattr(self, 'install_path'):
pth = self.expand_vars(self.install_path)
return sdk_path(pth)
2013-09-05 16:42:27 +03:00
p = self.version
if hasattr(self, 'bitness'):
p += '_' + str(self.bitness) + 'bit'
2013-11-13 19:25:57 +02:00
return sdk_path(os.path.join(self.id, p))
2013-09-05 16:42:27 +03:00
# Specifies the target directory this tool will be installed to.
def installation_dir(self):
dir = self.installation_path()
if path_points_to_directory(dir):
return dir
else:
return os.path.dirname(dir)
# Returns the configuration item that needs to be added to .emscripten to make this Tool active for the current user.
def activated_config(self):
if hasattr(self, 'activated_cfg'):
2014-07-03 23:38:51 +03:00
return to_unix_path(self.expand_vars(self.activated_cfg))
2014-04-24 00:57:59 +03:00
else:
return ''
def activated_environment(self):
if hasattr(self, 'activated_env'):
return self.expand_vars(self.activated_env)
2013-09-05 16:42:27 +03:00
else:
return ''
def compatible_with_this_os(self):
if hasattr(self, 'os'):
2013-10-28 13:29:57 +02:00
if self.os == 'all':
return True
2013-09-05 16:42:27 +03:00
if (WINDOWS and 'win' in self.os) or (LINUX and 'linux' in self.os) or (OSX and 'osx' in self.os):
return True
else:
return False
2013-10-28 13:29:57 +02:00
else:
if not hasattr(self, 'osx_url') and not hasattr(self, 'windows_url') and not hasattr(self, 'unix_url'):
return True
2013-09-05 16:42:27 +03:00
if OSX and hasattr(self, 'osx_url'):
return True
if WINDOWS and (hasattr(self, 'windows_url') or hasattr(self, 'windows_install_path')):
return True
2014-07-07 13:52:45 +03:00
if (LINUX or OSX) and hasattr(self, 'unix_url'):
2013-09-05 16:42:27 +03:00
return True
return hasattr(self, 'url')
def is_installed(self):
# If this tool/sdk depends on other tools, require that all dependencies are installed for this tool to count as being installed.
if hasattr(self, 'uses'):
for tool_name in self.uses:
tool = find_tool(tool_name)
if tool == None:
2015-03-31 15:44:34 +02:00
print("Manifest error: No tool by name '" + tool_name + "' found! This may indicate an internal SDK error!")
2013-09-05 16:42:27 +03:00
return False
if not tool.is_installed():
return False
if self.download_url() != None:
2014-11-18 19:02:12 +02:00
# For e.g. fastcomp clang from git repo, the activated PATH is the directory where the compiler is built to, and installation_path is
# the directory where the source tree exists. To distinguish between multiple packages sharing the same source
# (clang-master-32bit, clang-master-64bit, clang-incoming-32bit and clang-incoming-64bit each share the same git repo), require
# that in addition to the installation directory, each item in the activated PATH must exist.
activated_path = self.expand_vars(self.activated_path).split(';') if hasattr(self, 'activated_path') else [self.installation_path()]
def each_path_exists(pathlist):
for path in pathlist:
if not os.path.exists(path): return False
return True
content_exists = os.path.exists(self.installation_path()) and each_path_exists(activated_path) and (os.path.isfile(self.installation_path()) or num_files_in_directory(self.installation_path()) > 0)
2013-09-05 16:42:27 +03:00
if self.id == 'vs-tool': # vs-tool is a special tool since all versions must be installed to the same dir, so dir name will not differentiate the version.
return content_exists and get_installed_vstool_version(self.installation_path()) == self.version
else:
return content_exists
else:
return True # This tool does not contain downloadable elements, so it is installed by default.
def is_active(self):
if not self.is_installed():
return False
if self.id == 'vs-tool':
return True # vs-tool is a special tool since all versions must be installed to the same dir, which means that if this tool is installed, it is also active.
# All dependencies of this tool must be active as well.
deps = self.dependencies()
for tool in deps:
if not tool.is_active():
return False
activated_cfg = self.activated_config()
if activated_cfg == '':
return len(deps) > 0
2014-04-24 00:57:59 +03:00
2014-12-19 17:57:01 -05:00
activated_cfg = activated_cfg.split(';')
for cfg in activated_cfg:
cfg = cfg.strip()
(key, value) = parse_key_value(cfg)
# print 'activated cfg ' + key + ', value: ' + value
# if dot_emscripten.has_key(key):
# print 'dot_emscripten ' + dot_emscripten[key]
2015-03-31 15:44:34 +02:00
if key in dot_emscripten and dot_emscripten[key] != value:
2014-12-19 17:57:01 -05:00
return False
return True
2013-09-05 16:42:27 +03:00
2014-07-03 14:45:49 +03:00
# Returns true if the system environment variables requires by this tool are currently active.
def is_env_active(self):
if hasattr(self, 'activated_env'):
(key, value) = parse_key_value(self.activated_environment())
2014-07-03 17:38:23 +03:00
if not key in os.environ or to_unix_path(os.environ[key]) != to_unix_path(value):
2014-07-03 14:45:49 +03:00
return False
# if WINDOWS:
# env_var = win_get_active_environment_variable(key)
# if env_var != value:
# return False
if hasattr(self, 'activated_path'):
path = self.expand_vars(self.activated_path).replace('\\', '/')
2014-07-03 17:38:23 +03:00
path = path.split(ENVPATH_SEPARATOR)
for p in path:
path_items = os.environ['PATH'].replace('\\', '/').split(ENVPATH_SEPARATOR)
if not normalized_contains(path_items, p):
return False
2014-07-03 14:45:49 +03:00
return True
2014-07-03 13:43:37 +03:00
def win_activate_env_vars(self, permanently_activate):
2014-04-24 00:57:59 +03:00
if WINDOWS and hasattr(self, 'activated_env'):
(key, value) = parse_key_value(self.activated_environment())
2014-07-03 13:43:37 +03:00
if permanently_activate:
2014-04-24 00:57:59 +03:00
win_delete_environment_variable(key, False) # If there is an env var for the LOCAL USER with same name, it will hide the system var, so must remove that first.
2014-07-03 13:43:37 +03:00
win_set_environment_variable(key, value, permanently_activate)
2014-04-24 00:57:59 +03:00
2013-09-05 16:42:27 +03:00
# If this tool can be installed on this system, this function returns True.
# Otherwise, this function returns a string that describes the reason why this tool is not available.
def can_be_installed(self):
if self.id == 'vs-tool':
2013-11-08 13:53:07 +02:00
msbuild_dir = find_msbuild_dir()
if len(msbuild_dir) > 0:
2013-09-05 16:42:27 +03:00
return True
else:
2015-02-15 19:52:54 +02:00
return "Visual Studio 2010 was not found!"
2013-09-05 16:42:27 +03:00
else:
return True
def download_url(self):
if WINDOWS and hasattr(self, 'windows_url'):
return self.windows_url
elif OSX and hasattr(self, 'osx_url'):
return self.osx_url
elif (OSX or LINUX) and hasattr(self, 'unix_url'):
return self.unix_url
elif hasattr(self, 'url'):
return self.url
else:
return None
def install(self):
if self.can_be_installed() != True:
2015-03-31 15:44:34 +02:00
print("The tool '" + str(self) + "' is not available due to the reason: " + self.can_be_installed())
2013-09-05 16:42:27 +03:00
return False
2015-03-31 15:44:34 +02:00
print("Installing '" + str(self) + "'..")
2013-09-05 16:42:27 +03:00
if self.id == 'sdk':
for tool_name in self.uses:
tool = find_tool(tool_name)
if tool == None:
2015-03-31 15:44:34 +02:00
print("Manifest error: No tool by name '" + tool_name + "' found! This may indicate an internal SDK error!")
2013-09-05 16:42:27 +03:00
success = tool.install()
if not success:
return False
2015-03-31 15:44:34 +02:00
print("Done.")
2013-10-28 13:29:57 +02:00
return True
2013-09-05 16:42:27 +03:00
else:
url = self.download_url()
2014-07-03 23:38:51 +03:00
if hasattr(self, 'custom_install_script') and self.custom_install_script == 'build_fastcomp':
success = build_fastcomp_tool(self)
elif hasattr(self, 'git_branch'):
2013-09-05 16:42:27 +03:00
success = git_clone_checkout_and_pull(url, self.installation_path(), self.git_branch)
2014-12-19 17:57:01 -05:00
if success:
if hasattr(self, 'custom_install_script') and self.custom_install_script == 'build_optimizer':
success = build_optimizer_tool(self)
2013-09-05 16:42:27 +03:00
elif url.endswith('zip') or url.endswith('.tar') or url.endswith('.gz'):
2013-11-21 15:39:04 +02:00
download_even_if_exists = (self.id == 'vs-tool')
success = download_and_unzip(url, self.installation_path(), download_even_if_exists)
2013-09-05 16:42:27 +03:00
else:
2015-03-31 15:44:34 +02:00
dst_file = download_file(urljoin(emsdk_packages_url, self.download_url()), self.installation_path())
2013-09-30 14:27:20 +03:00
if dst_file:
success = True
else:
success = False
2013-09-05 16:42:27 +03:00
if not success:
2015-03-31 15:44:34 +02:00
print("Installation failed!")
2013-09-05 16:42:27 +03:00
return False
2015-03-31 15:44:34 +02:00
print("Done.")
2013-09-05 16:42:27 +03:00
2013-10-28 13:14:21 +02:00
# Sanity check that the installation succeeded, and if so, remove unneeded leftover installation files.
if self.is_installed():
self.cleanup_temp_install_files()
else:
2015-03-31 15:44:34 +02:00
print("Warning: The installation of '" + str(self) + "' seems to have failed, but no error was detected. Either something went wrong with the installation, or this may indicate an internal emsdk error.")
2013-09-05 16:42:27 +03:00
return True
2013-10-28 13:14:21 +02:00
def cleanup_temp_install_files(self):
url = self.download_url()
if url.endswith('zip') or url.endswith('.tar') or url.endswith('.gz'):
file_name = url.split('/')[-1]
tempzipfile = os.path.join('zips/', file_name)
rmfile(tempzipfile)
2013-09-05 16:42:27 +03:00
def uninstall(self):
if not self.is_installed():
2015-03-31 15:44:34 +02:00
print("Tool '" + str(self) + "' was not installed. No need to uninstall.")
2013-09-05 16:42:27 +03:00
return
2015-03-31 15:44:34 +02:00
print("Uninstalling tool '" + str(self) + "'..")
2013-09-05 16:42:27 +03:00
try:
2015-03-31 15:44:34 +02:00
print("Deleting path '" + self.installation_path() + "'")
2013-09-05 16:42:27 +03:00
shutil.rmtree(self.installation_path(), ignore_errors=True)
os.remove(self.installation_path())
except:
pass
2015-03-31 15:44:34 +02:00
print("Done.")
2013-09-05 16:42:27 +03:00
def dependencies(self):
if not hasattr(self, 'uses'):
return []
deps = []
for tool_name in self.uses:
tool = find_tool(tool_name)
if tool:
deps += [tool]
return deps
def recursive_dependencies(self):
if not hasattr(self, 'uses'):
return []
deps = []
for tool_name in self.uses:
tool = find_tool(tool_name)
if tool:
deps += [tool]
deps += tool.recursive_dependencies()
return deps
# A global registry of all known Emscripten SDK tools available in the SDK manifest.
tools = []
# A global registry of all known SDK toolsets.
sdks = []
# N.B. In both tools and sdks list above, we take the convention that the newest items are at the back of the list (ascending chronological order)
def find_tool(name):
for tool in tools:
if str(tool) == name:
return tool
return None
def find_sdk(name):
for sdk in sdks:
if str(sdk) == name:
return sdk
return None
2013-10-15 17:48:04 +03:00
def is_os_64bit(): # http://stackoverflow.com/questions/2208828/detect-64bit-os-windows-in-python
return platform.machine().endswith('64')
def find_latest_32bit_sdk():
for sdk in reversed(sdks): # Newest SDK is always at the end of the list.
if not hasattr(sdk, 'bitness') or sdk.bitness == 32: # If no 'bitness' field, it means the SDK is universal.
return sdk
return None
def find_latest_64bit_sdk():
for sdk in reversed(sdks): # Newest SDK is always at the end of the list.
if not hasattr(sdk, 'bitness') or sdk.bitness == 64: # If no 'bitness' field, it means the SDK is universal.
return sdk
return None
2013-09-05 16:42:27 +03:00
def find_latest_sdk():
2013-10-15 17:48:04 +03:00
if is_os_64bit():
return find_latest_64bit_sdk()
else:
return find_latest_32bit_sdk()
2013-09-05 16:42:27 +03:00
2014-07-03 17:56:57 +03:00
# Finds the best-matching python tool for use.
def find_used_python():
for t in reversed(tools): # Find newest tool first - those are always at the end of the list.
if t.id == 'python' and t.is_installed() and t.is_active() and t.is_env_active():
return t
for t in reversed(tools):
if t.id == 'python' and t.is_installed() and t.is_active():
return t
for t in reversed(tools):
if t.id == 'python' and t.is_installed():
return t
return None
2013-09-05 16:42:27 +03:00
def update_emsdk():
2013-09-05 19:57:06 +03:00
if WINDOWS:
2015-03-31 15:44:34 +02:00
download_and_unzip(urljoin(emsdk_packages_url, 'emsdk_windows_update.zip'), emsdk_path(), download_even_if_exists=True)
2013-10-28 13:15:29 +02:00
rmfile('zips/emsdk_windows_update.zip')
2014-07-07 15:15:43 +03:00
elif OSX or LINUX:
2015-03-31 15:44:34 +02:00
download_and_unzip(urljoin(emsdk_packages_url, 'emsdk_unix_update.tar.gz'), emsdk_path(), download_even_if_exists=True)
2014-07-07 15:15:43 +03:00
rmfile('zips/emsdk_unix_update.tar.gz')
2013-09-05 19:57:06 +03:00
else:
2015-03-31 15:44:34 +02:00
print('Unsupported OS, cannot update!')
2013-09-30 14:02:58 +03:00
2013-09-05 16:42:27 +03:00
def load_sdk_manifest():
global tools
try:
manifest = json.loads(open(sdk_path("emsdk_manifest.json"), "r").read())
2015-03-31 15:44:34 +02:00
except Exception as e:
print('Error parsing emsdk_manifest.json!')
print(str(e))
2013-09-05 16:42:27 +03:00
return
for tool in manifest['tools']:
t = Tool(tool)
if t.compatible_with_this_os():
2014-04-24 13:10:04 +03:00
if not hasattr(t, 'is_old'):
t.is_old = False
2013-09-05 16:42:27 +03:00
tools.append(t)
for sdk_str in manifest['sdks']:
sdk = Tool(sdk_str)
sdk.id = "sdk"
if sdk.compatible_with_this_os():
2014-04-24 13:10:04 +03:00
if not hasattr(sdk, 'is_old'):
sdk.is_old = False
2013-09-05 16:42:27 +03:00
sdks.append(sdk)
2013-11-17 14:33:02 +02:00
# Tests if the two given tools can be active at the same time.
# Currently only a simple check for name for same tool with different versions,
# possibly adds more logic in the future.
def can_simultaneously_activate(tool1, tool2):
return tool1.id != tool2.id
2014-07-03 13:43:37 +03:00
def remove_nonexisting_tools(tool_list, log_errors=True):
i = 0
while i < len(tool_list):
tool = tool_list[i]
if not tool.is_installed():
if log_errors:
2015-03-31 15:44:34 +02:00
print("The SDK/tool '" + str(tool) + "' cannot be activated since it is not installed! Skipping this tool...")
2014-07-03 13:43:37 +03:00
tool_list.pop(i)
continue
i += 1
return tool_list
2014-07-03 14:09:45 +03:00
# Expands dependencies for each tool, and removes ones that don't exist.
def process_tool_list(tools_to_activate, log_errors=True):
2013-11-17 14:33:02 +02:00
i = 0
# Gather dependencies for each tool
while i < len(tools_to_activate):
tool = tools_to_activate[i]
deps = tool.recursive_dependencies()
tools_to_activate = tools_to_activate[:i] + deps + tools_to_activate[i:]
i += len(deps)+1
2014-07-03 14:09:45 +03:00
tools_to_activate = remove_nonexisting_tools(tools_to_activate, log_errors=log_errors)
2013-11-17 14:33:02 +02:00
# Remove conflicting tools
i = 0
while i < len(tools_to_activate):
j = 0
while j < i:
secondary_tool = tools_to_activate[j]
primary_tool = tools_to_activate[i]
if not can_simultaneously_activate(primary_tool, secondary_tool):
tools_to_activate.pop(j)
j -= 1
i -= 1
j += 1
i += 1
2014-07-03 14:09:45 +03:00
return tools_to_activate
# Reconfigure .emscripten to choose the currently activated toolset, set PATH and other environment variables.
# Returns the full list of deduced tools that are now active.
def set_active_tools(tools_to_activate, permanently_activate):
tools_to_activate = process_tool_list(tools_to_activate, log_errors=True)
2013-11-17 14:33:02 +02:00
generate_dot_emscripten(tools_to_activate)
2013-09-05 16:42:27 +03:00
2014-07-03 14:09:45 +03:00
# Construct a .bat script that will be invoked to set env. vars and PATH
if WINDOWS:
env_string = construct_env(tools_to_activate, False)
2014-11-18 15:24:32 +02:00
open(EMSDK_SET_ENV, 'w').write(env_string)
2014-07-03 14:09:45 +03:00
2014-04-24 13:10:04 +03:00
# Apply environment variables to global all users section.
2014-07-03 13:43:37 +03:00
if WINDOWS and permanently_activate:
2014-04-24 13:10:04 +03:00
# Individual env. vars
2014-04-24 00:57:59 +03:00
for tool in tools_to_activate:
2014-07-03 13:43:37 +03:00
tool.win_activate_env_vars(permanently_activate=True)
2014-04-24 00:57:59 +03:00
2014-04-24 13:10:04 +03:00
# PATH variable
2014-07-03 13:43:37 +03:00
newpath, added_items = adjusted_path(tools_to_activate)
if newpath != os.environ['PATH']: # Are there any actual changes?
if len(newpath) < 1024:
win_set_environment_variable('PATH', newpath, system=True)
else:
2015-03-31 15:44:34 +02:00
print('ERROR! The new PATH is more than 1024 characters long! A PATH this long cannot be set via command line: please add the PATHs specified above to system PATH manually via Control Panel.', file=sys.stderr)
2014-07-03 14:09:45 +03:00
return tools_to_activate
2014-04-24 13:10:04 +03:00
2013-09-05 16:42:27 +03:00
def currently_active_sdk():
for sdk in reversed(sdks):
if sdk.is_active():
return sdk
return None
2013-09-10 17:18:04 +03:00
def currently_active_tools():
active_tools = []
for tool in tools:
if tool.is_active():
active_tools += [tool]
return active_tools
2014-04-24 13:10:04 +03:00
# http://stackoverflow.com/questions/480214/how-do-you-remove-duplicates-from-a-list-in-python-whilst-preserving-order
def unique_items(seq):
seen = set()
seen_add = seen.add
return [ x for x in seq if x not in seen and not seen_add(x)]
2014-07-03 17:38:23 +03:00
# Tests if a path is contained in the given list, but with separators normalized.
def normalized_contains(lst, elem):
elem = to_unix_path(elem)
for e in lst:
if elem == to_unix_path(e):
return True
return False
2014-04-24 13:10:04 +03:00
# Looks at the current PATH and adds and removes entries so that the PATH reflects
# the set of given active tools.
2014-07-03 13:43:37 +03:00
def adjusted_path(tools_to_activate, log_additions=False):
2013-09-10 17:18:04 +03:00
# These directories should be added to PATH
path_add = get_required_path(tools_to_activate)
# These already exist.
2014-07-03 15:14:45 +03:00
existing_path = os.environ['PATH'].split(ENVPATH_SEPARATOR)
emsdk_root_path = to_unix_path(emsdk_path())
existing_emsdk_tools = [item for item in existing_path if to_unix_path(item).startswith(emsdk_root_path)]
new_emsdk_tools = [item for item in path_add if not normalized_contains(existing_emsdk_tools, item)]
2014-07-03 13:43:37 +03:00
# Existing non-emsdk tools
2014-07-03 15:14:45 +03:00
existing_path = [item for item in existing_path if not to_unix_path(item).startswith(emsdk_root_path)]
new_path = [item for item in path_add if not normalized_contains(existing_path, item)]
2014-07-03 13:43:37 +03:00
return (ENVPATH_SEPARATOR.join(unique_items(existing_path + new_path)), new_emsdk_tools)
2013-09-10 17:18:04 +03:00
def construct_env_windows(tools_to_activate, permanent):
2015-01-23 16:21:21 +02:00
global emscripten_config_directory
2014-04-24 13:10:04 +03:00
env_string = ''
2014-07-03 13:43:37 +03:00
newpath, added_path = adjusted_path(tools_to_activate)
2014-07-03 14:09:45 +03:00
2013-09-10 17:18:04 +03:00
# Dont permanently add to PATH, since this will break the whole system if there are more than 1024 chars in PATH.
# (SETX truncates to set only 1024 chars)
# if permanent:
# print 'SETX PATH "' + newpath + '"'
# else:
2014-07-03 13:43:37 +03:00
if os.environ['PATH'] != newpath: # Don't bother setting the path if there are no changes.
env_string += 'SET PATH=' + newpath + '\n'
if len(added_path) > 0:
2015-03-31 15:44:34 +02:00
print('Adding directories to PATH:')
2014-07-03 13:43:37 +03:00
for item in added_path:
2015-03-31 15:44:34 +02:00
print('PATH += ' + item)
print('')
2014-07-03 13:43:37 +03:00
env_vars_to_add = []
2015-01-23 16:21:21 +02:00
em_config_path = os.path.normpath(os.path.join(emscripten_config_directory, '.emscripten'))
if not 'EM_CONFIG' in os.environ or to_unix_path(os.environ['EM_CONFIG']) != to_unix_path(em_config_path):
env_vars_to_add += [('EM_CONFIG', em_config_path)]
if emscripten_config_directory == emsdk_path():
em_cache_dir = sdk_path('.emscripten_cache')
if not 'EM_CACHE' in os.environ or to_unix_path(os.environ['EM_CACHE']) != to_unix_path(em_cache_dir):
env_vars_to_add += [('EM_CACHE', em_cache_dir)]
mkdir_p(em_cache_dir)
2013-09-10 17:18:04 +03:00
for tool in tools_to_activate:
if hasattr(tool, 'activated_env'):
(key, value) = parse_key_value(tool.activated_env)
2014-07-03 15:14:45 +03:00
value = to_native_path(tool.expand_vars(value))
if not key in os.environ or to_unix_path(os.environ[key]) != to_unix_path(value): # Don't set env. vars which are already set to the correct value.
2014-07-03 13:43:37 +03:00
env_vars_to_add += [(key, value)]
if len(env_vars_to_add) > 0:
2015-03-31 15:44:34 +02:00
print('Setting environment variables:')
2014-07-03 13:43:37 +03:00
for key, value in env_vars_to_add:
2013-09-10 17:18:04 +03:00
if permanent:
2014-04-24 13:10:04 +03:00
env_string += 'SETX ' + key + ' "' + value + '"\n'
2013-09-10 17:18:04 +03:00
else:
2014-04-24 13:10:04 +03:00
env_string += 'SET ' + key + '=' + value + '\n'
2015-03-31 15:44:34 +02:00
print(key + ' = ' + value)
print('')
2014-04-24 13:10:04 +03:00
return env_string
2013-09-10 17:18:04 +03:00
2014-07-03 18:50:00 +03:00
def construct_env_unix(tools_to_activate):
env_string = ''
newpath, added_path = adjusted_path(tools_to_activate)
if os.environ['PATH'] != newpath: # Don't bother setting the path if there are no changes.
2014-11-19 17:25:38 +02:00
env_string += 'export PATH="' + newpath + '"\n'
2014-07-03 18:50:00 +03:00
if len(added_path) > 0:
2015-03-31 15:44:34 +02:00
print('Adding directories to PATH:')
2014-07-03 18:50:00 +03:00
for item in added_path:
2015-03-31 15:44:34 +02:00
print('PATH += ' + item)
print('')
2014-07-03 18:50:00 +03:00
env_vars_to_add = []
for tool in tools_to_activate:
if hasattr(tool, 'activated_env'):
(key, value) = parse_key_value(tool.activated_env)
value = to_native_path(tool.expand_vars(value))
if not key in os.environ or to_unix_path(os.environ[key]) != to_unix_path(value): # Don't set env. vars which are already set to the correct value.
env_vars_to_add += [(key, value)]
if len(env_vars_to_add) > 0:
2015-03-31 15:44:34 +02:00
print('Setting environment variables:')
2014-07-03 18:50:00 +03:00
for key, value in env_vars_to_add:
2014-11-19 17:26:38 +02:00
env_string += 'export ' + key + '="' + value + '"\n'
2015-03-31 15:44:34 +02:00
print(key + ' = ' + value)
print('')
2014-07-03 18:50:00 +03:00
return env_string
2013-09-10 17:18:04 +03:00
def construct_env(tools_to_activate, permanent):
if WINDOWS:
2014-04-24 13:10:04 +03:00
return construct_env_windows(tools_to_activate, permanent)
2014-07-03 18:50:00 +03:00
else:
return construct_env_unix(tools_to_activate)
2013-09-10 17:18:04 +03:00
2014-11-18 15:24:32 +02:00
def silentremove(filename):
try:
os.remove(filename)
2015-03-31 15:44:34 +02:00
except OSError as e:
2014-11-18 15:24:32 +02:00
if e.errno != errno.ENOENT: raise
2013-09-05 16:42:27 +03:00
def main():
2015-01-23 16:21:21 +02:00
global emscripten_config_directory
2013-09-05 16:42:27 +03:00
load_dot_emscripten()
load_sdk_manifest()
usage_str = "usage: %prog --param1 .. --paramn <projectrootdir>"
2014-04-24 00:57:59 +03:00
2013-09-05 16:42:27 +03:00
# parser = optparse.OptionParser(usage=usage_str)
# parser.add_option('update', dest='update', action='store_true', default=False, help='Downloads and installs the latest Emscripten SDK components.')
# (options, args) = parser.parse_args(sys.argv)
if len(sys.argv) <= 1 or sys.argv[1] == 'help':
if len(sys.argv) <= 1:
2015-03-31 15:44:34 +02:00
print(' emsdk: No command given. Please call one of the following:')
2013-09-05 16:42:27 +03:00
else:
2015-03-31 15:44:34 +02:00
print(' emsdk: Available commands:')
2013-09-05 16:42:27 +03:00
2015-03-31 15:44:34 +02:00
print('''
2014-04-24 13:10:04 +03:00
emsdk list [--old] - Lists all available SDKs and tools and their
current installation status. With the --old
parameter, also historical versions are shown.
2013-09-05 16:42:27 +03:00
emsdk update - Fetches a list of updates from the net (but
does not install them)
emsdk install <tool/sdk> - Downloads and installs the given tool or SDK.
emsdk uninstall <tool/sdk> - Removes the given tool or SDK from disk.
2014-09-17 10:09:18 +03:00
emsdk activate <tool/sdk> - Activates the given tool or SDK in the
2015-03-31 15:44:34 +02:00
environment of the current shell.''')
2013-09-05 16:42:27 +03:00
if WINDOWS:
2015-03-31 15:44:34 +02:00
print('''
2015-01-23 16:21:21 +02:00
emsdk activate [--global] [--embedded] <tool/sdk>
- Activates the given tool or SDK in
the environment of the current
shell. If the --global option is
passed, the registration is done
globally to all users in the system
environment. If the --embedded option is
passed, all Emcripten configuration files as
well as the temp, cache and ports directories
are located inside the Emscripten SDK
directory rather than the user home directory.
2014-09-17 10:09:18 +03:00
2014-04-24 13:10:04 +03:00
emcmdprompt.bat - Spawns a new command prompt window with the
2015-03-31 15:44:34 +02:00
Emscripten environment active.''')
2014-09-17 10:09:18 +03:00
else:
2015-03-31 15:44:34 +02:00
print('''
2015-01-23 16:21:21 +02:00
emsdk activate [--embedded] <tool/sdk>
- Activates the given tool or SDK in the
environment of the current shell. If the
--embedded option is passed, all Emcripten
configuration files as well as the temp, cache
and ports directories are located inside the
Emscripten SDK directory rather than the user
2015-03-31 15:44:34 +02:00
home directory.''')
2014-04-24 13:10:04 +03:00
2013-09-05 16:42:27 +03:00
return 1
cmd = sys.argv[1]
2013-10-15 17:51:44 +03:00
2014-07-03 13:43:37 +03:00
if (cmd == 'update' or cmd == 'install' or cmd == 'activate') and len(sys.argv) >= 3:
2013-10-15 17:51:44 +03:00
if sys.argv[2] == 'latest':
sys.argv[2] = str(find_latest_sdk())
elif sys.argv[2] == 'latest-32bit':
sys.argv[2] = str(find_latest_32bit_sdk())
elif sys.argv[2] == 'latest-64bit':
sys.argv[2] = str(find_latest_64bit_sdk())
2013-09-05 16:42:27 +03:00
if cmd == 'list':
2015-03-31 15:44:34 +02:00
print('')
2014-04-24 13:10:04 +03:00
show_old = len(sys.argv) >= 3 and sys.argv[2] == '--old'
2014-07-03 14:45:49 +03:00
has_partially_active_tools = False
2013-09-05 16:42:27 +03:00
if len(tools) > 0:
2015-03-31 15:44:34 +02:00
print('The following individual tools exist:')
2013-09-05 16:42:27 +03:00
for tool in tools:
2014-04-24 13:10:04 +03:00
if tool.is_old and not show_old:
continue
2013-09-05 16:42:27 +03:00
if tool.can_be_installed() == True:
installed = '\tINSTALLED' if tool.is_installed() else ''
else:
installed = '\tNot available: ' + tool.can_be_installed()
2014-07-03 14:45:49 +03:00
tool_is_active = tool.is_active()
tool_is_env_active = tool_is_active and tool.is_env_active()
if tool_is_env_active: active = ' * '
elif tool_is_active:
active = '(*)'
has_partially_active_tools = True
else: active = ' '
2015-03-31 15:44:34 +02:00
print(' ' + active + ' {0: <25}'.format(str(tool)) + installed)
print('')
2013-09-05 16:42:27 +03:00
else:
2015-03-31 15:44:34 +02:00
print("There are no tools available. Run 'emsdk update' to fetch the latest set of tools.")
print('')
2013-09-05 16:42:27 +03:00
if len(sdks) > 0:
2015-03-31 15:44:34 +02:00
print('The following Emscripten SDK versions are available:')
2013-09-05 16:42:27 +03:00
for sdk in sdks:
2014-04-24 13:17:02 +03:00
if sdk.is_old and not show_old:
continue
2013-09-05 16:42:27 +03:00
installed = '\tINSTALLED' if sdk.is_installed() else ''
active = '*' if sdk.is_active() else ' '
2015-03-31 15:44:34 +02:00
print(' ' + active + ' {0: <25}'.format(str(sdk)) + installed)
print('')
print('Items marked with * are activated for the current user.')
2014-07-03 14:45:49 +03:00
if has_partially_active_tools:
2014-07-03 18:50:00 +03:00
env_cmd = 'emsdk_env.bat' if WINDOWS else 'source ./emsdk_env.sh'
2015-03-31 15:44:34 +02:00
print('Items marked with (*) are selected for use, but your current shell environment is not configured to use them. Type "' + env_cmd + '" to set up your current shell to use them, or call "emsdk activate --global <name_of_sdk>" to permanently activate them.')
2014-04-24 13:17:02 +03:00
if not show_old:
2015-03-31 15:44:34 +02:00
print('')
print("To access the historical archived versions, type 'emsdk list --old'")
2013-09-05 16:42:27 +03:00
2013-09-10 17:18:04 +03:00
return 0
elif cmd == 'construct_env':
2015-01-23 16:21:21 +02:00
# If .emscripten exists, we are configuring as embedded inside the emsdk directory.
if os.path.exists(os.path.join(emsdk_path(), '.emscripten')):
emscripten_config_directory = emsdk_path()
2014-11-18 15:24:32 +02:00
silentremove(EMSDK_SET_ENV) # Clean up old temp file up front, in case of failure later before we get to write out the new one.
2013-09-10 17:18:04 +03:00
tools_to_activate = currently_active_tools()
2014-07-03 14:45:49 +03:00
tools_to_activate = process_tool_list(tools_to_activate, log_errors=True)
2014-07-03 13:43:37 +03:00
env_string = construct_env(tools_to_activate, len(sys.argv) >= 3 and 'perm' in sys.argv[2])
2014-11-18 15:24:32 +02:00
open(EMSDK_SET_ENV, 'w').write(env_string)
2015-03-31 15:44:34 +02:00
if LINUX or OSX: os.chmod(EMSDK_SET_ENV, 0o755)
2013-09-05 16:42:27 +03:00
return 0
elif cmd == 'update':
update_emsdk()
2014-11-18 15:24:32 +02:00
silentremove(sdk_path(EMSDK_SET_ENV)) # Clean up litter after old emsdk update which may have left this temp file around.
2013-09-05 16:42:27 +03:00
return 0
elif cmd == 'activate':
2014-07-03 13:43:37 +03:00
permanently_activate = '--global' in sys.argv
if permanently_activate:
2015-03-31 15:44:34 +02:00
print('Registering active Emscripten environment globally for all users.')
print('')
2015-01-23 16:21:21 +02:00
embed_activation_to_sdk_dir = '--embedded' in sys.argv
if embed_activation_to_sdk_dir:
# Activating the emsdk tools locally relative to Emscripten SDK directory.
emscripten_config_directory = emsdk_path()
2015-03-31 15:44:34 +02:00
print('Writing .emscripten configuration file to Emscripten SDK directory ' + emscripten_config_directory)
2015-01-23 16:21:21 +02:00
else:
2015-03-31 15:44:34 +02:00
print('Writing .emscripten configuration file to user home directory ' + emscripten_config_directory)
2015-01-23 16:21:21 +02:00
# Remove .emscripten from emsdk dir, since its presence is used to detect whether emsdk is activate in embedded mode or not.
try:
os.remove(os.path.join(emsdk_path(), ".emscripten"))
except:
pass
2015-03-31 15:44:34 +02:00
sys.argv = [x for x in sys.argv if not x.startswith('--')]
2013-11-20 13:09:51 +02:00
# If called without arguments, activate latest versions of all tools
2013-09-05 16:42:27 +03:00
if len(sys.argv) <= 2:
2013-11-20 13:09:51 +02:00
tools_to_activate = list(tools)
2014-07-03 13:43:37 +03:00
tools_to_activate = remove_nonexisting_tools(tools_to_activate, log_errors=False)
2013-11-20 13:09:51 +02:00
else:
tools_to_activate = currently_active_tools()
for i in range(2, len(sys.argv)):
tool = find_tool(sys.argv[i])
if tool == None:
tool = find_sdk(sys.argv[i])
if tool == None:
2015-03-31 15:44:34 +02:00
print("Error: No tool or SDK found by name '" + sys.argv[i] + "'.")
2013-11-20 13:09:51 +02:00
return 1
tools_to_activate += [tool]
2014-07-03 14:09:45 +03:00
tools_to_activate = set_active_tools(tools_to_activate, permanently_activate=permanently_activate)
2014-09-17 10:09:18 +03:00
if WINDOWS and not permanently_activate:
2015-03-31 15:44:34 +02:00
print('To permanently register this environment globally to all users in Windows Registry, rerun the command with the option --global.')
2013-09-05 16:42:27 +03:00
return 0
elif cmd == 'install':
if len(sys.argv) <= 2:
2015-03-31 15:44:34 +02:00
print("Missing parameter. Type 'emsdk install <tool name>' to install a tool or an SDK. Type 'emsdk list' to obtain a list of available tools. Type 'emsdk install latest' to automatically install the newest version of the SDK.")
2013-09-05 16:42:27 +03:00
return 1
tool = find_tool(sys.argv[2])
if tool == None:
tool = find_sdk(sys.argv[2])
if tool == None:
2015-03-31 15:44:34 +02:00
print("Error: No tool or SDK found by name '" + sys.argv[2] + "'.")
2013-09-05 16:42:27 +03:00
return 1
2015-03-17 16:03:43 -07:00
success = tool.install()
if not success:
return 1
2013-09-05 16:42:27 +03:00
elif cmd == 'uninstall':
if len(sys.argv) <= 2:
2015-03-31 15:44:34 +02:00
print("Syntax error. Call 'emsdk uninstall <tool name>'. Call 'emsdk list' to obtain a list of available tools.")
2013-09-05 16:42:27 +03:00
return 1
tool = find_tool(sys.argv[2])
if tool == None:
2015-03-31 15:44:34 +02:00
print("Error: Tool by name '" + sys.argv[2] + "' was not found.")
2013-09-05 16:42:27 +03:00
return 1
tool.uninstall()
else:
2015-03-31 15:44:34 +02:00
print("Unknown command '" + cmd + "' given! Type 'emsdk help' to get a list of commands.")
2013-09-05 16:42:27 +03:00
return 1
if __name__ == '__main__':
sys.exit(main())