blob: af48625983cbc9337b42a7f1442a1acf646a72ec [file] [log] [blame] [edit]
# Copyright 2013 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.
import os
import platform
import shutil
import time
import re
import tempfile
from subprocess import PIPE, STDOUT
from runner import RunnerCore, path_from_root, env_modify, test_file
from runner import create_file, ensure_dir, make_executable, with_env_modify
from tools.config import EM_CONFIG
from tools.shared import EMCC
from tools.shared import CANONICAL_TEMP_DIR
from tools.shared import try_delete, config
from tools.shared import EXPECTED_LLVM_VERSION, Cache
from tools import shared, system_libs, utils
SANITY_FILE = shared.Cache.get_path('sanity.txt')
commands = [[EMCC], [path_from_root('tests', 'runner'), 'blahblah']]
def restore():
shutil.copyfile(EM_CONFIG + '_backup', EM_CONFIG)
# restore the config file and set it up for our uses
def restore_and_set_up():
restore()
with open(EM_CONFIG, 'a') as f:
# make LLVM_ROOT sensitive to the LLVM env var, as we test that
f.write('LLVM_ROOT = "%s"\n' % config.LLVM_ROOT)
# unfreeze the cache, so we can test that
f.write('FROZEN_CACHE = False\n')
# wipe the config and sanity files, creating a blank slate
def wipe():
try_delete(EM_CONFIG)
try_delete(SANITY_FILE)
def add_to_config(content):
with open(EM_CONFIG, 'a') as f:
f.write('\n' + content + '\n')
def get_basic_config():
return '''\
LLVM_ROOT = "%s"
BINARYEN_ROOT = "%s"
NODE_JS = %s
''' % (config.LLVM_ROOT, config.BINARYEN_ROOT, config.NODE_JS)
def make_fake_tool(filename, version, report_name=None):
if not report_name:
report_name = os.path.basename(filename)
print('make_fake_tool: %s' % filename)
ensure_dir(os.path.dirname(filename))
with open(filename, 'w') as f:
f.write('#!/bin/sh\n')
f.write('echo "%s version %s"\n' % (report_name, version))
f.write('echo "..."\n')
f.write('exit 0\n')
make_executable(filename)
def make_fake_clang(filename, version):
"""Create a fake clang that only handles --version
--version writes to stdout (unlike -v which writes to stderr)
"""
make_fake_tool(filename, version)
make_fake_tool(filename + '++', version)
def make_fake_llc(filename, targets):
"""Create a fake llc that only handles --version and writes target
list to stdout.
"""
print('make_fake_llc: %s' % filename)
ensure_dir(os.path.dirname(filename))
with open(filename, 'w') as f:
f.write('#!/bin/sh\n')
f.write('echo "llc fake output\nRegistered Targets:\n%s"' % targets)
make_executable(filename)
SANITY_MESSAGE = 'Emscripten: Running sanity checks'
EMBUILDER = path_from_root('embuilder.py')
# arguments to build a minimal hello world program, without even libc
# (-O1 avoids -O0's default assertions which bring in checking code;
# FILESYSTEM=0 avoids bringing libc for that)
# (ERROR_ON_UNDEFINED_SYMBOLS=0 is needed because __errno_location is
# not included on the native side but needed by a lot of JS libraries.)
MINIMAL_HELLO_WORLD = [test_file('hello_world_em_asm.c'), '-O1', '-s', 'FILESYSTEM=0', '-s', 'ERROR_ON_UNDEFINED_SYMBOLS=0']
class sanity(RunnerCore):
@classmethod
def setUpClass(cls):
super(sanity, cls).setUpClass()
# Unlike the other test suites we explicitly don't want to be skipping
# the sanity checks here
del os.environ['EMCC_SKIP_SANITY_CHECK']
assert os.path.exists(EM_CONFIG), 'To run these tests, we need a (working!) %s file to already exist' % EM_CONFIG
shutil.copyfile(EM_CONFIG, EM_CONFIG + '_backup')
print()
print('Running sanity checks.')
print('WARNING: This will modify %s, and in theory can break it although it should be restored properly. A backup will be saved in %s_backup' % (EM_CONFIG, EM_CONFIG))
print()
print('>>> the original settings file is:')
print(open(EM_CONFIG).read().strip())
print('<<<')
print()
assert 'EMCC_DEBUG' not in os.environ, 'do not run sanity checks in debug mode!'
@classmethod
def tearDownClass(cls):
super(sanity, cls).tearDownClass()
restore()
def setUp(self):
super(sanity, self).setUp()
wipe()
self.start_time = time.time()
def tearDown(self):
super(sanity, self).tearDown()
print('time:', time.time() - self.start_time)
def do(self, command, env=None):
print('Running: ' + ' '.join(command))
if type(command) is not list:
command = [command]
return self.run_process(command, stdout=PIPE, stderr=STDOUT, check=False, env=env).stdout
def check_working(self, command, expected=None):
if type(command) is not list:
command = [command]
if expected is None:
if command[0] == EMCC or (len(command) >= 2 and command[1] == EMCC):
expected = 'no input files'
else:
expected = "could not find the following tests: blahblah"
output = self.do(command)
self.assertContained(expected, output)
return output
# this should be the very first thing that runs. if this fails, everything else is irrelevant!
def test_aaa_normal(self):
for command in commands:
# Your existing EM_CONFIG should work!
restore_and_set_up()
self.check_working(command)
@with_env_modify({'EM_CONFIG': None})
def test_firstrun(self):
for command in commands:
wipe()
default_config = config.embedded_config
try:
temp_bin = tempfile.mkdtemp()
def make_new_executable(name):
open(os.path.join(temp_bin, name), 'w').close()
make_executable(os.path.join(temp_bin, name))
make_new_executable('llvm-dis')
make_new_executable('node')
with env_modify({'PATH': temp_bin + os.pathsep + os.environ['PATH']}):
output = self.do(command)
finally:
shutil.rmtree(temp_bin)
config_data = open(default_config).read()
try_delete(default_config)
self.assertContained('Welcome to Emscripten!', output)
self.assertContained('This is the first time any of the Emscripten tools has been run.', output)
self.assertContained('A settings file has been copied to %s, at absolute path: %s' % (default_config, default_config), output)
self.assertContained('It contains our best guesses for the important paths, which are:', output)
self.assertContained('LLVM_ROOT', output)
self.assertContained('NODE_JS', output)
if platform.system() != 'Windows':
# os.chmod can't make files executable on Windows
self.assertIdentical(temp_bin, re.search("^ *LLVM_ROOT *= (.*)$", output, re.M).group(1))
possible_nodes = [os.path.join(temp_bin, 'node')]
if os.path.exists('/usr/bin/nodejs'):
possible_nodes.append('/usr/bin/nodejs')
self.assertIdentical(possible_nodes, re.search("^ *NODE_JS *= (.*)$", output, re.M).group(1))
self.assertContained('Please edit the file if any of those are incorrect', output)
self.assertContained('This command will now exit. When you are done editing those paths, re-run it.', output)
self.assertTrue(output.strip().endswith('============='))
template_file = open(path_from_root('tools', 'settings_template.py')).read()
self.assertNotContained('{{{', config_data)
self.assertNotContained('}}}', config_data)
self.assertContained('{{{', template_file)
self.assertContained('}}}', template_file)
for content in ['EMSCRIPTEN_ROOT', 'LLVM_ROOT', 'NODE_JS', 'JS_ENGINES']:
self.assertContained(content, config_data)
# The guessed config should be ok
# XXX This depends on your local system! it is possible `which` guesses wrong
# try_delete('a.out.js')
# output = self.run_process([EMCC, test_file('hello_world.c')], stdout=PIPE, stderr=PIPE).output
# self.assertContained('hello, world!', self.run_js('a.out.js'), output)
# Second run, with bad EM_CONFIG
for settings in ['blah', 'LLVM_ROOT="blarg"; JS_ENGINES=[]; NODE_JS=[]; SPIDERMONKEY_ENGINE=[]']:
try:
with open(default_config, 'w') as f:
f.write(settings)
output = self.do(command)
if 'blah' in settings:
self.assertContained('Error in evaluating config file (%s)' % default_config, output)
elif 'runner' not in ' '.join(command):
self.assertContained('error: NODE_JS is set to empty value', output) # sanity check should fail
finally:
try_delete(default_config)
def test_llvm(self):
LLVM_WARNING = 'LLVM version appears incorrect'
restore_and_set_up()
# Clang should report the version number we expect, and emcc should not warn
assert shared.check_llvm_version()
output = self.check_working(EMCC)
self.assertNotContained(LLVM_WARNING, output)
# Fake a different llvm version
restore_and_set_up()
with open(EM_CONFIG, 'a') as f:
f.write('LLVM_ROOT = "' + self.in_dir('fake') + '"')
real_version_x, real_version_y = (int(x) for x in EXPECTED_LLVM_VERSION.split('.'))
make_fake_llc(self.in_dir('fake', 'llc'), 'wasm32 - WebAssembly 32-bit')
make_fake_tool(self.in_dir('fake', 'wasm-ld'), EXPECTED_LLVM_VERSION)
for inc_x in range(-2, 3):
for inc_y in range(-2, 3):
try_delete(SANITY_FILE)
expected_x = real_version_x + inc_x
expected_y = real_version_y + inc_y
if expected_x < 0 or expected_y < 0:
continue # must be a valid llvm version
print("mod LLVM version: %d %d -> %d %d" % (real_version_x, real_version_y, expected_x, expected_y))
make_fake_clang(self.in_dir('fake', 'clang'), '%s.%s' % (expected_x, expected_y))
make_fake_tool(self.in_dir('fake', 'llvm-ar'), '%s.%s' % (expected_x, expected_y))
make_fake_tool(self.in_dir('fake', 'llvm-nm'), '%s.%s' % (expected_x, expected_y))
did_modify = inc_x != 0 or inc_y != 0
if did_modify:
output = self.check_working(EMCC, LLVM_WARNING)
else:
output = self.check_working(EMCC)
self.assertNotContained(LLVM_WARNING, output)
def test_emscripten_root(self):
# The correct path
restore_and_set_up()
add_to_config("EMSCRIPTEN_ROOT = '%s'" % path_from_root())
self.check_working(EMCC)
# The correct path with extra stuff
restore_and_set_up()
add_to_config("EMSCRIPTEN_ROOT = '%s'" % (path_from_root() + os.path.sep))
self.check_working(EMCC)
def test_node(self):
NODE_WARNING = 'node version appears too old'
NODE_WARNING_2 = 'cannot check node version'
restore_and_set_up()
# Clang should report the version number we expect, and emcc should not warn
assert shared.check_node_version()
output = self.check_working(EMCC)
self.assertNotContained(NODE_WARNING, output)
# Fake a different node version
restore_and_set_up()
with open(EM_CONFIG, 'a') as f:
f.write('NODE_JS = "' + self.in_dir('fake', 'nodejs') + '"')
ensure_dir('fake')
for version, succeed in [('v0.8.0', False),
('v4.1.0', False),
('v4.1.1', True),
('v4.2.3-pre', True),
('cheez', False)]:
print(version, succeed)
try_delete(SANITY_FILE)
f = open(self.in_dir('fake', 'nodejs'), 'w')
f.write('#!/bin/sh\n')
f.write('''if [ $1 = "--version" ]; then
echo "%s"
else
%s $@
fi
''' % (version, ' '.join(config.NODE_JS)))
f.close()
make_executable(self.in_dir('fake', 'nodejs'))
if not succeed:
if version[0] == 'v':
self.check_working(EMCC, NODE_WARNING)
else:
self.check_working(EMCC, NODE_WARNING_2)
else:
output = self.check_working(EMCC)
self.assertNotContained(NODE_WARNING, output)
def test_emcc(self):
SANITY_FAIL_MESSAGE = 'sanity check failed to run'
# emcc should check sanity if no ${EM_CONFIG}_sanity
restore_and_set_up()
time.sleep(1)
assert not os.path.exists(SANITY_FILE) # restore is just the settings, not the sanity
output = self.check_working(EMCC)
self.assertContained(SANITY_MESSAGE, output)
# EMCC should have checked sanity successfully
old_sanity = open(SANITY_FILE).read()
self.assertNotContained(SANITY_FAIL_MESSAGE, output)
# emcc run again should not sanity check, because the sanity file is newer
output = self.check_working(EMCC)
self.assertNotContained(SANITY_MESSAGE, output)
self.assertNotContained(SANITY_FAIL_MESSAGE, output)
# incorrect sanity contents mean we *must* check
open(SANITY_FILE, 'w').write('wakawaka')
output = self.check_working(EMCC)
self.assertContained(SANITY_MESSAGE, output)
# correct sanity contents mean we need not check
open(SANITY_FILE, 'w').write(old_sanity)
output = self.check_working(EMCC)
self.assertNotContained(SANITY_MESSAGE, output)
# but with EMCC_DEBUG=1 we should check
with env_modify({'EMCC_DEBUG': '1'}):
output = self.check_working(EMCC)
try_delete(CANONICAL_TEMP_DIR)
self.assertContained(SANITY_MESSAGE, output)
output = self.check_working(EMCC)
self.assertNotContained(SANITY_MESSAGE, output)
# Make sure the test runner didn't do anything to the setup
output = self.check_working(EMCC)
self.assertNotContained(SANITY_MESSAGE, output)
self.assertNotContained(SANITY_FAIL_MESSAGE, output)
# emcc should also check sanity if the file is outdated
open(EM_CONFIG, 'a').write('# extra stuff\n')
output = self.check_working(EMCC)
self.assertContained(SANITY_MESSAGE, output)
self.assertNotContained(SANITY_FAIL_MESSAGE, output)
def test_em_config_env_var(self):
# emcc should be configurable directly from EM_CONFIG without any config file
restore_and_set_up()
create_file('main.cpp', '''
#include <stdio.h>
int main() {
printf("hello from emcc with no config file\\n");
return 0;
}
''')
wipe()
with env_modify({'EM_CONFIG': get_basic_config()}):
out = self.expect_fail([EMCC, 'main.cpp', '-Wno-deprecated', '-o', 'a.out.js'])
self.assertContained('error: Inline EM_CONFIG data no longer supported. Please use a config file.', out)
def clear_cache(self):
self.run_process([EMCC, '--clear-cache'])
self.assertCacheEmpty()
def assertCacheEmpty(self):
if os.path.exists(Cache.dirname):
# The cache is considered empty if it contains no files at all or just the cache.lock
self.assertIn(os.listdir(Cache.dirname), ([], ['cache.lock']))
def ensure_cache(self):
self.do([EMCC, '-O2', test_file('hello_world.c')])
def test_emcc_caching(self):
BUILDING_MESSAGE = 'generating system library: %s'
restore_and_set_up()
self.clear_cache()
# Building a file that *does* need something *should* trigger cache
# generation, but only the first time
libname = Cache.get_lib_name('libc++.a')
for i in range(3):
print(i)
self.clear()
output = self.do([EMCC, '-O' + str(i), test_file('hello_libcxx.cpp'), '-s', 'DISABLE_EXCEPTION_CATCHING=0'])
print('\n\n\n', output)
self.assertContainedIf(BUILDING_MESSAGE % libname, output, i == 0)
self.assertContained('hello, world!', self.run_js('a.out.js'))
self.assertExists(Cache.dirname)
self.assertExists(os.path.join(Cache.dirname, libname))
def test_cache_clearing_manual(self):
# Manual cache clearing
restore_and_set_up()
self.ensure_cache()
self.assertExists(Cache.dirname)
output = self.do([EMCC, '--clear-cache'])
self.assertIn('clearing cache', output)
self.assertIn(SANITY_MESSAGE, output)
self.assertCacheEmpty()
def test_cache_clearing_auto(self):
# Changing LLVM_ROOT, even without altering .emscripten, clears the cache
restore_and_set_up()
self.ensure_cache()
make_fake_clang(self.in_dir('fake', 'bin', 'clang'), EXPECTED_LLVM_VERSION)
make_fake_llc(self.in_dir('fake', 'bin', 'llc'), 'got wasm32 backend! WebAssembly 32-bit')
with env_modify({'EM_LLVM_ROOT': self.in_dir('fake', 'bin')}):
self.assertExists(Cache.dirname)
output = self.do([EMCC])
self.assertIn('clearing cache', output)
self.assertCacheEmpty()
# FROZEN_CACHE prevents cache clears, and prevents building
def test_FROZEN_CACHE(self):
restore_and_set_up()
self.clear_cache()
self.ensure_cache()
self.assertExists(Cache.dirname)
# changing config file should not clear cache
add_to_config('FROZEN_CACHE = True')
self.do([EMCC])
self.assertExists(Cache.dirname)
# building libraries is disallowed
output = self.do([EMBUILDER, 'build', 'libemmalloc'])
self.assertContained('FROZEN_CACHE is set, but cache file is missing', output)
# Test that if multiple processes attempt to access or build stuff to the
# cache on demand, that exactly one of the processes will, and the other
# processes will block to wait until that process finishes.
def test_emcc_multiprocess_cache_access(self):
restore_and_set_up()
create_file('test.c', r'''
#include <stdio.h>
int main() {
printf("hello, world!\n");
return 0;
}
''')
cache_dir_name = self.in_dir('test_cache')
libname = Cache.get_lib_name('libc.a')
with env_modify({'EM_CACHE': cache_dir_name}):
tasks = []
num_times_libc_was_built = 0
for i in range(3):
p = self.run_process([EMCC, 'test.c', '-o', '%d.js' % i], stderr=STDOUT, stdout=PIPE)
tasks += [p]
for p in tasks:
print('stdout:\n', p.stdout)
if 'generating system library: ' + libname in p.stdout:
num_times_libc_was_built += 1
# The cache directory must exist after the build
self.assertExists(cache_dir_name)
# The cache directory must contain a built libc
self.assertExists(os.path.join(cache_dir_name, libname))
# Exactly one child process should have triggered libc build!
self.assertEqual(num_times_libc_was_built, 1)
def test_emconfig(self):
restore_and_set_up()
fd, custom_config_filename = tempfile.mkstemp(prefix='.emscripten_config_')
orig_config = open(EM_CONFIG, 'r').read()
# Move the ~/.emscripten to a custom location.
with os.fdopen(fd, "w") as f:
f.write(get_basic_config())
# Make a syntax error in the original config file so that attempting to access it would fail.
open(EM_CONFIG, 'w').write('asdfasdfasdfasdf\n\'\'\'' + orig_config)
temp_dir = tempfile.mkdtemp(prefix='emscripten_temp_')
with utils.chdir(temp_dir):
self.run_process([EMCC, '--em-config', custom_config_filename] + MINIMAL_HELLO_WORLD + ['-O2'])
result = self.run_js('a.out.js')
self.assertContained('hello, world!', result)
# Clean up created temp files.
os.remove(custom_config_filename)
shutil.rmtree(temp_dir)
def test_emcc_ports(self):
restore_and_set_up()
# listing ports
out = self.do([EMCC, '--show-ports'])
self.assertContained('Available ports:', out)
self.assertContained('SDL2', out)
self.assertContained('SDL2_image', out)
self.assertContained('SDL2_net', out)
# using ports
RETRIEVING_MESSAGE = 'retrieving port'
BUILDING_MESSAGE = 'generating port'
PORTS_DIR = system_libs.Ports.get_dir()
for i in [0, 1]:
self.do([EMCC, '--clear-cache'])
print(i)
if i == 0:
try_delete(PORTS_DIR)
else:
self.do([EMCC, '--clear-ports'])
self.assertNotExists(PORTS_DIR)
# Building a file that doesn't need ports should not trigger anything
output = self.do([EMCC, test_file('hello_world_sdl.cpp')])
self.assertNotContained(RETRIEVING_MESSAGE, output)
self.assertNotContained(BUILDING_MESSAGE, output)
self.assertNotExists(PORTS_DIR)
def first_use():
output = self.do([EMCC, test_file('hello_world_sdl.cpp'), '-s', 'USE_SDL=2'])
self.assertContained(RETRIEVING_MESSAGE, output)
self.assertContained(BUILDING_MESSAGE, output)
self.assertExists(PORTS_DIR)
def second_use():
# Using it again avoids retrieve and build
output = self.do([EMCC, test_file('hello_world_sdl.cpp'), '-s', 'USE_SDL=2'])
self.assertNotContained(RETRIEVING_MESSAGE, output)
self.assertNotContained(BUILDING_MESSAGE, output)
# Building a file that need a port does trigger stuff
first_use()
second_use()
# if the url doesn't match, we retrieve and rebuild
with open(os.path.join(PORTS_DIR, 'sdl2', '.emscripten_url'), 'w') as f:
f.write('foo')
first_use()
second_use()
def test_js_engine_path(self):
# Test that running JS commands works for node, d8, and jsc and is not path dependent
restore_and_set_up()
sample_script = test_file('print_args.js')
# Fake some JS engines
# Note that the path contains 'd8'.
test_path = self.in_dir('fake', 'abcd8765')
ensure_dir(test_path)
jsengines = [('d8', config.V8_ENGINE),
('d8_g', config.V8_ENGINE),
('js', config.SPIDERMONKEY_ENGINE),
('node', config.NODE_JS),
('nodejs', config.NODE_JS)]
for filename, engine in jsengines:
try_delete(SANITY_FILE)
if type(engine) is list:
engine = engine[0]
if not engine:
print('WARNING: Not testing engine %s, not configured.' % (filename))
continue
print(filename, engine)
test_engine_path = os.path.join(test_path, filename)
with open(test_engine_path, 'w') as f:
f.write('#!/bin/sh\n')
f.write('exec %s $@\n' % (engine))
make_executable(test_engine_path)
out = self.run_js(sample_script, engine=test_engine_path, args=['--foo'])
self.assertEqual('0: --foo', out.strip())
def test_wacky_env(self):
restore_and_set_up()
def build():
return self.check_working([EMCC] + MINIMAL_HELLO_WORLD, '')
def test():
self.assertContained('hello, world!', self.run_js('a.out.js'))
print('normal build')
with env_modify({'EMCC_FORCE_STDLIBS': None}):
self.clear_cache()
build()
test()
print('wacky env vars, these should not mess our bootstrapping')
with env_modify({'EMCC_FORCE_STDLIBS': '1'}):
self.clear_cache()
build()
test()
def test_vanilla(self):
restore_and_set_up()
self.clear_cache()
def make_fake(report):
with open(EM_CONFIG, 'a') as f:
f.write('LLVM_ROOT = "' + self.in_dir('fake', 'bin') + '"\n')
# BINARYEN_ROOT needs to exist in the config, even though this test
# doesn't actually use it.
f.write('BINARYEN_ROOT= "%s"\n' % self.in_dir('fake', 'bin'))
make_fake_clang(self.in_dir('fake', 'bin', 'clang'), EXPECTED_LLVM_VERSION)
make_fake_llc(self.in_dir('fake', 'bin', 'llc'), report)
make_fake_tool(self.in_dir('fake', 'bin', 'wasm-ld'), EXPECTED_LLVM_VERSION)
# fake llc output
def test_with_fake(report, expected):
make_fake(report)
with env_modify({'EMCC_DEBUG': '1'}):
self.check_working([EMCC] + MINIMAL_HELLO_WORLD + ['-c'], expected)
test_with_fake('got js backend! JavaScript (asm.js, emscripten) backend', 'LLVM has not been built with the WebAssembly backend')
try_delete(CANONICAL_TEMP_DIR)
def test_required_config_settings(self):
# with no binaryen root, an error is shown
restore_and_set_up()
open(EM_CONFIG, 'a').write('\nBINARYEN_ROOT = ""\n')
self.check_working([EMCC, test_file('hello_world.c')], 'BINARYEN_ROOT is set to empty value in %s' % EM_CONFIG)
open(EM_CONFIG, 'a').write('\ndel BINARYEN_ROOT\n')
self.check_working([EMCC, test_file('hello_world.c')], 'BINARYEN_ROOT is not defined in %s' % EM_CONFIG)
def test_embuilder_force(self):
restore_and_set_up()
self.do([EMBUILDER, 'build', 'libemmalloc'])
# Second time it should not generate anything
self.assertNotContained('generating system library', self.do([EMBUILDER, 'build', 'libemmalloc']))
# Unless --force is specified
self.assertContained('generating system library', self.do([EMBUILDER, 'build', 'libemmalloc', '--force']))
def test_embuilder_force_port(self):
restore_and_set_up()
self.do([EMBUILDER, 'build', 'zlib'])
# Second time it should not generate anything
self.assertNotContained('generating port', self.do([EMBUILDER, 'build', 'zlib']))
# Unless --force is specified
self.assertContained('generating port', self.do([EMBUILDER, 'build', 'zlib', '--force']))
def test_embuilder_wasm_backend(self):
restore_and_set_up()
# the --lto flag makes us build wasm-bc
self.clear_cache()
self.run_process([EMBUILDER, 'build', 'libemmalloc'])
self.assertExists(os.path.join(config.CACHE, 'sysroot', 'lib', 'wasm32-emscripten'))
self.clear_cache()
self.run_process([EMBUILDER, 'build', 'libemmalloc', '--lto'])
self.assertExists(os.path.join(config.CACHE, 'sysroot', 'lib', 'wasm32-emscripten', 'lto'))
def test_binaryen_version(self):
restore_and_set_up()
with open(EM_CONFIG, 'a') as f:
f.write('\nBINARYEN_ROOT = "' + self.in_dir('fake') + '"')
make_fake_tool(self.in_dir('fake', 'bin', 'wasm-opt'), 'foo')
self.check_working([EMCC, test_file('hello_world.c')], 'error parsing binaryen version (wasm-opt version foo). Please check your binaryen installation')
make_fake_tool(self.in_dir('fake', 'bin', 'wasm-opt'), '70')
self.check_working([EMCC, test_file('hello_world.c')], 'unexpected binaryen version: 70 (expected ')