def test_llvm_fastcomp(self): WARNING = 'fastcomp in use, but LLVM has not been built with the JavaScript backend as a target' restore_and_set_up() # Should see js backend during sanity check self.assertTrue(shared.check_llvm()) output = self.check_working(EMCC) self.assertNotIn(WARNING, output) # Fake incorrect llc output, no mention of js backend restore_and_set_up() with open(CONFIG_FILE, 'a') as f: f.write('LLVM_ROOT = "' + self.in_dir('fake', 'bin') + '"') # print '1', open(CONFIG_FILE).read() make_fake_clang(self.in_dir('fake', 'bin', 'clang'), expected_llvm_version()) make_fake_llc(self.in_dir('fake', 'bin', 'llc'), 'no j-s backend for you!') self.check_working(EMCC, WARNING) # fake some more for fake in [ 'llvm-link', 'llvm-ar', 'opt', 'llvm-as', 'llvm-dis', 'llvm-nm', 'lli' ]: open(self.in_dir('fake', 'bin', fake), 'w').write('.') try_delete(SANITY_FILE) self.check_working(EMCC, WARNING)
def make_fake(report): with open(CONFIG_FILE, '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_lld(self.in_dir('fake', 'bin', 'wasm-ld'))
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.assertTrue(os.path.exists(Cache.dirname)) output = self.do([EMCC]) self.assertIn('clearing cache', output) self.assertCacheEmpty()
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_clang_version() output = self.check_working(EMCC) assert LLVM_WARNING not in output, output # Fake a different llvm version restore_and_set_up() with open(CONFIG_FILE, 'a') as f: f.write('LLVM_ROOT = "' + path_from_root('tests', 'fake') + '"') if not os.path.exists(path_from_root('tests', 'fake')): os.makedirs(path_from_root('tests', 'fake')) with env_modify({'EM_IGNORE_SANITY': '1'}): for x in range(-2, 3): for y in range(-2, 3): f = open(path_from_root('tests', 'fake', 'clang'), 'w') f.write('#!/bin/sh\n') expected_x, expected_y = (int(x) for x in expected_llvm_version().split('.')) expected_x += x expected_y += y if expected_x < 0 or expected_y < 0: continue # must be a valid llvm version print(expected_llvm_version(), x, y, expected_x, expected_y) f.write('echo "clang version %d.%d" 1>&2\n' % (expected_x, expected_y)) f.close() shutil.copyfile(path_from_root('tests', 'fake', 'clang'), path_from_root('tests', 'fake', 'clang++')) os.chmod(path_from_root('tests', 'fake', 'clang'), stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC) os.chmod(path_from_root('tests', 'fake', 'clang++'), stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC) if x != 0 or y != 0: output = self.check_working(EMCC, LLVM_WARNING) else: output = self.check_working(EMCC) assert LLVM_WARNING not in output, output
def test_emcc_caching(self): BUILDING_MESSAGE = 'generating system library: X' ERASING_MESSAGE = 'clearing cache' restore_and_set_up() self.erase_cache() # Building a file that *does* need something *should* trigger cache # generation, but only the first time libname = 'libc++' for i in range(3): print(i) self.clear() output = self.do([ EMCC, '-O' + str(i), '-s', '--llvm-lto', '0', path_from_root('tests', 'hello_libcxx.cpp'), '--save-bc', 'a.bc', '-s', 'DISABLE_EXCEPTION_CATCHING=0' ]) print('\n\n\n', output) assert (BUILDING_MESSAGE.replace('X', libname) in output) == (i == 0), 'Must only build the first time' self.assertContained('hello, world!', run_js('a.out.js')) self.assertExists(Cache.dirname) full_libname = libname + '.bc' if libname != 'libc++' else libname + '.a' self.assertExists(os.path.join(Cache.dirname, full_libname)) restore_and_set_up() # Manual cache clearing self.ensure_cache() self.assertTrue(os.path.exists(Cache.dirname)) self.assertTrue(os.path.exists(Cache.root_dirname)) output = self.do([PYTHON, EMCC, '--clear-cache']) self.assertIn(ERASING_MESSAGE, output) self.assertFalse(os.path.exists(Cache.dirname)) self.assertFalse(os.path.exists(Cache.root_dirname)) self.assertIn(SANITY_MESSAGE, output) # Changing LLVM_ROOT, even without altering .emscripten, clears the cache self.ensure_cache() make_fake_clang(path_from_root('tests', 'fake', 'bin', 'clang'), expected_llvm_version()) make_fake_llc(path_from_root('tests', 'fake', 'bin', 'llc'), 'js - JavaScript (asm.js, emscripten)') with env_modify({'LLVM': path_from_root('tests', 'fake', 'bin')}): self.assertTrue(os.path.exists(Cache.dirname)) output = self.do([PYTHON, EMCC]) self.assertIn(ERASING_MESSAGE, output) self.assertFalse(os.path.exists(Cache.dirname))
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(CONFIG_FILE, '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('.')) if shared.get_llvm_target() == shared.WASM_TARGET: make_fake_llc(self.in_dir('fake', 'llc'), 'wasm32 - WebAssembly 32-bit') make_fake_lld(self.in_dir('fake', 'wasm-ld')) else: make_fake_llc(self.in_dir('fake', 'llc'), 'js - JavaScript (asm.js, emscripten)') with env_modify({'EM_IGNORE_SANITY': '1'}): for inc_x in range(-2, 3): for inc_y in range(-2, 3): 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_x, expected_x, expected_y)) make_fake_clang(self.in_dir('fake', 'clang'), '%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_llvm_fastcomp(self): WARNING = 'fastcomp in use, but LLVM has not been built with the JavaScript backend as a target' WARNING2 = 'you can fall back to the older (pre-fastcomp) compiler core, although that is not recommended, see http://kripken.github.io/emscripten-site/docs/building_from_source/LLVM-Backend.html' restore_and_set_up() # Should see js backend during sanity check assert shared.check_fastcomp() output = self.check_working(EMCC) self.assertNotIn(WARNING, output) self.assertNotIn(WARNING2, output) # Fake incorrect llc output, no mention of js backend restore_and_set_up() with open(CONFIG_FILE, 'a') as f: f.write('LLVM_ROOT = "' + path_from_root('tests', 'fake', 'bin') + '"') # print '1', open(CONFIG_FILE).read() try_delete(path_from_root('tests', 'fake')) os.makedirs(path_from_root('tests', 'fake', 'bin')) with open(path_from_root('tests', 'fake', 'bin', 'llc'), 'w') as f: f.write('#!/bin/sh\n') f.write('echo "llc fake output\nRegistered Targets:\nno j-s backend for you!"') os.chmod(path_from_root('tests', 'fake', 'bin', 'llc'), stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC) output = self.check_working(EMCC, WARNING) output = self.check_working(EMCC, WARNING2) # fake some more for fake in ['llvm-link', 'clang', 'clang++', 'llvm-ar', 'opt', 'llvm-as', 'llvm-dis', 'llvm-nm', 'lli']: open(path_from_root('tests', 'fake', 'bin', fake), 'w').write('.') try_delete(SANITY_FILE) output = self.check_working(EMCC, WARNING) # make sure sanity checks notice there is no source dir with version # open(path_from_root('tests', 'fake', 'bin', 'llc'), 'w').write('#!/bin/sh\necho "Registered Targets: there IZ a js backend: JavaScript (asm.js, emscripten) backend"') open(path_from_root('tests', 'fake', 'bin', 'clang++'), 'w').write('#!/bin/sh\necho "clang version %s (blah blah)" >&2\necho "..." >&2\n' % expected_llvm_version()) os.chmod(path_from_root('tests', 'fake', 'bin', 'llc'), stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC) os.chmod(path_from_root('tests', 'fake', 'bin', 'clang++'), stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC) try_delete(SANITY_FILE) output = self.check_working(EMCC, 'did not see a source tree above or next to the LLVM root directory') VERSION_WARNING = 'Emscripten, llvm and clang repo versions do not match, this is dangerous' BUILD_VERSION_WARNING = 'Emscripten, llvm and clang build versions do not match, this is dangerous' # add version number open(path_from_root('tests', 'fake', 'emscripten-version.txt'), 'w').write('waka') try_delete(SANITY_FILE) output = self.check_working(EMCC, VERSION_WARNING) os.makedirs(path_from_root('tests', 'fake', 'tools', 'clang')) open(path_from_root('tests', 'fake', 'tools', 'clang', 'emscripten-version.txt'), 'w').write(EMSCRIPTEN_VERSION) try_delete(SANITY_FILE) output = self.check_working(EMCC, VERSION_WARNING) open(path_from_root('tests', 'fake', 'emscripten-version.txt'), 'w').write(EMSCRIPTEN_VERSION) try_delete(SANITY_FILE) output = self.check_working(EMCC) self.assertNotIn(VERSION_WARNING, output) open(path_from_root('tests', 'fake', 'tools', 'clang', 'emscripten-version.txt'), 'w').write('waka') try_delete(SANITY_FILE) output = self.check_working(EMCC, VERSION_WARNING) # restore clang version to ok, and fake the *build* versions open(path_from_root('tests', 'fake', 'tools', 'clang', 'emscripten-version.txt'), 'w').write(EMSCRIPTEN_VERSION) output = self.check_working(EMCC) self.assertNotIn(VERSION_WARNING, output) fake = '#!/bin/sh\necho "clang version %s (blah blah) (emscripten waka : waka)"\necho "..."\n' % expected_llvm_version() open(path_from_root('tests', 'fake', 'bin', 'clang'), 'w').write(fake) open(path_from_root('tests', 'fake', 'bin', 'clang++'), 'w').write(fake) os.chmod(path_from_root('tests', 'fake', 'bin', 'clang'), stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC) os.chmod(path_from_root('tests', 'fake', 'bin', 'clang++'), stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC) try_delete(SANITY_FILE) output = self.check_working(EMCC, BUILD_VERSION_WARNING) self.assertNotIn(VERSION_WARNING, output) # break clang repo version again, see it hides the build warning open(path_from_root('tests', 'fake', 'tools', 'clang', 'emscripten-version.txt'), 'w').write('waka') output = self.check_working(EMCC, VERSION_WARNING) self.assertNotIn(BUILD_VERSION_WARNING, output) restore_and_set_up() self.check_working([EMCC] + MINIMAL_HELLO_WORLD + ['-s', 'ASM_JS=0'], '''Compiler settings are incompatible with fastcomp. You can fall back to the older compiler core, although that is not recommended''')